mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Add ChunkGenerator
This generator collects values from the underlying generator until it has a specified amount of them, and then returns them in one "chunk". In case the underlying generator does not have enough elements for a specific chunk, the left-over elements are discarded. Closes #1538
This commit is contained in:
		| @@ -36,13 +36,14 @@ a test case, | |||||||
| * 2 fundamental generators | * 2 fundamental generators | ||||||
|   * `ValueGenerator<T>` -- contains only single element |   * `ValueGenerator<T>` -- contains only single element | ||||||
|   * `ValuesGenerator<T>` -- contains multiple elements |   * `ValuesGenerator<T>` -- contains multiple elements | ||||||
| * 4 generic generators that modify other generators | * 5 generic generators that modify other generators | ||||||
|   * `FilterGenerator<T, Predicate>` -- filters out elements from a generator |   * `FilterGenerator<T, Predicate>` -- filters out elements from a generator | ||||||
|   for which the predicate returns "false" |   for which the predicate returns "false" | ||||||
|   * `TakeGenerator<T>` -- takes first `n` elements from a generator |   * `TakeGenerator<T>` -- takes first `n` elements from a generator | ||||||
|   * `RepeatGenerator<T>` -- repeats output from a generator `n` times |   * `RepeatGenerator<T>` -- repeats output from a generator `n` times | ||||||
|   * `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 | ||||||
| * 3 specific purpose generators | * 3 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 | ||||||
| @@ -58,6 +59,7 @@ type, making their usage much nicer. These are | |||||||
| * `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>` | * `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>` | ||||||
| * `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`) | * `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`) | ||||||
| * `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`) | * `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`) | ||||||
|  | * `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>` | ||||||
| * `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 | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ | |||||||
| #include "internal/catch_capture_matchers.h" | #include "internal/catch_capture_matchers.h" | ||||||
| #endif | #endif | ||||||
| #include "internal/catch_generators.hpp" | #include "internal/catch_generators.hpp" | ||||||
|  | #include "internal/catch_generators_generic.hpp" | ||||||
| #include "internal/catch_generators_specific.hpp" | #include "internal/catch_generators_specific.hpp" | ||||||
|  |  | ||||||
| // These files are included here so the single_include script doesn't put them | // These files are included here so the single_include script doesn't put them | ||||||
|   | |||||||
| @@ -179,176 +179,6 @@ namespace Generators { | |||||||
|         return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); |         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&; |     auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; | ||||||
|  |  | ||||||
|     template<typename L> |     template<typename L> | ||||||
|   | |||||||
							
								
								
									
										230
									
								
								include/internal/catch_generators_generic.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								include/internal/catch_generators_generic.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Martin on 23/2/2019. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #ifndef TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED | ||||||
|  | #define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED | ||||||
|  |  | ||||||
|  | #include "catch_generators.hpp" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  | namespace Generators { | ||||||
|  |  | ||||||
|  |     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)) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename T> | ||||||
|  |     class ChunkGenerator final : public IGenerator<std::vector<T>> { | ||||||
|  |         std::vector<T> m_chunk; | ||||||
|  |         size_t m_chunk_size; | ||||||
|  |         GeneratorWrapper<T> m_generator; | ||||||
|  |         bool m_used_up = false; | ||||||
|  |     public: | ||||||
|  |         ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : | ||||||
|  |             m_chunk_size(size), m_generator(std::move(generator)) | ||||||
|  |         { | ||||||
|  |             m_chunk.reserve(m_chunk_size); | ||||||
|  |             m_chunk.push_back(m_generator.get()); | ||||||
|  |             for (size_t i = 1; i < m_chunk_size; ++i) { | ||||||
|  |                 if (!m_generator.next()) { | ||||||
|  |                     Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); | ||||||
|  |                 } | ||||||
|  |                 m_chunk.push_back(m_generator.get()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         std::vector<T> const& get() const override { | ||||||
|  |             return m_chunk; | ||||||
|  |         } | ||||||
|  |         bool next() override { | ||||||
|  |             m_chunk.clear(); | ||||||
|  |             for (size_t idx = 0; idx < m_chunk_size; ++idx) { | ||||||
|  |                 if (!m_generator.next()) { | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |                 m_chunk.push_back(m_generator.get()); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     template <typename T> | ||||||
|  |     GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { | ||||||
|  |         return GeneratorWrapper<std::vector<T>>( | ||||||
|  |             pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } // namespace Generators | ||||||
|  | } // namespace Catch | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #endif // TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED | ||||||
| @@ -102,6 +102,7 @@ set(INTERNAL_HEADERS | |||||||
|         ${HEADER_DIR}/internal/catch_external_interfaces.h |         ${HEADER_DIR}/internal/catch_external_interfaces.h | ||||||
|         ${HEADER_DIR}/internal/catch_fatal_condition.h |         ${HEADER_DIR}/internal/catch_fatal_condition.h | ||||||
|         ${HEADER_DIR}/internal/catch_generators.hpp |         ${HEADER_DIR}/internal/catch_generators.hpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_generators_generic.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_generators_specific.hpp |         ${HEADER_DIR}/internal/catch_generators_specific.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_impl.hpp |         ${HEADER_DIR}/internal/catch_impl.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_interfaces_capture.h |         ${HEADER_DIR}/internal/catch_interfaces_capture.h | ||||||
|   | |||||||
| @@ -417,6 +417,19 @@ 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: 1 > 0 | ||||||
| Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 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: 3 > 0 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 3 == 3 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 1 == 1 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 1 < 3 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.size() == 2 for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() == chunk2.back() for: 2 == 2 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk2.front() < 3 for: 2 < 3 | ||||||
|  | Generators.tests.cpp:<line number>: passed: chunk(2, value(1)), Catch::GeneratorException | ||||||
| Generators.tests.cpp:<line number>: passed: j < i for: -3 < 1 | 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: -2 < 1 | ||||||
| Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1 | Generators.tests.cpp:<line number>: passed: j < i for: -1 < 1 | ||||||
|   | |||||||
| @@ -1175,5 +1175,5 @@ due to unexpected exception with message: | |||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| test cases:  245 |  185 passed |  56 failed |  4 failed as expected | test cases:  245 |  185 passed |  56 failed |  4 failed as expected | ||||||
| assertions: 1365 | 1229 passed | 115 failed | 21 failed as expected | assertions: 1378 | 1242 passed | 115 failed | 21 failed as expected | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3080,6 +3080,117 @@ Generators.tests.cpp:<line number>: PASSED: | |||||||
| with expansion: | with expansion: | ||||||
|   3 > 0 |   3 > 0 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Number of elements in source is divisible by chunk size | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.size() == 2 ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() == chunk2.back() ) | ||||||
|  | with expansion: | ||||||
|  |   1 == 1 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Number of elements in source is divisible by chunk size | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.size() == 2 ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() == chunk2.back() ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Number of elements in source is divisible by chunk size | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.size() == 2 ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() == chunk2.back() ) | ||||||
|  | with expansion: | ||||||
|  |   3 == 3 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Number of elements in source is not divisible by chunk size | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.size() == 2 ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() == chunk2.back() ) | ||||||
|  | with expansion: | ||||||
|  |   1 == 1 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() < 3 ) | ||||||
|  | with expansion: | ||||||
|  |   1 < 3 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Number of elements in source is not divisible by chunk size | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.size() == 2 ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() == chunk2.back() ) | ||||||
|  | with expansion: | ||||||
|  |   2 == 2 | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE( chunk2.front() < 3 ) | ||||||
|  | with expansion: | ||||||
|  |   2 < 3 | ||||||
|  |  | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators -- adapters | ||||||
|  |   Chunking a generator into sized pieces | ||||||
|  |   Throws on too small generators | ||||||
|  | ------------------------------------------------------------------------------- | ||||||
|  | Generators.tests.cpp:<line number> | ||||||
|  | ............................................................................... | ||||||
|  |  | ||||||
|  | Generators.tests.cpp:<line number>: PASSED: | ||||||
|  |   REQUIRE_THROWS_AS( chunk(2, value(1)), Catch::GeneratorException ) | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Generators -- simple | Generators -- simple | ||||||
|   one |   one | ||||||
| @@ -10574,5 +10685,5 @@ Misc.tests.cpp:<line number>: PASSED: | |||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| test cases:  245 |  172 passed |  69 failed |  4 failed as expected | test cases:  245 |  172 passed |  69 failed |  4 failed as expected | ||||||
| assertions: 1379 | 1229 passed | 129 failed | 21 failed as expected | assertions: 1392 | 1242 passed | 129 failed | 21 failed as expected | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|     <property name="random-seed" value="1"/> |     <property name="random-seed" value="1"/> | ||||||
|   </properties> |   </properties> | ||||||
| loose text artifact | loose text artifact | ||||||
|   <testsuite name="<exe-name>" errors="17" failures="113" tests="1380" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> |   <testsuite name="<exe-name>" errors="17" failures="113" tests="1393" 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="# 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="#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}"/> |     <testcase classname="<exe-name>.global" name="#1027" time="{duration}"/> | ||||||
| @@ -347,6 +347,9 @@ Message.tests.cpp:<line number> | |||||||
|     <testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" 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/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 -- adapters/Repeating a generator" time="{duration}"/> | ||||||
|  |     <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is divisible by chunk size" time="{duration}"/> | ||||||
|  |     <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is not divisible by chunk size" time="{duration}"/> | ||||||
|  |     <testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Throws on too small generators" time="{duration}"/> | ||||||
|     <testcase classname="<exe-name>.global" name="Generators -- simple/one" 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 -- simple/two" time="{duration}"/> | ||||||
|     <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/> |     <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}"/> | ||||||
|   | |||||||
| @@ -3538,7 +3538,7 @@ | |||||||
|       </Section> |       </Section> | ||||||
|       <OverallResult success="true"/> |       <OverallResult success="true"/> | ||||||
|     </TestCase> |     </TestCase> | ||||||
|     <TestCase name="Generators -- adapters" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > |     <TestCase name="Generators -- adapters" tags="[generators][generic]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|       <Section name="Filtering by predicate" 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" > |         <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|           <Original> |           <Original> | ||||||
| @@ -3755,6 +3755,146 @@ | |||||||
|         </Expression> |         </Expression> | ||||||
|         <OverallResults successes="1" failures="0" expectedFailures="0"/> |         <OverallResults successes="1" failures="0" expectedFailures="0"/> | ||||||
|       </Section> |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.size() == 2 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() == chunk2.back() | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               1 == 1 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.size() == 2 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() == chunk2.back() | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Number of elements in source is divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.size() == 2 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() == chunk2.back() | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               3 == 3 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="2" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Number of elements in source is not divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.size() == 2 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() == chunk2.back() | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               1 == 1 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() < 3 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               1 < 3 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Number of elements in source is not divisible by chunk size" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.size() == 2 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() == chunk2.back() | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 == 2 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk2.front() < 3 | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               2 < 3 | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="3" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|  |       <Section name="Chunking a generator into sized pieces" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |         <Section name="Throws on too small generators" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |           <Expression success="true" type="REQUIRE_THROWS_AS" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
|  |             <Original> | ||||||
|  |               chunk(2, value(1)), Catch::GeneratorException | ||||||
|  |             </Original> | ||||||
|  |             <Expanded> | ||||||
|  |               chunk(2, value(1)), Catch::GeneratorException | ||||||
|  |             </Expanded> | ||||||
|  |           </Expression> | ||||||
|  |           <OverallResults successes="1" failures="0" expectedFailures="0"/> | ||||||
|  |         </Section> | ||||||
|  |         <OverallResults successes="1" failures="0" expectedFailures="0"/> | ||||||
|  |       </Section> | ||||||
|       <OverallResult success="true"/> |       <OverallResult success="true"/> | ||||||
|     </TestCase> |     </TestCase> | ||||||
|     <TestCase name="Generators -- simple" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > |     <TestCase name="Generators -- simple" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" > | ||||||
| @@ -12785,7 +12925,7 @@ loose text artifact | |||||||
|       </Section> |       </Section> | ||||||
|       <OverallResult success="true"/> |       <OverallResult success="true"/> | ||||||
|     </TestCase> |     </TestCase> | ||||||
|     <OverallResults successes="1229" failures="130" expectedFailures="21"/> |     <OverallResults successes="1242" failures="130" expectedFailures="21"/> | ||||||
|   </Group> |   </Group> | ||||||
|   <OverallResults successes="1229" failures="129" expectedFailures="21"/> |   <OverallResults successes="1242" failures="129" expectedFailures="21"/> | ||||||
| </Catch> | </Catch> | ||||||
|   | |||||||
| @@ -114,7 +114,7 @@ SCENARIO("Eating cucumbers", "[generators][approvals]") { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // There are also some generic generator manipulators | // There are also some generic generator manipulators | ||||||
| TEST_CASE("Generators -- adapters", "[generators]") { | TEST_CASE("Generators -- adapters", "[generators][generic]") { | ||||||
|     // TODO: This won't work yet, introduce GENERATE_VAR? |     // TODO: This won't work yet, introduce GENERATE_VAR? | ||||||
|     //auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 }); |     //auto numbers = Catch::Generators::values({ 1, 2, 3, 4, 5, 6 }); | ||||||
|     SECTION("Filtering by predicate") { |     SECTION("Filtering by predicate") { | ||||||
| @@ -144,6 +144,23 @@ TEST_CASE("Generators -- adapters", "[generators]") { | |||||||
|         auto j = GENERATE(repeat(2, values({ 1, 2, 3 }))); |         auto j = GENERATE(repeat(2, values({ 1, 2, 3 }))); | ||||||
|         REQUIRE(j > 0); |         REQUIRE(j > 0); | ||||||
|     } |     } | ||||||
|  |     SECTION("Chunking a generator into sized pieces") { | ||||||
|  |         SECTION("Number of elements in source is divisible by chunk size") { | ||||||
|  |             auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3, 3 }))); | ||||||
|  |             REQUIRE(chunk2.size() == 2); | ||||||
|  |             REQUIRE(chunk2.front() == chunk2.back()); | ||||||
|  |         } | ||||||
|  |         SECTION("Number of elements in source is not divisible by chunk size") { | ||||||
|  |             auto chunk2 = GENERATE(chunk(2, values({ 1, 1, 2, 2, 3 }))); | ||||||
|  |             REQUIRE(chunk2.size() == 2); | ||||||
|  |             REQUIRE(chunk2.front() == chunk2.back()); | ||||||
|  |             REQUIRE(chunk2.front() < 3); | ||||||
|  |         } | ||||||
|  |         SECTION("Throws on too small generators") { | ||||||
|  |             using namespace Catch::Generators; | ||||||
|  |             REQUIRE_THROWS_AS(chunk(2, value(1)), Catch::GeneratorException); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| // Note that because of the non-reproducibility of distributions, | // Note that because of the non-reproducibility of distributions, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský