1 1.1 christos #include "test/jemalloc_test.h" 2 1.1 christos 3 1.1 christos #include "jemalloc/internal/fb.h" 4 1.1 christos #include "test/nbits.h" 5 1.1 christos 6 1.1 christos static void 7 1.1 christos do_test_init(size_t nbits) { 8 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 9 1.1 christos fb_group_t *fb = malloc(sz); 10 1.1 christos /* Junk fb's contents. */ 11 1.1 christos memset(fb, 99, sz); 12 1.1 christos fb_init(fb, nbits); 13 1.1 christos for (size_t i = 0; i < nbits; i++) { 14 1.1 christos expect_false(fb_get(fb, nbits, i), 15 1.1 christos "bitmap should start empty"); 16 1.1 christos } 17 1.1 christos free(fb); 18 1.1 christos } 19 1.1 christos 20 1.1 christos TEST_BEGIN(test_fb_init) { 21 1.1 christos #define NB(nbits) \ 22 1.1 christos do_test_init(nbits); 23 1.1 christos NBITS_TAB 24 1.1 christos #undef NB 25 1.1 christos } 26 1.1 christos TEST_END 27 1.1 christos 28 1.1 christos static void 29 1.1 christos do_test_get_set_unset(size_t nbits) { 30 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 31 1.1 christos fb_group_t *fb = malloc(sz); 32 1.1 christos fb_init(fb, nbits); 33 1.1 christos /* Set the bits divisible by 3. */ 34 1.1 christos for (size_t i = 0; i < nbits; i++) { 35 1.1 christos if (i % 3 == 0) { 36 1.1 christos fb_set(fb, nbits, i); 37 1.1 christos } 38 1.1 christos } 39 1.1 christos /* Check them. */ 40 1.1 christos for (size_t i = 0; i < nbits; i++) { 41 1.1 christos expect_b_eq(i % 3 == 0, fb_get(fb, nbits, i), 42 1.1 christos "Unexpected bit at position %zu", i); 43 1.1 christos } 44 1.1 christos /* Unset those divisible by 5. */ 45 1.1 christos for (size_t i = 0; i < nbits; i++) { 46 1.1 christos if (i % 5 == 0) { 47 1.1 christos fb_unset(fb, nbits, i); 48 1.1 christos } 49 1.1 christos } 50 1.1 christos /* Check them. */ 51 1.1 christos for (size_t i = 0; i < nbits; i++) { 52 1.1 christos expect_b_eq(i % 3 == 0 && i % 5 != 0, fb_get(fb, nbits, i), 53 1.1 christos "Unexpected bit at position %zu", i); 54 1.1 christos } 55 1.1 christos free(fb); 56 1.1 christos } 57 1.1 christos 58 1.1 christos TEST_BEGIN(test_get_set_unset) { 59 1.1 christos #define NB(nbits) \ 60 1.1 christos do_test_get_set_unset(nbits); 61 1.1 christos NBITS_TAB 62 1.1 christos #undef NB 63 1.1 christos } 64 1.1 christos TEST_END 65 1.1 christos 66 1.1 christos static ssize_t 67 1.1 christos find_3_5_compute(ssize_t i, size_t nbits, bool bit, bool forward) { 68 1.1 christos for(; i < (ssize_t)nbits && i >= 0; i += (forward ? 1 : -1)) { 69 1.1 christos bool expected_bit = i % 3 == 0 || i % 5 == 0; 70 1.1 christos if (expected_bit == bit) { 71 1.1 christos return i; 72 1.1 christos } 73 1.1 christos } 74 1.1 christos return forward ? (ssize_t)nbits : (ssize_t)-1; 75 1.1 christos } 76 1.1 christos 77 1.1 christos static void 78 1.1 christos do_test_search_simple(size_t nbits) { 79 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 80 1.1 christos fb_group_t *fb = malloc(sz); 81 1.1 christos fb_init(fb, nbits); 82 1.1 christos 83 1.1 christos /* We pick multiples of 3 or 5. */ 84 1.1 christos for (size_t i = 0; i < nbits; i++) { 85 1.1 christos if (i % 3 == 0) { 86 1.1 christos fb_set(fb, nbits, i); 87 1.1 christos } 88 1.1 christos /* This tests double-setting a little, too. */ 89 1.1 christos if (i % 5 == 0) { 90 1.1 christos fb_set(fb, nbits, i); 91 1.1 christos } 92 1.1 christos } 93 1.1 christos for (size_t i = 0; i < nbits; i++) { 94 1.1 christos size_t ffs_compute = find_3_5_compute(i, nbits, true, true); 95 1.1 christos size_t ffs_search = fb_ffs(fb, nbits, i); 96 1.1 christos expect_zu_eq(ffs_compute, ffs_search, "ffs mismatch at %zu", i); 97 1.1 christos 98 1.1 christos ssize_t fls_compute = find_3_5_compute(i, nbits, true, false); 99 1.1 christos size_t fls_search = fb_fls(fb, nbits, i); 100 1.1 christos expect_zu_eq(fls_compute, fls_search, "fls mismatch at %zu", i); 101 1.1 christos 102 1.1 christos size_t ffu_compute = find_3_5_compute(i, nbits, false, true); 103 1.1 christos size_t ffu_search = fb_ffu(fb, nbits, i); 104 1.1 christos expect_zu_eq(ffu_compute, ffu_search, "ffu mismatch at %zu", i); 105 1.1 christos 106 1.1 christos size_t flu_compute = find_3_5_compute(i, nbits, false, false); 107 1.1 christos size_t flu_search = fb_flu(fb, nbits, i); 108 1.1 christos expect_zu_eq(flu_compute, flu_search, "flu mismatch at %zu", i); 109 1.1 christos } 110 1.1 christos 111 1.1 christos free(fb); 112 1.1 christos } 113 1.1 christos 114 1.1 christos TEST_BEGIN(test_search_simple) { 115 1.1 christos #define NB(nbits) \ 116 1.1 christos do_test_search_simple(nbits); 117 1.1 christos NBITS_TAB 118 1.1 christos #undef NB 119 1.1 christos } 120 1.1 christos TEST_END 121 1.1 christos 122 1.1 christos static void 123 1.1 christos expect_exhaustive_results(fb_group_t *mostly_full, fb_group_t *mostly_empty, 124 1.1 christos size_t nbits, size_t special_bit, size_t position) { 125 1.1 christos if (position < special_bit) { 126 1.1 christos expect_zu_eq(special_bit, fb_ffs(mostly_empty, nbits, position), 127 1.1 christos "mismatch at %zu, %zu", position, special_bit); 128 1.1 christos expect_zd_eq(-1, fb_fls(mostly_empty, nbits, position), 129 1.1 christos "mismatch at %zu, %zu", position, special_bit); 130 1.1 christos expect_zu_eq(position, fb_ffu(mostly_empty, nbits, position), 131 1.1 christos "mismatch at %zu, %zu", position, special_bit); 132 1.1 christos expect_zd_eq(position, fb_flu(mostly_empty, nbits, position), 133 1.1 christos "mismatch at %zu, %zu", position, special_bit); 134 1.1 christos 135 1.1 christos expect_zu_eq(position, fb_ffs(mostly_full, nbits, position), 136 1.1 christos "mismatch at %zu, %zu", position, special_bit); 137 1.1 christos expect_zd_eq(position, fb_fls(mostly_full, nbits, position), 138 1.1 christos "mismatch at %zu, %zu", position, special_bit); 139 1.1 christos expect_zu_eq(special_bit, fb_ffu(mostly_full, nbits, position), 140 1.1 christos "mismatch at %zu, %zu", position, special_bit); 141 1.1 christos expect_zd_eq(-1, fb_flu(mostly_full, nbits, position), 142 1.1 christos "mismatch at %zu, %zu", position, special_bit); 143 1.1 christos } else if (position == special_bit) { 144 1.1 christos expect_zu_eq(special_bit, fb_ffs(mostly_empty, nbits, position), 145 1.1 christos "mismatch at %zu, %zu", position, special_bit); 146 1.1 christos expect_zd_eq(special_bit, fb_fls(mostly_empty, nbits, position), 147 1.1 christos "mismatch at %zu, %zu", position, special_bit); 148 1.1 christos expect_zu_eq(position + 1, fb_ffu(mostly_empty, nbits, position), 149 1.1 christos "mismatch at %zu, %zu", position, special_bit); 150 1.1 christos expect_zd_eq(position - 1, fb_flu(mostly_empty, nbits, 151 1.1 christos position), "mismatch at %zu, %zu", position, special_bit); 152 1.1 christos 153 1.1 christos expect_zu_eq(position + 1, fb_ffs(mostly_full, nbits, position), 154 1.1 christos "mismatch at %zu, %zu", position, special_bit); 155 1.1 christos expect_zd_eq(position - 1, fb_fls(mostly_full, nbits, 156 1.1 christos position), "mismatch at %zu, %zu", position, special_bit); 157 1.1 christos expect_zu_eq(position, fb_ffu(mostly_full, nbits, position), 158 1.1 christos "mismatch at %zu, %zu", position, special_bit); 159 1.1 christos expect_zd_eq(position, fb_flu(mostly_full, nbits, position), 160 1.1 christos "mismatch at %zu, %zu", position, special_bit); 161 1.1 christos } else { 162 1.1 christos /* position > special_bit. */ 163 1.1 christos expect_zu_eq(nbits, fb_ffs(mostly_empty, nbits, position), 164 1.1 christos "mismatch at %zu, %zu", position, special_bit); 165 1.1 christos expect_zd_eq(special_bit, fb_fls(mostly_empty, nbits, 166 1.1 christos position), "mismatch at %zu, %zu", position, special_bit); 167 1.1 christos expect_zu_eq(position, fb_ffu(mostly_empty, nbits, position), 168 1.1 christos "mismatch at %zu, %zu", position, special_bit); 169 1.1 christos expect_zd_eq(position, fb_flu(mostly_empty, nbits, position), 170 1.1 christos "mismatch at %zu, %zu", position, special_bit); 171 1.1 christos 172 1.1 christos expect_zu_eq(position, fb_ffs(mostly_full, nbits, position), 173 1.1 christos "mismatch at %zu, %zu", position, special_bit); 174 1.1 christos expect_zd_eq(position, fb_fls(mostly_full, nbits, position), 175 1.1 christos "mismatch at %zu, %zu", position, special_bit); 176 1.1 christos expect_zu_eq(nbits, fb_ffu(mostly_full, nbits, position), 177 1.1 christos "mismatch at %zu, %zu", position, special_bit); 178 1.1 christos expect_zd_eq(special_bit, fb_flu(mostly_full, nbits, position), 179 1.1 christos "mismatch at %zu, %zu", position, special_bit); 180 1.1 christos } 181 1.1 christos } 182 1.1 christos 183 1.1 christos static void 184 1.1 christos do_test_search_exhaustive(size_t nbits) { 185 1.1 christos /* This test is quadratic; let's not get too big. */ 186 1.1 christos if (nbits > 1000) { 187 1.1 christos return; 188 1.1 christos } 189 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 190 1.1 christos fb_group_t *empty = malloc(sz); 191 1.1 christos fb_init(empty, nbits); 192 1.1 christos fb_group_t *full = malloc(sz); 193 1.1 christos fb_init(full, nbits); 194 1.1 christos fb_set_range(full, nbits, 0, nbits); 195 1.1 christos 196 1.1 christos for (size_t i = 0; i < nbits; i++) { 197 1.1 christos fb_set(empty, nbits, i); 198 1.1 christos fb_unset(full, nbits, i); 199 1.1 christos 200 1.1 christos for (size_t j = 0; j < nbits; j++) { 201 1.1 christos expect_exhaustive_results(full, empty, nbits, i, j); 202 1.1 christos } 203 1.1 christos fb_unset(empty, nbits, i); 204 1.1 christos fb_set(full, nbits, i); 205 1.1 christos } 206 1.1 christos 207 1.1 christos free(empty); 208 1.1 christos free(full); 209 1.1 christos } 210 1.1 christos 211 1.1 christos TEST_BEGIN(test_search_exhaustive) { 212 1.1 christos #define NB(nbits) \ 213 1.1 christos do_test_search_exhaustive(nbits); 214 1.1 christos NBITS_TAB 215 1.1 christos #undef NB 216 1.1 christos } 217 1.1 christos TEST_END 218 1.1 christos 219 1.1 christos TEST_BEGIN(test_range_simple) { 220 1.1 christos /* 221 1.1 christos * Just pick a constant big enough to have nontrivial middle sizes, and 222 1.1 christos * big enough that usages of things like weirdnum (below) near the 223 1.1 christos * beginning fit comfortably into the beginning of the bitmap. 224 1.1 christos */ 225 1.1 christos size_t nbits = 64 * 10; 226 1.1 christos size_t ngroups = FB_NGROUPS(nbits); 227 1.1 christos fb_group_t *fb = malloc(sizeof(fb_group_t) * ngroups); 228 1.1 christos fb_init(fb, nbits); 229 1.1 christos for (size_t i = 0; i < nbits; i++) { 230 1.1 christos if (i % 2 == 0) { 231 1.1 christos fb_set_range(fb, nbits, i, 1); 232 1.1 christos } 233 1.1 christos } 234 1.1 christos for (size_t i = 0; i < nbits; i++) { 235 1.1 christos expect_b_eq(i % 2 == 0, fb_get(fb, nbits, i), 236 1.1 christos "mismatch at position %zu", i); 237 1.1 christos } 238 1.1 christos fb_set_range(fb, nbits, 0, nbits / 2); 239 1.1 christos fb_unset_range(fb, nbits, nbits / 2, nbits / 2); 240 1.1 christos for (size_t i = 0; i < nbits; i++) { 241 1.1 christos expect_b_eq(i < nbits / 2, fb_get(fb, nbits, i), 242 1.1 christos "mismatch at position %zu", i); 243 1.1 christos } 244 1.1 christos 245 1.1 christos static const size_t weirdnum = 7; 246 1.1 christos fb_set_range(fb, nbits, 0, nbits); 247 1.1 christos fb_unset_range(fb, nbits, weirdnum, FB_GROUP_BITS + weirdnum); 248 1.1 christos for (size_t i = 0; i < nbits; i++) { 249 1.1 christos expect_b_eq(7 <= i && i <= 2 * weirdnum + FB_GROUP_BITS - 1, 250 1.1 christos !fb_get(fb, nbits, i), "mismatch at position %zu", i); 251 1.1 christos } 252 1.1 christos free(fb); 253 1.1 christos } 254 1.1 christos TEST_END 255 1.1 christos 256 1.1 christos static void 257 1.1 christos do_test_empty_full_exhaustive(size_t nbits) { 258 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 259 1.1 christos fb_group_t *empty = malloc(sz); 260 1.1 christos fb_init(empty, nbits); 261 1.1 christos fb_group_t *full = malloc(sz); 262 1.1 christos fb_init(full, nbits); 263 1.1 christos fb_set_range(full, nbits, 0, nbits); 264 1.1 christos 265 1.1 christos expect_true(fb_full(full, nbits), ""); 266 1.1 christos expect_false(fb_empty(full, nbits), ""); 267 1.1 christos expect_false(fb_full(empty, nbits), ""); 268 1.1 christos expect_true(fb_empty(empty, nbits), ""); 269 1.1 christos 270 1.1 christos for (size_t i = 0; i < nbits; i++) { 271 1.1 christos fb_set(empty, nbits, i); 272 1.1 christos fb_unset(full, nbits, i); 273 1.1 christos 274 1.1 christos expect_false(fb_empty(empty, nbits), "error at bit %zu", i); 275 1.1 christos if (nbits != 1) { 276 1.1 christos expect_false(fb_full(empty, nbits), 277 1.1 christos "error at bit %zu", i); 278 1.1 christos expect_false(fb_empty(full, nbits), 279 1.1 christos "error at bit %zu", i); 280 1.1 christos } else { 281 1.1 christos expect_true(fb_full(empty, nbits), 282 1.1 christos "error at bit %zu", i); 283 1.1 christos expect_true(fb_empty(full, nbits), 284 1.1 christos "error at bit %zu", i); 285 1.1 christos } 286 1.1 christos expect_false(fb_full(full, nbits), "error at bit %zu", i); 287 1.1 christos 288 1.1 christos fb_unset(empty, nbits, i); 289 1.1 christos fb_set(full, nbits, i); 290 1.1 christos } 291 1.1 christos 292 1.1 christos free(empty); 293 1.1 christos free(full); 294 1.1 christos } 295 1.1 christos 296 1.1 christos TEST_BEGIN(test_empty_full) { 297 1.1 christos #define NB(nbits) \ 298 1.1 christos do_test_empty_full_exhaustive(nbits); 299 1.1 christos NBITS_TAB 300 1.1 christos #undef NB 301 1.1 christos } 302 1.1 christos TEST_END 303 1.1 christos 304 1.1 christos /* 305 1.1 christos * This tests both iter_range and the longest range functionality, which is 306 1.1 christos * built closely on top of it. 307 1.1 christos */ 308 1.1 christos TEST_BEGIN(test_iter_range_simple) { 309 1.1 christos size_t set_limit = 30; 310 1.1 christos size_t nbits = 100; 311 1.1 christos fb_group_t fb[FB_NGROUPS(100)]; 312 1.1 christos 313 1.1 christos fb_init(fb, nbits); 314 1.1 christos 315 1.1 christos /* 316 1.1 christos * Failing to initialize these can lead to build failures with -Wall; 317 1.1 christos * the compiler can't prove that they're set. 318 1.1 christos */ 319 1.1 christos size_t begin = (size_t)-1; 320 1.1 christos size_t len = (size_t)-1; 321 1.1 christos bool result; 322 1.1 christos 323 1.1 christos /* A set of checks with only the first set_limit bits *set*. */ 324 1.1 christos fb_set_range(fb, nbits, 0, set_limit); 325 1.1 christos expect_zu_eq(set_limit, fb_srange_longest(fb, nbits), 326 1.1 christos "Incorrect longest set range"); 327 1.1 christos expect_zu_eq(nbits - set_limit, fb_urange_longest(fb, nbits), 328 1.1 christos "Incorrect longest unset range"); 329 1.1 christos for (size_t i = 0; i < set_limit; i++) { 330 1.1 christos result = fb_srange_iter(fb, nbits, i, &begin, &len); 331 1.1 christos expect_true(result, "Should have found a range at %zu", i); 332 1.1 christos expect_zu_eq(i, begin, "Incorrect begin at %zu", i); 333 1.1 christos expect_zu_eq(set_limit - i, len, "Incorrect len at %zu", i); 334 1.1 christos 335 1.1 christos result = fb_urange_iter(fb, nbits, i, &begin, &len); 336 1.1 christos expect_true(result, "Should have found a range at %zu", i); 337 1.1 christos expect_zu_eq(set_limit, begin, "Incorrect begin at %zu", i); 338 1.1 christos expect_zu_eq(nbits - set_limit, len, "Incorrect len at %zu", i); 339 1.1 christos 340 1.1 christos result = fb_srange_riter(fb, nbits, i, &begin, &len); 341 1.1 christos expect_true(result, "Should have found a range at %zu", i); 342 1.1 christos expect_zu_eq(0, begin, "Incorrect begin at %zu", i); 343 1.1 christos expect_zu_eq(i + 1, len, "Incorrect len at %zu", i); 344 1.1 christos 345 1.1 christos result = fb_urange_riter(fb, nbits, i, &begin, &len); 346 1.1 christos expect_false(result, "Should not have found a range at %zu", i); 347 1.1 christos } 348 1.1 christos for (size_t i = set_limit; i < nbits; i++) { 349 1.1 christos result = fb_srange_iter(fb, nbits, i, &begin, &len); 350 1.1 christos expect_false(result, "Should not have found a range at %zu", i); 351 1.1 christos 352 1.1 christos result = fb_urange_iter(fb, nbits, i, &begin, &len); 353 1.1 christos expect_true(result, "Should have found a range at %zu", i); 354 1.1 christos expect_zu_eq(i, begin, "Incorrect begin at %zu", i); 355 1.1 christos expect_zu_eq(nbits - i, len, "Incorrect len at %zu", i); 356 1.1 christos 357 1.1 christos result = fb_srange_riter(fb, nbits, i, &begin, &len); 358 1.1 christos expect_true(result, "Should have found a range at %zu", i); 359 1.1 christos expect_zu_eq(0, begin, "Incorrect begin at %zu", i); 360 1.1 christos expect_zu_eq(set_limit, len, "Incorrect len at %zu", i); 361 1.1 christos 362 1.1 christos result = fb_urange_riter(fb, nbits, i, &begin, &len); 363 1.1 christos expect_true(result, "Should have found a range at %zu", i); 364 1.1 christos expect_zu_eq(set_limit, begin, "Incorrect begin at %zu", i); 365 1.1 christos expect_zu_eq(i - set_limit + 1, len, "Incorrect len at %zu", i); 366 1.1 christos } 367 1.1 christos 368 1.1 christos /* A set of checks with only the first set_limit bits *unset*. */ 369 1.1 christos fb_unset_range(fb, nbits, 0, set_limit); 370 1.1 christos fb_set_range(fb, nbits, set_limit, nbits - set_limit); 371 1.1 christos expect_zu_eq(nbits - set_limit, fb_srange_longest(fb, nbits), 372 1.1 christos "Incorrect longest set range"); 373 1.1 christos expect_zu_eq(set_limit, fb_urange_longest(fb, nbits), 374 1.1 christos "Incorrect longest unset range"); 375 1.1 christos for (size_t i = 0; i < set_limit; i++) { 376 1.1 christos result = fb_srange_iter(fb, nbits, i, &begin, &len); 377 1.1 christos expect_true(result, "Should have found a range at %zu", i); 378 1.1 christos expect_zu_eq(set_limit, begin, "Incorrect begin at %zu", i); 379 1.1 christos expect_zu_eq(nbits - set_limit, len, "Incorrect len at %zu", i); 380 1.1 christos 381 1.1 christos result = fb_urange_iter(fb, nbits, i, &begin, &len); 382 1.1 christos expect_true(result, "Should have found a range at %zu", i); 383 1.1 christos expect_zu_eq(i, begin, "Incorrect begin at %zu", i); 384 1.1 christos expect_zu_eq(set_limit - i, len, "Incorrect len at %zu", i); 385 1.1 christos 386 1.1 christos result = fb_srange_riter(fb, nbits, i, &begin, &len); 387 1.1 christos expect_false(result, "Should not have found a range at %zu", i); 388 1.1 christos 389 1.1 christos result = fb_urange_riter(fb, nbits, i, &begin, &len); 390 1.1 christos expect_true(result, "Should not have found a range at %zu", i); 391 1.1 christos expect_zu_eq(0, begin, "Incorrect begin at %zu", i); 392 1.1 christos expect_zu_eq(i + 1, len, "Incorrect len at %zu", i); 393 1.1 christos } 394 1.1 christos for (size_t i = set_limit; i < nbits; i++) { 395 1.1 christos result = fb_srange_iter(fb, nbits, i, &begin, &len); 396 1.1 christos expect_true(result, "Should have found a range at %zu", i); 397 1.1 christos expect_zu_eq(i, begin, "Incorrect begin at %zu", i); 398 1.1 christos expect_zu_eq(nbits - i, len, "Incorrect len at %zu", i); 399 1.1 christos 400 1.1 christos result = fb_urange_iter(fb, nbits, i, &begin, &len); 401 1.1 christos expect_false(result, "Should not have found a range at %zu", i); 402 1.1 christos 403 1.1 christos result = fb_srange_riter(fb, nbits, i, &begin, &len); 404 1.1 christos expect_true(result, "Should have found a range at %zu", i); 405 1.1 christos expect_zu_eq(set_limit, begin, "Incorrect begin at %zu", i); 406 1.1 christos expect_zu_eq(i - set_limit + 1, len, "Incorrect len at %zu", i); 407 1.1 christos 408 1.1 christos result = fb_urange_riter(fb, nbits, i, &begin, &len); 409 1.1 christos expect_true(result, "Should have found a range at %zu", i); 410 1.1 christos expect_zu_eq(0, begin, "Incorrect begin at %zu", i); 411 1.1 christos expect_zu_eq(set_limit, len, "Incorrect len at %zu", i); 412 1.1 christos } 413 1.1 christos 414 1.1 christos } 415 1.1 christos TEST_END 416 1.1 christos 417 1.1 christos /* 418 1.1 christos * Doing this bit-by-bit is too slow for a real implementation, but for testing 419 1.1 christos * code, it's easy to get right. In the exhaustive tests, we'll compare the 420 1.1 christos * (fast but tricky) real implementation against the (slow but simple) testing 421 1.1 christos * one. 422 1.1 christos */ 423 1.1 christos static bool 424 1.1 christos fb_iter_simple(fb_group_t *fb, size_t nbits, size_t start, size_t *r_begin, 425 1.1 christos size_t *r_len, bool val, bool forward) { 426 1.1 christos ssize_t stride = (forward ? (ssize_t)1 : (ssize_t)-1); 427 1.1 christos ssize_t range_begin = (ssize_t)start; 428 1.1 christos for (; range_begin != (ssize_t)nbits && range_begin != -1; 429 1.1 christos range_begin += stride) { 430 1.1 christos if (fb_get(fb, nbits, range_begin) == val) { 431 1.1 christos ssize_t range_end = range_begin; 432 1.1 christos for (; range_end != (ssize_t)nbits && range_end != -1; 433 1.1 christos range_end += stride) { 434 1.1 christos if (fb_get(fb, nbits, range_end) != val) { 435 1.1 christos break; 436 1.1 christos } 437 1.1 christos } 438 1.1 christos if (forward) { 439 1.1 christos *r_begin = range_begin; 440 1.1 christos *r_len = range_end - range_begin; 441 1.1 christos } else { 442 1.1 christos *r_begin = range_end + 1; 443 1.1 christos *r_len = range_begin - range_end; 444 1.1 christos } 445 1.1 christos return true; 446 1.1 christos } 447 1.1 christos } 448 1.1 christos return false; 449 1.1 christos } 450 1.1 christos 451 1.1 christos /* Similar, but for finding longest ranges. */ 452 1.1 christos static size_t 453 1.1 christos fb_range_longest_simple(fb_group_t *fb, size_t nbits, bool val) { 454 1.1 christos size_t longest_so_far = 0; 455 1.1 christos for (size_t begin = 0; begin < nbits; begin++) { 456 1.1 christos if (fb_get(fb, nbits, begin) != val) { 457 1.1 christos continue; 458 1.1 christos } 459 1.1 christos size_t end = begin + 1; 460 1.1 christos for (; end < nbits; end++) { 461 1.1 christos if (fb_get(fb, nbits, end) != val) { 462 1.1 christos break; 463 1.1 christos } 464 1.1 christos } 465 1.1 christos if (end - begin > longest_so_far) { 466 1.1 christos longest_so_far = end - begin; 467 1.1 christos } 468 1.1 christos } 469 1.1 christos return longest_so_far; 470 1.1 christos } 471 1.1 christos 472 1.1 christos static void 473 1.1 christos expect_iter_results_at(fb_group_t *fb, size_t nbits, size_t pos, 474 1.1 christos bool val, bool forward) { 475 1.1 christos bool iter_res; 476 1.1 christos size_t iter_begin JEMALLOC_CC_SILENCE_INIT(0); 477 1.1 christos size_t iter_len JEMALLOC_CC_SILENCE_INIT(0); 478 1.1 christos if (val) { 479 1.1 christos if (forward) { 480 1.1 christos iter_res = fb_srange_iter(fb, nbits, pos, 481 1.1 christos &iter_begin, &iter_len); 482 1.1 christos } else { 483 1.1 christos iter_res = fb_srange_riter(fb, nbits, pos, 484 1.1 christos &iter_begin, &iter_len); 485 1.1 christos } 486 1.1 christos } else { 487 1.1 christos if (forward) { 488 1.1 christos iter_res = fb_urange_iter(fb, nbits, pos, 489 1.1 christos &iter_begin, &iter_len); 490 1.1 christos } else { 491 1.1 christos iter_res = fb_urange_riter(fb, nbits, pos, 492 1.1 christos &iter_begin, &iter_len); 493 1.1 christos } 494 1.1 christos } 495 1.1 christos 496 1.1 christos bool simple_iter_res; 497 1.1 christos /* 498 1.1 christos * These are dead stores, but the compiler can't always figure that out 499 1.1 christos * statically, and warns on the uninitialized variable. 500 1.1 christos */ 501 1.1 christos size_t simple_iter_begin = 0; 502 1.1 christos size_t simple_iter_len = 0; 503 1.1 christos simple_iter_res = fb_iter_simple(fb, nbits, pos, &simple_iter_begin, 504 1.1 christos &simple_iter_len, val, forward); 505 1.1 christos 506 1.1 christos expect_b_eq(iter_res, simple_iter_res, "Result mismatch at %zu", pos); 507 1.1 christos if (iter_res && simple_iter_res) { 508 1.1 christos assert_zu_eq(iter_begin, simple_iter_begin, 509 1.1 christos "Begin mismatch at %zu", pos); 510 1.1 christos expect_zu_eq(iter_len, simple_iter_len, 511 1.1 christos "Length mismatch at %zu", pos); 512 1.1 christos } 513 1.1 christos } 514 1.1 christos 515 1.1 christos static void 516 1.1 christos expect_iter_results(fb_group_t *fb, size_t nbits) { 517 1.1 christos for (size_t i = 0; i < nbits; i++) { 518 1.1 christos expect_iter_results_at(fb, nbits, i, false, false); 519 1.1 christos expect_iter_results_at(fb, nbits, i, false, true); 520 1.1 christos expect_iter_results_at(fb, nbits, i, true, false); 521 1.1 christos expect_iter_results_at(fb, nbits, i, true, true); 522 1.1 christos } 523 1.1 christos expect_zu_eq(fb_range_longest_simple(fb, nbits, true), 524 1.1 christos fb_srange_longest(fb, nbits), "Longest range mismatch"); 525 1.1 christos expect_zu_eq(fb_range_longest_simple(fb, nbits, false), 526 1.1 christos fb_urange_longest(fb, nbits), "Longest range mismatch"); 527 1.1 christos } 528 1.1 christos 529 1.1 christos static void 530 1.1 christos set_pattern_3(fb_group_t *fb, size_t nbits, bool zero_val) { 531 1.1 christos for (size_t i = 0; i < nbits; i++) { 532 1.1 christos if ((i % 6 < 3 && zero_val) || (i % 6 >= 3 && !zero_val)) { 533 1.1 christos fb_set(fb, nbits, i); 534 1.1 christos } else { 535 1.1 christos fb_unset(fb, nbits, i); 536 1.1 christos } 537 1.1 christos } 538 1.1 christos } 539 1.1 christos 540 1.1 christos static void 541 1.1 christos do_test_iter_range_exhaustive(size_t nbits) { 542 1.1 christos /* This test is also pretty slow. */ 543 1.1 christos if (nbits > 1000) { 544 1.1 christos return; 545 1.1 christos } 546 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 547 1.1 christos fb_group_t *fb = malloc(sz); 548 1.1 christos fb_init(fb, nbits); 549 1.1 christos 550 1.1 christos set_pattern_3(fb, nbits, /* zero_val */ true); 551 1.1 christos expect_iter_results(fb, nbits); 552 1.1 christos 553 1.1 christos set_pattern_3(fb, nbits, /* zero_val */ false); 554 1.1 christos expect_iter_results(fb, nbits); 555 1.1 christos 556 1.1 christos fb_set_range(fb, nbits, 0, nbits); 557 1.1 christos fb_unset_range(fb, nbits, 0, nbits / 2 == 0 ? 1 : nbits / 2); 558 1.1 christos expect_iter_results(fb, nbits); 559 1.1 christos 560 1.1 christos fb_unset_range(fb, nbits, 0, nbits); 561 1.1 christos fb_set_range(fb, nbits, 0, nbits / 2 == 0 ? 1: nbits / 2); 562 1.1 christos expect_iter_results(fb, nbits); 563 1.1 christos 564 1.1 christos free(fb); 565 1.1 christos } 566 1.1 christos 567 1.1 christos /* 568 1.1 christos * Like test_iter_range_simple, this tests both iteration and longest-range 569 1.1 christos * computation. 570 1.1 christos */ 571 1.1 christos TEST_BEGIN(test_iter_range_exhaustive) { 572 1.1 christos #define NB(nbits) \ 573 1.1 christos do_test_iter_range_exhaustive(nbits); 574 1.1 christos NBITS_TAB 575 1.1 christos #undef NB 576 1.1 christos } 577 1.1 christos TEST_END 578 1.1 christos 579 1.1 christos /* 580 1.1 christos * If all set bits in the bitmap are contiguous, in [set_start, set_end), 581 1.1 christos * returns the number of set bits in [scount_start, scount_end). 582 1.1 christos */ 583 1.1 christos static size_t 584 1.1 christos scount_contiguous(size_t set_start, size_t set_end, size_t scount_start, 585 1.1 christos size_t scount_end) { 586 1.1 christos /* No overlap. */ 587 1.1 christos if (set_end <= scount_start || scount_end <= set_start) { 588 1.1 christos return 0; 589 1.1 christos } 590 1.1 christos /* set range contains scount range */ 591 1.1 christos if (set_start <= scount_start && set_end >= scount_end) { 592 1.1 christos return scount_end - scount_start; 593 1.1 christos } 594 1.1 christos /* scount range contains set range. */ 595 1.1 christos if (scount_start <= set_start && scount_end >= set_end) { 596 1.1 christos return set_end - set_start; 597 1.1 christos } 598 1.1 christos /* Partial overlap, with set range starting first. */ 599 1.1 christos if (set_start < scount_start && set_end < scount_end) { 600 1.1 christos return set_end - scount_start; 601 1.1 christos } 602 1.1 christos /* Partial overlap, with scount range starting first. */ 603 1.1 christos if (scount_start < set_start && scount_end < set_end) { 604 1.1 christos return scount_end - set_start; 605 1.1 christos } 606 1.1 christos /* 607 1.1 christos * Trigger an assert failure; the above list should have been 608 1.1 christos * exhaustive. 609 1.1 christos */ 610 1.1 christos unreachable(); 611 1.1 christos } 612 1.1 christos 613 1.1 christos static size_t 614 1.1 christos ucount_contiguous(size_t set_start, size_t set_end, size_t ucount_start, 615 1.1 christos size_t ucount_end) { 616 1.1 christos /* No overlap. */ 617 1.1 christos if (set_end <= ucount_start || ucount_end <= set_start) { 618 1.1 christos return ucount_end - ucount_start; 619 1.1 christos } 620 1.1 christos /* set range contains ucount range */ 621 1.1 christos if (set_start <= ucount_start && set_end >= ucount_end) { 622 1.1 christos return 0; 623 1.1 christos } 624 1.1 christos /* ucount range contains set range. */ 625 1.1 christos if (ucount_start <= set_start && ucount_end >= set_end) { 626 1.1 christos return (ucount_end - ucount_start) - (set_end - set_start); 627 1.1 christos } 628 1.1 christos /* Partial overlap, with set range starting first. */ 629 1.1 christos if (set_start < ucount_start && set_end < ucount_end) { 630 1.1 christos return ucount_end - set_end; 631 1.1 christos } 632 1.1 christos /* Partial overlap, with ucount range starting first. */ 633 1.1 christos if (ucount_start < set_start && ucount_end < set_end) { 634 1.1 christos return set_start - ucount_start; 635 1.1 christos } 636 1.1 christos /* 637 1.1 christos * Trigger an assert failure; the above list should have been 638 1.1 christos * exhaustive. 639 1.1 christos */ 640 1.1 christos unreachable(); 641 1.1 christos } 642 1.1 christos 643 1.1 christos static void 644 1.1 christos expect_count_match_contiguous(fb_group_t *fb, size_t nbits, size_t set_start, 645 1.1 christos size_t set_end) { 646 1.1 christos for (size_t i = 0; i < nbits; i++) { 647 1.1 christos for (size_t j = i + 1; j <= nbits; j++) { 648 1.1 christos size_t cnt = j - i; 649 1.1 christos size_t scount_expected = scount_contiguous(set_start, 650 1.1 christos set_end, i, j); 651 1.1 christos size_t scount_computed = fb_scount(fb, nbits, i, cnt); 652 1.1 christos expect_zu_eq(scount_expected, scount_computed, 653 1.1 christos "fb_scount error with nbits=%zu, start=%zu, " 654 1.1 christos "cnt=%zu, with bits set in [%zu, %zu)", 655 1.1 christos nbits, i, cnt, set_start, set_end); 656 1.1 christos 657 1.1 christos size_t ucount_expected = ucount_contiguous(set_start, 658 1.1 christos set_end, i, j); 659 1.1 christos size_t ucount_computed = fb_ucount(fb, nbits, i, cnt); 660 1.1 christos assert_zu_eq(ucount_expected, ucount_computed, 661 1.1 christos "fb_ucount error with nbits=%zu, start=%zu, " 662 1.1 christos "cnt=%zu, with bits set in [%zu, %zu)", 663 1.1 christos nbits, i, cnt, set_start, set_end); 664 1.1 christos 665 1.1 christos } 666 1.1 christos } 667 1.1 christos } 668 1.1 christos 669 1.1 christos static void 670 1.1 christos do_test_count_contiguous(size_t nbits) { 671 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 672 1.1 christos fb_group_t *fb = malloc(sz); 673 1.1 christos 674 1.1 christos fb_init(fb, nbits); 675 1.1 christos 676 1.1 christos expect_count_match_contiguous(fb, nbits, 0, 0); 677 1.1 christos for (size_t i = 0; i < nbits; i++) { 678 1.1 christos fb_set(fb, nbits, i); 679 1.1 christos expect_count_match_contiguous(fb, nbits, 0, i + 1); 680 1.1 christos } 681 1.1 christos 682 1.1 christos for (size_t i = 0; i < nbits; i++) { 683 1.1 christos fb_unset(fb, nbits, i); 684 1.1 christos expect_count_match_contiguous(fb, nbits, i + 1, nbits); 685 1.1 christos } 686 1.1 christos 687 1.1 christos free(fb); 688 1.1 christos } 689 1.1 christos 690 1.1 christos TEST_BEGIN(test_count_contiguous_simple) { 691 1.1 christos enum {nbits = 300}; 692 1.1 christos fb_group_t fb[FB_NGROUPS(nbits)]; 693 1.1 christos fb_init(fb, nbits); 694 1.1 christos /* Just an arbitrary number. */ 695 1.1 christos size_t start = 23; 696 1.1 christos 697 1.1 christos fb_set_range(fb, nbits, start, 30 - start); 698 1.1 christos expect_count_match_contiguous(fb, nbits, start, 30); 699 1.1 christos 700 1.1 christos fb_set_range(fb, nbits, start, 40 - start); 701 1.1 christos expect_count_match_contiguous(fb, nbits, start, 40); 702 1.1 christos 703 1.1 christos fb_set_range(fb, nbits, start, 70 - start); 704 1.1 christos expect_count_match_contiguous(fb, nbits, start, 70); 705 1.1 christos 706 1.1 christos fb_set_range(fb, nbits, start, 120 - start); 707 1.1 christos expect_count_match_contiguous(fb, nbits, start, 120); 708 1.1 christos 709 1.1 christos fb_set_range(fb, nbits, start, 150 - start); 710 1.1 christos expect_count_match_contiguous(fb, nbits, start, 150); 711 1.1 christos 712 1.1 christos fb_set_range(fb, nbits, start, 200 - start); 713 1.1 christos expect_count_match_contiguous(fb, nbits, start, 200); 714 1.1 christos 715 1.1 christos fb_set_range(fb, nbits, start, 290 - start); 716 1.1 christos expect_count_match_contiguous(fb, nbits, start, 290); 717 1.1 christos } 718 1.1 christos TEST_END 719 1.1 christos 720 1.1 christos TEST_BEGIN(test_count_contiguous) { 721 1.1 christos #define NB(nbits) \ 722 1.1 christos /* This test is *particularly* slow in debug builds. */ \ 723 1.1 christos if ((!config_debug && nbits < 300) || nbits < 150) { \ 724 1.1 christos do_test_count_contiguous(nbits); \ 725 1.1 christos } 726 1.1 christos NBITS_TAB 727 1.1 christos #undef NB 728 1.1 christos } 729 1.1 christos TEST_END 730 1.1 christos 731 1.1 christos static void 732 1.1 christos expect_count_match_alternating(fb_group_t *fb_even, fb_group_t *fb_odd, 733 1.1 christos size_t nbits) { 734 1.1 christos for (size_t i = 0; i < nbits; i++) { 735 1.1 christos for (size_t j = i + 1; j <= nbits; j++) { 736 1.1 christos size_t cnt = j - i; 737 1.1 christos size_t odd_scount = cnt / 2 738 1.1 christos + (size_t)(cnt % 2 == 1 && i % 2 == 1); 739 1.1 christos size_t odd_scount_computed = fb_scount(fb_odd, nbits, 740 1.1 christos i, j - i); 741 1.1 christos assert_zu_eq(odd_scount, odd_scount_computed, 742 1.1 christos "fb_scount error with nbits=%zu, start=%zu, " 743 1.1 christos "cnt=%zu, with alternating bits set.", 744 1.1 christos nbits, i, j - i); 745 1.1 christos 746 1.1 christos size_t odd_ucount = cnt / 2 747 1.1 christos + (size_t)(cnt % 2 == 1 && i % 2 == 0); 748 1.1 christos size_t odd_ucount_computed = fb_ucount(fb_odd, nbits, 749 1.1 christos i, j - i); 750 1.1 christos assert_zu_eq(odd_ucount, odd_ucount_computed, 751 1.1 christos "fb_ucount error with nbits=%zu, start=%zu, " 752 1.1 christos "cnt=%zu, with alternating bits set.", 753 1.1 christos nbits, i, j - i); 754 1.1 christos 755 1.1 christos size_t even_scount = cnt / 2 756 1.1 christos + (size_t)(cnt % 2 == 1 && i % 2 == 0); 757 1.1 christos size_t even_scount_computed = fb_scount(fb_even, nbits, 758 1.1 christos i, j - i); 759 1.1 christos assert_zu_eq(even_scount, even_scount_computed, 760 1.1 christos "fb_scount error with nbits=%zu, start=%zu, " 761 1.1 christos "cnt=%zu, with alternating bits set.", 762 1.1 christos nbits, i, j - i); 763 1.1 christos 764 1.1 christos size_t even_ucount = cnt / 2 765 1.1 christos + (size_t)(cnt % 2 == 1 && i % 2 == 1); 766 1.1 christos size_t even_ucount_computed = fb_ucount(fb_even, nbits, 767 1.1 christos i, j - i); 768 1.1 christos assert_zu_eq(even_ucount, even_ucount_computed, 769 1.1 christos "fb_ucount error with nbits=%zu, start=%zu, " 770 1.1 christos "cnt=%zu, with alternating bits set.", 771 1.1 christos nbits, i, j - i); 772 1.1 christos } 773 1.1 christos } 774 1.1 christos } 775 1.1 christos 776 1.1 christos static void 777 1.1 christos do_test_count_alternating(size_t nbits) { 778 1.1 christos if (nbits > 1000) { 779 1.1 christos return; 780 1.1 christos } 781 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 782 1.1 christos fb_group_t *fb_even = malloc(sz); 783 1.1 christos fb_group_t *fb_odd = malloc(sz); 784 1.1 christos 785 1.1 christos fb_init(fb_even, nbits); 786 1.1 christos fb_init(fb_odd, nbits); 787 1.1 christos 788 1.1 christos for (size_t i = 0; i < nbits; i++) { 789 1.1 christos if (i % 2 == 0) { 790 1.1 christos fb_set(fb_even, nbits, i); 791 1.1 christos } else { 792 1.1 christos fb_set(fb_odd, nbits, i); 793 1.1 christos } 794 1.1 christos } 795 1.1 christos 796 1.1 christos expect_count_match_alternating(fb_even, fb_odd, nbits); 797 1.1 christos 798 1.1 christos free(fb_even); 799 1.1 christos free(fb_odd); 800 1.1 christos } 801 1.1 christos 802 1.1 christos TEST_BEGIN(test_count_alternating) { 803 1.1 christos #define NB(nbits) \ 804 1.1 christos do_test_count_alternating(nbits); 805 1.1 christos NBITS_TAB 806 1.1 christos #undef NB 807 1.1 christos } 808 1.1 christos TEST_END 809 1.1 christos 810 1.1 christos static void 811 1.1 christos do_test_bit_op(size_t nbits, bool (*op)(bool a, bool b), 812 1.1 christos void (*fb_op)(fb_group_t *dst, fb_group_t *src1, fb_group_t *src2, size_t nbits)) { 813 1.1 christos size_t sz = FB_NGROUPS(nbits) * sizeof(fb_group_t); 814 1.1 christos fb_group_t *fb1 = malloc(sz); 815 1.1 christos fb_group_t *fb2 = malloc(sz); 816 1.1 christos fb_group_t *fb_result = malloc(sz); 817 1.1 christos fb_init(fb1, nbits); 818 1.1 christos fb_init(fb2, nbits); 819 1.1 christos fb_init(fb_result, nbits); 820 1.1 christos 821 1.1 christos /* Just two random numbers. */ 822 1.1 christos const uint64_t prng_init1 = (uint64_t)0X4E9A9DE6A35691CDULL; 823 1.1 christos const uint64_t prng_init2 = (uint64_t)0X7856E396B063C36EULL; 824 1.1 christos 825 1.1 christos uint64_t prng1 = prng_init1; 826 1.1 christos uint64_t prng2 = prng_init2; 827 1.1 christos 828 1.1 christos for (size_t i = 0; i < nbits; i++) { 829 1.1 christos bool bit1 = ((prng1 & (1ULL << (i % 64))) != 0); 830 1.1 christos bool bit2 = ((prng2 & (1ULL << (i % 64))) != 0); 831 1.1 christos 832 1.1 christos if (bit1) { 833 1.1 christos fb_set(fb1, nbits, i); 834 1.1 christos } 835 1.1 christos if (bit2) { 836 1.1 christos fb_set(fb2, nbits, i); 837 1.1 christos } 838 1.1 christos 839 1.1 christos if (i % 64 == 0) { 840 1.1 christos prng1 = prng_state_next_u64(prng1); 841 1.1 christos prng2 = prng_state_next_u64(prng2); 842 1.1 christos } 843 1.1 christos } 844 1.1 christos 845 1.1 christos fb_op(fb_result, fb1, fb2, nbits); 846 1.1 christos 847 1.1 christos /* Reset the prngs to replay them. */ 848 1.1 christos prng1 = prng_init1; 849 1.1 christos prng2 = prng_init2; 850 1.1 christos 851 1.1 christos for (size_t i = 0; i < nbits; i++) { 852 1.1 christos bool bit1 = ((prng1 & (1ULL << (i % 64))) != 0); 853 1.1 christos bool bit2 = ((prng2 & (1ULL << (i % 64))) != 0); 854 1.1 christos 855 1.1 christos /* Original bitmaps shouldn't change. */ 856 1.1 christos expect_b_eq(bit1, fb_get(fb1, nbits, i), "difference at bit %zu", i); 857 1.1 christos expect_b_eq(bit2, fb_get(fb2, nbits, i), "difference at bit %zu", i); 858 1.1 christos 859 1.1 christos /* New one should be bitwise and. */ 860 1.1 christos expect_b_eq(op(bit1, bit2), fb_get(fb_result, nbits, i), 861 1.1 christos "difference at bit %zu", i); 862 1.1 christos 863 1.1 christos /* Update the same way we did last time. */ 864 1.1 christos if (i % 64 == 0) { 865 1.1 christos prng1 = prng_state_next_u64(prng1); 866 1.1 christos prng2 = prng_state_next_u64(prng2); 867 1.1 christos } 868 1.1 christos } 869 1.1 christos 870 1.1 christos free(fb1); 871 1.1 christos free(fb2); 872 1.1 christos free(fb_result); 873 1.1 christos } 874 1.1 christos 875 1.1 christos static bool 876 1.1 christos binary_and(bool a, bool b) { 877 1.1 christos return a & b; 878 1.1 christos } 879 1.1 christos 880 1.1 christos static void 881 1.1 christos do_test_bit_and(size_t nbits) { 882 1.1 christos do_test_bit_op(nbits, &binary_and, &fb_bit_and); 883 1.1 christos } 884 1.1 christos 885 1.1 christos TEST_BEGIN(test_bit_and) { 886 1.1 christos #define NB(nbits) \ 887 1.1 christos do_test_bit_and(nbits); 888 1.1 christos NBITS_TAB 889 1.1 christos #undef NB 890 1.1 christos } 891 1.1 christos TEST_END 892 1.1 christos 893 1.1 christos static bool 894 1.1 christos binary_or(bool a, bool b) { 895 1.1 christos return a | b; 896 1.1 christos } 897 1.1 christos 898 1.1 christos static void 899 1.1 christos do_test_bit_or(size_t nbits) { 900 1.1 christos do_test_bit_op(nbits, &binary_or, &fb_bit_or); 901 1.1 christos } 902 1.1 christos 903 1.1 christos TEST_BEGIN(test_bit_or) { 904 1.1 christos #define NB(nbits) \ 905 1.1 christos do_test_bit_or(nbits); 906 1.1 christos NBITS_TAB 907 1.1 christos #undef NB 908 1.1 christos } 909 1.1 christos TEST_END 910 1.1 christos 911 1.1 christos static bool 912 1.1 christos binary_not(bool a, bool b) { 913 1.1 christos (void)b; 914 1.1 christos return !a; 915 1.1 christos } 916 1.1 christos 917 1.1 christos static void 918 1.1 christos fb_bit_not_shim(fb_group_t *dst, fb_group_t *src1, fb_group_t *src2, 919 1.1 christos size_t nbits) { 920 1.1 christos (void)src2; 921 1.1 christos fb_bit_not(dst, src1, nbits); 922 1.1 christos } 923 1.1 christos 924 1.1 christos static void 925 1.1 christos do_test_bit_not(size_t nbits) { 926 1.1 christos do_test_bit_op(nbits, &binary_not, &fb_bit_not_shim); 927 1.1 christos } 928 1.1 christos 929 1.1 christos TEST_BEGIN(test_bit_not) { 930 1.1 christos #define NB(nbits) \ 931 1.1 christos do_test_bit_not(nbits); 932 1.1 christos NBITS_TAB 933 1.1 christos #undef NB 934 1.1 christos } 935 1.1 christos TEST_END 936 1.1 christos 937 1.1 christos int 938 1.1 christos main(void) { 939 1.1 christos return test_no_reentrancy( 940 1.1 christos test_fb_init, 941 1.1 christos test_get_set_unset, 942 1.1 christos test_search_simple, 943 1.1 christos test_search_exhaustive, 944 1.1 christos test_range_simple, 945 1.1 christos test_empty_full, 946 1.1 christos test_iter_range_simple, 947 1.1 christos test_iter_range_exhaustive, 948 1.1 christos test_count_contiguous_simple, 949 1.1 christos test_count_contiguous, 950 1.1 christos test_count_alternating, 951 1.1 christos test_bit_and, 952 1.1 christos test_bit_or, 953 1.1 christos test_bit_not); 954 1.1 christos } 955