]> git.proxmox.com Git - mirror_frr.git/blame - tests/lib/test_typelist.h
*: auto-convert to SPDX License IDs
[mirror_frr.git] / tests / lib / test_typelist.h
CommitLineData
acddc0ed 1// SPDX-License-Identifier: ISC
992f9967
DL
2/*
3 * Copyright (c) 2019 David Lamparter, for NetDEF, Inc.
992f9967
DL
4 */
5
6/* C++ called, they want their templates back */
7#define item concat(item_, TYPE)
8#define itm concat(itm_, TYPE)
507e0e5d 9#define itmswap concat(itmswap_, TYPE)
992f9967
DL
10#define head concat(head_, TYPE)
11#define list concat(TYPE, )
12#define list_head concat(TYPE, _head)
13#define list_item concat(TYPE, _item)
14#define list_cmp concat(TYPE, _cmp)
15#define list_hash concat(TYPE, _hash)
16#define list_init concat(TYPE, _init)
17#define list_fini concat(TYPE, _fini)
daf3441d 18#define list_const_first concat(TYPE, _const_first)
992f9967 19#define list_first concat(TYPE, _first)
daf3441d 20#define list_const_next concat(TYPE, _const_next)
992f9967
DL
21#define list_next concat(TYPE, _next)
22#define list_next_safe concat(TYPE, _next_safe)
643ea83b
DL
23#define list_const_last concat(TYPE, _const_last)
24#define list_last concat(TYPE, _last)
25#define list_const_prev concat(TYPE, _const_prev)
26#define list_prev concat(TYPE, _prev)
27#define list_prev_safe concat(TYPE, _prev_safe)
992f9967
DL
28#define list_count concat(TYPE, _count)
29#define list_add concat(TYPE, _add)
8c3d03b3
DL
30#define list_add_head concat(TYPE, _add_head)
31#define list_add_tail concat(TYPE, _add_tail)
32#define list_add_after concat(TYPE, _add_after)
992f9967
DL
33#define list_find concat(TYPE, _find)
34#define list_find_lt concat(TYPE, _find_lt)
35#define list_find_gteq concat(TYPE, _find_gteq)
f45897e4 36#define list_member concat(TYPE, _member)
40ee228d 37#define list_anywhere concat(TYPE, _anywhere)
992f9967
DL
38#define list_del concat(TYPE, _del)
39#define list_pop concat(TYPE, _pop)
507e0e5d 40#define list_swap_all concat(TYPE, _swap_all)
992f9967 41
507e0e5d 42#define ts_hash_head concat(ts_hash_head_, TYPE)
8c3d03b3 43
2214f160
DL
44#ifndef REALTYPE
45#define REALTYPE TYPE
46#endif
47
960b9a53 48PREDECL(REALTYPE, list);
992f9967
DL
49struct item {
50 uint64_t val;
51 struct list_item itm;
52 int scratchpad;
53};
54
8c3d03b3 55#if IS_SORTED(REALTYPE)
992f9967
DL
56static int list_cmp(const struct item *a, const struct item *b);
57
2214f160 58#if IS_HASH(REALTYPE)
992f9967 59static uint32_t list_hash(const struct item *a);
960b9a53 60DECLARE(REALTYPE, list, struct item, itm, list_cmp, list_hash);
992f9967
DL
61
62static uint32_t list_hash(const struct item *a)
63{
2214f160 64#ifdef SHITTY_HASH
992f9967 65 /* crappy hash to get some hash collisions */
27a6fc42 66 return (a->val & 0xFF) ^ (a->val << 29) ^ 0x55AA0000U;
2214f160
DL
67#else
68 return jhash_1word(a->val, 0xdeadbeef);
69#endif
992f9967
DL
70}
71
72#else
960b9a53 73DECLARE(REALTYPE, list, struct item, itm, list_cmp);
992f9967
DL
74#endif
75
76static int list_cmp(const struct item *a, const struct item *b)
77{
78 if (a->val > b->val)
79 return 1;
80 if (a->val < b->val)
81 return -1;
82 return 0;
83}
84
8c3d03b3 85#else /* !IS_SORTED */
960b9a53 86DECLARE(REALTYPE, list, struct item, itm);
8c3d03b3
DL
87#endif
88
992f9967 89#define NITEM 10000
507e0e5d
DL
90#define NITEM_SWAP 100 /* other container for swap */
91struct item itm[NITEM], itmswap[NITEM_SWAP];
2214f160 92static struct list_head head = concat(INIT_, REALTYPE)(head);
992f9967 93
507e0e5d
DL
94static void ts_hash_head(struct list_head *h, const char *text,
95 const char *expect)
8c3d03b3
DL
96{
97 int64_t us = monotime_since(&ref, NULL);
98 SHA256_CTX ctx;
99 struct item *item;
100 unsigned i = 0;
101 uint8_t hash[32];
102 char hashtext[65];
1dc46d1e 103 uint32_t swap_count, count;
8c3d03b3 104
507e0e5d 105 count = list_count(h);
1dc46d1e 106 swap_count = htonl(count);
8c3d03b3
DL
107
108 SHA256_Init(&ctx);
1dc46d1e 109 SHA256_Update(&ctx, &swap_count, sizeof(swap_count));
8c3d03b3 110
507e0e5d 111 frr_each (list, h, item) {
8c3d03b3
DL
112 struct {
113 uint32_t val_upper, val_lower, index;
114 } hashitem = {
115 htonl(item->val >> 32),
116 htonl(item->val & 0xFFFFFFFFULL),
117 htonl(i),
118 };
119 SHA256_Update(&ctx, &hashitem, sizeof(hashitem));
120 i++;
1dc46d1e 121 assert(i <= count);
8c3d03b3
DL
122 }
123 SHA256_Final(hash, &ctx);
124
125 for (i = 0; i < sizeof(hash); i++)
126 sprintf(hashtext + i * 2, "%02x", hash[i]);
127
fb84c629 128 printfrr("%7"PRId64"us %-25s %s%s\n", us, text,
8c3d03b3
DL
129 expect ? " " : "*", hashtext);
130 if (expect && strcmp(expect, hashtext)) {
fb84c629 131 printfrr("%-21s %s\n", "EXPECTED:", expect);
8c3d03b3
DL
132 assert(0);
133 }
134 monotime(&ref);
135}
136/* hashes will have different item ordering */
d0a0e597 137#if IS_HASH(REALTYPE) || IS_HEAP(REALTYPE)
507e0e5d
DL
138#define ts_hash(pos, csum) ts_hash_head(&head, pos, NULL)
139#define ts_hashx(pos, csum) ts_hash_head(&head, pos, NULL)
140#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, NULL)
8c3d03b3 141#else
507e0e5d
DL
142#define ts_hash(pos, csum) ts_hash_head(&head, pos, csum)
143#define ts_hashx(pos, csum) ts_hash_head(&head, pos, csum)
144#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, csum)
8c3d03b3
DL
145#endif
146
992f9967
DL
147static void concat(test_, TYPE)(void)
148{
149 size_t i, j, k, l;
150 struct prng *prng;
507e0e5d 151 struct prng *prng_swap __attribute__((unused));
8c3d03b3
DL
152 struct item *item, *prev __attribute__((unused));
153 struct item dummy __attribute__((unused));
992f9967
DL
154
155 memset(itm, 0, sizeof(itm));
156 for (i = 0; i < NITEM; i++)
157 itm[i].val = i;
158
507e0e5d
DL
159 memset(itmswap, 0, sizeof(itmswap));
160 for (i = 0; i < NITEM_SWAP; i++)
161 itmswap[i].val = i;
162
fb84c629 163 printfrr("%s start\n", str(TYPE));
992f9967
DL
164 ts_start();
165
166 list_init(&head);
992f9967 167 assert(list_first(&head) == NULL);
643ea83b
DL
168#if IS_REVERSE(REALTYPE)
169 assert(list_last(&head) == NULL);
170#endif
992f9967 171
8c3d03b3
DL
172 ts_hash("init", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
173
174#if IS_SORTED(REALTYPE)
992f9967
DL
175 prng = prng_new(0);
176 k = 0;
177 for (i = 0; i < NITEM; i++) {
178 j = prng_rand(prng) % NITEM;
179 if (itm[j].scratchpad == 0) {
180 list_add(&head, &itm[j]);
181 itm[j].scratchpad = 1;
182 k++;
d0a0e597
DL
183 }
184#if !IS_HEAP(REALTYPE)
185 else
992f9967 186 assert(list_add(&head, &itm[j]) == &itm[j]);
d0a0e597 187#endif
992f9967
DL
188 }
189 assert(list_count(&head) == k);
190 assert(list_first(&head) != NULL);
8c3d03b3 191 ts_hashx("fill", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
992f9967 192
507e0e5d
DL
193#if !IS_ATOMIC(REALTYPE)
194 struct list_head other;
195
196 list_init(&other);
197 list_swap_all(&head, &other);
198
199 assert(list_count(&head) == 0);
200 assert(!list_first(&head));
201 assert(list_count(&other) == k);
202 assert(list_first(&other) != NULL);
643ea83b
DL
203#if IS_REVERSE(REALTYPE)
204 assert(!list_last(&head));
205 assert(list_last(&other) != NULL);
206#endif
507e0e5d
DL
207 ts_hash_headx(
208 &other, "swap1",
209 "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
210
211 prng_swap = prng_new(0x1234dead);
212 l = 0;
213 for (i = 0; i < NITEM_SWAP; i++) {
214 j = prng_rand(prng_swap) % NITEM_SWAP;
215 if (itmswap[j].scratchpad == 0) {
216 list_add(&head, &itmswap[j]);
217 itmswap[j].scratchpad = 1;
218 l++;
219 }
220#if !IS_HEAP(REALTYPE)
221 else {
222 struct item *rv = list_add(&head, &itmswap[j]);
223 assert(rv == &itmswap[j]);
224 }
225#endif
226 }
227 assert(list_count(&head) == l);
228 assert(list_first(&head) != NULL);
229 ts_hash_headx(
230 &head, "swap-fill",
231 "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6");
232
233 list_swap_all(&head, &other);
234
235 assert(list_count(&other) == l);
236 assert(list_first(&other));
237 ts_hash_headx(
238 &other, "swap2a",
239 "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6");
240 assert(list_count(&head) == k);
241 assert(list_first(&head) != NULL);
242 ts_hash_headx(
243 &head, "swap2b",
244 "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
9de36e51
DL
245
246 while (list_pop(&other))
247 ;
248 list_fini(&other);
249 prng_free(prng_swap);
250
251 ts_ref("swap-cleanup");
507e0e5d
DL
252#endif /* !IS_ATOMIC */
253
992f9967 254 k = 0;
daf3441d
DL
255
256#if IS_ATOMIC(REALTYPE)
257 struct list_head *chead = &head;
258 struct item *citem, *cprev = NULL;
259
260 frr_each(list, chead, citem) {
261#else
262 const struct list_head *chead = &head;
263 const struct item *citem, *cprev = NULL;
264
265 frr_each(list_const, chead, citem) {
266#endif
267
d0a0e597 268#if IS_HASH(REALTYPE) || IS_HEAP(REALTYPE)
992f9967 269 /* hash table doesn't give sorting */
daf3441d 270 (void)cprev;
992f9967 271#else
daf3441d 272 assert(!cprev || cprev->val < citem->val);
643ea83b
DL
273#if IS_REVERSE(REALTYPE)
274 assert(list_const_prev(chead, citem) == cprev);
275#endif
992f9967 276#endif
daf3441d 277 cprev = citem;
992f9967
DL
278 k++;
279 }
daf3441d 280 assert(list_count(chead) == k);
643ea83b
DL
281#if IS_REVERSE(REALTYPE)
282 assert(cprev == list_const_last(chead));
283#endif
992f9967
DL
284 ts_ref("walk");
285
643ea83b
DL
286#if IS_REVERSE(REALTYPE) && !IS_HASH(REALTYPE) && !IS_HEAP(REALTYPE)
287 cprev = NULL;
288 k = 0;
289
290 frr_rev_each(list_const, chead, citem) {
291 assert(!cprev || cprev->val > citem->val);
292 assert(list_const_next(chead, citem) == cprev);
293
294 cprev = citem;
295 k++;
296 }
297 assert(list_count(chead) == k);
298 assert(cprev == list_const_first(chead));
299
300 ts_ref("reverse-walk");
301#endif
302
2214f160 303#if IS_UNIQ(REALTYPE)
992f9967
DL
304 prng_free(prng);
305 prng = prng_new(0);
306
307 for (i = 0; i < NITEM; i++) {
308 j = prng_rand(prng) % NITEM;
309 dummy.val = j;
310 assert(list_find(&head, &dummy) == &itm[j]);
311 }
312 ts_ref("find");
313
314 for (i = 0; i < NITEM; i++) {
315 j = prng_rand(prng) % NITEM;
316 memset(&dummy, 0, sizeof(dummy));
317 dummy.val = j;
318 if (itm[j].scratchpad)
319 assert(list_add(&head, &dummy) == &itm[j]);
320 else {
321 assert(list_add(&head, &dummy) == NULL);
7de7c75b 322 assert(list_del(&head, &dummy) != NULL);
992f9967
DL
323 }
324 }
8c3d03b3 325 ts_hashx("add-dup", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
d0a0e597
DL
326
327#elif IS_HEAP(REALTYPE)
328 /* heap - partially sorted. */
329 prev = NULL;
f45897e4 330 l = k / 4;
d0a0e597
DL
331 for (i = 0; i < l; i++) {
332 item = list_pop(&head);
333 if (prev)
334 assert(prev->val < item->val);
335 item->scratchpad = 0;
336 k--;
337 prev = item;
338 }
f45897e4
DL
339 ts_hash("pop#1", NULL);
340
341 for (i = 0; i < NITEM; i++)
342 assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
343 "%zu should:%d is:%d", i, itm[i].scratchpad,
344 list_member(&head, &itm[i]));
345 ts_hash("member", NULL);
346
347 l = k / 2;
348 for (; i < l; i++) {
349 item = list_pop(&head);
350 if (prev)
351 assert(prev->val < item->val);
352 item->scratchpad = 0;
353 k--;
354 prev = item;
355 }
356 ts_hash("pop#2", NULL);
d0a0e597
DL
357
358#else /* !IS_UNIQ(REALTYPE) && !IS_HEAP(REALTYPE) */
992f9967
DL
359 for (i = 0; i < NITEM; i++) {
360 j = prng_rand(prng) % NITEM;
361 memset(&dummy, 0, sizeof(dummy));
362 dummy.val = j;
363
364 list_add(&head, &dummy);
365 if (itm[j].scratchpad) {
366 struct item *lt, *gteq, dummy2;
367
368 assert(list_next(&head, &itm[j]) == &dummy ||
369 list_next(&head, &dummy) == &itm[j]);
370
371 memset(&dummy2, 0, sizeof(dummy));
372 dummy2.val = j;
373 lt = list_find_lt(&head, &dummy2);
374 gteq = list_find_gteq(&head, &dummy2);
375
376 assert(gteq == &itm[j] || gteq == &dummy);
377 if (lt)
378 assert(list_next(&head, lt) == &itm[j] ||
379 list_next(&head, lt) == &dummy);
380 else
381 assert(list_first(&head) == &itm[j] ||
382 list_first(&head) == &dummy);
383 } else if (list_next(&head, &dummy))
384 assert(list_next(&head, &dummy)->val > j);
7de7c75b 385 assert(list_del(&head, &dummy) != NULL);
992f9967 386 }
8c3d03b3 387 ts_hash("add-dup+find_{lt,gteq}", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
992f9967 388#endif
d0a0e597 389#if !IS_HASH(REALTYPE) && !IS_HEAP(REALTYPE)
992f9967
DL
390 prng_free(prng);
391 prng = prng_new(123456);
392
393 l = 0;
394 for (i = 0; i < NITEM; i++) {
395 struct item *lt, *gteq, *tmp;
396
397 j = prng_rand(prng) % NITEM;
398 dummy.val = j;
399
400 lt = list_find_lt(&head, &dummy);
401 gteq = list_find_gteq(&head, &dummy);
402
403 if (lt) {
404 assert(lt->val < j);
405 tmp = list_next(&head, lt);
406 assert(tmp == gteq);
407 assert(!tmp || tmp->val >= j);
408 } else
409 assert(gteq == list_first(&head));
c258527b 410
992f9967
DL
411 if (gteq)
412 assert(gteq->val >= j);
413 }
414 ts_ref("find_{lt,gteq}");
415#endif /* !IS_HASH */
416
417 prng_free(prng);
418 prng = prng_new(0);
419
420 l = 0;
421 for (i = 0; i < NITEM; i++) {
422 (void)prng_rand(prng);
423 j = prng_rand(prng) % NITEM;
424 if (itm[j].scratchpad == 1) {
7de7c75b 425 assert(list_del(&head, &itm[j]) != NULL);
992f9967
DL
426 itm[j].scratchpad = 0;
427 l++;
428 }
429 }
430 assert(l + list_count(&head) == k);
8c3d03b3 431 ts_hashx("del", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
992f9967 432
f45897e4
DL
433#if !IS_ATOMIC(REALTYPE)
434 for (i = 0; i < NITEM; i++)
435 assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
436 "%zu should:%d is:%d", i, itm[i].scratchpad,
437 list_member(&head, &itm[i]));
438 ts_hashx("member", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
439#endif
440
81fddbe7 441 frr_each_safe(list, &head, item) {
992f9967
DL
442 assert(item->scratchpad != 0);
443
444 if (item->val & 1) {
7de7c75b 445 assert(list_del(&head, item) != NULL);
992f9967
DL
446 item->scratchpad = 0;
447 l++;
448 }
449 }
450 assert(l + list_count(&head) == k);
81fddbe7 451 ts_hashx("frr_each_safe+del", "e0beb71dd963a75af05b722b8e71b61b304587d860c8accdc4349067542b86bb");
8c3d03b3
DL
452
453#else /* !IS_SORTED */
454 prng = prng_new(0);
455 k = 0;
456 for (i = 0; i < NITEM; i++) {
457 j = prng_rand(prng) % NITEM;
458 if (itm[j].scratchpad == 0) {
459 list_add_tail(&head, &itm[j]);
460 itm[j].scratchpad = 1;
461 k++;
462 }
463 }
464 assert(list_count(&head) == k);
465 assert(list_first(&head) != NULL);
643ea83b
DL
466#if IS_REVERSE(REALTYPE)
467 assert(list_last(&head) != NULL);
468#endif
8c3d03b3
DL
469 ts_hash("fill / add_tail", "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
470
507e0e5d
DL
471#if !IS_ATOMIC(REALTYPE)
472 struct list_head other;
473
474 list_init(&other);
475 list_swap_all(&head, &other);
476
477 assert(list_count(&head) == 0);
478 assert(!list_first(&head));
479 assert(list_count(&other) == k);
480 assert(list_first(&other) != NULL);
643ea83b
DL
481#if IS_REVERSE(REALTYPE)
482 assert(!list_last(&head));
483 assert(list_last(&other) != NULL);
484#endif
507e0e5d
DL
485 ts_hash_head(
486 &other, "swap1",
487 "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
488
489 prng_swap = prng_new(0x1234dead);
490 l = 0;
491 for (i = 0; i < NITEM_SWAP; i++) {
492 j = prng_rand(prng_swap) % NITEM_SWAP;
493 if (itmswap[j].scratchpad == 0) {
494 list_add_tail(&head, &itmswap[j]);
495 itmswap[j].scratchpad = 1;
496 l++;
497 }
498 }
499 assert(list_count(&head) == l);
500 assert(list_first(&head) != NULL);
501 ts_hash_head(
502 &head, "swap-fill",
503 "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909");
504
505 list_swap_all(&head, &other);
506
507 assert(list_count(&other) == l);
508 assert(list_first(&other));
509 ts_hash_head(
510 &other, "swap2a",
511 "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909");
512 assert(list_count(&head) == k);
513 assert(list_first(&head) != NULL);
514 ts_hash_head(
515 &head, "swap2b",
516 "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
9de36e51
DL
517
518 while (list_pop(&other))
519 ;
520 list_fini(&other);
521 prng_free(prng_swap);
522
523 ts_ref("swap-cleanup");
507e0e5d
DL
524#endif
525
8c3d03b3
DL
526 for (i = 0; i < NITEM / 2; i++) {
527 j = prng_rand(prng) % NITEM;
528 if (itm[j].scratchpad == 1) {
7de7c75b 529 assert(list_del(&head, &itm[j]) != NULL);
8c3d03b3
DL
530 itm[j].scratchpad = 0;
531 k--;
532 }
533 }
534 ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
535
f45897e4 536#if !IS_ATOMIC(REALTYPE)
40ee228d 537 for (i = 0; i < NITEM; i++) {
f45897e4
DL
538 assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
539 "%zu should:%d is:%d", i, itm[i].scratchpad,
540 list_member(&head, &itm[i]));
40ee228d
DL
541 assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
542 "%zu should:%d is:%d", i, itm[i].scratchpad,
543 list_anywhere(&itm[i]));
544 }
f45897e4
DL
545 ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
546#endif
547
8c3d03b3 548 l = 0;
f45897e4
DL
549 while (l < (k / 4) && (prev = list_pop(&head))) {
550 assert(prev->scratchpad != 0);
551
552 prev->scratchpad = 0;
553 l++;
554 }
555 ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
556
557#if !IS_ATOMIC(REALTYPE)
40ee228d 558 for (i = 0; i < NITEM; i++) {
f45897e4
DL
559 assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
560 "%zu should:%d is:%d", i, itm[i].scratchpad,
561 list_member(&head, &itm[i]));
40ee228d
DL
562 assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
563 "%zu should:%d is:%d", i, itm[i].scratchpad,
564 list_anywhere(&itm[i]));
565 }
f45897e4
DL
566 ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
567#endif
643ea83b
DL
568#if IS_REVERSE(REALTYPE)
569 i = 0;
570 prev = NULL;
571
572 frr_rev_each (list, &head, item) {
573 assert(item->scratchpad != 0);
574 assert(list_next(&head, item) == prev);
575
576 i++;
577 prev = item;
578 }
579 assert(list_first(&head) == prev);
580 assert(list_count(&head) == i);
581 ts_hash("reverse-walk", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
582#endif
f45897e4 583
8c3d03b3
DL
584 while ((item = list_pop(&head))) {
585 assert(item->scratchpad != 0);
586
587 item->scratchpad = 0;
588 l++;
589 }
590 assert(l == k);
591 assert(list_count(&head) == 0);
592 assert(list_first(&head) == NULL);
f45897e4 593 ts_hash("pop#2", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
8c3d03b3
DL
594
595 prng_free(prng);
596 prng = prng_new(0x1e5a2d69);
597
598 k = 0;
599 for (i = 0; i < NITEM; i++) {
600 j = prng_rand(prng) % NITEM;
601 if (itm[j].scratchpad == 0) {
602 list_add_head(&head, &itm[j]);
603 itm[j].scratchpad = 1;
604 k++;
605 }
606 }
607 assert(list_count(&head) == k);
608 assert(list_first(&head) != NULL);
609 ts_hash("fill / add_head", "3084d8f8a28b8c756ccc0a92d60d86f6d776273734ddc3f9e1d89526f5ca2795");
610
611 for (i = 0; i < NITEM / 2; i++) {
612 j = prng_rand(prng) % NITEM;
613 if (itm[j].scratchpad == 1) {
7de7c75b 614 assert(list_del(&head, &itm[j]) != NULL);
8c3d03b3
DL
615 itm[j].scratchpad = 0;
616 k--;
617 }
618 }
619 ts_hash("del-prng", "dc916fa7ea4418792c7c8232d74df2887f9975ead4222f4b977be6bc0b52285e");
620
621 l = 0;
622 while ((item = list_pop(&head))) {
623 assert(item->scratchpad != 0);
624
625 item->scratchpad = 0;
626 l++;
627 }
628 assert(l == k);
629 assert(list_count(&head) == 0);
630 assert(list_first(&head) == NULL);
631 ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
632
633 prng_free(prng);
634 prng = prng_new(0x692d1e5a);
635
636 k = 0;
637 for (i = 0; i < NITEM; i++) {
638 j = prng_rand(prng) % NITEM;
639 if (itm[j].scratchpad == 0) {
640 if (prng_rand(prng) & 1) {
641 list_add_tail(&head, &itm[j]);
642 } else {
643 list_add_head(&head, &itm[j]);
644 }
645 itm[j].scratchpad = 1;
646 k++;
647 }
648 }
649 assert(list_count(&head) == k);
650 assert(list_first(&head) != NULL);
651 ts_hash("fill / add_{head,tail}", "93fa180a575c96e4b6c3775c2de7843ee3254dd6ed5af699bbe155f994114b06");
652
d0a0e597
DL
653 for (i = 0; i < NITEM * 3; i++) {
654 int op = prng_rand(prng);
655 j = prng_rand(prng) % NITEM;
656
657 if (op & 1) {
658 /* delete or pop */
659 if (op & 2) {
660 item = list_pop(&head);
661 if (!item)
662 continue;
663 } else {
664 item = &itm[j];
665 if (item->scratchpad == 0)
666 continue;
7de7c75b 667 assert(list_del(&head, item) != NULL);
d0a0e597
DL
668 }
669 item->scratchpad = 0;
670 k--;
671 } else {
672 item = &itm[j];
673 if (item->scratchpad != 0)
674 continue;
675
676 item->scratchpad = 1;
677 k++;
678
679 switch ((op >> 1) & 1) {
680 case 0:
681 list_add_head(&head, item);
682 break;
683 case 1:
684 list_add_tail(&head, item);
685 break;
686 default:
687 assert(0);
688 }
689 }
690 }
691 assert(list_count(&head) == k);
692 assert(list_first(&head) != NULL);
693 ts_hash("prng add/del", "4909f31d06bb006efca4dfeebddb8de071733ddf502f89b6d532155208bbc6df");
694
695#if !IS_ATOMIC(REALTYPE)
696 /* variant with add_after */
697
8c3d03b3
DL
698 for (i = 0; i < NITEM * 3; i++) {
699 int op = prng_rand(prng);
700 j = prng_rand(prng) % NITEM;
701
702 if (op & 1) {
703 /* delete or pop */
704 if (op & 2) {
705 item = list_pop(&head);
706 if (!item)
707 continue;
708 } else {
709 item = &itm[j];
710 if (item->scratchpad == 0)
711 continue;
7de7c75b 712 assert(list_del(&head, item) != NULL);
8c3d03b3
DL
713 }
714 item->scratchpad = 0;
715 k--;
716 } else {
717 item = &itm[j];
718 if (item->scratchpad != 0)
719 continue;
720
721 item->scratchpad = 1;
722 k++;
723
724 switch ((op >> 1) & 3) {
725 case 0:
726 list_add_head(&head, item);
727 break;
728 case 1:
729 list_add_tail(&head, item);
730 break;
731 case 2:
732 case 3:
733 prev = NULL;
734 l = 0;
735 do {
736 j = prng_rand(prng) % NITEM;
737 prev = &itm[j];
738 if (prev->scratchpad == 0
739 || prev == item)
740 prev = NULL;
741 l++;
742 } while (!prev && l < 10);
743 list_add_after(&head, prev, item);
744 break;
745 default:
746 assert(0);
747 }
748 }
749 }
750 assert(list_count(&head) == k);
751 assert(list_first(&head) != NULL);
d0a0e597
DL
752 ts_hash("prng add/after/del", "84c5fc83294eabebb9808ccbba32a303c4fca084db87ed1277d2bae1f8c5bee4");
753#endif
8c3d03b3
DL
754
755 l = 0;
756#endif
992f9967
DL
757
758 while ((item = list_pop(&head))) {
759 assert(item->scratchpad != 0);
760
761 item->scratchpad = 0;
762 l++;
763 }
764 assert(l == k);
765 assert(list_count(&head) == 0);
766 assert(list_first(&head) == NULL);
8c3d03b3 767 ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
992f9967
DL
768
769 list_fini(&head);
770 ts_ref("fini");
771 ts_end();
9de36e51 772 prng_free(prng);
fb84c629 773 printfrr("%s end\n", str(TYPE));
992f9967
DL
774}
775
507e0e5d 776#undef ts_hash
8c3d03b3 777#undef ts_hashx
507e0e5d
DL
778#undef ts_hash_head
779#undef ts_hash_headx
8c3d03b3 780
992f9967
DL
781#undef item
782#undef itm
507e0e5d 783#undef itmswap
992f9967
DL
784#undef head
785#undef list
786#undef list_head
787#undef list_item
788#undef list_cmp
789#undef list_hash
790#undef list_init
791#undef list_fini
792#undef list_first
793#undef list_next
794#undef list_next_safe
643ea83b
DL
795#undef list_const_first
796#undef list_const_next
797#undef list_last
798#undef list_prev
799#undef list_prev_safe
800#undef list_const_last
801#undef list_const_prev
992f9967
DL
802#undef list_count
803#undef list_add
8c3d03b3
DL
804#undef list_add_head
805#undef list_add_tail
806#undef list_add_after
992f9967
DL
807#undef list_find
808#undef list_find_lt
809#undef list_find_gteq
f45897e4 810#undef list_member
40ee228d 811#undef list_anywhere
992f9967
DL
812#undef list_del
813#undef list_pop
507e0e5d 814#undef list_swap_all
992f9967 815
2214f160 816#undef REALTYPE
992f9967 817#undef TYPE