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