2 * Hierarchical bitmap unit-tests.
4 * Copyright (C) 2012 Red Hat Inc.
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
12 #include "qemu/osdep.h"
13 #include "qemu/hbitmap.h"
14 #include "qemu/bitmap.h"
15 #include "block/block.h"
17 #define LOG_BITS_PER_LONG (BITS_PER_LONG == 32 ? 5 : 6)
19 #define L1 BITS_PER_LONG
20 #define L2 (BITS_PER_LONG * L1)
21 #define L3 (BITS_PER_LONG * L2)
23 typedef struct TestHBitmapData
{
33 static int64_t check_hbitmap_iter_next(HBitmapIter
*hbi
)
37 next0
= hbitmap_iter_next(hbi
, false);
38 next1
= hbitmap_iter_next(hbi
, true);
40 g_assert_cmpint(next0
, ==, next1
);
45 /* Check that the HBitmap and the shadow bitmap contain the same data,
46 * ignoring the same "first" bits.
48 static void hbitmap_test_check(TestHBitmapData
*data
,
57 hbitmap_iter_init(&hbi
, data
->hb
, first
);
61 next
= check_hbitmap_iter_next(&hbi
);
67 pos
= i
>> LOG_BITS_PER_LONG
;
68 bit
= i
& (BITS_PER_LONG
- 1);
70 g_assert_cmpint(data
->bits
[pos
] & (1UL << bit
), ==, 0);
73 if (next
== data
->size
) {
77 pos
= i
>> LOG_BITS_PER_LONG
;
78 bit
= i
& (BITS_PER_LONG
- 1);
81 g_assert_cmpint(data
->bits
[pos
] & (1UL << bit
), !=, 0);
85 g_assert_cmpint(count
<< data
->granularity
, ==, hbitmap_count(data
->hb
));
89 /* This is provided instead of a test setup function so that the sizes
90 are kept in the test functions (and not in main()) */
91 static void hbitmap_test_init(TestHBitmapData
*data
,
92 uint64_t size
, int granularity
)
95 data
->hb
= hbitmap_alloc(size
, granularity
);
97 n
= DIV_ROUND_UP(size
, BITS_PER_LONG
);
101 data
->bits
= g_new0(unsigned long, n
);
103 data
->granularity
= granularity
;
105 hbitmap_test_check(data
, 0);
109 static void hbitmap_test_init_meta(TestHBitmapData
*data
,
110 uint64_t size
, int granularity
,
113 hbitmap_test_init(data
, size
, granularity
);
114 data
->meta
= hbitmap_create_meta(data
->hb
, meta_chunk
);
117 static inline size_t hbitmap_test_array_size(size_t bits
)
119 size_t n
= DIV_ROUND_UP(bits
, BITS_PER_LONG
);
123 static void hbitmap_test_truncate_impl(TestHBitmapData
*data
,
128 data
->old_size
= data
->size
;
131 if (data
->size
== data
->old_size
) {
135 n
= hbitmap_test_array_size(size
);
136 m
= hbitmap_test_array_size(data
->old_size
);
137 data
->bits
= g_realloc(data
->bits
, sizeof(unsigned long) * n
);
139 memset(&data
->bits
[m
], 0x00, sizeof(unsigned long) * (n
- m
));
142 /* If we shrink to an uneven multiple of sizeof(unsigned long),
143 * scrub the leftover memory. */
144 if (data
->size
< data
->old_size
) {
145 m
= size
% (sizeof(unsigned long) * 8);
147 unsigned long mask
= (1ULL << m
) - 1;
148 data
->bits
[n
-1] &= mask
;
152 hbitmap_truncate(data
->hb
, size
);
155 static void hbitmap_test_teardown(TestHBitmapData
*data
,
160 hbitmap_free_meta(data
->hb
);
162 hbitmap_free(data
->hb
);
169 /* Set a range in the HBitmap and in the shadow "simple" bitmap.
170 * The two bitmaps are then tested against each other.
172 static void hbitmap_test_set(TestHBitmapData
*data
,
173 uint64_t first
, uint64_t count
)
175 hbitmap_set(data
->hb
, first
, count
);
176 while (count
-- != 0) {
177 size_t pos
= first
>> LOG_BITS_PER_LONG
;
178 int bit
= first
& (BITS_PER_LONG
- 1);
181 data
->bits
[pos
] |= 1UL << bit
;
184 if (data
->granularity
== 0) {
185 hbitmap_test_check(data
, 0);
189 /* Reset a range in the HBitmap and in the shadow "simple" bitmap.
191 static void hbitmap_test_reset(TestHBitmapData
*data
,
192 uint64_t first
, uint64_t count
)
194 hbitmap_reset(data
->hb
, first
, count
);
195 while (count
-- != 0) {
196 size_t pos
= first
>> LOG_BITS_PER_LONG
;
197 int bit
= first
& (BITS_PER_LONG
- 1);
200 data
->bits
[pos
] &= ~(1UL << bit
);
203 if (data
->granularity
== 0) {
204 hbitmap_test_check(data
, 0);
208 static void hbitmap_test_reset_all(TestHBitmapData
*data
)
212 hbitmap_reset_all(data
->hb
);
214 n
= DIV_ROUND_UP(data
->size
, BITS_PER_LONG
);
218 memset(data
->bits
, 0, n
* sizeof(unsigned long));
220 if (data
->granularity
== 0) {
221 hbitmap_test_check(data
, 0);
225 static void hbitmap_test_check_get(TestHBitmapData
*data
)
230 for (i
= 0; i
< data
->size
; i
++) {
231 size_t pos
= i
>> LOG_BITS_PER_LONG
;
232 int bit
= i
& (BITS_PER_LONG
- 1);
233 unsigned long val
= data
->bits
[pos
] & (1UL << bit
);
234 count
+= hbitmap_get(data
->hb
, i
);
235 g_assert_cmpint(hbitmap_get(data
->hb
, i
), ==, val
!= 0);
237 g_assert_cmpint(count
, ==, hbitmap_count(data
->hb
));
240 static void test_hbitmap_zero(TestHBitmapData
*data
,
243 hbitmap_test_init(data
, 0, 0);
246 static void test_hbitmap_unaligned(TestHBitmapData
*data
,
249 hbitmap_test_init(data
, L3
+ 23, 0);
250 hbitmap_test_set(data
, 0, 1);
251 hbitmap_test_set(data
, L3
+ 22, 1);
254 static void test_hbitmap_iter_empty(TestHBitmapData
*data
,
257 hbitmap_test_init(data
, L1
, 0);
260 static void test_hbitmap_iter_partial(TestHBitmapData
*data
,
263 hbitmap_test_init(data
, L3
, 0);
264 hbitmap_test_set(data
, 0, L3
);
265 hbitmap_test_check(data
, 1);
266 hbitmap_test_check(data
, L1
- 1);
267 hbitmap_test_check(data
, L1
);
268 hbitmap_test_check(data
, L1
* 2 - 1);
269 hbitmap_test_check(data
, L2
- 1);
270 hbitmap_test_check(data
, L2
);
271 hbitmap_test_check(data
, L2
+ 1);
272 hbitmap_test_check(data
, L2
+ L1
);
273 hbitmap_test_check(data
, L2
+ L1
* 2 - 1);
274 hbitmap_test_check(data
, L2
* 2 - 1);
275 hbitmap_test_check(data
, L2
* 2);
276 hbitmap_test_check(data
, L2
* 2 + 1);
277 hbitmap_test_check(data
, L2
* 2 + L1
);
278 hbitmap_test_check(data
, L2
* 2 + L1
* 2 - 1);
279 hbitmap_test_check(data
, L3
/ 2);
282 static void test_hbitmap_set_all(TestHBitmapData
*data
,
285 hbitmap_test_init(data
, L3
, 0);
286 hbitmap_test_set(data
, 0, L3
);
289 static void test_hbitmap_get_all(TestHBitmapData
*data
,
292 hbitmap_test_init(data
, L3
, 0);
293 hbitmap_test_set(data
, 0, L3
);
294 hbitmap_test_check_get(data
);
297 static void test_hbitmap_get_some(TestHBitmapData
*data
,
300 hbitmap_test_init(data
, 2 * L2
, 0);
301 hbitmap_test_set(data
, 10, 1);
302 hbitmap_test_check_get(data
);
303 hbitmap_test_set(data
, L1
- 1, 1);
304 hbitmap_test_check_get(data
);
305 hbitmap_test_set(data
, L1
, 1);
306 hbitmap_test_check_get(data
);
307 hbitmap_test_set(data
, L2
- 1, 1);
308 hbitmap_test_check_get(data
);
309 hbitmap_test_set(data
, L2
, 1);
310 hbitmap_test_check_get(data
);
313 static void test_hbitmap_set_one(TestHBitmapData
*data
,
316 hbitmap_test_init(data
, 2 * L2
, 0);
317 hbitmap_test_set(data
, 10, 1);
318 hbitmap_test_set(data
, L1
- 1, 1);
319 hbitmap_test_set(data
, L1
, 1);
320 hbitmap_test_set(data
, L2
- 1, 1);
321 hbitmap_test_set(data
, L2
, 1);
324 static void test_hbitmap_set_two_elem(TestHBitmapData
*data
,
327 hbitmap_test_init(data
, 2 * L2
, 0);
328 hbitmap_test_set(data
, L1
- 1, 2);
329 hbitmap_test_set(data
, L1
* 2 - 1, 4);
330 hbitmap_test_set(data
, L1
* 4, L1
+ 1);
331 hbitmap_test_set(data
, L1
* 8 - 1, L1
+ 1);
332 hbitmap_test_set(data
, L2
- 1, 2);
333 hbitmap_test_set(data
, L2
+ L1
- 1, 8);
334 hbitmap_test_set(data
, L2
+ L1
* 4, L1
+ 1);
335 hbitmap_test_set(data
, L2
+ L1
* 8 - 1, L1
+ 1);
338 static void test_hbitmap_set(TestHBitmapData
*data
,
341 hbitmap_test_init(data
, L3
* 2, 0);
342 hbitmap_test_set(data
, L1
- 1, L1
+ 2);
343 hbitmap_test_set(data
, L1
* 3 - 1, L1
+ 2);
344 hbitmap_test_set(data
, L1
* 5, L1
* 2 + 1);
345 hbitmap_test_set(data
, L1
* 8 - 1, L1
* 2 + 1);
346 hbitmap_test_set(data
, L2
- 1, L1
+ 2);
347 hbitmap_test_set(data
, L2
+ L1
* 2 - 1, L1
+ 2);
348 hbitmap_test_set(data
, L2
+ L1
* 4, L1
* 2 + 1);
349 hbitmap_test_set(data
, L2
+ L1
* 7 - 1, L1
* 2 + 1);
350 hbitmap_test_set(data
, L2
* 2 - 1, L3
* 2 - L2
* 2);
353 static void test_hbitmap_set_twice(TestHBitmapData
*data
,
356 hbitmap_test_init(data
, L1
* 3, 0);
357 hbitmap_test_set(data
, 0, L1
* 3);
358 hbitmap_test_set(data
, L1
, 1);
361 static void test_hbitmap_set_overlap(TestHBitmapData
*data
,
364 hbitmap_test_init(data
, L3
* 2, 0);
365 hbitmap_test_set(data
, L1
- 1, L1
+ 2);
366 hbitmap_test_set(data
, L1
* 2 - 1, L1
* 2 + 2);
367 hbitmap_test_set(data
, 0, L1
* 3);
368 hbitmap_test_set(data
, L1
* 8 - 1, L2
);
369 hbitmap_test_set(data
, L2
, L1
);
370 hbitmap_test_set(data
, L2
- L1
- 1, L1
* 8 + 2);
371 hbitmap_test_set(data
, L2
, L3
- L2
+ 1);
372 hbitmap_test_set(data
, L3
- L1
, L1
* 3);
373 hbitmap_test_set(data
, L3
- 1, 3);
374 hbitmap_test_set(data
, L3
- 1, L2
);
377 static void test_hbitmap_reset_empty(TestHBitmapData
*data
,
380 hbitmap_test_init(data
, L3
, 0);
381 hbitmap_test_reset(data
, 0, L3
);
384 static void test_hbitmap_reset(TestHBitmapData
*data
,
387 hbitmap_test_init(data
, L3
* 2, 0);
388 hbitmap_test_set(data
, L1
- 1, L1
+ 2);
389 hbitmap_test_reset(data
, L1
* 2 - 1, L1
* 2 + 2);
390 hbitmap_test_set(data
, 0, L1
* 3);
391 hbitmap_test_reset(data
, L1
* 8 - 1, L2
);
392 hbitmap_test_set(data
, L2
, L1
);
393 hbitmap_test_reset(data
, L2
- L1
- 1, L1
* 8 + 2);
394 hbitmap_test_set(data
, L2
, L3
- L2
+ 1);
395 hbitmap_test_reset(data
, L3
- L1
, L1
* 3);
396 hbitmap_test_set(data
, L3
- 1, 3);
397 hbitmap_test_reset(data
, L3
- 1, L2
);
398 hbitmap_test_set(data
, 0, L3
* 2);
399 hbitmap_test_reset(data
, 0, L1
);
400 hbitmap_test_reset(data
, 0, L2
);
401 hbitmap_test_reset(data
, L3
, L3
);
402 hbitmap_test_set(data
, L3
/ 2, L3
);
405 static void test_hbitmap_reset_all(TestHBitmapData
*data
,
408 hbitmap_test_init(data
, L3
* 2, 0);
409 hbitmap_test_set(data
, L1
- 1, L1
+ 2);
410 hbitmap_test_reset_all(data
);
411 hbitmap_test_set(data
, 0, L1
* 3);
412 hbitmap_test_reset_all(data
);
413 hbitmap_test_set(data
, L2
, L1
);
414 hbitmap_test_reset_all(data
);
415 hbitmap_test_set(data
, L2
, L3
- L2
+ 1);
416 hbitmap_test_reset_all(data
);
417 hbitmap_test_set(data
, L3
- 1, 3);
418 hbitmap_test_reset_all(data
);
419 hbitmap_test_set(data
, 0, L3
* 2);
420 hbitmap_test_reset_all(data
);
421 hbitmap_test_set(data
, L3
/ 2, L3
);
422 hbitmap_test_reset_all(data
);
425 static void test_hbitmap_granularity(TestHBitmapData
*data
,
428 /* Note that hbitmap_test_check has to be invoked manually in this test. */
429 hbitmap_test_init(data
, L1
, 1);
430 hbitmap_test_set(data
, 0, 1);
431 g_assert_cmpint(hbitmap_count(data
->hb
), ==, 2);
432 hbitmap_test_check(data
, 0);
433 hbitmap_test_set(data
, 2, 1);
434 g_assert_cmpint(hbitmap_count(data
->hb
), ==, 4);
435 hbitmap_test_check(data
, 0);
436 hbitmap_test_set(data
, 0, 3);
437 g_assert_cmpint(hbitmap_count(data
->hb
), ==, 4);
438 hbitmap_test_reset(data
, 0, 1);
439 g_assert_cmpint(hbitmap_count(data
->hb
), ==, 2);
442 static void test_hbitmap_iter_granularity(TestHBitmapData
*data
,
447 /* Note that hbitmap_test_check has to be invoked manually in this test. */
448 hbitmap_test_init(data
, 131072 << 7, 7);
449 hbitmap_iter_init(&hbi
, data
->hb
, 0);
450 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), <, 0);
452 hbitmap_test_set(data
, ((L2
+ L1
+ 1) << 7) + 8, 8);
453 hbitmap_iter_init(&hbi
, data
->hb
, 0);
454 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), ==, (L2
+ L1
+ 1) << 7);
455 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), <, 0);
457 hbitmap_iter_init(&hbi
, data
->hb
, (L2
+ L1
+ 2) << 7);
458 g_assert_cmpint(hbitmap_iter_next(&hbi
, true), <, 0);
460 hbitmap_test_set(data
, (131072 << 7) - 8, 8);
461 hbitmap_iter_init(&hbi
, data
->hb
, 0);
462 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), ==, (L2
+ L1
+ 1) << 7);
463 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), ==, 131071 << 7);
464 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), <, 0);
466 hbitmap_iter_init(&hbi
, data
->hb
, (L2
+ L1
+ 2) << 7);
467 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), ==, 131071 << 7);
468 g_assert_cmpint(check_hbitmap_iter_next(&hbi
), <, 0);
471 static void hbitmap_test_set_boundary_bits(TestHBitmapData
*data
, ssize_t diff
)
473 size_t size
= data
->size
;
476 hbitmap_test_set(data
, 0, 1);
478 /* Last bit in new, shortened map */
479 hbitmap_test_set(data
, size
+ diff
- 1, 1);
481 /* First bit to be truncated away */
482 hbitmap_test_set(data
, size
+ diff
, 1);
485 hbitmap_test_set(data
, size
- 1, 1);
486 if (data
->granularity
== 0) {
487 hbitmap_test_check_get(data
);
491 static void hbitmap_test_check_boundary_bits(TestHBitmapData
*data
)
493 size_t size
= MIN(data
->size
, data
->old_size
);
495 if (data
->granularity
== 0) {
496 hbitmap_test_check_get(data
);
497 hbitmap_test_check(data
, 0);
499 /* If a granularity was set, note that every distinct
500 * (bit >> granularity) value that was set will increase
501 * the bit pop count by 2^granularity, not just 1.
503 * The hbitmap_test_check facility does not currently tolerate
504 * non-zero granularities, so test the boundaries and the population
507 g_assert(hbitmap_get(data
->hb
, 0));
508 g_assert(hbitmap_get(data
->hb
, size
- 1));
509 g_assert_cmpint(2 << data
->granularity
, ==, hbitmap_count(data
->hb
));
513 /* Generic truncate test. */
514 static void hbitmap_test_truncate(TestHBitmapData
*data
,
519 hbitmap_test_init(data
, size
, granularity
);
520 hbitmap_test_set_boundary_bits(data
, diff
);
521 hbitmap_test_truncate_impl(data
, size
+ diff
);
522 hbitmap_test_check_boundary_bits(data
);
525 static void test_hbitmap_truncate_nop(TestHBitmapData
*data
,
528 hbitmap_test_truncate(data
, L2
, 0, 0);
532 * Grow by an amount smaller than the granularity, without crossing
533 * a granularity alignment boundary. Effectively a NOP.
535 static void test_hbitmap_truncate_grow_negligible(TestHBitmapData
*data
,
538 size_t size
= L2
- 1;
542 hbitmap_test_truncate(data
, size
, diff
, granularity
);
546 * Shrink by an amount smaller than the granularity, without crossing
547 * a granularity alignment boundary. Effectively a NOP.
549 static void test_hbitmap_truncate_shrink_negligible(TestHBitmapData
*data
,
556 hbitmap_test_truncate(data
, size
, diff
, granularity
);
560 * Grow by an amount smaller than the granularity, but crossing over
561 * a granularity alignment boundary.
563 static void test_hbitmap_truncate_grow_tiny(TestHBitmapData
*data
,
566 size_t size
= L2
- 2;
570 hbitmap_test_truncate(data
, size
, diff
, granularity
);
574 * Shrink by an amount smaller than the granularity, but crossing over
575 * a granularity alignment boundary.
577 static void test_hbitmap_truncate_shrink_tiny(TestHBitmapData
*data
,
580 size_t size
= L2
- 1;
584 hbitmap_test_truncate(data
, size
, diff
, granularity
);
588 * Grow by an amount smaller than sizeof(long), and not crossing over
589 * a sizeof(long) alignment boundary.
591 static void test_hbitmap_truncate_grow_small(TestHBitmapData
*data
,
594 size_t size
= L2
+ 1;
595 size_t diff
= sizeof(long) / 2;
597 hbitmap_test_truncate(data
, size
, diff
, 0);
601 * Shrink by an amount smaller than sizeof(long), and not crossing over
602 * a sizeof(long) alignment boundary.
604 static void test_hbitmap_truncate_shrink_small(TestHBitmapData
*data
,
608 size_t diff
= sizeof(long) / 2;
610 hbitmap_test_truncate(data
, size
, -diff
, 0);
614 * Grow by an amount smaller than sizeof(long), while crossing over
615 * a sizeof(long) alignment boundary.
617 static void test_hbitmap_truncate_grow_medium(TestHBitmapData
*data
,
620 size_t size
= L2
- 1;
621 size_t diff
= sizeof(long) / 2;
623 hbitmap_test_truncate(data
, size
, diff
, 0);
627 * Shrink by an amount smaller than sizeof(long), while crossing over
628 * a sizeof(long) alignment boundary.
630 static void test_hbitmap_truncate_shrink_medium(TestHBitmapData
*data
,
633 size_t size
= L2
+ 1;
634 size_t diff
= sizeof(long) / 2;
636 hbitmap_test_truncate(data
, size
, -diff
, 0);
640 * Grow by an amount larger than sizeof(long).
642 static void test_hbitmap_truncate_grow_large(TestHBitmapData
*data
,
646 size_t diff
= 8 * sizeof(long);
648 hbitmap_test_truncate(data
, size
, diff
, 0);
652 * Shrink by an amount larger than sizeof(long).
654 static void test_hbitmap_truncate_shrink_large(TestHBitmapData
*data
,
658 size_t diff
= 8 * sizeof(long);
660 hbitmap_test_truncate(data
, size
, -diff
, 0);
663 static void hbitmap_check_meta(TestHBitmapData
*data
,
664 int64_t start
, int count
)
668 for (i
= 0; i
< data
->size
; i
++) {
669 if (i
>= start
&& i
< start
+ count
) {
670 g_assert(hbitmap_get(data
->meta
, i
));
672 g_assert(!hbitmap_get(data
->meta
, i
));
677 static void hbitmap_test_meta(TestHBitmapData
*data
,
678 int64_t start
, int count
,
679 int64_t check_start
, int check_count
)
681 hbitmap_reset_all(data
->hb
);
682 hbitmap_reset_all(data
->meta
);
684 /* Test "unset" -> "unset" will not update meta. */
685 hbitmap_reset(data
->hb
, start
, count
);
686 hbitmap_check_meta(data
, 0, 0);
688 /* Test "unset" -> "set" will update meta */
689 hbitmap_set(data
->hb
, start
, count
);
690 hbitmap_check_meta(data
, check_start
, check_count
);
692 /* Test "set" -> "set" will not update meta */
693 hbitmap_reset_all(data
->meta
);
694 hbitmap_set(data
->hb
, start
, count
);
695 hbitmap_check_meta(data
, 0, 0);
697 /* Test "set" -> "unset" will update meta */
698 hbitmap_reset_all(data
->meta
);
699 hbitmap_reset(data
->hb
, start
, count
);
700 hbitmap_check_meta(data
, check_start
, check_count
);
703 static void hbitmap_test_meta_do(TestHBitmapData
*data
, int chunk_size
)
705 uint64_t size
= chunk_size
* 100;
706 hbitmap_test_init_meta(data
, size
, 0, chunk_size
);
708 hbitmap_test_meta(data
, 0, 1, 0, chunk_size
);
709 hbitmap_test_meta(data
, 0, chunk_size
, 0, chunk_size
);
710 hbitmap_test_meta(data
, chunk_size
- 1, 1, 0, chunk_size
);
711 hbitmap_test_meta(data
, chunk_size
- 1, 2, 0, chunk_size
* 2);
712 hbitmap_test_meta(data
, chunk_size
- 1, chunk_size
+ 1, 0, chunk_size
* 2);
713 hbitmap_test_meta(data
, chunk_size
- 1, chunk_size
+ 2, 0, chunk_size
* 3);
714 hbitmap_test_meta(data
, 7 * chunk_size
- 1, chunk_size
+ 2,
715 6 * chunk_size
, chunk_size
* 3);
716 hbitmap_test_meta(data
, size
- 1, 1, size
- chunk_size
, chunk_size
);
717 hbitmap_test_meta(data
, 0, size
, 0, size
);
720 static void test_hbitmap_meta_byte(TestHBitmapData
*data
, const void *unused
)
722 hbitmap_test_meta_do(data
, BITS_PER_BYTE
);
725 static void test_hbitmap_meta_word(TestHBitmapData
*data
, const void *unused
)
727 hbitmap_test_meta_do(data
, BITS_PER_LONG
);
730 static void test_hbitmap_meta_sector(TestHBitmapData
*data
, const void *unused
)
732 hbitmap_test_meta_do(data
, BDRV_SECTOR_SIZE
* BITS_PER_BYTE
);
736 * Create an HBitmap and test set/unset.
738 static void test_hbitmap_meta_one(TestHBitmapData
*data
, const void *unused
)
741 int64_t offsets
[] = {
742 0, 1, L1
- 1, L1
, L1
+ 1, L2
- 1, L2
, L2
+ 1, L3
- 1, L3
, L3
+ 1
745 hbitmap_test_init_meta(data
, L3
* 2, 0, 1);
746 for (i
= 0; i
< ARRAY_SIZE(offsets
); i
++) {
747 hbitmap_test_meta(data
, offsets
[i
], 1, offsets
[i
], 1);
748 hbitmap_test_meta(data
, offsets
[i
], L1
, offsets
[i
], L1
);
749 hbitmap_test_meta(data
, offsets
[i
], L2
, offsets
[i
], L2
);
753 static void test_hbitmap_serialize_align(TestHBitmapData
*data
,
758 hbitmap_test_init(data
, L3
* 2, 3);
759 g_assert(hbitmap_is_serializable(data
->hb
));
761 r
= hbitmap_serialization_align(data
->hb
);
762 g_assert_cmpint(r
, ==, 64 << 3);
765 static void test_hbitmap_meta_zero(TestHBitmapData
*data
, const void *unused
)
767 hbitmap_test_init_meta(data
, 0, 0, 1);
769 hbitmap_check_meta(data
, 0, 0);
772 static void hbitmap_test_serialize_range(TestHBitmapData
*data
,
773 uint8_t *buf
, size_t buf_size
,
774 uint64_t pos
, uint64_t count
)
777 unsigned long *el
= (unsigned long *)buf
;
779 assert(hbitmap_granularity(data
->hb
) == 0);
780 hbitmap_reset_all(data
->hb
);
781 memset(buf
, 0, buf_size
);
783 hbitmap_set(data
->hb
, pos
, count
);
786 g_assert(hbitmap_is_serializable(data
->hb
));
787 hbitmap_serialize_part(data
->hb
, buf
, 0, data
->size
);
789 /* Serialized buffer is inherently LE, convert it back manually to test */
790 for (i
= 0; i
< buf_size
/ sizeof(unsigned long); i
++) {
791 el
[i
] = (BITS_PER_LONG
== 32 ? le32_to_cpu(el
[i
]) : le64_to_cpu(el
[i
]));
794 for (i
= 0; i
< data
->size
; i
++) {
795 int is_set
= test_bit(i
, (unsigned long *)buf
);
796 if (i
>= pos
&& i
< pos
+ count
) {
803 /* Re-serialize for deserialization testing */
804 memset(buf
, 0, buf_size
);
805 hbitmap_serialize_part(data
->hb
, buf
, 0, data
->size
);
806 hbitmap_reset_all(data
->hb
);
808 g_assert(hbitmap_is_serializable(data
->hb
));
809 hbitmap_deserialize_part(data
->hb
, buf
, 0, data
->size
, true);
811 for (i
= 0; i
< data
->size
; i
++) {
812 int is_set
= hbitmap_get(data
->hb
, i
);
813 if (i
>= pos
&& i
< pos
+ count
) {
821 static void test_hbitmap_serialize_basic(TestHBitmapData
*data
,
827 uint64_t positions
[] = { 0, 1, L1
- 1, L1
, L2
- 1, L2
, L2
+ 1, L3
- 1 };
828 int num_positions
= ARRAY_SIZE(positions
);
830 hbitmap_test_init(data
, L3
, 0);
831 g_assert(hbitmap_is_serializable(data
->hb
));
832 buf_size
= hbitmap_serialization_size(data
->hb
, 0, data
->size
);
833 buf
= g_malloc0(buf_size
);
835 for (i
= 0; i
< num_positions
; i
++) {
836 for (j
= 0; j
< num_positions
; j
++) {
837 hbitmap_test_serialize_range(data
, buf
, buf_size
,
839 MIN(positions
[j
], L3
- positions
[i
]));
846 static void test_hbitmap_serialize_part(TestHBitmapData
*data
,
852 uint64_t positions
[] = { 0, 1, L1
- 1, L1
, L2
- 1, L2
, L2
+ 1, L3
- 1 };
853 int num_positions
= ARRAY_SIZE(positions
);
855 hbitmap_test_init(data
, L3
, 0);
857 buf
= g_malloc0(buf_size
);
859 for (i
= 0; i
< num_positions
; i
++) {
860 hbitmap_set(data
->hb
, positions
[i
], 1);
863 g_assert(hbitmap_is_serializable(data
->hb
));
865 for (i
= 0; i
< data
->size
; i
+= buf_size
) {
866 unsigned long *el
= (unsigned long *)buf
;
867 hbitmap_serialize_part(data
->hb
, buf
, i
, buf_size
);
868 for (j
= 0; j
< buf_size
/ sizeof(unsigned long); j
++) {
869 el
[j
] = (BITS_PER_LONG
== 32 ? le32_to_cpu(el
[j
]) : le64_to_cpu(el
[j
]));
872 for (j
= 0; j
< buf_size
; j
++) {
873 bool should_set
= false;
874 for (k
= 0; k
< num_positions
; k
++) {
875 if (positions
[k
] == j
+ i
) {
880 g_assert_cmpint(should_set
, ==, test_bit(j
, (unsigned long *)buf
));
887 static void test_hbitmap_serialize_zeroes(TestHBitmapData
*data
,
893 uint64_t min_l1
= MAX(L1
, 64);
894 uint64_t positions
[] = { 0, min_l1
, L2
, L3
- min_l1
};
895 int num_positions
= ARRAY_SIZE(positions
);
897 hbitmap_test_init(data
, L3
, 0);
899 for (i
= 0; i
< num_positions
; i
++) {
900 hbitmap_set(data
->hb
, positions
[i
], L1
);
903 g_assert(hbitmap_is_serializable(data
->hb
));
905 for (i
= 0; i
< num_positions
; i
++) {
906 hbitmap_deserialize_zeroes(data
->hb
, positions
[i
], min_l1
, true);
907 hbitmap_iter_init(&iter
, data
->hb
, 0);
908 next
= check_hbitmap_iter_next(&iter
);
909 if (i
== num_positions
- 1) {
910 g_assert_cmpint(next
, ==, -1);
912 g_assert_cmpint(next
, ==, positions
[i
+ 1]);
917 static void hbitmap_test_add(const char *testpath
,
918 void (*test_func
)(TestHBitmapData
*data
, const void *user_data
))
920 g_test_add(testpath
, TestHBitmapData
, NULL
, NULL
, test_func
,
921 hbitmap_test_teardown
);
924 static void test_hbitmap_iter_and_reset(TestHBitmapData
*data
,
929 hbitmap_test_init(data
, L1
* 2, 0);
930 hbitmap_set(data
->hb
, 0, data
->size
);
932 hbitmap_iter_init(&hbi
, data
->hb
, BITS_PER_LONG
- 1);
934 check_hbitmap_iter_next(&hbi
);
936 hbitmap_reset_all(data
->hb
);
937 check_hbitmap_iter_next(&hbi
);
940 static void test_hbitmap_next_zero_check(TestHBitmapData
*data
, int64_t start
)
942 int64_t ret1
= hbitmap_next_zero(data
->hb
, start
);
943 int64_t ret2
= start
;
944 for ( ; ret2
< data
->size
&& hbitmap_get(data
->hb
, ret2
); ret2
++) {
947 if (ret2
== data
->size
) {
951 g_assert_cmpint(ret1
, ==, ret2
);
954 static void test_hbitmap_next_zero_do(TestHBitmapData
*data
, int granularity
)
956 hbitmap_test_init(data
, L3
, granularity
);
957 test_hbitmap_next_zero_check(data
, 0);
958 test_hbitmap_next_zero_check(data
, L3
- 1);
960 hbitmap_set(data
->hb
, L2
, 1);
961 test_hbitmap_next_zero_check(data
, 0);
962 test_hbitmap_next_zero_check(data
, L2
- 1);
963 test_hbitmap_next_zero_check(data
, L2
);
964 test_hbitmap_next_zero_check(data
, L2
+ 1);
966 hbitmap_set(data
->hb
, L2
+ 5, L1
);
967 test_hbitmap_next_zero_check(data
, 0);
968 test_hbitmap_next_zero_check(data
, L2
+ 1);
969 test_hbitmap_next_zero_check(data
, L2
+ 2);
970 test_hbitmap_next_zero_check(data
, L2
+ 5);
971 test_hbitmap_next_zero_check(data
, L2
+ L1
- 1);
972 test_hbitmap_next_zero_check(data
, L2
+ L1
);
974 hbitmap_set(data
->hb
, L2
* 2, L3
- L2
* 2);
975 test_hbitmap_next_zero_check(data
, L2
* 2 - L1
);
976 test_hbitmap_next_zero_check(data
, L2
* 2 - 2);
977 test_hbitmap_next_zero_check(data
, L2
* 2 - 1);
978 test_hbitmap_next_zero_check(data
, L2
* 2);
979 test_hbitmap_next_zero_check(data
, L3
- 1);
981 hbitmap_set(data
->hb
, 0, L3
);
982 test_hbitmap_next_zero_check(data
, 0);
985 static void test_hbitmap_next_zero_0(TestHBitmapData
*data
, const void *unused
)
987 test_hbitmap_next_zero_do(data
, 0);
990 static void test_hbitmap_next_zero_4(TestHBitmapData
*data
, const void *unused
)
992 test_hbitmap_next_zero_do(data
, 4);
995 int main(int argc
, char **argv
)
997 g_test_init(&argc
, &argv
, NULL
);
998 hbitmap_test_add("/hbitmap/size/0", test_hbitmap_zero
);
999 hbitmap_test_add("/hbitmap/size/unaligned", test_hbitmap_unaligned
);
1000 hbitmap_test_add("/hbitmap/iter/empty", test_hbitmap_iter_empty
);
1001 hbitmap_test_add("/hbitmap/iter/partial", test_hbitmap_iter_partial
);
1002 hbitmap_test_add("/hbitmap/iter/granularity", test_hbitmap_iter_granularity
);
1003 hbitmap_test_add("/hbitmap/get/all", test_hbitmap_get_all
);
1004 hbitmap_test_add("/hbitmap/get/some", test_hbitmap_get_some
);
1005 hbitmap_test_add("/hbitmap/set/all", test_hbitmap_set_all
);
1006 hbitmap_test_add("/hbitmap/set/one", test_hbitmap_set_one
);
1007 hbitmap_test_add("/hbitmap/set/two-elem", test_hbitmap_set_two_elem
);
1008 hbitmap_test_add("/hbitmap/set/general", test_hbitmap_set
);
1009 hbitmap_test_add("/hbitmap/set/twice", test_hbitmap_set_twice
);
1010 hbitmap_test_add("/hbitmap/set/overlap", test_hbitmap_set_overlap
);
1011 hbitmap_test_add("/hbitmap/reset/empty", test_hbitmap_reset_empty
);
1012 hbitmap_test_add("/hbitmap/reset/general", test_hbitmap_reset
);
1013 hbitmap_test_add("/hbitmap/reset/all", test_hbitmap_reset_all
);
1014 hbitmap_test_add("/hbitmap/granularity", test_hbitmap_granularity
);
1016 hbitmap_test_add("/hbitmap/truncate/nop", test_hbitmap_truncate_nop
);
1017 hbitmap_test_add("/hbitmap/truncate/grow/negligible",
1018 test_hbitmap_truncate_grow_negligible
);
1019 hbitmap_test_add("/hbitmap/truncate/shrink/negligible",
1020 test_hbitmap_truncate_shrink_negligible
);
1021 hbitmap_test_add("/hbitmap/truncate/grow/tiny",
1022 test_hbitmap_truncate_grow_tiny
);
1023 hbitmap_test_add("/hbitmap/truncate/shrink/tiny",
1024 test_hbitmap_truncate_shrink_tiny
);
1025 hbitmap_test_add("/hbitmap/truncate/grow/small",
1026 test_hbitmap_truncate_grow_small
);
1027 hbitmap_test_add("/hbitmap/truncate/shrink/small",
1028 test_hbitmap_truncate_shrink_small
);
1029 hbitmap_test_add("/hbitmap/truncate/grow/medium",
1030 test_hbitmap_truncate_grow_medium
);
1031 hbitmap_test_add("/hbitmap/truncate/shrink/medium",
1032 test_hbitmap_truncate_shrink_medium
);
1033 hbitmap_test_add("/hbitmap/truncate/grow/large",
1034 test_hbitmap_truncate_grow_large
);
1035 hbitmap_test_add("/hbitmap/truncate/shrink/large",
1036 test_hbitmap_truncate_shrink_large
);
1038 hbitmap_test_add("/hbitmap/meta/zero", test_hbitmap_meta_zero
);
1039 hbitmap_test_add("/hbitmap/meta/one", test_hbitmap_meta_one
);
1040 hbitmap_test_add("/hbitmap/meta/byte", test_hbitmap_meta_byte
);
1041 hbitmap_test_add("/hbitmap/meta/word", test_hbitmap_meta_word
);
1042 hbitmap_test_add("/hbitmap/meta/sector", test_hbitmap_meta_sector
);
1044 hbitmap_test_add("/hbitmap/serialize/align",
1045 test_hbitmap_serialize_align
);
1046 hbitmap_test_add("/hbitmap/serialize/basic",
1047 test_hbitmap_serialize_basic
);
1048 hbitmap_test_add("/hbitmap/serialize/part",
1049 test_hbitmap_serialize_part
);
1050 hbitmap_test_add("/hbitmap/serialize/zeroes",
1051 test_hbitmap_serialize_zeroes
);
1053 hbitmap_test_add("/hbitmap/iter/iter_and_reset",
1054 test_hbitmap_iter_and_reset
);
1056 hbitmap_test_add("/hbitmap/next_zero/next_zero_0",
1057 test_hbitmap_next_zero_0
);
1058 hbitmap_test_add("/hbitmap/next_zero/next_zero_4",
1059 test_hbitmap_next_zero_4
);