/root/bitcoin/src/test/fuzz/bitdeque.cpp
Line | Count | Source |
1 | | // Copyright (c) 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 <random.h> |
6 | | #include <test/fuzz/FuzzedDataProvider.h> |
7 | | #include <test/fuzz/util.h> |
8 | | #include <util/bitdeque.h> |
9 | | |
10 | | #include <deque> |
11 | | #include <vector> |
12 | | |
13 | | namespace { |
14 | | |
15 | | constexpr int LEN_BITS = 16; |
16 | | constexpr int RANDDATA_BITS = 20; |
17 | | |
18 | | using bitdeque_type = bitdeque<128>; |
19 | | |
20 | | //! Deterministic random vector of bools, for begin/end insertions to draw from. |
21 | | std::vector<bool> RANDDATA; |
22 | | |
23 | | void InitRandData() |
24 | 0 | { |
25 | 0 | FastRandomContext ctx(true); |
26 | 0 | RANDDATA.clear(); |
27 | 0 | for (size_t i = 0; i < (1U << RANDDATA_BITS) + (1U << LEN_BITS); ++i) { |
28 | 0 | RANDDATA.push_back(ctx.randbool()); |
29 | 0 | } |
30 | 0 | } |
31 | | |
32 | | } // namespace |
33 | | |
34 | | FUZZ_TARGET(bitdeque, .init = InitRandData) |
35 | 0 | { |
36 | 0 | FuzzedDataProvider provider(buffer.data(), buffer.size()); |
37 | 0 | FastRandomContext ctx(true); |
38 | |
|
39 | 0 | size_t maxlen = (1U << provider.ConsumeIntegralInRange<size_t>(0, LEN_BITS)) - 1; |
40 | 0 | size_t limitlen = 4 * maxlen; |
41 | |
|
42 | 0 | std::deque<bool> deq; |
43 | 0 | bitdeque_type bitdeq; |
44 | |
|
45 | 0 | const auto& cdeq = deq; |
46 | 0 | const auto& cbitdeq = bitdeq; |
47 | |
|
48 | 0 | size_t initlen = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
49 | 0 | while (initlen) { |
50 | 0 | bool val = ctx.randbool(); |
51 | 0 | deq.push_back(val); |
52 | 0 | bitdeq.push_back(val); |
53 | 0 | --initlen; |
54 | 0 | } |
55 | |
|
56 | 0 | const auto iter_limit{maxlen > 6000 ? 90U : 900U}; |
57 | 0 | LIMITED_WHILE(provider.remaining_bytes() > 0, iter_limit) |
58 | 0 | { |
59 | 0 | CallOneOf( |
60 | 0 | provider, |
61 | 0 | [&] { |
62 | | // constructor() |
63 | 0 | deq = std::deque<bool>{}; |
64 | 0 | bitdeq = bitdeque_type{}; |
65 | 0 | }, |
66 | 0 | [&] { |
67 | | // clear() |
68 | 0 | deq.clear(); |
69 | 0 | bitdeq.clear(); |
70 | 0 | }, |
71 | 0 | [&] { |
72 | | // resize() |
73 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
74 | 0 | deq.resize(count); |
75 | 0 | bitdeq.resize(count); |
76 | 0 | }, |
77 | 0 | [&] { |
78 | | // assign(count, val) |
79 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
80 | 0 | bool val = ctx.randbool(); |
81 | 0 | deq.assign(count, val); |
82 | 0 | bitdeq.assign(count, val); |
83 | 0 | }, |
84 | 0 | [&] { |
85 | | // constructor(count, val) |
86 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
87 | 0 | bool val = ctx.randbool(); |
88 | 0 | deq = std::deque<bool>(count, val); |
89 | 0 | bitdeq = bitdeque_type(count, val); |
90 | 0 | }, |
91 | 0 | [&] { |
92 | | // constructor(count) |
93 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
94 | 0 | deq = std::deque<bool>(count); |
95 | 0 | bitdeq = bitdeque_type(count); |
96 | 0 | }, |
97 | 0 | [&] { |
98 | | // construct(begin, end) |
99 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
100 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
101 | 0 | auto rand_end = rand_begin + count; |
102 | 0 | deq = std::deque<bool>(rand_begin, rand_end); |
103 | 0 | bitdeq = bitdeque_type(rand_begin, rand_end); |
104 | 0 | }, |
105 | 0 | [&] { |
106 | | // assign(begin, end) |
107 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
108 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
109 | 0 | auto rand_end = rand_begin + count; |
110 | 0 | deq.assign(rand_begin, rand_end); |
111 | 0 | bitdeq.assign(rand_begin, rand_end); |
112 | 0 | }, |
113 | 0 | [&] { |
114 | | // construct(initializer_list) |
115 | 0 | std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool(), ctx.randbool(), ctx.randbool()}; |
116 | 0 | deq = std::deque<bool>(ilist); |
117 | 0 | bitdeq = bitdeque_type(ilist); |
118 | 0 | }, |
119 | 0 | [&] { |
120 | | // assign(initializer_list) |
121 | 0 | std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool()}; |
122 | 0 | deq.assign(ilist); |
123 | 0 | bitdeq.assign(ilist); |
124 | 0 | }, |
125 | 0 | [&] { |
126 | | // operator=(const&) |
127 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
128 | 0 | bool val = ctx.randbool(); |
129 | 0 | const std::deque<bool> deq2(count, val); |
130 | 0 | deq = deq2; |
131 | 0 | const bitdeque_type bitdeq2(count, val); |
132 | 0 | bitdeq = bitdeq2; |
133 | 0 | }, |
134 | 0 | [&] { |
135 | | // operator=(&&) |
136 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
137 | 0 | bool val = ctx.randbool(); |
138 | 0 | std::deque<bool> deq2(count, val); |
139 | 0 | deq = std::move(deq2); |
140 | 0 | bitdeque_type bitdeq2(count, val); |
141 | 0 | bitdeq = std::move(bitdeq2); |
142 | 0 | }, |
143 | 0 | [&] { |
144 | | // deque swap |
145 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
146 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
147 | 0 | auto rand_end = rand_begin + count; |
148 | 0 | std::deque<bool> deq2(rand_begin, rand_end); |
149 | 0 | bitdeque_type bitdeq2(rand_begin, rand_end); |
150 | 0 | using std::swap; |
151 | 0 | assert(deq.size() == bitdeq.size()); |
152 | 0 | assert(deq2.size() == bitdeq2.size()); |
153 | 0 | swap(deq, deq2); |
154 | 0 | swap(bitdeq, bitdeq2); |
155 | 0 | assert(deq.size() == bitdeq.size()); |
156 | 0 | assert(deq2.size() == bitdeq2.size()); |
157 | 0 | }, |
158 | 0 | [&] { |
159 | | // deque.swap |
160 | 0 | auto count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
161 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
162 | 0 | auto rand_end = rand_begin + count; |
163 | 0 | std::deque<bool> deq2(rand_begin, rand_end); |
164 | 0 | bitdeque_type bitdeq2(rand_begin, rand_end); |
165 | 0 | assert(deq.size() == bitdeq.size()); |
166 | 0 | assert(deq2.size() == bitdeq2.size()); |
167 | 0 | deq.swap(deq2); |
168 | 0 | bitdeq.swap(bitdeq2); |
169 | 0 | assert(deq.size() == bitdeq.size()); |
170 | 0 | assert(deq2.size() == bitdeq2.size()); |
171 | 0 | }, |
172 | 0 | [&] { |
173 | | // operator=(initializer_list) |
174 | 0 | std::initializer_list<bool> ilist{ctx.randbool(), ctx.randbool(), ctx.randbool()}; |
175 | 0 | deq = ilist; |
176 | 0 | bitdeq = ilist; |
177 | 0 | }, |
178 | 0 | [&] { |
179 | | // iterator arithmetic |
180 | 0 | auto pos1 = provider.ConsumeIntegralInRange<long>(0, cdeq.size()); |
181 | 0 | auto pos2 = provider.ConsumeIntegralInRange<long>(0, cdeq.size()); |
182 | 0 | auto it = deq.begin() + pos1; |
183 | 0 | auto bitit = bitdeq.begin() + pos1; |
184 | 0 | if ((size_t)pos1 != cdeq.size()) assert(*it == *bitit); |
185 | 0 | assert(it - deq.begin() == pos1); |
186 | 0 | assert(bitit - bitdeq.begin() == pos1); |
187 | 0 | if (provider.ConsumeBool()) { |
188 | 0 | it += pos2 - pos1; |
189 | 0 | bitit += pos2 - pos1; |
190 | 0 | } else { |
191 | 0 | it -= pos1 - pos2; |
192 | 0 | bitit -= pos1 - pos2; |
193 | 0 | } |
194 | 0 | if ((size_t)pos2 != cdeq.size()) assert(*it == *bitit); |
195 | 0 | assert(deq.end() - it == bitdeq.end() - bitit); |
196 | 0 | if (provider.ConsumeBool()) { |
197 | 0 | if ((size_t)pos2 != cdeq.size()) { |
198 | 0 | ++it; |
199 | 0 | ++bitit; |
200 | 0 | } |
201 | 0 | } else { |
202 | 0 | if (pos2 != 0) { |
203 | 0 | --it; |
204 | 0 | --bitit; |
205 | 0 | } |
206 | 0 | } |
207 | 0 | assert(deq.end() - it == bitdeq.end() - bitit); |
208 | 0 | }, |
209 | 0 | [&] { |
210 | | // begin() and end() |
211 | 0 | assert(deq.end() - deq.begin() == bitdeq.end() - bitdeq.begin()); |
212 | 0 | }, |
213 | 0 | [&] { |
214 | | // begin() and end() (const) |
215 | 0 | assert(cdeq.end() - cdeq.begin() == cbitdeq.end() - cbitdeq.begin()); |
216 | 0 | }, |
217 | 0 | [&] { |
218 | | // rbegin() and rend() |
219 | 0 | assert(deq.rend() - deq.rbegin() == bitdeq.rend() - bitdeq.rbegin()); |
220 | 0 | }, |
221 | 0 | [&] { |
222 | | // rbegin() and rend() (const) |
223 | 0 | assert(cdeq.rend() - cdeq.rbegin() == cbitdeq.rend() - cbitdeq.rbegin()); |
224 | 0 | }, |
225 | 0 | [&] { |
226 | | // cbegin() and cend() |
227 | 0 | assert(cdeq.cend() - cdeq.cbegin() == cbitdeq.cend() - cbitdeq.cbegin()); |
228 | 0 | }, |
229 | 0 | [&] { |
230 | | // crbegin() and crend() |
231 | 0 | assert(cdeq.crend() - cdeq.crbegin() == cbitdeq.crend() - cbitdeq.crbegin()); |
232 | 0 | }, |
233 | 0 | [&] { |
234 | | // size() and maxsize() |
235 | 0 | assert(cdeq.size() == cbitdeq.size()); |
236 | 0 | assert(cbitdeq.size() <= cbitdeq.max_size()); |
237 | 0 | }, |
238 | 0 | [&] { |
239 | | // empty |
240 | 0 | assert(cdeq.empty() == cbitdeq.empty()); |
241 | 0 | }, |
242 | 0 | [&] { |
243 | | // at (in range) and flip |
244 | 0 | if (!cdeq.empty()) { |
245 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
246 | 0 | auto& ref = deq.at(pos); |
247 | 0 | auto bitref = bitdeq.at(pos); |
248 | 0 | assert(ref == bitref); |
249 | 0 | if (ctx.randbool()) { |
250 | 0 | ref = !ref; |
251 | 0 | bitref.flip(); |
252 | 0 | } |
253 | 0 | } |
254 | 0 | }, |
255 | 0 | [&] { |
256 | | // at (maybe out of range) and bit assign |
257 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() + maxlen); |
258 | 0 | bool newval = ctx.randbool(); |
259 | 0 | bool throw_deq{false}, throw_bitdeq{false}; |
260 | 0 | bool val_deq{false}, val_bitdeq{false}; |
261 | 0 | try { |
262 | 0 | auto& ref = deq.at(pos); |
263 | 0 | val_deq = ref; |
264 | 0 | ref = newval; |
265 | 0 | } catch (const std::out_of_range&) { |
266 | 0 | throw_deq = true; |
267 | 0 | } |
268 | 0 | try { |
269 | 0 | auto ref = bitdeq.at(pos); |
270 | 0 | val_bitdeq = ref; |
271 | 0 | ref = newval; |
272 | 0 | } catch (const std::out_of_range&) { |
273 | 0 | throw_bitdeq = true; |
274 | 0 | } |
275 | 0 | assert(throw_deq == throw_bitdeq); |
276 | 0 | assert(throw_bitdeq == (pos >= cdeq.size())); |
277 | 0 | if (!throw_deq) assert(val_deq == val_bitdeq); |
278 | 0 | }, |
279 | 0 | [&] { |
280 | | // at (maybe out of range) (const) |
281 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() + maxlen); |
282 | 0 | bool throw_deq{false}, throw_bitdeq{false}; |
283 | 0 | bool val_deq{false}, val_bitdeq{false}; |
284 | 0 | try { |
285 | 0 | auto& ref = cdeq.at(pos); |
286 | 0 | val_deq = ref; |
287 | 0 | } catch (const std::out_of_range&) { |
288 | 0 | throw_deq = true; |
289 | 0 | } |
290 | 0 | try { |
291 | 0 | auto ref = cbitdeq.at(pos); |
292 | 0 | val_bitdeq = ref; |
293 | 0 | } catch (const std::out_of_range&) { |
294 | 0 | throw_bitdeq = true; |
295 | 0 | } |
296 | 0 | assert(throw_deq == throw_bitdeq); |
297 | 0 | assert(throw_bitdeq == (pos >= cdeq.size())); |
298 | 0 | if (!throw_deq) assert(val_deq == val_bitdeq); |
299 | 0 | }, |
300 | 0 | [&] { |
301 | | // operator[] |
302 | 0 | if (!cdeq.empty()) { |
303 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
304 | 0 | assert(deq[pos] == bitdeq[pos]); |
305 | 0 | if (ctx.randbool()) { |
306 | 0 | deq[pos] = !deq[pos]; |
307 | 0 | bitdeq[pos].flip(); |
308 | 0 | } |
309 | 0 | } |
310 | 0 | }, |
311 | 0 | [&] { |
312 | | // operator[] const |
313 | 0 | if (!cdeq.empty()) { |
314 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
315 | 0 | assert(deq[pos] == bitdeq[pos]); |
316 | 0 | } |
317 | 0 | }, |
318 | 0 | [&] { |
319 | | // front() |
320 | 0 | if (!cdeq.empty()) { |
321 | 0 | auto& ref = deq.front(); |
322 | 0 | auto bitref = bitdeq.front(); |
323 | 0 | assert(ref == bitref); |
324 | 0 | if (ctx.randbool()) { |
325 | 0 | ref = !ref; |
326 | 0 | bitref = !bitref; |
327 | 0 | } |
328 | 0 | } |
329 | 0 | }, |
330 | 0 | [&] { |
331 | | // front() const |
332 | 0 | if (!cdeq.empty()) { |
333 | 0 | auto& ref = cdeq.front(); |
334 | 0 | auto bitref = cbitdeq.front(); |
335 | 0 | assert(ref == bitref); |
336 | 0 | } |
337 | 0 | }, |
338 | 0 | [&] { |
339 | | // back() and swap(bool, ref) |
340 | 0 | if (!cdeq.empty()) { |
341 | 0 | auto& ref = deq.back(); |
342 | 0 | auto bitref = bitdeq.back(); |
343 | 0 | assert(ref == bitref); |
344 | 0 | if (ctx.randbool()) { |
345 | 0 | ref = !ref; |
346 | 0 | bitref.flip(); |
347 | 0 | } |
348 | 0 | } |
349 | 0 | }, |
350 | 0 | [&] { |
351 | | // back() const |
352 | 0 | if (!cdeq.empty()) { |
353 | 0 | const auto& cdeq = deq; |
354 | 0 | const auto& cbitdeq = bitdeq; |
355 | 0 | auto& ref = cdeq.back(); |
356 | 0 | auto bitref = cbitdeq.back(); |
357 | 0 | assert(ref == bitref); |
358 | 0 | } |
359 | 0 | }, |
360 | 0 | [&] { |
361 | | // push_back() |
362 | 0 | if (cdeq.size() < limitlen) { |
363 | 0 | bool val = ctx.randbool(); |
364 | 0 | if (cdeq.empty()) { |
365 | 0 | deq.push_back(val); |
366 | 0 | bitdeq.push_back(val); |
367 | 0 | } else { |
368 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
369 | 0 | auto& ref = deq[pos]; |
370 | 0 | auto bitref = bitdeq[pos]; |
371 | 0 | assert(ref == bitref); |
372 | 0 | deq.push_back(val); |
373 | 0 | bitdeq.push_back(val); |
374 | 0 | assert(ref == bitref); // references are not invalidated |
375 | 0 | } |
376 | 0 | } |
377 | 0 | }, |
378 | 0 | [&] { |
379 | | // push_front() |
380 | 0 | if (cdeq.size() < limitlen) { |
381 | 0 | bool val = ctx.randbool(); |
382 | 0 | if (cdeq.empty()) { |
383 | 0 | deq.push_front(val); |
384 | 0 | bitdeq.push_front(val); |
385 | 0 | } else { |
386 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
387 | 0 | auto& ref = deq[pos]; |
388 | 0 | auto bitref = bitdeq[pos]; |
389 | 0 | assert(ref == bitref); |
390 | 0 | deq.push_front(val); |
391 | 0 | bitdeq.push_front(val); |
392 | 0 | assert(ref == bitref); // references are not invalidated |
393 | 0 | } |
394 | 0 | } |
395 | 0 | }, |
396 | 0 | [&] { |
397 | | // pop_back() |
398 | 0 | if (!cdeq.empty()) { |
399 | 0 | if (cdeq.size() == 1) { |
400 | 0 | deq.pop_back(); |
401 | 0 | bitdeq.pop_back(); |
402 | 0 | } else { |
403 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 2); |
404 | 0 | auto& ref = deq[pos]; |
405 | 0 | auto bitref = bitdeq[pos]; |
406 | 0 | assert(ref == bitref); |
407 | 0 | deq.pop_back(); |
408 | 0 | bitdeq.pop_back(); |
409 | 0 | assert(ref == bitref); // references to other elements are not invalidated |
410 | 0 | } |
411 | 0 | } |
412 | 0 | }, |
413 | 0 | [&] { |
414 | | // pop_front() |
415 | 0 | if (!cdeq.empty()) { |
416 | 0 | if (cdeq.size() == 1) { |
417 | 0 | deq.pop_front(); |
418 | 0 | bitdeq.pop_front(); |
419 | 0 | } else { |
420 | 0 | size_t pos = provider.ConsumeIntegralInRange<size_t>(1, cdeq.size() - 1); |
421 | 0 | auto& ref = deq[pos]; |
422 | 0 | auto bitref = bitdeq[pos]; |
423 | 0 | assert(ref == bitref); |
424 | 0 | deq.pop_front(); |
425 | 0 | bitdeq.pop_front(); |
426 | 0 | assert(ref == bitref); // references to other elements are not invalidated |
427 | 0 | } |
428 | 0 | } |
429 | 0 | }, |
430 | 0 | [&] { |
431 | | // erase (in middle, single) |
432 | 0 | if (!cdeq.empty()) { |
433 | 0 | size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - 1); |
434 | 0 | size_t after = cdeq.size() - 1 - before; |
435 | 0 | auto it = deq.erase(cdeq.begin() + before); |
436 | 0 | auto bitit = bitdeq.erase(cbitdeq.begin() + before); |
437 | 0 | assert(it == cdeq.begin() + before && it == cdeq.end() - after); |
438 | 0 | assert(bitit == cbitdeq.begin() + before && bitit == cbitdeq.end() - after); |
439 | 0 | } |
440 | 0 | }, |
441 | 0 | [&] { |
442 | | // erase (at front, range) |
443 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
444 | 0 | auto it = deq.erase(cdeq.begin(), cdeq.begin() + count); |
445 | 0 | auto bitit = bitdeq.erase(cbitdeq.begin(), cbitdeq.begin() + count); |
446 | 0 | assert(it == deq.begin()); |
447 | 0 | assert(bitit == bitdeq.begin()); |
448 | 0 | }, |
449 | 0 | [&] { |
450 | | // erase (at back, range) |
451 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
452 | 0 | auto it = deq.erase(cdeq.end() - count, cdeq.end()); |
453 | 0 | auto bitit = bitdeq.erase(cbitdeq.end() - count, cbitdeq.end()); |
454 | 0 | assert(it == deq.end()); |
455 | 0 | assert(bitit == bitdeq.end()); |
456 | 0 | }, |
457 | 0 | [&] { |
458 | | // erase (in middle, range) |
459 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
460 | 0 | size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size() - count); |
461 | 0 | size_t after = cdeq.size() - count - before; |
462 | 0 | auto it = deq.erase(cdeq.begin() + before, cdeq.end() - after); |
463 | 0 | auto bitit = bitdeq.erase(cbitdeq.begin() + before, cbitdeq.end() - after); |
464 | 0 | assert(it == cdeq.begin() + before && it == cdeq.end() - after); |
465 | 0 | assert(bitit == cbitdeq.begin() + before && bitit == cbitdeq.end() - after); |
466 | 0 | }, |
467 | 0 | [&] { |
468 | | // insert/emplace (in middle, single) |
469 | 0 | if (cdeq.size() < limitlen) { |
470 | 0 | size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
471 | 0 | bool val = ctx.randbool(); |
472 | 0 | bool do_emplace = provider.ConsumeBool(); |
473 | 0 | auto it = deq.insert(cdeq.begin() + before, val); |
474 | 0 | auto bitit = do_emplace ? bitdeq.emplace(cbitdeq.begin() + before, val) |
475 | 0 | : bitdeq.insert(cbitdeq.begin() + before, val); |
476 | 0 | assert(it == deq.begin() + before); |
477 | 0 | assert(bitit == bitdeq.begin() + before); |
478 | 0 | } |
479 | 0 | }, |
480 | 0 | [&] { |
481 | | // insert (at front, begin/end) |
482 | 0 | if (cdeq.size() < limitlen) { |
483 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
484 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
485 | 0 | auto rand_end = rand_begin + count; |
486 | 0 | auto it = deq.insert(cdeq.begin(), rand_begin, rand_end); |
487 | 0 | auto bitit = bitdeq.insert(cbitdeq.begin(), rand_begin, rand_end); |
488 | 0 | assert(it == cdeq.begin()); |
489 | 0 | assert(bitit == cbitdeq.begin()); |
490 | 0 | } |
491 | 0 | }, |
492 | 0 | [&] { |
493 | | // insert (at back, begin/end) |
494 | 0 | if (cdeq.size() < limitlen) { |
495 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
496 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
497 | 0 | auto rand_end = rand_begin + count; |
498 | 0 | auto it = deq.insert(cdeq.end(), rand_begin, rand_end); |
499 | 0 | auto bitit = bitdeq.insert(cbitdeq.end(), rand_begin, rand_end); |
500 | 0 | assert(it == cdeq.end() - count); |
501 | 0 | assert(bitit == cbitdeq.end() - count); |
502 | 0 | } |
503 | 0 | }, |
504 | 0 | [&] { |
505 | | // insert (in middle, range) |
506 | 0 | if (cdeq.size() < limitlen) { |
507 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
508 | 0 | size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
509 | 0 | bool val = ctx.randbool(); |
510 | 0 | auto it = deq.insert(cdeq.begin() + before, count, val); |
511 | 0 | auto bitit = bitdeq.insert(cbitdeq.begin() + before, count, val); |
512 | 0 | assert(it == deq.begin() + before); |
513 | 0 | assert(bitit == bitdeq.begin() + before); |
514 | 0 | } |
515 | 0 | }, |
516 | 0 | [&] { |
517 | | // insert (in middle, begin/end) |
518 | 0 | if (cdeq.size() < limitlen) { |
519 | 0 | size_t count = provider.ConsumeIntegralInRange<size_t>(0, maxlen); |
520 | 0 | size_t before = provider.ConsumeIntegralInRange<size_t>(0, cdeq.size()); |
521 | 0 | auto rand_begin = RANDDATA.begin() + ctx.randbits(RANDDATA_BITS); |
522 | 0 | auto rand_end = rand_begin + count; |
523 | 0 | auto it = deq.insert(cdeq.begin() + before, rand_begin, rand_end); |
524 | 0 | auto bitit = bitdeq.insert(cbitdeq.begin() + before, rand_begin, rand_end); |
525 | 0 | assert(it == deq.begin() + before); |
526 | 0 | assert(bitit == bitdeq.begin() + before); |
527 | 0 | } |
528 | 0 | }); |
529 | 0 | } |
530 | 0 | { |
531 | 0 | assert(deq.size() == bitdeq.size()); |
532 | 0 | auto it = deq.begin(); |
533 | 0 | auto bitit = bitdeq.begin(); |
534 | 0 | auto itend = deq.end(); |
535 | 0 | while (it != itend) { |
536 | 0 | assert(*it == *bitit); |
537 | 0 | ++it; |
538 | 0 | ++bitit; |
539 | 0 | } |
540 | 0 | } |
541 | 0 | } |