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
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.
23 #define vg_assert(e) assert(e)
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"
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
52 static UInt
myrandom( void )
54 seed
= (1103515245 * seed
+ 12345);
58 static void* allocate_node(const HChar
* cc
, SizeT szB
)
59 { return malloc(szB
); }
61 static void free_node(void* p
)
65 //---------------------------------------------------------------------------
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
)
76 sprintf(buf
, "%ld", *(Word
*)p
);
80 __attribute__((unused
))
81 static Word
wordCmp(void* vkey
, void* velem
)
83 return *(Word
*)vkey
- *(Word
*)velem
;
86 void example1singleset(OSet
* oset
, char *descr
)
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
));
106 sorted_elts
[i
] = *(vs
[i
]);
109 for (i
= 0; i
< NN
; i
++) {
110 UWord r1
= myrandom() % NN
;
111 UWord r2
= myrandom() % NN
;
117 // Insert the elements
118 for (i
= 0; i
< NN
; i
++) {
119 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
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
++) {
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.
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
);
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;
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.
178 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
179 for (i
= 0; i
< NN
; i
++) {
181 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
184 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
186 // Check we can find all the elements we inserted, and the right values
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.
197 VG_(OSetGen_ResetIter
)(oset
);
198 while ( (pv
= VG_(OSetGen_Next
)(oset
)) ) {
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
210 for (i
= 0; i
< NN
; i
+= 2) {
211 pv
= VG_(OSetGen_Remove
)(oset
, vs
[i
]);
213 assert( pv
== vs
[i
] );
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
);
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
]);
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
253 for (i
= 3; i
< NN
; i
++) {
254 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
258 OSet_Print(oset
, descr
, wordToStr
);
264 OSet
*oset
, *oset_empty_clone
;
266 // Create a static OSet of UWords. This one uses fast (built-in)
269 // First a single oset, no pool allocator.
270 oset
= VG_(OSetGen_Create
)(0,
272 allocate_node
, "oset_test.1", free_node
);
273 example1singleset(oset
, "single oset, no pool allocator");
276 VG_(OSetGen_Destroy
)(oset
);
278 // Then same, but with a group allocator
279 oset
= VG_(OSetGen_Create_With_Pool
)(0,
281 allocate_node
, "oset_test.1",
284 example1singleset(oset
, "single oset, pool allocator");
287 VG_(OSetGen_Destroy
)(oset
);
290 // Then two sets, sharing a group allocator.
291 oset
= VG_(OSetGen_Create_With_Pool
)
294 allocate_node
, "oset_test.1", free_node
,
296 oset_empty_clone
= VG_(OSetGen_EmptyClone
) (oset
);
297 example1singleset(oset
, "oset, shared pool");
298 example1singleset(oset_empty_clone
, "cloned oset, shared pool");
301 VG_(OSetGen_Destroy
)(oset_empty_clone
);
302 VG_(OSetGen_Destroy
)(oset
);
312 // Create a static OSet of UWords. This one uses fast (built-in)
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
++) {
328 for (i
= 0; i
< NN
; i
++) {
329 UWord r1
= myrandom() % NN
;
330 UWord r2
= myrandom() % NN
;
336 // Insert the elements
337 for (i
= 0; i
< NN
; i
++) {
338 VG_(OSetWord_Insert
)(oset
, vs
[i
]);
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.
352 assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
353 for (i
= 0; i
< NN
; i
++) {
355 assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
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.
369 VG_(OSetWord_ResetIter
)(oset
);
370 while ( VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) ) {
373 assert(prev
== curr
);
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
]) );
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
414 for (i
= 3; i
< NN
; i
++) {
415 VG_(OSetWord_Insert
)(oset
, vs
[i
]);
419 OSet_Print(oset
, "oset1b", wordToStr
);
422 VG_(OSetWord_Destroy
)(oset
);
426 //---------------------------------------------------------------------------
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.
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
);
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;
472 // Create a dynamic OSet of Blocks. This one uses slow (custom)
474 OSet
* oset
= VG_(OSetGen_Create
)(offsetof(Block
, first
),
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
));
490 vs
[i
]->first
= i
*10 + 1;
491 vs
[i
]->last
= vs
[i
]->first
+ 2;
495 for (i
= 0; i
< NN
; i
++) {
496 Int r1
= myrandom() % NN
;
497 Int r2
= myrandom() % NN
;
503 // Insert the elements
504 for (i
= 0; i
< NN
; i
++) {
505 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
509 vg_assert( NN
== VG_(OSetGen_Size
)(oset
) );
511 // Check we can find all the elements we inserted, within the full range
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.
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
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.
542 VG_(OSetGen_ResetIter
)(oset
);
543 while ( (pv
= VG_(OSetGen_Next
)(oset
)) ) {
545 assert(prev
.last
< curr
.first
);
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
555 for (i
= 0; i
< NN
; i
+= 2) {
556 a
= vs
[i
]->first
; assert( vs
[i
] == VG_(OSetGen_Remove
)(oset
, &a
) );
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
]);
595 VG_(OSetGen_Destroy
)(oset
);
598 //-----------------------------------------------------------------------
600 //-----------------------------------------------------------------------