mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-22 21:36:11 +01:00
Add a generator that takes an iterator pair
This commit is contained in:
parent
b8b765d55e
commit
319cb9e1da
@ -46,13 +46,16 @@ a test case,
|
|||||||
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
* `MapGenerator<T, U, Func>` -- returns the result of applying `Func`
|
||||||
on elements from a different generator
|
on elements from a different generator
|
||||||
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
|
* `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator
|
||||||
* 3 specific purpose generators
|
* 4 specific purpose generators
|
||||||
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
* `RandomIntegerGenerator<Integral>` -- generates random Integrals from range
|
||||||
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
* `RandomFloatGenerator<Float>` -- generates random Floats from range
|
||||||
* `RangeGenerator<T>` -- generates all values inside a specific range
|
* `RangeGenerator<T>` -- generates all values inside a specific range
|
||||||
|
* `IteratorGenerator<T>` -- copies and returns values from an iterator range
|
||||||
|
|
||||||
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
|
> `ChunkGenerator<T>`, `RandomIntegerGenerator<Integral>`, `RandomFloatGenerator<Float>` and `RangeGenerator<T>` were introduced in Catch 2.7.0.
|
||||||
|
|
||||||
|
> `IteratorGenerator<T>` was introduced in Catch X.Y.Z.
|
||||||
|
|
||||||
The generators also have associated helper functions that infer their
|
The generators also have associated helper functions that infer their
|
||||||
type, making their usage much nicer. These are
|
type, making their usage much nicer. These are
|
||||||
|
|
||||||
@ -68,9 +71,12 @@ type, making their usage much nicer. These are
|
|||||||
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
|
||||||
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
|
||||||
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
|
||||||
|
* `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator<T>`
|
||||||
|
|
||||||
> `chunk()`, `random()` and both `range()` functions were introduced in Catch 2.7.0.
|
> `chunk()`, `random()` and both `range()` functions were introduced in Catch 2.7.0.
|
||||||
|
|
||||||
|
> `from_range` has been introduced in Catch X.Y.Z
|
||||||
|
|
||||||
And can be used as shown in the example below to create a generator
|
And can be used as shown in the example below to create a generator
|
||||||
that returns 100 odd random number:
|
that returns 100 odd random number:
|
||||||
|
|
||||||
|
@ -128,6 +128,39 @@ GeneratorWrapper<T> range(T const& start, T const& end) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class IteratorGenerator final : public IGenerator<T> {
|
||||||
|
static_assert(!std::is_same<T, bool>::value,
|
||||||
|
"IteratorGenerator currently does not support bools"
|
||||||
|
"because of std::vector<bool> specialization");
|
||||||
|
|
||||||
|
std::vector<T> m_elems;
|
||||||
|
size_t m_current = 0;
|
||||||
|
public:
|
||||||
|
template <typename InputIterator, typename InputSentinel>
|
||||||
|
IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
|
||||||
|
if (m_elems.empty()) {
|
||||||
|
Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T const& get() const override {
|
||||||
|
return m_elems[m_current];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next() override {
|
||||||
|
++m_current;
|
||||||
|
return m_current != m_elems.size();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename InputIterator,
|
||||||
|
typename InputSentinel,
|
||||||
|
typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
|
||||||
|
GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
|
||||||
|
return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Generators
|
} // namespace Generators
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
@ -310,6 +310,12 @@ Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6
|
|||||||
Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4
|
Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive)
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive)
|
||||||
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING"
|
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING"
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
|
Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom()
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom()
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom(), std::exception
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception - not std'; expression was: throwCustom(), std::exception
|
||||||
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom std exception'
|
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom std exception'
|
||||||
|
@ -1380,6 +1380,6 @@ due to unexpected exception with message:
|
|||||||
Why would you throw a std::string?
|
Why would you throw a std::string?
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 300 | 226 passed | 70 failed | 4 failed as expected
|
test cases: 301 | 227 passed | 70 failed | 4 failed as expected
|
||||||
assertions: 1564 | 1412 passed | 131 failed | 21 failed as expected
|
assertions: 1570 | 1418 passed | 131 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -2381,6 +2381,72 @@ Matchers.tests.cpp:<line number>: FAILED:
|
|||||||
with expansion:
|
with expansion:
|
||||||
"this string contains 'abc' as a substring" contains: "STRING"
|
"this string contains 'abc' as a substring" contains: "STRING"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copy and then generate a range
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Generators.tests.cpp:<line number>
|
||||||
|
...............................................................................
|
||||||
|
|
||||||
|
Generators.tests.cpp:<line number>: PASSED:
|
||||||
|
REQUIRE( elem % 2 == 1 )
|
||||||
|
with expansion:
|
||||||
|
1 == 1
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Custom exceptions can be translated when testing for nothrow
|
Custom exceptions can be translated when testing for nothrow
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -12499,6 +12565,6 @@ Misc.tests.cpp:<line number>
|
|||||||
Misc.tests.cpp:<line number>: PASSED:
|
Misc.tests.cpp:<line number>: PASSED:
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
test cases: 300 | 210 passed | 86 failed | 4 failed as expected
|
test cases: 301 | 211 passed | 86 failed | 4 failed as expected
|
||||||
assertions: 1581 | 1412 passed | 148 failed | 21 failed as expected
|
assertions: 1587 | 1418 passed | 148 failed | 21 failed as expected
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<testsuitesloose text artifact
|
<testsuitesloose text artifact
|
||||||
>
|
>
|
||||||
<testsuite name="<exe-name>" errors="17" failures="132" tests="1582" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
<testsuite name="<exe-name>" errors="17" failures="132" tests="1588" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
|
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
|
||||||
<property name="random-seed" value="1"/>
|
<property name="random-seed" value="1"/>
|
||||||
@ -254,6 +254,7 @@ Matchers.tests.cpp:<line number>
|
|||||||
Matchers.tests.cpp:<line number>
|
Matchers.tests.cpp:<line number>
|
||||||
</failure>
|
</failure>
|
||||||
</testcase>
|
</testcase>
|
||||||
|
<testcase classname="<exe-name>.global" name="Copy and then generate a range" time="{duration}"/>
|
||||||
<testcase classname="<exe-name>.global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
|
<testcase classname="<exe-name>.global" name="Custom exceptions can be translated when testing for nothrow" time="{duration}">
|
||||||
<error message="throwCustom()" type="REQUIRE_NOTHROW">
|
<error message="throwCustom()" type="REQUIRE_NOTHROW">
|
||||||
custom exception - not std
|
custom exception - not std
|
||||||
|
@ -2816,6 +2816,57 @@ Nor would this
|
|||||||
</Expression>
|
</Expression>
|
||||||
<OverallResult success="false"/>
|
<OverallResult success="false"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
|
<TestCase name="Copy and then generate a range" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
|
||||||
|
<Original>
|
||||||
|
elem % 2 == 1
|
||||||
|
</Original>
|
||||||
|
<Expanded>
|
||||||
|
1 == 1
|
||||||
|
</Expanded>
|
||||||
|
</Expression>
|
||||||
|
<OverallResult success="true"/>
|
||||||
|
</TestCase>
|
||||||
<TestCase name="Custom exceptions can be translated when testing for nothrow" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
<TestCase name="Custom exceptions can be translated when testing for nothrow" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||||
<Expression success="false" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
<Expression success="false" type="REQUIRE_NOTHROW" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
|
||||||
<Original>
|
<Original>
|
||||||
@ -14872,7 +14923,7 @@ loose text artifact
|
|||||||
</Section>
|
</Section>
|
||||||
<OverallResult success="true"/>
|
<OverallResult success="true"/>
|
||||||
</TestCase>
|
</TestCase>
|
||||||
<OverallResults successes="1412" failures="149" expectedFailures="21"/>
|
<OverallResults successes="1418" failures="149" expectedFailures="21"/>
|
||||||
</Group>
|
</Group>
|
||||||
<OverallResults successes="1412" failures="148" expectedFailures="21"/>
|
<OverallResults successes="1418" failures="148" expectedFailures="21"/>
|
||||||
</Catch>
|
</Catch>
|
||||||
|
@ -212,3 +212,28 @@ TEST_CASE("Nested generators and captured variables", "[generators]") {
|
|||||||
auto values = GENERATE_COPY(range(from, to));
|
auto values = GENERATE_COPY(range(from, to));
|
||||||
REQUIRE(values > -6);
|
REQUIRE(values > -6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::vector<int> make_data() {
|
||||||
|
return { 1, 3, 5, 7, 9, 11 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TEST_CASE("Copy and then generate a range", "[generators]") {
|
||||||
|
static auto data = make_data();
|
||||||
|
|
||||||
|
// It is important to notice that a generator is only initialized
|
||||||
|
// **once** per run. What this means is that modifying data will not
|
||||||
|
// modify the underlying generator.
|
||||||
|
auto elem = GENERATE_REF(from_range(data.begin(), data.end()));
|
||||||
|
REQUIRE(elem % 2 == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user