14#include "hegel/core.h"
57 template <
typename T,
typename =
void>
58 struct is_equality_comparable : std::false_type {};
60 struct is_equality_comparable<
61 T, std::void_t<decltype(std::declval<const T&>() ==
62 std::declval<const T&>())>>
66 collection_max_size(
const std::optional<size_t>& max_size) {
67 return max_size ?
static_cast<uint64_t
>(*max_size)
68 : hegel::internal::no_max_size;
77 class VectorsGenerator :
public IGenerator<std::vector<T>> {
79 VectorsGenerator(Generator<T> elements, VectorsParams params = {})
80 : elements_(std::move(elements)), params_(params) {
81 if (params_.max_size && params_.min_size > *params_.max_size) {
82 throw std::invalid_argument(
"Cannot have max_size < min_size");
84 if (params_.unique && !detail::is_equality_comparable<T>::value) {
85 throw std::invalid_argument(
86 "vectors(..., {.unique = true}) requires an "
87 "equality-comparable element type");
91 std::vector<T> do_draw(
const TestCase& tc)
const override {
92 namespace hi = hegel::internal;
93 hi::start_span(tc, hi::SpanLabel::List);
94 hi::CollectionHandle collection(
96 detail::collection_max_size(params_.max_size));
97 std::vector<T> result;
98 while (collection.more(tc)) {
99 T element = elements_.do_draw(tc);
100 if constexpr (detail::is_equality_comparable<T>::value) {
101 if (params_.unique &&
102 std::find(result.begin(), result.end(), element) !=
104 collection.reject(tc,
"duplicate element");
108 result.push_back(std::move(element));
115 Generator<T> elements_;
116 VectorsParams params_;
121 template <
typename T>
class SetsGenerator :
public IGenerator<std::set<T>> {
123 SetsGenerator(Generator<T> elements, SetsParams params = {})
124 : elements_(std::move(elements)), params_(params) {
125 if (params_.max_size && params_.min_size > *params_.max_size) {
126 throw std::invalid_argument(
"Cannot have max_size < min_size");
130 std::set<T> do_draw(
const TestCase& tc)
const override {
131 namespace hi = hegel::internal;
132 hi::start_span(tc, hi::SpanLabel::Set);
133 hi::CollectionHandle collection(
134 tc, params_.min_size,
135 detail::collection_max_size(params_.max_size));
137 while (collection.more(tc)) {
138 if (!result.insert(elements_.do_draw(tc)).second) {
139 collection.reject(tc,
"duplicate element");
147 Generator<T> elements_;
154 template <
typename K,
typename V>
155 class MapsGenerator :
public IGenerator<std::map<K, V>> {
157 MapsGenerator(Generator<K> keys, Generator<V> values,
158 MapsParams params = {})
159 : keys_(std::move(keys)), values_(std::move(values)),
161 if (params_.max_size && params_.min_size > *params_.max_size) {
162 throw std::invalid_argument(
"Cannot have max_size < min_size");
166 std::map<K, V> do_draw(
const TestCase& tc)
const override {
167 namespace hi = hegel::internal;
168 hi::start_span(tc, hi::SpanLabel::Map);
169 hi::CollectionHandle collection(
170 tc, params_.min_size,
171 detail::collection_max_size(params_.max_size));
172 std::map<K, V> result;
173 while (collection.more(tc)) {
174 K key = keys_.do_draw(tc);
175 if (result.find(key) != result.end()) {
176 collection.reject(tc,
"duplicate key");
179 result.emplace(std::move(key), values_.do_draw(tc));
187 Generator<V> values_;
209 template <
typename T>
212 return Generator<std::vector<T>>(
213 new VectorsGenerator<T>(std::move(elements), params));
229 template <
typename T>
231 return Generator<std::set<T>>(
232 new SetsGenerator<T>(std::move(elements), params));
257 template <
typename K,
typename V>
260 return Generator<std::map<K, V>>(
new MapsGenerator<K, V>(
261 std::move(keys), std::move(values), params));
267 template <
typename Tuple,
typename GenTuple,
size_t... Is>
268 Tuple draw_tuple_impl(
const GenTuple& gens, std::index_sequence<Is...>,
269 const TestCase& tc) {
270 return Tuple{std::get<Is>(gens).do_draw(tc)...};
277 template <
typename... Ts>
278 class TuplesGenerator :
public IGenerator<std::tuple<Ts...>> {
280 using ResultTuple = std::tuple<Ts...>;
282 explicit TuplesGenerator(Generator<Ts>... gens)
283 : gens_(std::move(gens)...) {}
285 ResultTuple do_draw(
const TestCase& tc)
const override {
286 namespace hi = hegel::internal;
287 hi::start_span(tc, hi::SpanLabel::Tuple);
288 ResultTuple result = detail::draw_tuple_impl<ResultTuple>(
289 gens_, std::index_sequence_for<Ts...>{}, tc);
295 std::tuple<Generator<Ts>...> gens_;
313 template <
typename... Ts>
316 new TuplesGenerator<Ts...>(std::move(gens)...));
323 template <
typename T,
size_t N>
324 class ArrayGenerator :
public IGenerator<std::array<T, N>> {
326 explicit ArrayGenerator(Generator<T> element)
327 : element_(std::move(element)) {}
329 std::array<T, N> do_draw(
const TestCase& tc)
const override {
330 namespace hi = hegel::internal;
331 hi::start_span(tc, hi::SpanLabel::Tuple);
332 std::array<T, N> result =
333 draw_all(tc, std::make_index_sequence<N>{});
341 template <
size_t... Is>
342 std::array<T, N> draw_all(
const TestCase& tc,
343 std::index_sequence<Is...>)
const {
344 return std::array<T, N>{
345 (
static_cast<void>(Is), element_.do_draw(tc))...};
348 Generator<T> element_;
370 template <
typename T,
size_t N>
373 new ArrayGenerator<T, N>(std::move(element)));
The base class of all generators.
Definition core.h:67
Hegel generators.
Definition core.h:17
Generator< std::tuple< Ts... > > tuples(Generator< Ts >... gens)
Generate tuples from multiple generators.
Definition collections.h:314
Generator< std::vector< T > > vectors(Generator< T > elements, VectorsParams params={})
Generate vectors with elements from another generator.
Definition collections.h:210
Generator< std::array< T, N > > arrays(Generator< T > element)
Generate fixed-size arrays.
Definition collections.h:371
Generator< std::set< T > > sets(Generator< T > elements, SetsParams params={})
Generate sets with elements from another generator.
Definition collections.h:230
Generator< std::map< K, V > > maps(Generator< K > keys, Generator< V > values, MapsParams params={})
Generate maps with configurable key and value types.
Definition collections.h:258
Base interface for generators.
Definition core.h:29
Parameters for maps() generator.
Definition collections.h:44
std::optional< size_t > max_size
Definition collections.h:46
size_t min_size
Minimum number of entries.
Definition collections.h:45
Parameters for sets() generator.
Definition collections.h:35
std::optional< size_t > max_size
Definition collections.h:37
size_t min_size
Minimum set size.
Definition collections.h:36
Parameters for vectors() generator.
Definition collections.h:25
size_t min_size
Minimum vector size.
Definition collections.h:26
bool unique
If true, all elements must be unique.
Definition collections.h:29
std::optional< size_t > max_size
Definition collections.h:27