]> git.proxmox.com Git - mirror_qemu.git/blame - tests/test-hbitmap.c
block: BdrvDirtyBitmap serialization interface
[mirror_qemu.git] / tests / test-hbitmap.c
CommitLineData
e7c033c3
PB
1/*
2 * Hierarchical bitmap unit-tests.
3 *
4 * Copyright (C) 2012 Red Hat Inc.
5 *
6 * Author: Paolo Bonzini <pbonzini@redhat.com>
7 *
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.
10 */
11
681c28a3 12#include "qemu/osdep.h"
e7c033c3 13#include "qemu/hbitmap.h"
4b62818a 14#include "block/block.h"
e7c033c3
PB
15
16#define LOG_BITS_PER_LONG (BITS_PER_LONG == 32 ? 5 : 6)
17
18#define L1 BITS_PER_LONG
19#define L2 (BITS_PER_LONG * L1)
20#define L3 (BITS_PER_LONG * L2)
21
22typedef struct TestHBitmapData {
23 HBitmap *hb;
4b62818a 24 HBitmap *meta;
e7c033c3
PB
25 unsigned long *bits;
26 size_t size;
a94e87c0 27 size_t old_size;
e7c033c3
PB
28 int granularity;
29} TestHBitmapData;
30
31
32/* Check that the HBitmap and the shadow bitmap contain the same data,
33 * ignoring the same "first" bits.
34 */
35static void hbitmap_test_check(TestHBitmapData *data,
36 uint64_t first)
37{
38 uint64_t count = 0;
39 size_t pos;
40 int bit;
41 HBitmapIter hbi;
42 int64_t i, next;
43
44 hbitmap_iter_init(&hbi, data->hb, first);
45
46 i = first;
47 for (;;) {
48 next = hbitmap_iter_next(&hbi);
49 if (next < 0) {
50 next = data->size;
51 }
52
53 while (i < next) {
54 pos = i >> LOG_BITS_PER_LONG;
55 bit = i & (BITS_PER_LONG - 1);
56 i++;
57 g_assert_cmpint(data->bits[pos] & (1UL << bit), ==, 0);
58 }
59
60 if (next == data->size) {
61 break;
62 }
63
64 pos = i >> LOG_BITS_PER_LONG;
65 bit = i & (BITS_PER_LONG - 1);
66 i++;
67 count++;
68 g_assert_cmpint(data->bits[pos] & (1UL << bit), !=, 0);
69 }
70
71 if (first == 0) {
72 g_assert_cmpint(count << data->granularity, ==, hbitmap_count(data->hb));
73 }
74}
75
76/* This is provided instead of a test setup function so that the sizes
77 are kept in the test functions (and not in main()) */
78static void hbitmap_test_init(TestHBitmapData *data,
79 uint64_t size, int granularity)
80{
81 size_t n;
82 data->hb = hbitmap_alloc(size, granularity);
83
30f549c2 84 n = DIV_ROUND_UP(size, BITS_PER_LONG);
e7c033c3
PB
85 if (n == 0) {
86 n = 1;
87 }
88 data->bits = g_new0(unsigned long, n);
89 data->size = size;
90 data->granularity = granularity;
1b095244
PB
91 if (size) {
92 hbitmap_test_check(data, 0);
93 }
e7c033c3
PB
94}
95
4b62818a
FZ
96static void hbitmap_test_init_meta(TestHBitmapData *data,
97 uint64_t size, int granularity,
98 int meta_chunk)
99{
100 hbitmap_test_init(data, size, granularity);
101 data->meta = hbitmap_create_meta(data->hb, meta_chunk);
102}
103
a94e87c0
JS
104static inline size_t hbitmap_test_array_size(size_t bits)
105{
30f549c2 106 size_t n = DIV_ROUND_UP(bits, BITS_PER_LONG);
a94e87c0
JS
107 return n ? n : 1;
108}
109
110static void hbitmap_test_truncate_impl(TestHBitmapData *data,
111 size_t size)
112{
113 size_t n;
114 size_t m;
115 data->old_size = data->size;
116 data->size = size;
117
118 if (data->size == data->old_size) {
119 return;
120 }
121
122 n = hbitmap_test_array_size(size);
123 m = hbitmap_test_array_size(data->old_size);
124 data->bits = g_realloc(data->bits, sizeof(unsigned long) * n);
125 if (n > m) {
126 memset(&data->bits[m], 0x00, sizeof(unsigned long) * (n - m));
127 }
128
129 /* If we shrink to an uneven multiple of sizeof(unsigned long),
130 * scrub the leftover memory. */
131 if (data->size < data->old_size) {
132 m = size % (sizeof(unsigned long) * 8);
133 if (m) {
134 unsigned long mask = (1ULL << m) - 1;
135 data->bits[n-1] &= mask;
136 }
137 }
138
139 hbitmap_truncate(data->hb, size);
140}
141
e7c033c3
PB
142static void hbitmap_test_teardown(TestHBitmapData *data,
143 const void *unused)
144{
145 if (data->hb) {
4b62818a
FZ
146 if (data->meta) {
147 hbitmap_free_meta(data->hb);
148 }
e7c033c3
PB
149 hbitmap_free(data->hb);
150 data->hb = NULL;
151 }
012aef07
MA
152 g_free(data->bits);
153 data->bits = NULL;
e7c033c3
PB
154}
155
156/* Set a range in the HBitmap and in the shadow "simple" bitmap.
157 * The two bitmaps are then tested against each other.
158 */
159static void hbitmap_test_set(TestHBitmapData *data,
160 uint64_t first, uint64_t count)
161{
162 hbitmap_set(data->hb, first, count);
163 while (count-- != 0) {
164 size_t pos = first >> LOG_BITS_PER_LONG;
165 int bit = first & (BITS_PER_LONG - 1);
166 first++;
167
168 data->bits[pos] |= 1UL << bit;
169 }
170
171 if (data->granularity == 0) {
172 hbitmap_test_check(data, 0);
173 }
174}
175
176/* Reset a range in the HBitmap and in the shadow "simple" bitmap.
177 */
178static void hbitmap_test_reset(TestHBitmapData *data,
179 uint64_t first, uint64_t count)
180{
181 hbitmap_reset(data->hb, first, count);
182 while (count-- != 0) {
183 size_t pos = first >> LOG_BITS_PER_LONG;
184 int bit = first & (BITS_PER_LONG - 1);
185 first++;
186
187 data->bits[pos] &= ~(1UL << bit);
188 }
189
190 if (data->granularity == 0) {
191 hbitmap_test_check(data, 0);
192 }
193}
194
c6a8c328
WC
195static void hbitmap_test_reset_all(TestHBitmapData *data)
196{
197 size_t n;
198
199 hbitmap_reset_all(data->hb);
200
30f549c2 201 n = DIV_ROUND_UP(data->size, BITS_PER_LONG);
c6a8c328
WC
202 if (n == 0) {
203 n = 1;
204 }
205 memset(data->bits, 0, n * sizeof(unsigned long));
206
207 if (data->granularity == 0) {
208 hbitmap_test_check(data, 0);
209 }
210}
211
e7c033c3
PB
212static void hbitmap_test_check_get(TestHBitmapData *data)
213{
214 uint64_t count = 0;
215 uint64_t i;
216
217 for (i = 0; i < data->size; i++) {
218 size_t pos = i >> LOG_BITS_PER_LONG;
219 int bit = i & (BITS_PER_LONG - 1);
220 unsigned long val = data->bits[pos] & (1UL << bit);
221 count += hbitmap_get(data->hb, i);
222 g_assert_cmpint(hbitmap_get(data->hb, i), ==, val != 0);
223 }
224 g_assert_cmpint(count, ==, hbitmap_count(data->hb));
225}
226
227static void test_hbitmap_zero(TestHBitmapData *data,
228 const void *unused)
229{
230 hbitmap_test_init(data, 0, 0);
231}
232
233static void test_hbitmap_unaligned(TestHBitmapData *data,
234 const void *unused)
235{
236 hbitmap_test_init(data, L3 + 23, 0);
237 hbitmap_test_set(data, 0, 1);
238 hbitmap_test_set(data, L3 + 22, 1);
239}
240
241static void test_hbitmap_iter_empty(TestHBitmapData *data,
242 const void *unused)
243{
244 hbitmap_test_init(data, L1, 0);
245}
246
247static void test_hbitmap_iter_partial(TestHBitmapData *data,
248 const void *unused)
249{
250 hbitmap_test_init(data, L3, 0);
251 hbitmap_test_set(data, 0, L3);
252 hbitmap_test_check(data, 1);
253 hbitmap_test_check(data, L1 - 1);
254 hbitmap_test_check(data, L1);
255 hbitmap_test_check(data, L1 * 2 - 1);
256 hbitmap_test_check(data, L2 - 1);
257 hbitmap_test_check(data, L2);
258 hbitmap_test_check(data, L2 + 1);
259 hbitmap_test_check(data, L2 + L1);
260 hbitmap_test_check(data, L2 + L1 * 2 - 1);
261 hbitmap_test_check(data, L2 * 2 - 1);
262 hbitmap_test_check(data, L2 * 2);
263 hbitmap_test_check(data, L2 * 2 + 1);
264 hbitmap_test_check(data, L2 * 2 + L1);
265 hbitmap_test_check(data, L2 * 2 + L1 * 2 - 1);
266 hbitmap_test_check(data, L3 / 2);
267}
268
e7c033c3
PB
269static void test_hbitmap_set_all(TestHBitmapData *data,
270 const void *unused)
271{
272 hbitmap_test_init(data, L3, 0);
273 hbitmap_test_set(data, 0, L3);
274}
275
276static void test_hbitmap_get_all(TestHBitmapData *data,
277 const void *unused)
278{
279 hbitmap_test_init(data, L3, 0);
280 hbitmap_test_set(data, 0, L3);
281 hbitmap_test_check_get(data);
282}
283
284static void test_hbitmap_get_some(TestHBitmapData *data,
285 const void *unused)
286{
287 hbitmap_test_init(data, 2 * L2, 0);
288 hbitmap_test_set(data, 10, 1);
289 hbitmap_test_check_get(data);
290 hbitmap_test_set(data, L1 - 1, 1);
291 hbitmap_test_check_get(data);
292 hbitmap_test_set(data, L1, 1);
293 hbitmap_test_check_get(data);
294 hbitmap_test_set(data, L2 - 1, 1);
295 hbitmap_test_check_get(data);
296 hbitmap_test_set(data, L2, 1);
297 hbitmap_test_check_get(data);
298}
299
300static void test_hbitmap_set_one(TestHBitmapData *data,
301 const void *unused)
302{
303 hbitmap_test_init(data, 2 * L2, 0);
304 hbitmap_test_set(data, 10, 1);
305 hbitmap_test_set(data, L1 - 1, 1);
306 hbitmap_test_set(data, L1, 1);
307 hbitmap_test_set(data, L2 - 1, 1);
308 hbitmap_test_set(data, L2, 1);
309}
310
311static void test_hbitmap_set_two_elem(TestHBitmapData *data,
312 const void *unused)
313{
314 hbitmap_test_init(data, 2 * L2, 0);
315 hbitmap_test_set(data, L1 - 1, 2);
316 hbitmap_test_set(data, L1 * 2 - 1, 4);
317 hbitmap_test_set(data, L1 * 4, L1 + 1);
318 hbitmap_test_set(data, L1 * 8 - 1, L1 + 1);
319 hbitmap_test_set(data, L2 - 1, 2);
320 hbitmap_test_set(data, L2 + L1 - 1, 8);
321 hbitmap_test_set(data, L2 + L1 * 4, L1 + 1);
322 hbitmap_test_set(data, L2 + L1 * 8 - 1, L1 + 1);
323}
324
325static void test_hbitmap_set(TestHBitmapData *data,
326 const void *unused)
327{
328 hbitmap_test_init(data, L3 * 2, 0);
329 hbitmap_test_set(data, L1 - 1, L1 + 2);
330 hbitmap_test_set(data, L1 * 3 - 1, L1 + 2);
331 hbitmap_test_set(data, L1 * 5, L1 * 2 + 1);
332 hbitmap_test_set(data, L1 * 8 - 1, L1 * 2 + 1);
333 hbitmap_test_set(data, L2 - 1, L1 + 2);
334 hbitmap_test_set(data, L2 + L1 * 2 - 1, L1 + 2);
335 hbitmap_test_set(data, L2 + L1 * 4, L1 * 2 + 1);
336 hbitmap_test_set(data, L2 + L1 * 7 - 1, L1 * 2 + 1);
337 hbitmap_test_set(data, L2 * 2 - 1, L3 * 2 - L2 * 2);
338}
339
340static void test_hbitmap_set_twice(TestHBitmapData *data,
341 const void *unused)
342{
343 hbitmap_test_init(data, L1 * 3, 0);
344 hbitmap_test_set(data, 0, L1 * 3);
345 hbitmap_test_set(data, L1, 1);
346}
347
348static void test_hbitmap_set_overlap(TestHBitmapData *data,
349 const void *unused)
350{
351 hbitmap_test_init(data, L3 * 2, 0);
352 hbitmap_test_set(data, L1 - 1, L1 + 2);
353 hbitmap_test_set(data, L1 * 2 - 1, L1 * 2 + 2);
354 hbitmap_test_set(data, 0, L1 * 3);
355 hbitmap_test_set(data, L1 * 8 - 1, L2);
356 hbitmap_test_set(data, L2, L1);
357 hbitmap_test_set(data, L2 - L1 - 1, L1 * 8 + 2);
358 hbitmap_test_set(data, L2, L3 - L2 + 1);
359 hbitmap_test_set(data, L3 - L1, L1 * 3);
360 hbitmap_test_set(data, L3 - 1, 3);
361 hbitmap_test_set(data, L3 - 1, L2);
362}
363
364static void test_hbitmap_reset_empty(TestHBitmapData *data,
365 const void *unused)
366{
367 hbitmap_test_init(data, L3, 0);
368 hbitmap_test_reset(data, 0, L3);
369}
370
371static void test_hbitmap_reset(TestHBitmapData *data,
372 const void *unused)
373{
374 hbitmap_test_init(data, L3 * 2, 0);
375 hbitmap_test_set(data, L1 - 1, L1 + 2);
376 hbitmap_test_reset(data, L1 * 2 - 1, L1 * 2 + 2);
377 hbitmap_test_set(data, 0, L1 * 3);
378 hbitmap_test_reset(data, L1 * 8 - 1, L2);
379 hbitmap_test_set(data, L2, L1);
380 hbitmap_test_reset(data, L2 - L1 - 1, L1 * 8 + 2);
381 hbitmap_test_set(data, L2, L3 - L2 + 1);
382 hbitmap_test_reset(data, L3 - L1, L1 * 3);
383 hbitmap_test_set(data, L3 - 1, 3);
384 hbitmap_test_reset(data, L3 - 1, L2);
385 hbitmap_test_set(data, 0, L3 * 2);
386 hbitmap_test_reset(data, 0, L1);
387 hbitmap_test_reset(data, 0, L2);
388 hbitmap_test_reset(data, L3, L3);
389 hbitmap_test_set(data, L3 / 2, L3);
390}
391
c6a8c328
WC
392static void test_hbitmap_reset_all(TestHBitmapData *data,
393 const void *unused)
394{
395 hbitmap_test_init(data, L3 * 2, 0);
396 hbitmap_test_set(data, L1 - 1, L1 + 2);
397 hbitmap_test_reset_all(data);
398 hbitmap_test_set(data, 0, L1 * 3);
399 hbitmap_test_reset_all(data);
400 hbitmap_test_set(data, L2, L1);
401 hbitmap_test_reset_all(data);
402 hbitmap_test_set(data, L2, L3 - L2 + 1);
403 hbitmap_test_reset_all(data);
404 hbitmap_test_set(data, L3 - 1, 3);
405 hbitmap_test_reset_all(data);
406 hbitmap_test_set(data, 0, L3 * 2);
407 hbitmap_test_reset_all(data);
408 hbitmap_test_set(data, L3 / 2, L3);
409 hbitmap_test_reset_all(data);
410}
411
e7c033c3
PB
412static void test_hbitmap_granularity(TestHBitmapData *data,
413 const void *unused)
414{
415 /* Note that hbitmap_test_check has to be invoked manually in this test. */
416 hbitmap_test_init(data, L1, 1);
417 hbitmap_test_set(data, 0, 1);
418 g_assert_cmpint(hbitmap_count(data->hb), ==, 2);
419 hbitmap_test_check(data, 0);
420 hbitmap_test_set(data, 2, 1);
421 g_assert_cmpint(hbitmap_count(data->hb), ==, 4);
422 hbitmap_test_check(data, 0);
423 hbitmap_test_set(data, 0, 3);
424 g_assert_cmpint(hbitmap_count(data->hb), ==, 4);
425 hbitmap_test_reset(data, 0, 1);
426 g_assert_cmpint(hbitmap_count(data->hb), ==, 2);
427}
428
429static void test_hbitmap_iter_granularity(TestHBitmapData *data,
430 const void *unused)
431{
432 HBitmapIter hbi;
433
434 /* Note that hbitmap_test_check has to be invoked manually in this test. */
435 hbitmap_test_init(data, 131072 << 7, 7);
436 hbitmap_iter_init(&hbi, data->hb, 0);
437 g_assert_cmpint(hbitmap_iter_next(&hbi), <, 0);
438
439 hbitmap_test_set(data, ((L2 + L1 + 1) << 7) + 8, 8);
440 hbitmap_iter_init(&hbi, data->hb, 0);
441 g_assert_cmpint(hbitmap_iter_next(&hbi), ==, (L2 + L1 + 1) << 7);
442 g_assert_cmpint(hbitmap_iter_next(&hbi), <, 0);
443
444 hbitmap_iter_init(&hbi, data->hb, (L2 + L1 + 2) << 7);
445 g_assert_cmpint(hbitmap_iter_next(&hbi), <, 0);
446
447 hbitmap_test_set(data, (131072 << 7) - 8, 8);
448 hbitmap_iter_init(&hbi, data->hb, 0);
449 g_assert_cmpint(hbitmap_iter_next(&hbi), ==, (L2 + L1 + 1) << 7);
450 g_assert_cmpint(hbitmap_iter_next(&hbi), ==, 131071 << 7);
451 g_assert_cmpint(hbitmap_iter_next(&hbi), <, 0);
452
453 hbitmap_iter_init(&hbi, data->hb, (L2 + L1 + 2) << 7);
454 g_assert_cmpint(hbitmap_iter_next(&hbi), ==, 131071 << 7);
455 g_assert_cmpint(hbitmap_iter_next(&hbi), <, 0);
456}
457
a94e87c0
JS
458static void hbitmap_test_set_boundary_bits(TestHBitmapData *data, ssize_t diff)
459{
460 size_t size = data->size;
461
462 /* First bit */
463 hbitmap_test_set(data, 0, 1);
464 if (diff < 0) {
465 /* Last bit in new, shortened map */
466 hbitmap_test_set(data, size + diff - 1, 1);
467
468 /* First bit to be truncated away */
469 hbitmap_test_set(data, size + diff, 1);
470 }
471 /* Last bit */
472 hbitmap_test_set(data, size - 1, 1);
473 if (data->granularity == 0) {
474 hbitmap_test_check_get(data);
475 }
476}
477
478static void hbitmap_test_check_boundary_bits(TestHBitmapData *data)
479{
480 size_t size = MIN(data->size, data->old_size);
481
482 if (data->granularity == 0) {
483 hbitmap_test_check_get(data);
484 hbitmap_test_check(data, 0);
485 } else {
486 /* If a granularity was set, note that every distinct
487 * (bit >> granularity) value that was set will increase
488 * the bit pop count by 2^granularity, not just 1.
489 *
490 * The hbitmap_test_check facility does not currently tolerate
491 * non-zero granularities, so test the boundaries and the population
492 * count manually.
493 */
494 g_assert(hbitmap_get(data->hb, 0));
495 g_assert(hbitmap_get(data->hb, size - 1));
496 g_assert_cmpint(2 << data->granularity, ==, hbitmap_count(data->hb));
497 }
498}
499
500/* Generic truncate test. */
501static void hbitmap_test_truncate(TestHBitmapData *data,
502 size_t size,
503 ssize_t diff,
504 int granularity)
505{
506 hbitmap_test_init(data, size, granularity);
507 hbitmap_test_set_boundary_bits(data, diff);
508 hbitmap_test_truncate_impl(data, size + diff);
509 hbitmap_test_check_boundary_bits(data);
510}
511
512static void test_hbitmap_truncate_nop(TestHBitmapData *data,
513 const void *unused)
514{
515 hbitmap_test_truncate(data, L2, 0, 0);
516}
517
518/**
519 * Grow by an amount smaller than the granularity, without crossing
520 * a granularity alignment boundary. Effectively a NOP.
521 */
522static void test_hbitmap_truncate_grow_negligible(TestHBitmapData *data,
523 const void *unused)
524{
525 size_t size = L2 - 1;
526 size_t diff = 1;
527 int granularity = 1;
528
529 hbitmap_test_truncate(data, size, diff, granularity);
530}
531
532/**
533 * Shrink by an amount smaller than the granularity, without crossing
534 * a granularity alignment boundary. Effectively a NOP.
535 */
536static void test_hbitmap_truncate_shrink_negligible(TestHBitmapData *data,
537 const void *unused)
538{
539 size_t size = L2;
540 ssize_t diff = -1;
541 int granularity = 1;
542
543 hbitmap_test_truncate(data, size, diff, granularity);
544}
545
546/**
547 * Grow by an amount smaller than the granularity, but crossing over
548 * a granularity alignment boundary.
549 */
550static void test_hbitmap_truncate_grow_tiny(TestHBitmapData *data,
551 const void *unused)
552{
553 size_t size = L2 - 2;
554 ssize_t diff = 1;
555 int granularity = 1;
556
557 hbitmap_test_truncate(data, size, diff, granularity);
558}
559
560/**
561 * Shrink by an amount smaller than the granularity, but crossing over
562 * a granularity alignment boundary.
563 */
564static void test_hbitmap_truncate_shrink_tiny(TestHBitmapData *data,
565 const void *unused)
566{
567 size_t size = L2 - 1;
568 ssize_t diff = -1;
569 int granularity = 1;
570
571 hbitmap_test_truncate(data, size, diff, granularity);
572}
573
574/**
575 * Grow by an amount smaller than sizeof(long), and not crossing over
576 * a sizeof(long) alignment boundary.
577 */
578static void test_hbitmap_truncate_grow_small(TestHBitmapData *data,
579 const void *unused)
580{
581 size_t size = L2 + 1;
582 size_t diff = sizeof(long) / 2;
583
584 hbitmap_test_truncate(data, size, diff, 0);
585}
586
587/**
588 * Shrink by an amount smaller than sizeof(long), and not crossing over
589 * a sizeof(long) alignment boundary.
590 */
591static void test_hbitmap_truncate_shrink_small(TestHBitmapData *data,
592 const void *unused)
593{
594 size_t size = L2;
595 size_t diff = sizeof(long) / 2;
596
597 hbitmap_test_truncate(data, size, -diff, 0);
598}
599
600/**
601 * Grow by an amount smaller than sizeof(long), while crossing over
602 * a sizeof(long) alignment boundary.
603 */
604static void test_hbitmap_truncate_grow_medium(TestHBitmapData *data,
605 const void *unused)
606{
607 size_t size = L2 - 1;
608 size_t diff = sizeof(long) / 2;
609
610 hbitmap_test_truncate(data, size, diff, 0);
611}
612
613/**
614 * Shrink by an amount smaller than sizeof(long), while crossing over
615 * a sizeof(long) alignment boundary.
616 */
617static void test_hbitmap_truncate_shrink_medium(TestHBitmapData *data,
618 const void *unused)
619{
620 size_t size = L2 + 1;
621 size_t diff = sizeof(long) / 2;
622
623 hbitmap_test_truncate(data, size, -diff, 0);
624}
625
626/**
627 * Grow by an amount larger than sizeof(long).
628 */
629static void test_hbitmap_truncate_grow_large(TestHBitmapData *data,
630 const void *unused)
631{
632 size_t size = L2;
633 size_t diff = 8 * sizeof(long);
634
635 hbitmap_test_truncate(data, size, diff, 0);
636}
637
638/**
639 * Shrink by an amount larger than sizeof(long).
640 */
641static void test_hbitmap_truncate_shrink_large(TestHBitmapData *data,
642 const void *unused)
643{
644 size_t size = L2;
645 size_t diff = 8 * sizeof(long);
646
647 hbitmap_test_truncate(data, size, -diff, 0);
648}
649
4b62818a
FZ
650static void hbitmap_check_meta(TestHBitmapData *data,
651 int64_t start, int count)
652{
653 int64_t i;
654
655 for (i = 0; i < data->size; i++) {
656 if (i >= start && i < start + count) {
657 g_assert(hbitmap_get(data->meta, i));
658 } else {
659 g_assert(!hbitmap_get(data->meta, i));
660 }
661 }
662}
663
664static void hbitmap_test_meta(TestHBitmapData *data,
665 int64_t start, int count,
666 int64_t check_start, int check_count)
667{
668 hbitmap_reset_all(data->hb);
669 hbitmap_reset_all(data->meta);
670
671 /* Test "unset" -> "unset" will not update meta. */
672 hbitmap_reset(data->hb, start, count);
673 hbitmap_check_meta(data, 0, 0);
674
675 /* Test "unset" -> "set" will update meta */
676 hbitmap_set(data->hb, start, count);
677 hbitmap_check_meta(data, check_start, check_count);
678
679 /* Test "set" -> "set" will not update meta */
680 hbitmap_reset_all(data->meta);
681 hbitmap_set(data->hb, start, count);
682 hbitmap_check_meta(data, 0, 0);
683
684 /* Test "set" -> "unset" will update meta */
685 hbitmap_reset_all(data->meta);
686 hbitmap_reset(data->hb, start, count);
687 hbitmap_check_meta(data, check_start, check_count);
688}
689
690static void hbitmap_test_meta_do(TestHBitmapData *data, int chunk_size)
691{
692 uint64_t size = chunk_size * 100;
693 hbitmap_test_init_meta(data, size, 0, chunk_size);
694
695 hbitmap_test_meta(data, 0, 1, 0, chunk_size);
696 hbitmap_test_meta(data, 0, chunk_size, 0, chunk_size);
697 hbitmap_test_meta(data, chunk_size - 1, 1, 0, chunk_size);
698 hbitmap_test_meta(data, chunk_size - 1, 2, 0, chunk_size * 2);
699 hbitmap_test_meta(data, chunk_size - 1, chunk_size + 1, 0, chunk_size * 2);
700 hbitmap_test_meta(data, chunk_size - 1, chunk_size + 2, 0, chunk_size * 3);
701 hbitmap_test_meta(data, 7 * chunk_size - 1, chunk_size + 2,
702 6 * chunk_size, chunk_size * 3);
703 hbitmap_test_meta(data, size - 1, 1, size - chunk_size, chunk_size);
704 hbitmap_test_meta(data, 0, size, 0, size);
705}
706
707static void test_hbitmap_meta_byte(TestHBitmapData *data, const void *unused)
708{
709 hbitmap_test_meta_do(data, BITS_PER_BYTE);
710}
711
712static void test_hbitmap_meta_word(TestHBitmapData *data, const void *unused)
713{
714 hbitmap_test_meta_do(data, BITS_PER_LONG);
715}
716
717static void test_hbitmap_meta_sector(TestHBitmapData *data, const void *unused)
718{
719 hbitmap_test_meta_do(data, BDRV_SECTOR_SIZE * BITS_PER_BYTE);
720}
721
722/**
723 * Create an HBitmap and test set/unset.
724 */
725static void test_hbitmap_meta_one(TestHBitmapData *data, const void *unused)
726{
727 int i;
728 int64_t offsets[] = {
729 0, 1, L1 - 1, L1, L1 + 1, L2 - 1, L2, L2 + 1, L3 - 1, L3, L3 + 1
730 };
731
732 hbitmap_test_init_meta(data, L3 * 2, 0, 1);
733 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
734 hbitmap_test_meta(data, offsets[i], 1, offsets[i], 1);
735 hbitmap_test_meta(data, offsets[i], L1, offsets[i], L1);
736 hbitmap_test_meta(data, offsets[i], L2, offsets[i], L2);
737 }
738}
739
740static void test_hbitmap_meta_zero(TestHBitmapData *data, const void *unused)
741{
742 hbitmap_test_init_meta(data, 0, 0, 1);
743
744 hbitmap_check_meta(data, 0, 0);
745}
746
e7c033c3
PB
747static void hbitmap_test_add(const char *testpath,
748 void (*test_func)(TestHBitmapData *data, const void *user_data))
749{
750 g_test_add(testpath, TestHBitmapData, NULL, NULL, test_func,
751 hbitmap_test_teardown);
752}
753
754int main(int argc, char **argv)
755{
756 g_test_init(&argc, &argv, NULL);
757 hbitmap_test_add("/hbitmap/size/0", test_hbitmap_zero);
758 hbitmap_test_add("/hbitmap/size/unaligned", test_hbitmap_unaligned);
759 hbitmap_test_add("/hbitmap/iter/empty", test_hbitmap_iter_empty);
e7c033c3
PB
760 hbitmap_test_add("/hbitmap/iter/partial", test_hbitmap_iter_partial);
761 hbitmap_test_add("/hbitmap/iter/granularity", test_hbitmap_iter_granularity);
762 hbitmap_test_add("/hbitmap/get/all", test_hbitmap_get_all);
763 hbitmap_test_add("/hbitmap/get/some", test_hbitmap_get_some);
764 hbitmap_test_add("/hbitmap/set/all", test_hbitmap_set_all);
765 hbitmap_test_add("/hbitmap/set/one", test_hbitmap_set_one);
766 hbitmap_test_add("/hbitmap/set/two-elem", test_hbitmap_set_two_elem);
767 hbitmap_test_add("/hbitmap/set/general", test_hbitmap_set);
768 hbitmap_test_add("/hbitmap/set/twice", test_hbitmap_set_twice);
769 hbitmap_test_add("/hbitmap/set/overlap", test_hbitmap_set_overlap);
770 hbitmap_test_add("/hbitmap/reset/empty", test_hbitmap_reset_empty);
771 hbitmap_test_add("/hbitmap/reset/general", test_hbitmap_reset);
c6a8c328 772 hbitmap_test_add("/hbitmap/reset/all", test_hbitmap_reset_all);
e7c033c3 773 hbitmap_test_add("/hbitmap/granularity", test_hbitmap_granularity);
a94e87c0
JS
774
775 hbitmap_test_add("/hbitmap/truncate/nop", test_hbitmap_truncate_nop);
776 hbitmap_test_add("/hbitmap/truncate/grow/negligible",
777 test_hbitmap_truncate_grow_negligible);
778 hbitmap_test_add("/hbitmap/truncate/shrink/negligible",
779 test_hbitmap_truncate_shrink_negligible);
780 hbitmap_test_add("/hbitmap/truncate/grow/tiny",
781 test_hbitmap_truncate_grow_tiny);
782 hbitmap_test_add("/hbitmap/truncate/shrink/tiny",
783 test_hbitmap_truncate_shrink_tiny);
784 hbitmap_test_add("/hbitmap/truncate/grow/small",
785 test_hbitmap_truncate_grow_small);
786 hbitmap_test_add("/hbitmap/truncate/shrink/small",
787 test_hbitmap_truncate_shrink_small);
788 hbitmap_test_add("/hbitmap/truncate/grow/medium",
789 test_hbitmap_truncate_grow_medium);
790 hbitmap_test_add("/hbitmap/truncate/shrink/medium",
791 test_hbitmap_truncate_shrink_medium);
792 hbitmap_test_add("/hbitmap/truncate/grow/large",
793 test_hbitmap_truncate_grow_large);
794 hbitmap_test_add("/hbitmap/truncate/shrink/large",
795 test_hbitmap_truncate_shrink_large);
4b62818a
FZ
796
797 hbitmap_test_add("/hbitmap/meta/zero", test_hbitmap_meta_zero);
798 hbitmap_test_add("/hbitmap/meta/one", test_hbitmap_meta_one);
799 hbitmap_test_add("/hbitmap/meta/byte", test_hbitmap_meta_byte);
800 hbitmap_test_add("/hbitmap/meta/word", test_hbitmap_meta_word);
801 hbitmap_test_add("/hbitmap/meta/sector", test_hbitmap_meta_sector);
e7c033c3
PB
802 g_test_run();
803
804 return 0;
805}