memcheck/tests/unit_oset.c: Fix compiler warnings
[valgrind.git] / memcheck / tests / unit_oset.c
blobff93398ae89bfe75eae339b67e3958c7368ec868
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 Addr first;
438 Addr 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) %lu..%lu (%d)>", b->b1, b->first, b->last, b->b2);
449 return buf;
452 static Word blockCmp(const void* vkey, const void* velem)
454 Addr key = *(const Addr*)vkey;
455 const Block* elem = (const Block*)velem;
457 assert(elem->first <= elem->last);
458 if (key < elem->first) return -1;
459 if (key > elem->last) return 1;
460 return 0;
463 void example2(void)
465 Int i, n;
466 Addr a;
467 Block* vs[NN];
468 Block v, prev;
469 Block *pv;
471 // Create a dynamic OSet of Blocks. This one uses slow (custom)
472 // comparisons.
473 OSet* oset = VG_(OSetGen_Create)(offsetof(Block, first),
474 blockCmp,
475 allocate_node, "oset_test.3", free_node);
477 // Try some operations on an empty OSet to ensure they don't screw up.
478 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
479 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
480 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
481 vg_assert( ! VG_(OSetGen_Next)(oset) );
482 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
484 // Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
485 // no dups, and shuffle them randomly.
486 for (i = 0; i < NN; i++) {
487 vs[i] = VG_(OSetGen_AllocNode)(oset, sizeof(Block));
488 vs[i]->b1 = i;
489 vs[i]->first = i*10 + 1;
490 vs[i]->last = vs[i]->first + 2;
491 vs[i]->b2 = i+1;
493 seed = 0;
494 for (i = 0; i < NN; i++) {
495 Int r1 = myrandom() % NN;
496 Int r2 = myrandom() % NN;
497 Block* tmp = vs[r1];
498 vs[r1] = vs[r2];
499 vs[r2] = tmp;
502 // Insert the elements
503 for (i = 0; i < NN; i++) {
504 VG_(OSetGen_Insert)(oset, vs[i]);
507 // Check the size
508 vg_assert( NN == VG_(OSetGen_Size)(oset) );
510 // Check we can find all the elements we inserted, within the full range
511 // of each Block.
512 for (i = 0; i < NN; i++) {
513 a = vs[i]->first + 0; assert( VG_(OSetGen_Contains)(oset, &a) );
514 a = vs[i]->first + 1; assert( VG_(OSetGen_Contains)(oset, &a) );
515 a = vs[i]->first + 2; assert( VG_(OSetGen_Contains)(oset, &a) );
518 // Check we cannot find elements we did not insert, below and above the
519 // ranges of the inserted elements.
520 a = 0;
521 assert( ! VG_(OSetGen_Contains)(oset, &a) );
522 for (i = 0; i < NN; i++) {
523 a = vs[i]->first - 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
524 a = vs[i]->first + 3; assert( ! VG_(OSetGen_Contains)(oset, &a) );
527 // Check we can find all the elements we inserted, and the right values
528 // are returned.
529 for (i = 0; i < NN; i++) {
530 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
531 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
532 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
533 assert( vs[i] == VG_(OSetGen_LookupWithCmp)(oset, &a, blockCmp) );
536 // Check that we can iterate over the OSet elements in sorted order, and
537 // there is the right number of them.
538 n = 0;
539 pv = NULL;
540 prev.last = 0;
541 VG_(OSetGen_ResetIter)(oset);
542 while ( (pv = VG_(OSetGen_Next)(oset)) ) {
543 Block curr = *pv;
544 assert(prev.last < curr.first);
545 prev = curr;
546 n++;
548 assert(NN == n);
549 vg_assert( ! VG_(OSetGen_Next)(oset) );
550 vg_assert( ! VG_(OSetGen_Next)(oset) );
552 // Check that we can remove half of the elements, and that their values
553 // are as expected.
554 for (i = 0; i < NN; i += 2) {
555 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
558 // Check the size
559 vg_assert( NN/2 == VG_(OSetGen_Size)(oset) );
561 // Check we can find the remaining elements (with the right values).
562 for (i = 1; i < NN; i += 2) {
563 a = vs[i]->first + 0; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
564 a = vs[i]->first + 1; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
565 a = vs[i]->first + 2; assert( vs[i] == VG_(OSetGen_Lookup)(oset, &a) );
568 // Check we cannot find any of the elements we removed.
569 for (i = 0; i < NN; i += 2) {
570 a = vs[i]->first + 0; assert( ! VG_(OSetGen_Contains)(oset, &a) );
571 a = vs[i]->first + 1; assert( ! VG_(OSetGen_Contains)(oset, &a) );
572 a = vs[i]->first + 2; assert( ! VG_(OSetGen_Contains)(oset, &a) );
575 // Check that we can remove the remaining half of the elements, and that
576 // their values are as expected.
577 for (i = 1; i < NN; i += 2) {
578 a = vs[i]->first; assert( vs[i] == VG_(OSetGen_Remove)(oset, &a) );
581 // Try some more operations on the empty OSet to ensure they don't screw up.
582 vg_assert( ! VG_(OSetGen_Contains)(oset, &v) );
583 vg_assert( ! VG_(OSetGen_Lookup)(oset, &v) );
584 vg_assert( ! VG_(OSetGen_Remove)(oset, &v) );
585 vg_assert( ! VG_(OSetGen_Next)(oset) );
586 vg_assert( 0 == VG_(OSetGen_Size)(oset) );
588 // Re-insert all elements, to give OSetGen_Destroy something to work with.
589 for (i = 0; i < NN; i++) {
590 VG_(OSetGen_Insert)(oset, vs[i]);
593 // Destroy the OSet
594 VG_(OSetGen_Destroy)(oset);
597 //-----------------------------------------------------------------------
598 // main()
599 //-----------------------------------------------------------------------
601 int main(void)
603 example1();
604 example1b();
605 example2();
606 return 0;