Line data Source code
1 : // Copyright (c) 2015-2022 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include <test/fuzz/FuzzedDataProvider.h>
6 : #include <test/fuzz/fuzz.h>
7 :
8 : #include <prevector.h>
9 : #include <vector>
10 :
11 : #include <reverse_iterator.h>
12 : #include <serialize.h>
13 : #include <streams.h>
14 :
15 : namespace {
16 :
17 : template <unsigned int N, typename T>
18 0 : class prevector_tester
19 : {
20 : typedef std::vector<T> realtype;
21 : realtype real_vector;
22 : realtype real_vector_alt;
23 :
24 : typedef prevector<N, T> pretype;
25 2 : pretype pre_vector;
26 : pretype pre_vector_alt;
27 :
28 : typedef typename pretype::size_type Size;
29 :
30 : public:
31 0 : void test() const
32 : {
33 0 : const pretype& const_pre_vector = pre_vector;
34 0 : assert(real_vector.size() == pre_vector.size());
35 0 : assert(real_vector.empty() == pre_vector.empty());
36 0 : for (Size s = 0; s < real_vector.size(); s++) {
37 0 : assert(real_vector[s] == pre_vector[s]);
38 0 : assert(&(pre_vector[s]) == &(pre_vector.begin()[s]));
39 0 : assert(&(pre_vector[s]) == &*(pre_vector.begin() + s));
40 0 : assert(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
41 0 : }
42 : // assert(realtype(pre_vector) == real_vector);
43 0 : assert(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
44 0 : assert(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
45 0 : size_t pos = 0;
46 0 : for (const T& v : pre_vector) {
47 0 : assert(v == real_vector[pos]);
48 0 : ++pos;
49 : }
50 0 : for (const T& v : reverse_iterate(pre_vector)) {
51 0 : --pos;
52 0 : assert(v == real_vector[pos]);
53 : }
54 0 : for (const T& v : const_pre_vector) {
55 0 : assert(v == real_vector[pos]);
56 0 : ++pos;
57 : }
58 0 : for (const T& v : reverse_iterate(const_pre_vector)) {
59 0 : --pos;
60 0 : assert(v == real_vector[pos]);
61 : }
62 0 : DataStream ss1{};
63 0 : DataStream ss2{};
64 0 : ss1 << real_vector;
65 0 : ss2 << pre_vector;
66 0 : assert(ss1.size() == ss2.size());
67 0 : for (Size s = 0; s < ss1.size(); s++) {
68 0 : assert(ss1[s] == ss2[s]);
69 0 : }
70 0 : }
71 :
72 0 : void resize(Size s)
73 : {
74 0 : real_vector.resize(s);
75 0 : assert(real_vector.size() == s);
76 0 : pre_vector.resize(s);
77 0 : assert(pre_vector.size() == s);
78 0 : }
79 :
80 0 : void reserve(Size s)
81 : {
82 0 : real_vector.reserve(s);
83 0 : assert(real_vector.capacity() >= s);
84 0 : pre_vector.reserve(s);
85 0 : assert(pre_vector.capacity() >= s);
86 0 : }
87 :
88 0 : void insert(Size position, const T& value)
89 : {
90 0 : real_vector.insert(real_vector.begin() + position, value);
91 0 : pre_vector.insert(pre_vector.begin() + position, value);
92 0 : }
93 :
94 0 : void insert(Size position, Size count, const T& value)
95 : {
96 0 : real_vector.insert(real_vector.begin() + position, count, value);
97 0 : pre_vector.insert(pre_vector.begin() + position, count, value);
98 0 : }
99 :
100 : template <typename I>
101 0 : void insert_range(Size position, I first, I last)
102 : {
103 0 : real_vector.insert(real_vector.begin() + position, first, last);
104 0 : pre_vector.insert(pre_vector.begin() + position, first, last);
105 0 : }
106 :
107 0 : void erase(Size position)
108 : {
109 0 : real_vector.erase(real_vector.begin() + position);
110 0 : pre_vector.erase(pre_vector.begin() + position);
111 0 : }
112 :
113 0 : void erase(Size first, Size last)
114 : {
115 0 : real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
116 0 : pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
117 0 : }
118 :
119 0 : void update(Size pos, const T& value)
120 : {
121 0 : real_vector[pos] = value;
122 0 : pre_vector[pos] = value;
123 0 : }
124 :
125 0 : void push_back(const T& value)
126 : {
127 0 : real_vector.push_back(value);
128 0 : pre_vector.push_back(value);
129 0 : }
130 :
131 0 : void pop_back()
132 : {
133 0 : real_vector.pop_back();
134 0 : pre_vector.pop_back();
135 0 : }
136 :
137 0 : void clear()
138 : {
139 0 : real_vector.clear();
140 0 : pre_vector.clear();
141 0 : }
142 :
143 0 : void assign(Size n, const T& value)
144 : {
145 0 : real_vector.assign(n, value);
146 0 : pre_vector.assign(n, value);
147 0 : }
148 :
149 0 : Size size() const
150 : {
151 0 : return real_vector.size();
152 : }
153 :
154 : Size capacity() const
155 : {
156 : return pre_vector.capacity();
157 : }
158 :
159 0 : void shrink_to_fit()
160 : {
161 0 : pre_vector.shrink_to_fit();
162 0 : }
163 :
164 0 : void swap() noexcept
165 : {
166 0 : real_vector.swap(real_vector_alt);
167 0 : pre_vector.swap(pre_vector_alt);
168 0 : }
169 :
170 0 : void move()
171 : {
172 0 : real_vector = std::move(real_vector_alt);
173 0 : real_vector_alt.clear();
174 0 : pre_vector = std::move(pre_vector_alt);
175 0 : pre_vector_alt.clear();
176 0 : }
177 :
178 0 : void copy()
179 : {
180 0 : real_vector = real_vector_alt;
181 0 : pre_vector = pre_vector_alt;
182 0 : }
183 :
184 0 : void resize_uninitialized(realtype values)
185 : {
186 0 : size_t r = values.size();
187 0 : size_t s = real_vector.size() / 2;
188 0 : if (real_vector.capacity() < s + r) {
189 0 : real_vector.reserve(s + r);
190 0 : }
191 0 : real_vector.resize(s);
192 0 : pre_vector.resize_uninitialized(s);
193 0 : for (auto v : values) {
194 0 : real_vector.push_back(v);
195 : }
196 0 : auto p = pre_vector.size();
197 0 : pre_vector.resize_uninitialized(p + r);
198 0 : for (auto v : values) {
199 0 : pre_vector[p] = v;
200 0 : ++p;
201 : }
202 0 : }
203 : };
204 :
205 : } // namespace
206 :
207 4 : FUZZ_TARGET(prevector)
208 : {
209 0 : FuzzedDataProvider prov(buffer.data(), buffer.size());
210 0 : prevector_tester<8, int> test;
211 :
212 0 : LIMITED_WHILE(prov.remaining_bytes(), 3000)
213 : {
214 0 : switch (prov.ConsumeIntegralInRange<int>(0, 13 + 3 * (test.size() > 0))) {
215 : case 0:
216 0 : test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), prov.ConsumeIntegral<int>());
217 0 : break;
218 : case 1:
219 0 : test.resize(std::max(0, std::min(30, (int)test.size() + prov.ConsumeIntegralInRange<int>(0, 4) - 2)));
220 0 : break;
221 : case 2:
222 0 : test.insert(prov.ConsumeIntegralInRange<size_t>(0, test.size()), 1 + prov.ConsumeBool(), prov.ConsumeIntegral<int>());
223 0 : break;
224 : case 3: {
225 0 : int del = prov.ConsumeIntegralInRange<int>(0, test.size());
226 0 : int beg = prov.ConsumeIntegralInRange<int>(0, test.size() - del);
227 0 : test.erase(beg, beg + del);
228 0 : break;
229 : }
230 : case 4:
231 0 : test.push_back(prov.ConsumeIntegral<int>());
232 0 : break;
233 : case 5: {
234 : int values[4];
235 0 : int num = 1 + prov.ConsumeIntegralInRange<int>(0, 3);
236 0 : for (int k = 0; k < num; ++k) {
237 0 : values[k] = prov.ConsumeIntegral<int>();
238 0 : }
239 0 : test.insert_range(prov.ConsumeIntegralInRange<size_t>(0, test.size()), values, values + num);
240 0 : break;
241 : }
242 : case 6: {
243 0 : int num = 1 + prov.ConsumeIntegralInRange<int>(0, 15);
244 0 : std::vector<int> values(num);
245 0 : for (auto& v : values) {
246 0 : v = prov.ConsumeIntegral<int>();
247 : }
248 0 : test.resize_uninitialized(values);
249 : break;
250 0 : }
251 : case 7:
252 0 : test.reserve(prov.ConsumeIntegralInRange<size_t>(0, 32767));
253 0 : break;
254 : case 8:
255 0 : test.shrink_to_fit();
256 0 : break;
257 : case 9:
258 0 : test.clear();
259 0 : break;
260 : case 10:
261 0 : test.assign(prov.ConsumeIntegralInRange<size_t>(0, 32767), prov.ConsumeIntegral<int>());
262 0 : break;
263 : case 11:
264 0 : test.swap();
265 0 : break;
266 : case 12:
267 0 : test.copy();
268 0 : break;
269 : case 13:
270 0 : test.move();
271 0 : break;
272 : case 14:
273 0 : test.update(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1), prov.ConsumeIntegral<int>());
274 0 : break;
275 : case 15:
276 0 : test.erase(prov.ConsumeIntegralInRange<size_t>(0, test.size() - 1));
277 0 : break;
278 : case 16:
279 0 : test.pop_back();
280 0 : break;
281 : }
282 0 : }
283 :
284 0 : test.test();
285 0 : }
|