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