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