Add 32bit time64 syscalls for arm, mips32, ppc32 and x86.
[valgrind.git] / memcheck / tests / unit_oset.c
blob1d2d2556108b5260898c953a521d698d682b7ad4
2 #include <assert.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
7 #include "pub_core_basics.h"
8 #include "pub_core_libcbase.h"
9 #include "pub_core_libcassert.h"
10 #include "pub_core_libcprint.h"
12 // I need this to avoid some signedness warnings, not sure why
13 // #define Char char
14 // jrs 19 Aug 2005: m_oset.c relies on Char being a signed char.
15 // It appears that plain 'char' on ppc32 is unsigned and so the
16 // above #define screws up the AVL tree balancing logic and
17 // leads to segfaults. Commenting it out and using the standard
18 // definition of Char from pub_core_basics.h seems a good solution
19 // as that has the same signedness on all platforms.
21 // Crudely redirect various VG_(foo)() functions to their libc equivalents.
22 #undef vg_assert
23 #define vg_assert(e) assert(e)
24 #undef vg_assert2
25 #define vg_assert2(e, fmt, args...) assert(e)
27 #define vgPlain_printf printf
28 #define vgPlain_memset memset
29 #define vgPlain_memcpy memcpy
30 #define vgPlain_memmove memmove
31 #define vgPlain_strcmp strcmp
33 // Crudely replace some functions (in m_xarray.c, but not needed for
34 // this unit test) by (hopefully) failing asserts.
35 #define vgPlain_ssort(a,b,c,d) assert(a)
36 #define vgPlain_vcbprintf(a,b,...) assert(a == b)
37 #include "coregrind/m_xarray.c"
38 #undef vgPlain_ssort
39 #undef vgPlain_vcbprintf
40 #include "coregrind/m_poolalloc.c"
41 #include "coregrind/m_oset.c"
43 #define NN 1000 // Size of OSets being created
46 /* Consistent random number generator, so it produces the
47 same results on all platforms. */
49 #define random error_do_not_use_libc_random
51 static UInt seed = 0;
52 static UInt myrandom( void )
54 seed = (1103515245 * seed + 12345);
55 return seed;
58 static void* allocate_node(const HChar* cc, SizeT szB)
59 { return malloc(szB); }
61 static void free_node(void* p)
62 { return free(p); }
65 //---------------------------------------------------------------------------
66 // Word example
67 //---------------------------------------------------------------------------
69 // This example shows that an element can be a single value (in this
70 // case a Word), in which case the element is also the key.
72 __attribute__((unused))
73 static const HChar *wordToStr(const void *p)
75 static HChar buf[32];
76 sprintf(buf, "%ld", *(Word*)p);
77 return buf;
80 __attribute__((unused))
81 static Word wordCmp(void* vkey, void* velem)
83 return *(Word*)vkey - *(Word*)velem;
86 void example1singleset(OSet* oset, char *descr)
88 Int i, n;
89 UWord v, prev;
90 UWord* vs[NN];
91 UWord *pv;
92 UWord sorted_elts[NN]; // Used to test VG_(OSetGen_ResetIterAt)
94 // Try some operations on an empty OSet to ensure they don't screw up.
95 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
96 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
97 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
98 vg_assert( ! VG_(OSetGen_Next)(oset) );
99 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
101 // Create some elements, with gaps (they're all even) but no dups,
102 // and shuffle them randomly.
103 for (i = 0; i < NN; i++) {
104 vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Word));
105 *(vs[i]) = 2*(i+1);
106 sorted_elts[i] = *(vs[i]);
108 seed = 0;
109 for (i = 0; i < NN; i++) {
110 UWord r1 = myrandom() % NN;
111 UWord r2 = myrandom() % NN;
112 UWord* tmp= vs[r1];
113 vs[r1] = vs[r2];
114 vs[r2] = tmp;
117 // Insert the elements
118 for (i = 0; i < NN; i++) {
119 VG_(OSetGen_Insert)(oset, vs[i]);
122 // Check the size
123 vg_assert( NN == VG_(OSetGen_Size)(oset) );
125 // Check we can find all the elements we inserted
126 for (i = 0; i < NN; i++) {
127 assert( VG_(OSetGen_Contains)(oset, vs[i]) );
130 #define FULLCHECKEVERY 20
131 // Check VG_(OSetGen_ResetIterAt) works before, at, and after each element.
132 // For some elements, we check all the successive elements.
133 for (i = 0; i < NN; i++) {
134 UWord k;
135 UWord *pval;
136 Int j;
138 // check ResetIterAt just before an elt gives this elt.
139 k = sorted_elts[i] - 1;
140 VG_(OSetGen_ResetIterAt) (oset, &k);
141 // Check all elts till the end
142 for (j = i; j < NN; j++) {
143 pval = VG_(OSetGen_Next)(oset);
144 assert (*pval == sorted_elts[j]);
145 if (i % FULLCHECKEVERY != 0) break;
148 // check ResetIterAt at an elt gives this elt.
149 k = sorted_elts[i];
150 VG_(OSetGen_ResetIterAt) (oset, &k);
151 // Check all elts till the end
152 for (j = i; j < NN; j++) {
153 pval = VG_(OSetGen_Next)(oset);
154 assert (*pval == sorted_elts[j]);
155 if (i % FULLCHECKEVERY != 0) break;
158 // check ResetIterAt after an elt gives the next elt or nothing
159 // when we reset after the last elt.
160 k = sorted_elts[i] + 1;
161 VG_(OSetGen_ResetIterAt) (oset, &k);
162 if (i < NN - 1) {
163 for (j = i+1; j < NN; j++) {
164 pval = VG_(OSetGen_Next)(oset);
165 assert (*pval == sorted_elts[j]);
166 if (i % FULLCHECKEVERY != 0) break;
168 } else {
169 pval = VG_(OSetGen_Next)(oset);
170 assert (pval == NULL);
175 // Check we cannot find elements we did not insert, below, within (odd
176 // numbers), and above the inserted elements.
177 v = 0;
178 assert( ! VG_(OSetGen_Contains)(oset, &v) );
179 for (i = 0; i < NN; i++) {
180 v = *(vs[i]) + 1;
181 assert( ! VG_(OSetGen_Contains)(oset, &v) );
183 v = 2*(NN+1);
184 assert( ! VG_(OSetGen_Contains)(oset, &v) );
186 // Check we can find all the elements we inserted, and the right values
187 // are returned.
188 for (i = 0; i < NN; i++) {
189 assert( vs[i] == VG_(OSetGen_Lookup)(oset, vs[i]) );
192 // Check that we can iterate over the OSet elements in sorted order, and
193 // there is the right number of them.
194 n = 0;
195 pv = NULL;
196 prev = 0;
197 VG_(OSetGen_ResetIter)(oset);
198 while ( (pv = VG_(OSetGen_Next)(oset)) ) {
199 UWord curr = *pv;
200 assert(prev < curr);
201 prev = curr;
202 n++;
204 assert(NN == n);
205 vg_assert( ! VG_(OSetGen_Next)(oset) );
206 vg_assert( ! VG_(OSetGen_Next)(oset) );
208 // Check that we can remove half of the elements, and that their values
209 // are as expected.
210 for (i = 0; i < NN; i += 2) {
211 pv = VG_(OSetGen_Remove)(oset, vs[i]);
212 assert( pv );
213 assert( pv == vs[i] );
216 // Check the size
217 vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
219 // Check we can find the remaining elements (with the right values).
220 for (i = 1; i < NN; i += 2) {
221 pv = VG_(OSetGen_LookupWithCmp)(oset, vs[i], NULL);
222 assert( pv );
223 assert( pv == vs[i] );
226 // Check we cannot find any of the elements we removed.
227 for (i = 0; i < NN; i += 2) {
228 assert( ! VG_(OSetGen_Contains)(oset, vs[i]) );
231 // Check that we can remove the remaining half of the elements, and that
232 // their values are as expected.
233 for (i = 1; i < NN; i += 2) {
234 pv = VG_(OSetGen_Remove)(oset, vs[i]);
235 assert( pv );
236 assert( pv == vs[i] );
239 // Try some more operations on the empty OSet to ensure they don't screw up.
240 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
241 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
242 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
243 vg_assert( ! VG_(OSetGen_Next)(oset) );
244 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
246 // Free a few elements
247 VG_(OSetGen_FreeNode)(oset, vs[0]);
248 VG_(OSetGen_FreeNode)(oset, vs[1]);
249 VG_(OSetGen_FreeNode)(oset, vs[2]);
251 // Re-insert remaining elements, to give OSetGen_Destroy something to
252 // work with.
253 for (i = 3; i < NN; i++) {
254 VG_(OSetGen_Insert)(oset, vs[i]);
257 // Print the list
258 OSet_Print(oset, descr, wordToStr);
262 void example1(void)
264 OSet *oset, *oset_empty_clone;
266 // Create a static OSet of UWords. This one uses fast (built-in)
267 // comparisons.
269 // First a single oset, no pool allocator.
270 oset = VG_(OSetGen_Create)(0,
271 NULL,
272 allocate_node, "oset_test.1", free_node);
273 example1singleset(oset, "single oset, no pool allocator");
275 // Destroy the OSet
276 VG_(OSetGen_Destroy)(oset);
278 // Then same, but with a group allocator
279 oset = VG_(OSetGen_Create_With_Pool)(0,
280 NULL,
281 allocate_node, "oset_test.1",
282 free_node,
283 101, sizeof(Word));
284 example1singleset(oset, "single oset, pool allocator");
286 // Destroy the OSet
287 VG_(OSetGen_Destroy)(oset);
290 // Then two sets, sharing a group allocator.
291 oset = VG_(OSetGen_Create_With_Pool)
293 NULL,
294 allocate_node, "oset_test.1", free_node,
295 101, sizeof(Word));
296 oset_empty_clone = VG_(OSetGen_EmptyClone) (oset);
297 example1singleset(oset, "oset, shared pool");
298 example1singleset(oset_empty_clone, "cloned oset, shared pool");
299 // Destroy both OSet
301 VG_(OSetGen_Destroy)(oset_empty_clone);
302 VG_(OSetGen_Destroy)(oset);
306 void example1b(void)
308 Int i, n;
309 UWord v = 0, prev;
310 UWord vs[NN];
312 // Create a static OSet of UWords. This one uses fast (built-in)
313 // comparisons.
314 OSet* oset = VG_(OSetWord_Create)(allocate_node, "oset_test.2", free_node);
316 // Try some operations on an empty OSet to ensure they don't screw up.
317 vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
318 vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
319 vg_assert( ! VG_(OSetWord_Next)(oset, (UWord *)&v) );
320 vg_assert( 0 == VG_(OSetWord_Size)(oset) );
322 // Create some elements, with gaps (they're all even) but no dups,
323 // and shuffle them randomly.
324 for (i = 0; i < NN; i++) {
325 vs[i] = 2*i;
327 seed = 0;
328 for (i = 0; i < NN; i++) {
329 UWord r1 = myrandom() % NN;
330 UWord r2 = myrandom() % NN;
331 UWord tmp = vs[r1];
332 vs[r1] = vs[r2];
333 vs[r2] = tmp;
336 // Insert the elements
337 for (i = 0; i < NN; i++) {
338 VG_(OSetWord_Insert)(oset, vs[i]);
341 // Check the size
342 vg_assert( NN == VG_(OSetWord_Size)(oset) );
344 // Check we can find all the elements we inserted
345 for (i = 0; i < NN; i++) {
346 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
349 // Check we cannot find elements we did not insert, below, within (odd
350 // numbers), and above the inserted elements.
351 v = 0xffffffff;
352 assert( ! VG_(OSetWord_Contains)(oset, v) );
353 for (i = 0; i < NN; i++) {
354 v = vs[i] + 1;
355 assert( ! VG_(OSetWord_Contains)(oset, v) );
357 v = NN*2;
358 assert( ! VG_(OSetWord_Contains)(oset, v) );
360 // Check we can find all the elements we inserted.
361 for (i = 0; i < NN; i++) {
362 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
365 // Check that we can iterate over the OSet elements in sorted order, and
366 // there is the right number of them.
367 n = 0;
368 prev = 0;
369 VG_(OSetWord_ResetIter)(oset);
370 while ( VG_(OSetWord_Next)(oset, (UWord *)&v) ) {
371 UWord curr = v;
372 if (n == 0)
373 assert(prev == curr);
374 else
375 assert(prev < curr);
376 prev = curr;
377 n++;
379 assert(NN == n);
380 vg_assert( ! VG_(OSetWord_Next)(oset, (UWord *)&v) );
381 vg_assert( ! VG_(OSetWord_Next)(oset, (UWord *)&v) );
383 // Check that we can remove half of the elements.
384 for (i = 0; i < NN; i += 2) {
385 assert( VG_(OSetWord_Remove)(oset, vs[i]) );
388 // Check the size
389 vg_assert( NN/2 == VG_(OSetWord_Size)(oset) );
391 // Check we can find the remaining elements (with the right values).
392 for (i = 1; i < NN; i += 2) {
393 assert( VG_(OSetWord_Contains)(oset, vs[i]) );
396 // Check we cannot find any of the elements we removed.
397 for (i = 0; i < NN; i += 2) {
398 assert( ! VG_(OSetWord_Contains)(oset, vs[i]) );
401 // Check that we can remove the remaining half of the elements.
402 for (i = 1; i < NN; i += 2) {
403 assert( VG_(OSetWord_Remove)(oset, vs[i]) );
406 // Try some more operations on the empty OSet to ensure they don't screw up.
407 vg_assert( ! VG_(OSetWord_Contains)(oset, v) );
408 vg_assert( ! VG_(OSetWord_Remove)(oset, v) );
409 vg_assert( ! VG_(OSetWord_Next)(oset, (UWord *)&v) );
410 vg_assert( 0 == VG_(OSetWord_Size)(oset) );
412 // Re-insert remaining elements, to give OSetWord_Destroy something to
413 // work with.
414 for (i = 3; i < NN; i++) {
415 VG_(OSetWord_Insert)(oset, vs[i]);
418 // Print the list
419 OSet_Print(oset, "oset1b", wordToStr);
421 // Destroy the OSet
422 VG_(OSetWord_Destroy)(oset);
426 //---------------------------------------------------------------------------
427 // Struct example
428 //---------------------------------------------------------------------------
430 // This element shows that a key can be in the middle of the element, and
431 // be of arbitrary size and even span multiple (contiguous) fields. It
432 // also demonstrates how an OSet can be used to implement a list of
433 // non-overlapping intervals.
435 typedef struct {
436 Int b1;
437 RegWord first;
438 RegWord last;
439 Int b2;
441 Block;
443 __attribute__((unused))
444 static HChar *blockToStr(void *p)
446 static HChar buf[32];
447 Block* b = (Block*)p;
448 sprintf(buf, "<(%d) %" FMT_REGWORD "u..%" FMT_REGWORD "u (%d)>",
449 b->b1, b->first, b->last, b->b2);
450 return buf;
453 static Word blockCmp(const void* vkey, const void* velem)
455 RegWord key = *(const RegWord*)vkey;
456 const Block* elem = (const Block*)velem;
458 assert(elem->first <= elem->last);
459 if (key < elem->first) return -1;
460 if (key > elem->last) return 1;
461 return 0;
464 void example2(void)
466 Int i, n;
467 RegWord a;
468 Block* vs[NN];
469 Block v, prev;
470 Block *pv;
472 // Create a dynamic OSet of Blocks. This one uses slow (custom)
473 // comparisons.
474 OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
475 blockCmp,
476 allocate_node, "oset_test.3", free_node);
478 // Try some operations on an empty OSet to ensure they don't screw up.
479 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
480 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
481 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
482 vg_assert( ! VG_(OSetGen_Next)(oset) );
483 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
485 // Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
486 // no dups, and shuffle them randomly.
487 for (i = 0; i < NN; i++) {
488 vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Block));
489 vs[i]->b1 = i;
490 vs[i]->first = i*10 + 1;
491 vs[i]->last = vs[i]->first + 2;
492 vs[i]->b2 = i+1;
494 seed = 0;
495 for (i = 0; i < NN; i++) {
496 Int r1 = myrandom() % NN;
497 Int r2 = myrandom() % NN;
498 Block* tmp = vs[r1];
499 vs[r1] = vs[r2];
500 vs[r2] = tmp;
503 // Insert the elements
504 for (i = 0; i < NN; i++) {
505 VG_(OSetGen_Insert)(oset, vs[i]);
508 // Check the size
509 vg_assert( NN == VG_(OSetGen_Size)(oset) );
511 // Check we can find all the elements we inserted, within the full range
512 // of each Block.
513 for (i = 0; i < NN; i++) {
514 a = vs[i]->first + 0; assert( VG_(OSetGen_Contains)(oset, &a) );
515 a = vs[i]->first + 1; assert( VG_(OSetGen_Contains)(oset, &a) );
516 a = vs[i]->first + 2; assert( VG_(OSetGen_Contains)(oset, &a) );
519 // Check we cannot find elements we did not insert, below and above the
520 // ranges of the inserted elements.
521 a = 0;
522 assert( ! VG_(OSetGen_Contains)(oset, &a) );
523 for (i = 0; i < NN; i++) {
524 a = vs[i]->first - 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
525 a = vs[i]->first + 3; assert( ! VG_(OSetGen_Contains)(oset, &a) );
528 // Check we can find all the elements we inserted, and the right values
529 // are returned.
530 for (i = 0; i < NN; i++) {
531 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
532 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
533 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
534 assert( vs[i] == VG_(OSetGen_LookupWithCmp)(oset, &a, blockCmp) );
537 // Check that we can iterate over the OSet elements in sorted order, and
538 // there is the right number of them.
539 n = 0;
540 pv = NULL;
541 prev.last = 0;
542 VG_(OSetGen_ResetIter)(oset);
543 while ( (pv = VG_(OSetGen_Next)(oset)) ) {
544 Block curr = *pv;
545 assert(prev.last < curr.first);
546 prev = curr;
547 n++;
549 assert(NN == n);
550 vg_assert( ! VG_(OSetGen_Next)(oset) );
551 vg_assert( ! VG_(OSetGen_Next)(oset) );
553 // Check that we can remove half of the elements, and that their values
554 // are as expected.
555 for (i = 0; i < NN; i += 2) {
556 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
559 // Check the size
560 vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
562 // Check we can find the remaining elements (with the right values).
563 for (i = 1; i < NN; i += 2) {
564 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
565 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
566 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
569 // Check we cannot find any of the elements we removed.
570 for (i = 0; i < NN; i += 2) {
571 a = vs[i]->first + 0; assert( ! VG_(OSetGen_Contains)(oset, &a) );
572 a = vs[i]->first + 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
573 a = vs[i]->first + 2; assert( ! VG_(OSetGen_Contains)(oset, &a) );
576 // Check that we can remove the remaining half of the elements, and that
577 // their values are as expected.
578 for (i = 1; i < NN; i += 2) {
579 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
582 // Try some more operations on the empty OSet to ensure they don't screw up.
583 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
584 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
585 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
586 vg_assert( ! VG_(OSetGen_Next)(oset) );
587 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
589 // Re-insert all elements, to give OSetGen_Destroy something to work with.
590 for (i = 0; i < NN; i++) {
591 VG_(OSetGen_Insert)(oset, vs[i]);
594 // Destroy the OSet
595 VG_(OSetGen_Destroy)(oset);
598 //-----------------------------------------------------------------------
599 // main()
600 //-----------------------------------------------------------------------
602 int main(void)
604 example1();
605 example1b();
606 example2();
607 return 0;