ZeroErr
Loading...
Searching...
No Matches
container_of.h
Go to the documentation of this file.
1#pragma once
3
6#include <limits>
7#include <stdexcept>
8
10
11namespace zeroerr {
12
37 int min_size = 0, max_size = 100, size = -1;
38
39 void WithMaxSize(unsigned value) { max_size = checkedSize(value); }
40 void WithMinSize(unsigned value) { min_size = checkedSize(value); }
41 void WithSize(unsigned value) { size = checkedSize(value); }
42
43protected:
44 static int checkedSize(unsigned value) {
45 if (value > static_cast<unsigned>((std::numeric_limits<int>::max)()))
46 throw std::invalid_argument("Container size exceeds supported range");
47 return static_cast<int>(value);
48 }
49
50 void validate() const {
51 if (size < -1 || min_size < 0 || max_size < min_size)
52 throw std::invalid_argument("Invalid container size bounds");
53 }
54
55 unsigned randomSize(Rng& rng) const {
56 validate();
57 if (size != -1) return static_cast<unsigned>(size);
58 return rng.bounded(static_cast<uint32_t>(max_size) -
59 static_cast<uint32_t>(min_size) + 1U) + min_size;
60 }
61
62 template <class Inner, class Corpus>
63 void mutate(Rng& rng, Corpus& v, bool only_shrink, const Inner& inner) const {
64 validate();
65 const size_t lower = static_cast<size_t>(size == -1 ? min_size : size);
66 const size_t upper = static_cast<size_t>(size == -1 ? max_size : size);
67 if (v.size() < lower || v.size() > upper)
68 throw std::invalid_argument("Corpus violates container size bounds");
69 const unsigned action = rng.bounded(5);
70 if (size == -1 && action == 0) {
71 if (v.size() > lower)
72 v.erase(v.begin() + rng.bounded(static_cast<uint32_t>(v.size())));
73 } else if (size == -1 && action == 1 && !only_shrink) {
74 if (v.size() < upper) v.push_back(inner.GetRandomCorpus(rng));
75 } else if (!v.empty()) {
76 inner.Mutate(rng, v[rng.bounded(static_cast<uint32_t>(v.size()))], only_shrink);
77 }
78 }
79
80};
81
82
83template <typename T, typename InnerDomain>
84class AssociativeContainerOf : public Domain<T, std::vector<typename InnerDomain::CorpusType>>,
85 public ContainerOfBase {
86 InnerDomain inner_domain;
87
88public:
89 using ValueType = T;
90 using CorpusType = std::vector<typename InnerDomain::CorpusType>;
91
92 AssociativeContainerOf(InnerDomain&& inner_domain) : inner_domain(std::move(inner_domain)) {}
93
94 virtual ValueType GetValue(const CorpusType& v) const override {
95 ValueType result;
96 for (const auto& elem : v) {
97 result.insert(inner_domain.GetValue(elem));
98 }
99 return result;
100 }
101
102 virtual CorpusType FromValue(const ValueType& v) const override {
103 CorpusType result;
104 for (const auto& elem : v) {
105 result.push_back(inner_domain.FromValue(elem));
106 }
107 return result;
108 }
109
110 CorpusType GetRandomCorpus(Rng& rng) const override {
111 unsigned E = randomSize(rng);
112 CorpusType result;
113 result.reserve(E);
114 for (unsigned i = 0; i < E; i++) {
115 result.push_back(inner_domain.GetRandomCorpus(rng));
116 }
117 return result;
118 }
119
120 void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
121 mutate(rng, v, only_shrink, inner_domain);
122 }
123};
124
125template <typename T, typename InnerDomain>
126class SequenceContainerOf : public Domain<T, std::vector<typename InnerDomain::CorpusType>>,
127 public ContainerOfBase {
128 InnerDomain inner_domain;
129
130public:
131 using ValueType = T;
132 using CorpusType = std::vector<typename InnerDomain::CorpusType>;
133
134 SequenceContainerOf(InnerDomain&& inner_domain) : inner_domain(std::move(inner_domain)) {}
135
136 virtual ValueType GetValue(const CorpusType& v) const override {
137 return ValueType(v.begin(), v.end());
138 }
139 virtual CorpusType FromValue(const ValueType& v) const override {
140 return CorpusType(v.begin(), v.end());
141 }
142
143 CorpusType GetRandomCorpus(Rng& rng) const override {
144 unsigned E = randomSize(rng);
145 CorpusType result;
146 result.reserve(E);
147 for (unsigned i = 0; i < E; i++) {
148 result.push_back(inner_domain.GetRandomCorpus(rng));
149 }
150 return result;
151 }
152
153 void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
154 mutate(rng, v, only_shrink, inner_domain);
155 }
156};
157
158
159// ContainerOf<T>(inner) combinator creates a domain for a container T (eg, a
160// std::vector, std::set, etc) where elements are created from `inner`.
161//
162// Example usage:
163//
164// ContainerOf<std::vector<int>>(InRange(1, 2021))
165//
166// The domain also supports customizing the minimum and maximum size via the
167// `WithSize`, `WithMinSize` and `WithMaxSize` functions. Eg:
168//
169// ContainerOf<std::vector<int>>(Arbitrary<int>()).WithMaxSize(5)
170//
171template <typename T, typename Inner>
172typename std::enable_if<detail::is_associative_container<T>::value,
173 AssociativeContainerOf<T, Inner>>::type
174ContainerOf(Inner&& inner) {
175 return AssociativeContainerOf<T, Inner>(std::move(inner));
176}
177
178template <typename T, typename Inner>
179typename std::enable_if<!detail::is_associative_container<T>::value &&
180 detail::is_container<T>::value,
181 SequenceContainerOf<T, Inner>>::type
182ContainerOf(Inner&& inner) {
183 return SequenceContainerOf<T, Inner>(std::move(inner));
184}
185
186// We can also support with a template template parameter, so that we can use
187// the name of the container instead of the complete type. In such case,
188// the ValueType of the inner domain should be passed into the container
189//
190// ContainerOf<std::vector>(Positive<int>()).WithSize(3);
191//
192template <template <typename, typename...> class T, typename... Inner,
193 typename C = T<typename Inner::ValueType...>>
194auto ContainerOf(Inner... inner) -> decltype(ContainerOf<C>(std::move(inner)...)) {
195 return ContainerOf<C>(std::move(inner)...);
196}
197
198
199} // namespace zeroerr
200
Definition container_of.h:85
std::vector< typename InnerDomain::CorpusType > CorpusType
Definition container_of.h:90
AssociativeContainerOf(InnerDomain &&inner_domain)
Definition container_of.h:92
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition container_of.h:120
T ValueType
Definition container_of.h:89
CorpusType GetRandomCorpus(Rng &rng) const override
Definition container_of.h:110
virtual CorpusType FromValue(const ValueType &v) const override
Definition container_of.h:102
virtual ValueType GetValue(const CorpusType &v) const override
Definition container_of.h:94
Domain class for generating random values of a specific type.
Definition domain.h:21
Definition rng.h:30
uint32_t bounded(uint32_t range) noexcept
Definition rng.h:126
Definition container_of.h:127
SequenceContainerOf(InnerDomain &&inner_domain)
Definition container_of.h:134
virtual ValueType GetValue(const CorpusType &v) const override
Definition container_of.h:136
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition container_of.h:153
CorpusType GetRandomCorpus(Rng &rng) const override
Definition container_of.h:143
virtual CorpusType FromValue(const ValueType &v) const override
Definition container_of.h:139
T ValueType
Definition container_of.h:131
std::vector< typename InnerDomain::CorpusType > CorpusType
Definition container_of.h:132
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:283
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:235
STL namespace.
Definition assert_text.cpp:5
std::enable_if< detail::is_associative_container< T >::value, AssociativeContainerOf< T, Inner > >::type ContainerOf(Inner &&inner)
Definition container_of.h:174
ContainerOf is a domain that generates random containers filled with elements from an inner domain.
Definition container_of.h:36
int min_size
Definition container_of.h:37
unsigned randomSize(Rng &rng) const
Definition container_of.h:55
void mutate(Rng &rng, Corpus &v, bool only_shrink, const Inner &inner) const
Definition container_of.h:63
void WithMinSize(unsigned value)
Definition container_of.h:40
static int checkedSize(unsigned value)
Definition container_of.h:44
void validate() const
Definition container_of.h:50
int max_size
Definition container_of.h:37
void WithSize(unsigned value)
Definition container_of.h:41
void WithMaxSize(unsigned value)
Definition container_of.h:39
int size
Definition container_of.h:37