1 /*
2 Copyright (c) 2006, 2020, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <gtest/gtest.h>
26 #include <sys/types.h>
27
28 #include "my_bitmap.h"
29 #include "my_inttypes.h"
30 #include "my_thread.h"
31
32 namespace my_bitmap_unittest {
33
34 const uint MAX_TESTED_BITMAP_SIZE = 1024;
35
get_rand_bit(uint bitsize)36 uint get_rand_bit(uint bitsize) { return (rand() % bitsize); }
37
test_set_get_clear_bit(MY_BITMAP * map,uint bitsize)38 bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) {
39 uint i, test_bit;
40 uint no_loops = bitsize > 128 ? 128 : bitsize;
41 for (i = 0; i < no_loops; i++) {
42 test_bit = get_rand_bit(bitsize);
43 bitmap_set_bit(map, test_bit);
44 if (!bitmap_is_set(map, test_bit)) goto error1;
45 bitmap_clear_bit(map, test_bit);
46 if (bitmap_is_set(map, test_bit)) goto error2;
47 }
48 return false;
49 error1:
50 ADD_FAILURE() << "Error in set bit bit=" << test_bit;
51 return true;
52 error2:
53 ADD_FAILURE() << "Error in clear bit bit=" << test_bit;
54 return true;
55 }
56
test_flip_bit(MY_BITMAP * map,uint bitsize)57 bool test_flip_bit(MY_BITMAP *map, uint bitsize) {
58 uint i, test_bit;
59 uint no_loops = bitsize > 128 ? 128 : bitsize;
60 for (i = 0; i < no_loops; i++) {
61 test_bit = get_rand_bit(bitsize);
62 bitmap_flip_bit(map, test_bit);
63 if (!bitmap_is_set(map, test_bit)) goto error1;
64 bitmap_flip_bit(map, test_bit);
65 if (bitmap_is_set(map, test_bit)) goto error2;
66 }
67 return false;
68 error1:
69 ADD_FAILURE() << "Error in flip bit 1 bit=" << test_bit;
70 return true;
71 error2:
72 ADD_FAILURE() << "Error in flip bit 2 bit=" << test_bit;
73 return true;
74 }
75
test_get_all_bits(MY_BITMAP * map,uint bitsize)76 bool test_get_all_bits(MY_BITMAP *map, uint bitsize) {
77 uint i;
78 bitmap_set_all(map);
79 if (!bitmap_is_set_all(map)) goto error1;
80 if (!bitmap_is_prefix(map, bitsize)) goto error5;
81 bitmap_clear_all(map);
82 if (!bitmap_is_clear_all(map)) goto error2;
83 if (!bitmap_is_prefix(map, 0)) goto error6;
84 for (i = 0; i < bitsize; i++) bitmap_set_bit(map, i);
85 if (!bitmap_is_set_all(map)) goto error3;
86 for (i = 0; i < bitsize; i++) bitmap_clear_bit(map, i);
87 if (!bitmap_is_clear_all(map)) goto error4;
88 return false;
89 error1:
90 ADD_FAILURE() << "Error in set_all";
91 return true;
92 error2:
93 ADD_FAILURE() << "Error in clear_all";
94 return true;
95 error3:
96 ADD_FAILURE() << "Error in bitmap_is_set_all";
97 return true;
98 error4:
99 ADD_FAILURE() << "Error in bitmap_is_clear_all";
100 return true;
101 error5:
102 ADD_FAILURE() << "Error in set_all through set_prefix";
103 return true;
104 error6:
105 ADD_FAILURE() << "Error in clear_all through set_prefix";
106 return true;
107 }
108
test_compare_operators(MY_BITMAP * map,uint bitsize)109 bool test_compare_operators(MY_BITMAP *map, uint bitsize) {
110 uint i, j, test_bit1, test_bit2, test_bit3, test_bit4;
111 uint no_loops = bitsize > 128 ? 128 : bitsize;
112 MY_BITMAP map2_obj, map3_obj;
113 MY_BITMAP *map2 = &map2_obj, *map3 = &map3_obj;
114 my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
115 my_bitmap_map map3buf[MAX_TESTED_BITMAP_SIZE];
116 bitmap_init(&map2_obj, map2buf, bitsize);
117 bitmap_init(&map3_obj, map3buf, bitsize);
118 bitmap_clear_all(map2);
119 bitmap_clear_all(map3);
120 for (i = 0; i < no_loops; i++) {
121 test_bit1 = get_rand_bit(bitsize);
122 bitmap_set_prefix(map, test_bit1);
123 test_bit2 = get_rand_bit(bitsize);
124 bitmap_set_prefix(map2, test_bit2);
125 bitmap_intersect(map, map2);
126 test_bit3 = test_bit2 < test_bit1 ? test_bit2 : test_bit1;
127 bitmap_set_prefix(map3, test_bit3);
128 if (!bitmap_cmp(map, map3)) goto error1;
129 bitmap_clear_all(map);
130 bitmap_clear_all(map2);
131 bitmap_clear_all(map3);
132 test_bit1 = get_rand_bit(bitsize);
133 test_bit2 = get_rand_bit(bitsize);
134 test_bit3 = get_rand_bit(bitsize);
135 bitmap_set_prefix(map, test_bit1);
136 bitmap_set_prefix(map2, test_bit2);
137 test_bit3 = test_bit2 > test_bit1 ? test_bit2 : test_bit1;
138 bitmap_set_prefix(map3, test_bit3);
139 bitmap_union(map, map2);
140 if (!bitmap_cmp(map, map3)) goto error2;
141 bitmap_clear_all(map);
142 bitmap_clear_all(map2);
143 bitmap_clear_all(map3);
144 test_bit1 = get_rand_bit(bitsize);
145 test_bit2 = get_rand_bit(bitsize);
146 test_bit3 = get_rand_bit(bitsize);
147 bitmap_set_prefix(map, test_bit1);
148 bitmap_set_prefix(map2, test_bit2);
149 bitmap_xor(map, map2);
150 test_bit3 = test_bit2 > test_bit1 ? test_bit2 : test_bit1;
151 test_bit4 = test_bit2 < test_bit1 ? test_bit2 : test_bit1;
152 bitmap_set_prefix(map3, test_bit3);
153 for (j = 0; j < test_bit4; j++) bitmap_clear_bit(map3, j);
154 if (!bitmap_cmp(map, map3)) goto error3;
155 bitmap_clear_all(map);
156 bitmap_clear_all(map2);
157 bitmap_clear_all(map3);
158 test_bit1 = get_rand_bit(bitsize);
159 test_bit2 = get_rand_bit(bitsize);
160 test_bit3 = get_rand_bit(bitsize);
161 bitmap_set_prefix(map, test_bit1);
162 bitmap_set_prefix(map2, test_bit2);
163 bitmap_subtract(map, map2);
164 if (test_bit2 < test_bit1) {
165 bitmap_set_prefix(map3, test_bit1);
166 for (j = 0; j < test_bit2; j++) bitmap_clear_bit(map3, j);
167 }
168 if (!bitmap_cmp(map, map3)) goto error4;
169 bitmap_clear_all(map);
170 bitmap_clear_all(map2);
171 bitmap_clear_all(map3);
172 test_bit1 = get_rand_bit(bitsize);
173 bitmap_set_prefix(map, test_bit1);
174 bitmap_invert(map);
175 bitmap_set_all(map3);
176 for (j = 0; j < test_bit1; j++) bitmap_clear_bit(map3, j);
177 if (!bitmap_cmp(map, map3)) goto error5;
178 bitmap_clear_all(map);
179 bitmap_clear_all(map3);
180 }
181 return false;
182 error1:
183 ADD_FAILURE() << "intersect error size1=" << test_bit1
184 << ",size2=" << test_bit2;
185 return true;
186 error2:
187 ADD_FAILURE() << "union error size1=" << test_bit1 << ",size2=" << test_bit2;
188 return true;
189 error3:
190 ADD_FAILURE() << "xor error size1=" << test_bit1 << ",size2=" << test_bit2;
191 return true;
192 error4:
193 ADD_FAILURE() << "subtract error size1=" << test_bit1
194 << ",size2=" << test_bit2;
195 return true;
196 error5:
197 ADD_FAILURE() << "invert error size=" << test_bit1;
198 return true;
199 }
200
test_count_bits_set(MY_BITMAP * map,uint bitsize)201 bool test_count_bits_set(MY_BITMAP *map, uint bitsize) {
202 uint i, bit_count = 0, test_bit;
203 uint no_loops = bitsize > 128 ? 128 : bitsize;
204 for (i = 0; i < no_loops; i++) {
205 test_bit = get_rand_bit(bitsize);
206 if (!bitmap_is_set(map, test_bit)) {
207 bitmap_set_bit(map, test_bit);
208 bit_count++;
209 }
210 }
211 if (bit_count == 0 && bitsize > 0) goto error1;
212 if (bitmap_bits_set(map) != bit_count) goto error2;
213 return false;
214 error1:
215 ADD_FAILURE() << "No bits set";
216 return true;
217 error2:
218 ADD_FAILURE() << "Wrong count of bits set";
219 return true;
220 }
221
test_get_first_bit(MY_BITMAP * map,uint bitsize)222 bool test_get_first_bit(MY_BITMAP *map, uint bitsize) {
223 uint i, test_bit = 0;
224 uint no_loops = bitsize > 128 ? 128 : bitsize;
225
226 bitmap_set_all(map);
227 for (i = 0; i < bitsize; i++) bitmap_clear_bit(map, i);
228 if (bitmap_get_first_set(map) != MY_BIT_NONE) goto error1;
229 bitmap_clear_all(map);
230 for (i = 0; i < bitsize; i++) bitmap_set_bit(map, i);
231 if (bitmap_get_first(map) != MY_BIT_NONE) goto error2;
232 bitmap_clear_all(map);
233
234 for (i = 0; i < no_loops; i++) {
235 test_bit = get_rand_bit(bitsize);
236 bitmap_set_bit(map, test_bit);
237 if (bitmap_get_first_set(map) != test_bit) goto error1;
238 bitmap_set_all(map);
239 bitmap_clear_bit(map, test_bit);
240 if (bitmap_get_first(map) != test_bit) goto error2;
241 bitmap_clear_all(map);
242 }
243 return false;
244 error1:
245 ADD_FAILURE() << "get_first_set error prefix_size=" << test_bit;
246 return true;
247 error2:
248 ADD_FAILURE() << "get_first error prefix_size=" << test_bit;
249 return true;
250 }
251
test_set_next_bit(MY_BITMAP * map,uint bitsize)252 bool test_set_next_bit(MY_BITMAP *map, uint bitsize) {
253 uint i, j, test_bit;
254 uint no_loops = bitsize > 128 ? 128 : bitsize;
255 for (i = 0; i < no_loops; i++) {
256 test_bit = get_rand_bit(bitsize);
257 for (j = 0; j < test_bit; j++) bitmap_set_next(map);
258 if (!bitmap_is_prefix(map, test_bit)) goto error1;
259 bitmap_clear_all(map);
260 }
261 return false;
262 error1:
263 ADD_FAILURE() << "set_next error prefix_size=" << test_bit;
264 return true;
265 }
266
test_get_next_bit(MY_BITMAP * map,uint bitsize)267 bool test_get_next_bit(MY_BITMAP *map, uint bitsize) {
268 uint i, bit_count = 0, test_bit, next_count = 0;
269 uint no_loops = bitsize > 128 ? 128 : bitsize;
270 for (i = 0; i < no_loops; i++) {
271 test_bit = get_rand_bit(bitsize);
272 if (!bitmap_is_set(map, test_bit)) {
273 bitmap_set_bit(map, test_bit);
274 bit_count++;
275 }
276 }
277 if (bit_count == 0 && bitsize > 0) goto error1;
278 if (bitmap_bits_set(map) != bit_count) goto error2;
279
280 for (test_bit = bitmap_get_first_set(map); test_bit != MY_BIT_NONE;
281 test_bit = bitmap_get_next_set(map, test_bit)) {
282 if (test_bit >= bitsize) goto error3;
283 if (!bitmap_is_set(map, test_bit)) goto error4;
284 next_count++;
285 }
286 if (next_count != bit_count) goto error5;
287 return false;
288 error1:
289 ADD_FAILURE() << "No bits set";
290 return true;
291 error2:
292 ADD_FAILURE() << "Wrong count of bits set";
293 return true;
294 error3:
295 ADD_FAILURE() << "get_next_set out of range";
296 return true;
297 error4:
298 ADD_FAILURE() << "get_next_set bit not set";
299 return true;
300 error5:
301 ADD_FAILURE() << "Wrong count get_next_set";
302 return true;
303 }
304
test_prefix(MY_BITMAP * map,uint bitsize)305 bool test_prefix(MY_BITMAP *map, uint bitsize) {
306 uint i, j, test_bit;
307 uint no_loops = bitsize > 128 ? 128 : bitsize;
308 for (i = 0; i < no_loops; i++) {
309 test_bit = get_rand_bit(bitsize);
310 bitmap_set_prefix(map, test_bit);
311 if (!bitmap_is_prefix(map, test_bit)) goto error1;
312 bitmap_clear_all(map);
313 for (j = 0; j < test_bit; j++) bitmap_set_bit(map, j);
314 if (!bitmap_is_prefix(map, test_bit)) goto error2;
315 bitmap_set_all(map);
316 for (j = bitsize - 1; ~(j - test_bit); j--) bitmap_clear_bit(map, j);
317 if (!bitmap_is_prefix(map, test_bit)) goto error3;
318 bitmap_clear_all(map);
319 }
320 for (i = 0; i < bitsize; i++) {
321 if (bitmap_is_prefix(map, i + 1)) goto error4;
322 bitmap_set_bit(map, i);
323 if (!bitmap_is_prefix(map, i + 1)) goto error5;
324 test_bit = get_rand_bit(bitsize);
325 bitmap_set_bit(map, test_bit);
326 if (test_bit <= i && !bitmap_is_prefix(map, i + 1))
327 goto error5;
328 else if (test_bit > i) {
329 if (bitmap_is_prefix(map, i + 1)) goto error4;
330 bitmap_clear_bit(map, test_bit);
331 }
332 }
333 return false;
334 error1:
335 ADD_FAILURE() << "prefix1 error prefix_size=" << test_bit;
336 return true;
337 error2:
338 ADD_FAILURE() << "prefix2 error prefix_size=" << test_bit;
339 return true;
340 error3:
341 ADD_FAILURE() << "prefix3 error prefix_size=" << test_bit;
342 return true;
343 error4:
344 ADD_FAILURE() << "prefix4 error i=" << i;
345 return true;
346 error5:
347 ADD_FAILURE() << "prefix5 error i=" << i;
348 return true;
349 }
350
test_compare(MY_BITMAP * map,uint bitsize)351 bool test_compare(MY_BITMAP *map, uint bitsize) {
352 MY_BITMAP map2;
353 my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
354 uint i, test_bit;
355 uint no_loops = bitsize > 128 ? 128 : bitsize;
356 bitmap_init(&map2, map2buf, bitsize);
357
358 /* Test all 4 possible combinations of set/unset bits. */
359 for (i = 0; i < no_loops; i++) {
360 test_bit = get_rand_bit(bitsize);
361 bitmap_clear_bit(map, test_bit);
362 bitmap_clear_bit(&map2, test_bit);
363 if (!bitmap_is_subset(map, &map2)) goto error_is_subset;
364 bitmap_set_bit(map, test_bit);
365 if (bitmap_is_subset(map, &map2)) goto error_is_subset;
366 bitmap_set_bit(&map2, test_bit);
367 if (!bitmap_is_subset(map, &map2)) goto error_is_subset;
368 bitmap_clear_bit(map, test_bit);
369 if (!bitmap_is_subset(map, &map2)) goto error_is_subset;
370 /* Note that test_bit is not cleared i map2. */
371 }
372 bitmap_clear_all(map);
373 bitmap_clear_all(&map2);
374 /* Test all 4 possible combinations of set/unset bits. */
375 for (i = 0; i < no_loops; i++) {
376 test_bit = get_rand_bit(bitsize);
377 if (bitmap_is_overlapping(map, &map2)) goto error_is_overlapping;
378 bitmap_set_bit(map, test_bit);
379 if (bitmap_is_overlapping(map, &map2)) goto error_is_overlapping;
380 bitmap_set_bit(&map2, test_bit);
381 if (!bitmap_is_overlapping(map, &map2)) goto error_is_overlapping;
382 bitmap_clear_bit(map, test_bit);
383 if (bitmap_is_overlapping(map, &map2)) goto error_is_overlapping;
384 bitmap_clear_bit(&map2, test_bit);
385 /* Note that test_bit is not cleared i map2. */
386 }
387 return false;
388 error_is_subset:
389 ADD_FAILURE() << "is_subset error";
390 return true;
391 error_is_overlapping:
392 ADD_FAILURE() << "is_overlapping error";
393 return true;
394 }
395
test_intersect(MY_BITMAP * map,uint bitsize)396 bool test_intersect(MY_BITMAP *map, uint bitsize) {
397 uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1);
398 MY_BITMAP map2;
399 my_bitmap_map *map2buf = new my_bitmap_map[bitsize2];
400 bitmap_init(&map2, map2buf, bitsize2);
401
402 uint test_bit1 = get_rand_bit(bitsize);
403 uint test_bit2 = get_rand_bit(bitsize2);
404
405 if (test_bit2 < bitsize) {
406 // test_bit2 can be set in map, so the intersection is not empty iff
407 // test_bit1 == test_bit2
408 bitmap_set_bit(map, test_bit1);
409 bitmap_set_bit(&map2, test_bit2);
410 bitmap_intersect(map, &map2);
411 if (test_bit1 == test_bit2) {
412 if (!bitmap_is_set(map, test_bit1)) goto error;
413 bitmap_clear_bit(map, test_bit2);
414 } else {
415 if (bitmap_is_set(map, test_bit1)) goto error;
416 }
417 } else {
418 // test_bit2 cannot be set in map, so the intersection should be empty
419 bitmap_set_bit(map, test_bit1);
420 bitmap_set_bit(&map2, test_bit2);
421 bitmap_intersect(map, &map2);
422 }
423
424 if (!bitmap_is_clear_all(map)) goto error;
425
426 bitmap_set_all(map);
427 bitmap_set_all(&map2);
428 for (uint i = 0; i < bitsize2; i++) bitmap_clear_bit(&map2, i);
429 bitmap_intersect(map, &map2);
430 if (!bitmap_is_clear_all(map)) goto error;
431 delete[] map2buf;
432 return false;
433 error:
434 delete[] map2buf;
435 ADD_FAILURE() << "intersect error bit1=" << test_bit1
436 << ",bit2=" << test_bit2;
437 return true;
438 }
439
440 class BitMapTest : public ::testing::TestWithParam<uint> {
441 protected:
SetUp()442 virtual void SetUp() {
443 bitsize = GetParam();
444 ASSERT_FALSE(bitmap_init(&map, buf, bitsize));
445 bitmap_clear_all(&map);
446 }
447
448 MY_BITMAP map;
449 my_bitmap_map buf[MAX_TESTED_BITMAP_SIZE];
450 uint bitsize;
451 };
452
453 const uint test_values[] = {
454 1, 2, 3, 4, 5,
455 6, 7, 8, 9, 10,
456 11, 12, 13, 14, 15,
457 16, 17, 18, 19, 20,
458 21, 22, 23, 24, 25,
459 26, 27, 28, 29, 30,
460 31, 32, 33, 34, 35,
461 36, 37, 38, 39, 40,
462 2 * 32U - 1, 2 * 32U, 2 * 32U + 1, 3 * 32U - 1, 3 * 32U,
463 3 * 32U + 1, 4 * 32U - 1, 4 * 32U, 4 * 32U + 1, MAX_TESTED_BITMAP_SIZE};
464
465 INSTANTIATE_TEST_SUITE_P(Foo, BitMapTest, ::testing::ValuesIn(test_values));
466
TEST_P(BitMapTest,TestSetGetClearBit)467 TEST_P(BitMapTest, TestSetGetClearBit) {
468 EXPECT_FALSE(test_set_get_clear_bit(&map, bitsize)) << "bitsize=" << bitsize;
469 }
470
TEST_P(BitMapTest,TestFlipBit)471 TEST_P(BitMapTest, TestFlipBit) {
472 EXPECT_FALSE(test_flip_bit(&map, bitsize)) << "bitsize=" << bitsize;
473 }
474
TEST_P(BitMapTest,TestGetAllBits)475 TEST_P(BitMapTest, TestGetAllBits) {
476 EXPECT_FALSE(test_get_all_bits(&map, bitsize)) << "bitsize=" << bitsize;
477 }
478
TEST_P(BitMapTest,TestCompareOperators)479 TEST_P(BitMapTest, TestCompareOperators) {
480 EXPECT_FALSE(test_compare_operators(&map, bitsize)) << "bitsize=" << bitsize;
481 }
482
TEST_P(BitMapTest,TestCountBitsSet)483 TEST_P(BitMapTest, TestCountBitsSet) {
484 EXPECT_FALSE(test_count_bits_set(&map, bitsize)) << "bitsize=" << bitsize;
485 }
486
TEST_P(BitMapTest,TestGetFirstBit)487 TEST_P(BitMapTest, TestGetFirstBit) {
488 EXPECT_FALSE(test_get_first_bit(&map, bitsize)) << "bitsize=" << bitsize;
489 }
490
TEST_P(BitMapTest,TestSetNextBit)491 TEST_P(BitMapTest, TestSetNextBit) {
492 EXPECT_FALSE(test_set_next_bit(&map, bitsize)) << "bitsize=" << bitsize;
493 }
494
TEST_P(BitMapTest,TestGetNextBit)495 TEST_P(BitMapTest, TestGetNextBit) {
496 EXPECT_FALSE(test_get_next_bit(&map, bitsize)) << "bitsize=" << bitsize;
497 }
498
TEST_P(BitMapTest,TestPrefix)499 TEST_P(BitMapTest, TestPrefix) {
500 EXPECT_FALSE(test_prefix(&map, bitsize)) << "bitsize=" << bitsize;
501 }
502
TEST_P(BitMapTest,TestCompare)503 TEST_P(BitMapTest, TestCompare) {
504 EXPECT_FALSE(test_compare(&map, bitsize)) << "bitsize=" << bitsize;
505 }
506
TEST_P(BitMapTest,TestIntersect)507 TEST_P(BitMapTest, TestIntersect) {
508 EXPECT_FALSE(test_intersect(&map, bitsize)) << "bitsize=" << bitsize;
509 }
510
511 // Bug#11761614
512
bitmap_set_prefix_t()513 bool bitmap_set_prefix_t() {
514 MY_BITMAP map;
515 my_bitmap_map buf[2]; /* 64-bit buffer */
516 uint32 _max = ~((uint32)0);
517 bitmap_init(&map, buf, 32);
518
519 // set all bits in the 2nd half of the buf
520 buf[1] = _max;
521 bitmap_clear_all(&map);
522
523 /*
524 Choose prefix_size as number that is not a multiple
525 of 8, so that leftover bits in the last prefix byte
526 will be set separately.
527 */
528 bitmap_set_prefix(&map, 31);
529 // 2nd half should remain unaltered
530 return (buf[1] == _max);
531 }
532
TEST(BitMapTestEx,TestSetPrefixEx)533 TEST(BitMapTestEx, TestSetPrefixEx) { EXPECT_TRUE(bitmap_set_prefix_t()); }
534
535 } // namespace my_bitmap_unittest
536