ZeroErr
arbitrary.h
Go to the documentation of this file.
1 #pragma once
3 
5 
9 
10 #include <limits>
11 
13 
14 namespace zeroerr {
15 
16 template <typename T, typename = void>
17 class Arbitrary {
18  static_assert(detail::always_false<T>::value, "No Arbitrary specialization for this type");
19 };
20 
21 template <>
22 class Arbitrary<bool> : public DomainConvertable<bool> {
23 public:
24  using ValueType = bool;
25  using CorpusType = bool;
26 
27  CorpusType GetRandomCorpus(Rng& rng) const override { return rng.bounded(2); }
28 
29  void Mutate(Rng&, CorpusType& v, bool) const override { v = !v; }
30 };
31 
32 
33 template <typename T>
35  typename std::enable_if<std::is_integral<T>::value && !std::numeric_limits<T>::is_signed,
36  void>::type;
37 template <typename T>
38 class Arbitrary<T, is_unsigned_int<T>> : public DomainConvertable<T> {
39 public:
40  using ValueType = T;
41  using CorpusType = T;
42 
43  CorpusType GetRandomCorpus(Rng& rng) const override { return static_cast<T>(rng.bounded(100)); }
44 
45  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
46  v = static_cast<T>(rng.bounded(100));
47  }
48 };
49 
50 template <typename T>
52  typename std::enable_if<std::is_integral<T>::value && std::numeric_limits<T>::is_signed,
53  void>::type;
54 
55 template <typename T>
56 class Arbitrary<T, is_signed_int<T>> : public DomainConvertable<T> {
57 public:
58  using ValueType = T;
59  using CorpusType = T;
60 
61  CorpusType GetRandomCorpus(Rng& rng) const override { return static_cast<T>(rng.bounded(100)); }
62 
63  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
64  v = static_cast<T>(rng.bounded(100));
65  v -= 50;
66  }
67 };
68 
69 template <typename T>
70 using is_float_point = typename std::enable_if<std::is_floating_point<T>::value, void>::type;
71 template <typename T>
72 class Arbitrary<T, is_float_point<T>> : public DomainConvertable<T> {
73 public:
74  using ValueType = T;
75  using CorpusType = T;
76 
77  CorpusType GetRandomCorpus(Rng& rng) const override {
78  return static_cast<T>(rng.bounded(1000));
79  }
80 
81  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
82  v = static_cast<T>(rng.bounded(1000));
83  }
84 };
85 
86 
87 template <typename T>
88 using is_string =
89  typename std::enable_if<detail::is_specialization<T, std::basic_string>::value>::type;
90 
91 template <typename T>
92 class Arbitrary<T, is_string<T>> : public Domain<T, std::vector<typename T::value_type>> {
94 
95 public:
96  using ValueType = T;
97  using CorpusType = std::vector<typename T::value_type>;
98 
99  ValueType GetValue(const CorpusType& v) const override { return ValueType(v.begin(), v.end()); }
100  CorpusType FromValue(const ValueType& v) const override {
101  return CorpusType(v.begin(), v.end());
102  }
103 
104  CorpusType GetRandomCorpus(Rng& rng) const override { return impl.GetRandomCorpus(rng); }
105 
106  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
107  impl.Mutate(rng, v, only_shrink);
108  }
109 };
110 
111 
112 template <typename T>
114  typename std::enable_if<!detail::is_specialization<T, std::basic_string>::value,
115  decltype(
116  // Iterable
117  T().begin(), T().end(), T().size(),
118  // Values are mutable
119  // This rejects associative containers, for example
120  // *T().begin() = std::declval<value_type_t<T>>(),
121  // Can insert and erase elements
122  T().insert(T().end(), std::declval<typename T::value_type>()),
123  T().erase(T().begin()),
124  //
125  (void)0)>::type;
126 template <typename T>
128  : public SequenceContainerOf<T, Arbitrary<typename T::value_type>> {
129 public:
131  : SequenceContainerOf<T, Arbitrary<typename T::value_type>>(
132  Arbitrary<typename T::value_type>{}) {}
133 };
134 
135 template <typename T, typename U>
136 class Arbitrary<std::pair<T, U>>
137  : public AggregateOf<
138  std::pair<typename std::remove_const<T>::type, typename std::remove_const<U>::type>> {};
139 
140 
141 template <typename... T>
142 class Arbitrary<std::tuple<T...>>
143  : public AggregateOf<std::tuple<typename std::remove_const<T>::type...>> {};
144 
145 template <typename T>
146 class Arbitrary<const T> : public Arbitrary<T> {};
147 
148 
149 } // namespace zeroerr
150 
Definition: aggregate_of.h:17
T ValueType
Definition: arbitrary.h:74
T CorpusType
Definition: arbitrary.h:75
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: arbitrary.h:77
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: arbitrary.h:81
Arbitrary()
Definition: arbitrary.h:130
T ValueType
Definition: arbitrary.h:58
T CorpusType
Definition: arbitrary.h:59
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: arbitrary.h:61
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: arbitrary.h:63
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: arbitrary.h:106
CorpusType FromValue(const ValueType &v) const override
Definition: arbitrary.h:100
ValueType GetValue(const CorpusType &v) const override
Definition: arbitrary.h:99
T ValueType
Definition: arbitrary.h:96
std::vector< typename T::value_type > CorpusType
Definition: arbitrary.h:97
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: arbitrary.h:104
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: arbitrary.h:45
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: arbitrary.h:43
T CorpusType
Definition: arbitrary.h:41
bool ValueType
Definition: arbitrary.h:24
void Mutate(Rng &, CorpusType &v, bool) const override
Definition: arbitrary.h:29
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: arbitrary.h:27
bool CorpusType
Definition: arbitrary.h:25
Definition: arbitrary.h:17
Definition: domain.h:42
Domain class for generating random values of a specific type.
Definition: domain.h:22
Definition: rng.h:30
uint32_t bounded(uint32_t range) noexcept
Definition: rng.h:126
Definition: container_of.h:74
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
Definition: benchmark.cpp:17
typename std::enable_if< std::is_integral< T >::value &&!std::numeric_limits< T >::is_signed, void >::type is_unsigned_int
Definition: arbitrary.h:36
typename std::enable_if< std::is_integral< T >::value &&std::numeric_limits< T >::is_signed, void >::type is_signed_int
Definition: arbitrary.h:53
typename std::enable_if< detail::is_specialization< T, std::basic_string >::value >::type is_string
Definition: arbitrary.h:89
typename std::enable_if< std::is_floating_point< T >::value, void >::type is_float_point
Definition: arbitrary.h:70
typename std::enable_if<!detail::is_specialization< T, std::basic_string >::value, decltype(T().begin(), T().end(), T().size(), T().insert(T().end(), std::declval< typename T::value_type >()), T().erase(T().begin()),(void) 0)>::type is_modifable
Definition: arbitrary.h:125
Definition: typetraits.h:42