9#include "hegel/generators/numeric.h"
48 class VectorsGenerator :
public IGenerator<std::vector<T>> {
51 : elements_(std::move(elements)), params_(params) {
52 if (params_.max_size && params_.min_size > *params_.max_size) {
53 throw std::invalid_argument(
"Cannot have max_size < min_size");
57 std::optional<BasicGenerator<std::vector<T>>>
58 as_basic()
const override {
59 auto basic = elements_.as_basic();
63 hegel::internal::json::json schema = {
65 {
"elements", basic->schema},
66 {
"min_size", params_.min_size},
67 {
"unique", params_.unique}};
69 schema[
"max_size"] = *params_.max_size;
71 auto parse = basic->parse;
72 return BasicGenerator<std::vector<T>>{
74 [parse = std::move(parse)](
75 const hegel::internal::json::json_raw_ref& raw)
77 std::vector<T> result;
78 auto items = raw.iterate();
79 result.reserve(items.size());
80 for (
const auto& item : items) {
81 result.push_back(parse(item));
87 std::vector<T> do_draw(
const TestCase& tc)
const override {
88 if (
auto basic = as_basic()) {
89 return basic->do_draw(tc);
91 size_t max_size = params_.max_size.value_or(100);
92 auto length_gen = integers<size_t>(
93 {.min_value = params_.min_size, .max_value = max_size});
94 size_t len = length_gen.do_draw(tc);
95 std::vector<T> result;
97 for (
size_t i = 0; i < len; ++i) {
98 result.push_back(elements_.do_draw(tc));
104 Generator<T> elements_;
105 VectorsParams params_;
110 template <
typename T>
class SetsGenerator :
public IGenerator<std::set<T>> {
112 SetsGenerator(Generator<T> elements, SetsParams params = {})
113 : elements_(std::move(elements)), params_(params) {
114 if (params_.max_size && params_.min_size > *params_.max_size) {
115 throw std::invalid_argument(
"Cannot have max_size < min_size");
119 std::optional<BasicGenerator<std::set<T>>> as_basic()
const override {
120 auto basic = elements_.as_basic();
124 hegel::internal::json::json schema = {
126 {
"elements", basic->schema},
127 {
"min_size", params_.min_size},
129 if (params_.max_size)
130 schema[
"max_size"] = *params_.max_size;
132 auto parse = basic->parse;
133 return BasicGenerator<std::set<T>>{
135 [parse = std::move(parse)](
136 const hegel::internal::json::json_raw_ref& raw)
139 for (
const auto& item : raw.iterate()) {
140 result.insert(parse(item));
146 std::set<T> do_draw(
const TestCase& tc)
const override {
147 if (
auto basic = as_basic()) {
148 return basic->do_draw(tc);
150 size_t max_size = params_.max_size.value_or(20);
151 auto length_gen = integers<size_t>(
152 {.min_value = params_.min_size, .max_value = max_size});
153 size_t target_len = length_gen.do_draw(tc);
156 while (result.size() < target_len && attempts < target_len * 10) {
157 result.insert(elements_.do_draw(tc));
164 Generator<T> elements_;
171 template <
typename K,
typename V>
172 class MapsGenerator :
public IGenerator<std::map<K, V>> {
174 MapsGenerator(Generator<K> keys, Generator<V> values,
175 MapsParams params = {})
176 : keys_(std::move(keys)), values_(std::move(values)),
178 if (params_.max_size && params_.min_size > *params_.max_size) {
179 throw std::invalid_argument(
"Cannot have max_size < min_size");
183 std::optional<BasicGenerator<std::map<K, V>>>
184 as_basic()
const override {
185 auto k_basic = keys_.as_basic();
186 auto v_basic = values_.as_basic();
187 if (!k_basic || !v_basic)
190 hegel::internal::json::json schema = {
192 {
"keys", k_basic->schema},
193 {
"values", v_basic->schema},
194 {
"min_size", params_.min_size}};
195 if (params_.max_size)
196 schema[
"max_size"] = *params_.max_size;
198 auto kp = k_basic->parse;
199 auto vp = v_basic->parse;
201 return BasicGenerator<std::map<K, V>>{
203 [kp = std::move(kp), vp = std::move(vp)](
204 const hegel::internal::json::json_raw_ref& raw)
206 std::map<K, V> result;
207 for (
const auto& pair : raw.iterate()) {
208 result.emplace(kp(pair[0]), vp(pair[1]));
214 std::map<K, V> do_draw(
const TestCase& tc)
const override {
215 if (
auto basic = as_basic()) {
216 return basic->do_draw(tc);
218 size_t max_size = params_.max_size.value_or(20);
219 auto length_gen = integers<size_t>(
220 {.min_value = params_.min_size, .max_value = max_size});
221 size_t len = length_gen.do_draw(tc);
222 std::map<K, V> result;
223 while (result.size() < len) {
224 K key = keys_.do_draw(tc);
225 V value = values_.do_draw(tc);
226 result[std::move(key)] = std::move(value);
233 Generator<V> values_;
255 template <
typename T>
258 return Generator<std::vector<T>>(
259 new VectorsGenerator<T>(std::move(elements), params));
275 template <
typename T>
277 return Generator<std::set<T>>(
278 new SetsGenerator<T>(std::move(elements), params));
303 template <
typename K,
typename V>
306 return Generator<std::map<K, V>>(
new MapsGenerator<K, V>(
307 std::move(keys), std::move(values), params));
313 template <
typename Tuple,
typename GenTuple,
size_t... Is>
314 Tuple draw_tuple_impl(
const GenTuple& gens, std::index_sequence<Is...>,
315 const TestCase& tc) {
316 return Tuple{std::get<Is>(gens).do_draw(tc)...};
323 template <
typename... Ts>
324 class TuplesGenerator :
public IGenerator<std::tuple<Ts...>> {
326 using ResultTuple = std::tuple<Ts...>;
328 explicit TuplesGenerator(Generator<Ts>... gens)
329 : gens_(std::move(gens)...) {}
331 std::optional<BasicGenerator<ResultTuple>> as_basic()
const override {
332 auto basics = std::apply(
333 [](
const auto&... g) {
334 return std::make_tuple(g.as_basic()...);
337 bool all_basic = std::apply(
338 [](
const auto&... b) {
return (b.has_value() && ...); },
343 hegel::internal::json::json elements =
344 hegel::internal::json::json::array();
346 [&elements](
const auto&... b) {
347 (elements.push_back(b->schema), ...);
351 hegel::internal::json::json schema = {{
"type",
"tuple"},
352 {
"elements", elements}};
354 auto parsers = std::apply(
355 [](
const auto&... b) {
return std::make_tuple(b->parse...); },
358 return BasicGenerator<ResultTuple>{
360 [parsers = std::move(parsers)](
361 const hegel::internal::json::json_raw_ref& raw)
363 return [&]<
size_t... Is>(std::index_sequence<Is...>) {
364 return ResultTuple{std::get<Is>(parsers)(raw[Is])...};
365 }(std::index_sequence_for<Ts...>{});
369 ResultTuple do_draw(
const TestCase& tc)
const override {
370 if (
auto basic = as_basic()) {
371 return basic->do_draw(tc);
373 return detail::draw_tuple_impl<ResultTuple>(
374 gens_, std::index_sequence_for<Ts...>{}, tc);
378 std::tuple<Generator<Ts>...> gens_;
396 template <
typename... Ts>
399 new TuplesGenerator<Ts...>(std::move(gens)...));
The base class of all generators.
Definition core.h:157
Hegel generators.
Definition core.h:16
Generator< std::tuple< Ts... > > tuples(Generator< Ts >... gens)
Generate tuples from multiple generators.
Definition collections.h:397
Generator< std::vector< T > > vectors(Generator< T > elements, VectorsParams params={})
Generate vectors with elements from another generator.
Definition collections.h:256
Generator< std::set< T > > sets(Generator< T > elements, SetsParams params={})
Generate sets with elements from another generator.
Definition collections.h:276
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:304
Parameters for maps() generator.
Definition collections.h:37
std::optional< size_t > max_size
Maximum number of entries. Default: 20.
Definition collections.h:40
size_t min_size
Minimum number of entries.
Definition collections.h:38
Parameters for sets() generator.
Definition collections.h:29
std::optional< size_t > max_size
Maximum set size. Default: 20.
Definition collections.h:31
size_t min_size
Minimum set size.
Definition collections.h:30
Parameters for vectors() generator.
Definition collections.h:20
size_t min_size
Minimum vector size.
Definition collections.h:21
bool unique
If true, all elements must be unique.
Definition collections.h:23
std::optional< size_t > max_size
Maximum vector size. Default: 100.
Definition collections.h:22