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.
96 vg_assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
97 vg_assert( ! VG_(OSetGen_Lookup
)(oset
, &v
) );
98 vg_assert( ! VG_(OSetGen_Remove
)(oset
, &v
) );
99 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
100 vg_assert( 0 == VG_(OSetGen_Size
)(oset
) );
102 // Create some elements, with gaps (they're all even) but no dups,
103 // and shuffle them randomly.
104 for (i
= 0; i
< NN
; i
++) {
105 vs
[i
] = VG_(OSetGen_AllocNode
)(oset
, sizeof(Word
));
107 sorted_elts
[i
] = *(vs
[i
]);
110 for (i
= 0; i
< NN
; i
++) {
111 UWord r1
= myrandom() % NN
;
112 UWord r2
= myrandom() % NN
;
118 // Insert the elements
119 for (i
= 0; i
< NN
; i
++) {
120 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
124 vg_assert( NN
== VG_(OSetGen_Size
)(oset
) );
126 // Check we can find all the elements we inserted
127 for (i
= 0; i
< NN
; i
++) {
128 assert( VG_(OSetGen_Contains
)(oset
, vs
[i
]) );
131 #define FULLCHECKEVERY 20
132 // Check VG_(OSetGen_ResetIterAt) works before, at, and after each element.
133 // For some elements, we check all the successive elements.
134 for (i
= 0; i
< NN
; i
++) {
139 // check ResetIterAt just before an elt gives this elt.
140 k
= sorted_elts
[i
] - 1;
141 VG_(OSetGen_ResetIterAt
) (oset
, &k
);
142 // Check all elts till the end
143 for (j
= i
; j
< NN
; j
++) {
144 pval
= VG_(OSetGen_Next
)(oset
);
145 assert (*pval
== sorted_elts
[j
]);
146 if (i
% FULLCHECKEVERY
!= 0) break;
149 // check ResetIterAt at an elt gives this elt.
151 VG_(OSetGen_ResetIterAt
) (oset
, &k
);
152 // Check all elts till the end
153 for (j
= i
; j
< NN
; j
++) {
154 pval
= VG_(OSetGen_Next
)(oset
);
155 assert (*pval
== sorted_elts
[j
]);
156 if (i
% FULLCHECKEVERY
!= 0) break;
159 // check ResetIterAt after an elt gives the next elt or nothing
160 // when we reset after the last elt.
161 k
= sorted_elts
[i
] + 1;
162 VG_(OSetGen_ResetIterAt
) (oset
, &k
);
164 for (j
= i
+1; j
< NN
; j
++) {
165 pval
= VG_(OSetGen_Next
)(oset
);
166 assert (*pval
== sorted_elts
[j
]);
167 if (i
% FULLCHECKEVERY
!= 0) break;
170 pval
= VG_(OSetGen_Next
)(oset
);
171 assert (pval
== NULL
);
176 // Check we cannot find elements we did not insert, below, within (odd
177 // numbers), and above the inserted elements.
179 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
180 for (i
= 0; i
< NN
; i
++) {
182 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
185 assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
187 // Check we can find all the elements we inserted, and the right values
189 for (i
= 0; i
< NN
; i
++) {
190 assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, vs
[i
]) );
193 // Check that we can iterate over the OSet elements in sorted order, and
194 // there is the right number of them.
198 VG_(OSetGen_ResetIter
)(oset
);
199 while ( (pv
= VG_(OSetGen_Next
)(oset
)) ) {
206 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
207 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
209 // Check that we can remove half of the elements, and that their values
211 for (i
= 0; i
< NN
; i
+= 2) {
212 pv
= VG_(OSetGen_Remove
)(oset
, vs
[i
]);
214 assert( pv
== vs
[i
] );
218 vg_assert( NN
/2 == VG_(OSetGen_Size
)(oset
) );
220 // Check we can find the remaining elements (with the right values).
221 for (i
= 1; i
< NN
; i
+= 2) {
222 pv
= VG_(OSetGen_LookupWithCmp
)(oset
, vs
[i
], NULL
);
224 assert( pv
== vs
[i
] );
227 // Check we cannot find any of the elements we removed.
228 for (i
= 0; i
< NN
; i
+= 2) {
229 assert( ! VG_(OSetGen_Contains
)(oset
, vs
[i
]) );
232 // Check that we can remove the remaining half of the elements, and that
233 // their values are as expected.
234 for (i
= 1; i
< NN
; i
+= 2) {
235 pv
= VG_(OSetGen_Remove
)(oset
, vs
[i
]);
237 assert( pv
== vs
[i
] );
240 // Try some more operations on the empty OSet to ensure they don't screw up.
241 vg_assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
242 vg_assert( ! VG_(OSetGen_Lookup
)(oset
, &v
) );
243 vg_assert( ! VG_(OSetGen_Remove
)(oset
, &v
) );
244 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
245 vg_assert( 0 == VG_(OSetGen_Size
)(oset
) );
247 // Free a few elements
248 VG_(OSetGen_FreeNode
)(oset
, vs
[0]);
249 VG_(OSetGen_FreeNode
)(oset
, vs
[1]);
250 VG_(OSetGen_FreeNode
)(oset
, vs
[2]);
252 // Re-insert remaining elements, to give OSetGen_Destroy something to
254 for (i
= 3; i
< NN
; i
++) {
255 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
259 OSet_Print(oset
, descr
, wordToStr
);
265 OSet
*oset
, *oset_empty_clone
;
267 // Create a static OSet of UWords. This one uses fast (built-in)
270 // First a single oset, no pool allocator.
271 oset
= VG_(OSetGen_Create
)(0,
273 allocate_node
, "oset_test.1", free_node
);
274 example1singleset(oset
, "single oset, no pool allocator");
277 VG_(OSetGen_Destroy
)(oset
);
279 // Then same, but with a group allocator
280 oset
= VG_(OSetGen_Create_With_Pool
)(0,
282 allocate_node
, "oset_test.1",
285 example1singleset(oset
, "single oset, pool allocator");
288 VG_(OSetGen_Destroy
)(oset
);
291 // Then two sets, sharing a group allocator.
292 oset
= VG_(OSetGen_Create_With_Pool
)
295 allocate_node
, "oset_test.1", free_node
,
297 oset_empty_clone
= VG_(OSetGen_EmptyClone
) (oset
);
298 example1singleset(oset
, "oset, shared pool");
299 example1singleset(oset_empty_clone
, "cloned oset, shared pool");
302 VG_(OSetGen_Destroy
)(oset_empty_clone
);
303 VG_(OSetGen_Destroy
)(oset
);
313 // Create a static OSet of UWords. This one uses fast (built-in)
315 OSet
* oset
= VG_(OSetWord_Create
)(allocate_node
, "oset_test.2", free_node
);
317 // Try some operations on an empty OSet to ensure they don't screw up.
318 vg_assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
319 vg_assert( ! VG_(OSetWord_Remove
)(oset
, v
) );
320 vg_assert( ! VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) );
321 vg_assert( 0 == VG_(OSetWord_Size
)(oset
) );
323 // Create some elements, with gaps (they're all even) but no dups,
324 // and shuffle them randomly.
325 for (i
= 0; i
< NN
; i
++) {
329 for (i
= 0; i
< NN
; i
++) {
330 UWord r1
= myrandom() % NN
;
331 UWord r2
= myrandom() % NN
;
337 // Insert the elements
338 for (i
= 0; i
< NN
; i
++) {
339 VG_(OSetWord_Insert
)(oset
, vs
[i
]);
343 vg_assert( NN
== VG_(OSetWord_Size
)(oset
) );
345 // Check we can find all the elements we inserted
346 for (i
= 0; i
< NN
; i
++) {
347 assert( VG_(OSetWord_Contains
)(oset
, vs
[i
]) );
350 // Check we cannot find elements we did not insert, below, within (odd
351 // numbers), and above the inserted elements.
353 assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
354 for (i
= 0; i
< NN
; i
++) {
356 assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
359 assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
361 // Check we can find all the elements we inserted.
362 for (i
= 0; i
< NN
; i
++) {
363 assert( VG_(OSetWord_Contains
)(oset
, vs
[i
]) );
366 // Check that we can iterate over the OSet elements in sorted order, and
367 // there is the right number of them.
370 VG_(OSetWord_ResetIter
)(oset
);
371 while ( VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) ) {
374 assert(prev
== curr
);
381 vg_assert( ! VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) );
382 vg_assert( ! VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) );
384 // Check that we can remove half of the elements.
385 for (i
= 0; i
< NN
; i
+= 2) {
386 assert( VG_(OSetWord_Remove
)(oset
, vs
[i
]) );
390 vg_assert( NN
/2 == VG_(OSetWord_Size
)(oset
) );
392 // Check we can find the remaining elements (with the right values).
393 for (i
= 1; i
< NN
; i
+= 2) {
394 assert( VG_(OSetWord_Contains
)(oset
, vs
[i
]) );
397 // Check we cannot find any of the elements we removed.
398 for (i
= 0; i
< NN
; i
+= 2) {
399 assert( ! VG_(OSetWord_Contains
)(oset
, vs
[i
]) );
402 // Check that we can remove the remaining half of the elements.
403 for (i
= 1; i
< NN
; i
+= 2) {
404 assert( VG_(OSetWord_Remove
)(oset
, vs
[i
]) );
407 // Try some more operations on the empty OSet to ensure they don't screw up.
408 vg_assert( ! VG_(OSetWord_Contains
)(oset
, v
) );
409 vg_assert( ! VG_(OSetWord_Remove
)(oset
, v
) );
410 vg_assert( ! VG_(OSetWord_Next
)(oset
, (UWord
*)&v
) );
411 vg_assert( 0 == VG_(OSetWord_Size
)(oset
) );
413 // Re-insert remaining elements, to give OSetWord_Destroy something to
415 for (i
= 3; i
< NN
; i
++) {
416 VG_(OSetWord_Insert
)(oset
, vs
[i
]);
420 OSet_Print(oset
, "oset1b", wordToStr
);
423 VG_(OSetWord_Destroy
)(oset
);
427 //---------------------------------------------------------------------------
429 //---------------------------------------------------------------------------
431 // This element shows that a key can be in the middle of the element, and
432 // be of arbitrary size and even span multiple (contiguous) fields. It
433 // also demonstrates how an OSet can be used to implement a list of
434 // non-overlapping intervals.
444 __attribute__((unused
))
445 static HChar
*blockToStr(void *p
)
447 static HChar buf
[32];
448 Block
* b
= (Block
*)p
;
449 sprintf(buf
, "<(%d) %" FMT_REGWORD
"u..%" FMT_REGWORD
"u (%d)>",
450 b
->b1
, b
->first
, b
->last
, b
->b2
);
454 static Word
blockCmp(const void* vkey
, const void* velem
)
456 RegWord key
= *(const RegWord
*)vkey
;
457 const Block
* elem
= (const Block
*)velem
;
459 assert(elem
->first
<= elem
->last
);
460 if (key
< elem
->first
) return -1;
461 if (key
> elem
->last
) return 1;
473 // Create a dynamic OSet of Blocks. This one uses slow (custom)
475 OSet
* oset
= VG_(OSetGen_Create
)(offsetof(Block
, first
),
477 allocate_node
, "oset_test.3", free_node
);
479 // Try some operations on an empty OSet to ensure they don't screw up.
480 vg_assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
481 vg_assert( ! VG_(OSetGen_Lookup
)(oset
, &v
) );
482 vg_assert( ! VG_(OSetGen_Remove
)(oset
, &v
) );
483 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
484 vg_assert( 0 == VG_(OSetGen_Size
)(oset
) );
486 // Create some inputs, with gaps -- intervals are 1..3, 11..13, ... -- but
487 // no dups, and shuffle them randomly.
488 for (i
= 0; i
< NN
; i
++) {
489 vs
[i
] = VG_(OSetGen_AllocNode
)(oset
, sizeof(Block
));
491 vs
[i
]->first
= i
*10 + 1;
492 vs
[i
]->last
= vs
[i
]->first
+ 2;
496 for (i
= 0; i
< NN
; i
++) {
497 Int r1
= myrandom() % NN
;
498 Int r2
= myrandom() % NN
;
504 // Insert the elements
505 for (i
= 0; i
< NN
; i
++) {
506 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
510 vg_assert( NN
== VG_(OSetGen_Size
)(oset
) );
512 // Check we can find all the elements we inserted, within the full range
514 for (i
= 0; i
< NN
; i
++) {
515 a
= vs
[i
]->first
+ 0; assert( VG_(OSetGen_Contains
)(oset
, &a
) );
516 a
= vs
[i
]->first
+ 1; assert( VG_(OSetGen_Contains
)(oset
, &a
) );
517 a
= vs
[i
]->first
+ 2; assert( VG_(OSetGen_Contains
)(oset
, &a
) );
520 // Check we cannot find elements we did not insert, below and above the
521 // ranges of the inserted elements.
523 assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
524 for (i
= 0; i
< NN
; i
++) {
525 a
= vs
[i
]->first
- 1; assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
526 a
= vs
[i
]->first
+ 3; assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
529 // Check we can find all the elements we inserted, and the right values
531 for (i
= 0; i
< NN
; i
++) {
532 a
= vs
[i
]->first
+ 0; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
533 a
= vs
[i
]->first
+ 1; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
534 a
= vs
[i
]->first
+ 2; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
535 assert( vs
[i
] == VG_(OSetGen_LookupWithCmp
)(oset
, &a
, blockCmp
) );
538 // Check that we can iterate over the OSet elements in sorted order, and
539 // there is the right number of them.
543 VG_(OSetGen_ResetIter
)(oset
);
544 while ( (pv
= VG_(OSetGen_Next
)(oset
)) ) {
546 assert(prev
.last
< curr
.first
);
551 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
552 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
554 // Check that we can remove half of the elements, and that their values
556 for (i
= 0; i
< NN
; i
+= 2) {
557 a
= vs
[i
]->first
; assert( vs
[i
] == VG_(OSetGen_Remove
)(oset
, &a
) );
561 vg_assert( NN
/2 == VG_(OSetGen_Size
)(oset
) );
563 // Check we can find the remaining elements (with the right values).
564 for (i
= 1; i
< NN
; i
+= 2) {
565 a
= vs
[i
]->first
+ 0; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
566 a
= vs
[i
]->first
+ 1; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
567 a
= vs
[i
]->first
+ 2; assert( vs
[i
] == VG_(OSetGen_Lookup
)(oset
, &a
) );
570 // Check we cannot find any of the elements we removed.
571 for (i
= 0; i
< NN
; i
+= 2) {
572 a
= vs
[i
]->first
+ 0; assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
573 a
= vs
[i
]->first
+ 1; assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
574 a
= vs
[i
]->first
+ 2; assert( ! VG_(OSetGen_Contains
)(oset
, &a
) );
577 // Check that we can remove the remaining half of the elements, and that
578 // their values are as expected.
579 for (i
= 1; i
< NN
; i
+= 2) {
580 a
= vs
[i
]->first
; assert( vs
[i
] == VG_(OSetGen_Remove
)(oset
, &a
) );
583 // Try some more operations on the empty OSet to ensure they don't screw up.
584 vg_assert( ! VG_(OSetGen_Contains
)(oset
, &v
) );
585 vg_assert( ! VG_(OSetGen_Lookup
)(oset
, &v
) );
586 vg_assert( ! VG_(OSetGen_Remove
)(oset
, &v
) );
587 vg_assert( ! VG_(OSetGen_Next
)(oset
) );
588 vg_assert( 0 == VG_(OSetGen_Size
)(oset
) );
590 // Re-insert all elements, to give OSetGen_Destroy something to work with.
591 for (i
= 0; i
< NN
; i
++) {
592 VG_(OSetGen_Insert
)(oset
, vs
[i
]);
596 VG_(OSetGen_Destroy
)(oset
);
599 //-----------------------------------------------------------------------
601 //-----------------------------------------------------------------------