1/**
2* The purpose of this test is to check that we can call CRoaring from C++
3*/
4
5#include <type_traits>
6#include <assert.h>
7#include <roaring/roaring.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12#include <iostream>
13#include "roaring.hh"
14#include "roaring64map.hh"
15extern "C" {
16#include "test.h"
17}
18
19
20static_assert(std::is_nothrow_move_constructible<Roaring>::value,
21 "Expected Roaring to be no except move constructable");
22
23bool roaring_iterator_sumall(uint32_t value, void *param) {
24 *(uint32_t *)param += value;
25 return true; // we always process all values
26}
27
28bool roaring_iterator_sumall64(uint64_t value, void *param) {
29 *(uint64_t *)param += value;
30 return true; // we always process all values
31}
32
33
34void serial_test(void **) {
35 uint32_t values[] = {5, 2, 3, 4, 1};
36 Roaring r1(sizeof(values)/sizeof(uint32_t), values);
37 uint32_t serializesize = r1.getSizeInBytes();
38 char *serializedbytes = new char [serializesize];
39 r1.write(serializedbytes);
40 Roaring t = Roaring::read(serializedbytes);
41 assert_true(r1 == t);
42 char *copy = new char[serializesize];
43 memcpy(copy, serializedbytes, serializesize);
44 Roaring t2 = Roaring::read(copy);
45 assert_true(t2== t);
46 delete[] serializedbytes;
47 delete[] copy;
48}
49
50void test_example(bool copy_on_write) {
51 // create a new empty bitmap
52 roaring_bitmap_t *r1 = roaring_bitmap_create();
53 roaring_bitmap_set_copy_on_write(r1, copy_on_write);
54 assert_ptr_not_equal(r1, NULL);
55
56 // then we can add values
57 for (uint32_t i = 100; i < 1000; i++) {
58 roaring_bitmap_add(r1, i);
59 }
60 // check whether a value is contained
61 assert_true(roaring_bitmap_contains(r1, 500));
62
63 // compute how many bits there are:
64 uint64_t cardinality = roaring_bitmap_get_cardinality(r1);
65 printf("Cardinality = %d \n", (int)cardinality);
66 assert_int_equal(900, cardinality);
67
68 // if your bitmaps have long runs, you can compress them by calling
69 // run_optimize
70 size_t size = roaring_bitmap_portable_size_in_bytes(r1);
71 roaring_bitmap_run_optimize(r1);
72 size_t compact_size = roaring_bitmap_portable_size_in_bytes(r1);
73 printf("size before run optimize %zu bytes, and after %zu bytes\n", size,
74 compact_size);
75 // create a new bitmap with varargs
76 roaring_bitmap_t *r2 = roaring_bitmap_of(5, 1, 2, 3, 5, 6);
77 assert_ptr_not_equal(r2, NULL);
78 roaring_bitmap_printf(r2);
79 printf("\n");
80 // we can also create a bitmap from a pointer to 32-bit integers
81 const uint32_t values[] = {2, 3, 4};
82 roaring_bitmap_t *r3 = roaring_bitmap_of_ptr(3, values);
83 roaring_bitmap_set_copy_on_write(r3, copy_on_write);
84 // we can also go in reverse and go from arrays to bitmaps
85 uint64_t card1 = roaring_bitmap_get_cardinality(r1);
86 uint32_t *arr1 = new uint32_t[card1];
87 assert_ptr_not_equal(arr1, NULL);
88 roaring_bitmap_to_uint32_array(r1, arr1);
89
90 roaring_bitmap_t *r1f = roaring_bitmap_of_ptr(card1, arr1);
91 delete[] arr1;
92 assert_ptr_not_equal(r1f, NULL);
93
94 // bitmaps shall be equal
95 assert_true(roaring_bitmap_equals(r1, r1f));
96 roaring_bitmap_free(r1f);
97
98 // we can copy and compare bitmaps
99 roaring_bitmap_t *z = roaring_bitmap_copy(r3);
100 roaring_bitmap_set_copy_on_write(z, copy_on_write);
101 assert_true(roaring_bitmap_equals(r3, z));
102
103 roaring_bitmap_free(z);
104
105 // we can compute union two-by-two
106 roaring_bitmap_t *r1_2_3 = roaring_bitmap_or(r1, r2);
107 roaring_bitmap_set_copy_on_write(r1_2_3, copy_on_write);
108 roaring_bitmap_or_inplace(r1_2_3, r3);
109
110 // we can compute a big union
111 const roaring_bitmap_t *allmybitmaps[] = {r1, r2, r3};
112 roaring_bitmap_t *bigunion = roaring_bitmap_or_many(3, allmybitmaps);
113 assert_true(roaring_bitmap_equals(r1_2_3, bigunion));
114 roaring_bitmap_t *bigunionheap =
115 roaring_bitmap_or_many_heap(3, allmybitmaps);
116 assert_true(roaring_bitmap_equals(r1_2_3, bigunionheap));
117 roaring_bitmap_free(r1_2_3);
118 roaring_bitmap_free(bigunion);
119 roaring_bitmap_free(bigunionheap);
120
121 // we can compute intersection two-by-two
122 roaring_bitmap_t *i1_2 = roaring_bitmap_and(r1, r2);
123 roaring_bitmap_free(i1_2);
124
125 // we can write a bitmap to a pointer and recover it later
126 size_t expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
127 char *serializedbytes = (char *)malloc(expectedsize);
128 roaring_bitmap_portable_serialize(r1, serializedbytes);
129 roaring_bitmap_t *t = roaring_bitmap_portable_deserialize(serializedbytes);
130 assert_true(expectedsize == roaring_bitmap_portable_size_in_bytes(t));
131 assert_true(roaring_bitmap_equals(r1, t));
132 roaring_bitmap_free(t);
133 free(serializedbytes);
134
135 // we can iterate over all values using custom functions
136 uint32_t counter = 0;
137 roaring_iterate(r1, roaring_iterator_sumall, &counter);
138 /**
139 * void roaring_iterator_sumall(uint32_t value, void *param) {
140 * *(uint32_t *) param += value;
141 * }
142 *
143 */
144
145 roaring_bitmap_free(r1);
146 roaring_bitmap_free(r2);
147 roaring_bitmap_free(r3);
148}
149
150void test_example_cpp(bool copy_on_write) {
151 // create a new empty bitmap
152 Roaring r1;
153 r1.setCopyOnWrite(copy_on_write);
154 // then we can add values
155 for (uint32_t i = 100; i < 1000; i++) {
156 r1.add(i);
157 }
158
159 // check whether a value is contained
160 assert_true(r1.contains(500));
161
162 // compute how many bits there are:
163 uint64_t cardinality = r1.cardinality();
164 std::cout << "Cardinality = " << cardinality << std::endl;
165
166 // if your bitmaps have long runs, you can compress them by calling
167 // run_optimize
168 size_t size = r1.getSizeInBytes();
169 r1.runOptimize();
170 size_t compact_size = r1.getSizeInBytes();
171
172 std::cout << "size before run optimize " << size << " bytes, and after "
173 << compact_size << " bytes." << std::endl;
174
175 // create a new bitmap with varargs
176 Roaring r2 = Roaring::bitmapOf(5, 1, 2, 3, 5, 6);
177
178 r2.printf();
179 printf("\n");
180
181 // test select
182 uint32_t element;
183 r2.select(3, &element);
184 assert_true(element == 5);
185
186 assert_true(r2.minimum() == 1);
187
188 assert_true(r2.maximum() == 6);
189
190 assert_true(r2.rank(4) == 3);
191
192 // we can also create a bitmap from a pointer to 32-bit integers
193 const uint32_t values[] = {2, 3, 4};
194 Roaring r3(3, values);
195 r3.setCopyOnWrite(copy_on_write);
196
197 // we can also go in reverse and go from arrays to bitmaps
198 uint64_t card1 = r1.cardinality();
199 uint32_t *arr1 = new uint32_t[card1];
200 assert_true(arr1 != NULL);
201 r1.toUint32Array(arr1);
202 Roaring r1f(card1, arr1);
203 delete[] arr1;
204
205 // bitmaps shall be equal
206 assert_true(r1 == r1f);
207
208 // we can copy and compare bitmaps
209 Roaring z(r3);
210 z.setCopyOnWrite(copy_on_write);
211 assert_true(r3 == z);
212
213 // we can compute union two-by-two
214 Roaring r1_2_3 = r1 | r2;
215 r1_2_3.setCopyOnWrite(copy_on_write);
216 r1_2_3 |= r3;
217
218 // we can compute a big union
219 const Roaring *allmybitmaps[] = {&r1, &r2, &r3};
220 Roaring bigunion = Roaring::fastunion(3, allmybitmaps);
221 assert_true(r1_2_3 == bigunion);
222
223 // we can compute intersection two-by-two
224 Roaring i1_2 = r1 & r2;
225
226 // we can write a bitmap to a pointer and recover it later
227 size_t expectedsize = r1.getSizeInBytes();
228 char *serializedbytes = new char[expectedsize];
229 r1.write(serializedbytes);
230 Roaring t = Roaring::read(serializedbytes);
231 assert_true(expectedsize == t.getSizeInBytes());
232 assert_true(r1 == t);
233
234 Roaring t2 = Roaring::readSafe(serializedbytes,expectedsize);
235 assert_true(expectedsize == t2.getSizeInBytes());
236 assert_true(r1 == t2);
237
238 delete[] serializedbytes;
239
240 // we can iterate over all values using custom functions
241 uint32_t counter = 0;
242 r1.iterate(roaring_iterator_sumall, &counter);
243 /**
244 * void roaring_iterator_sumall(uint32_t value, void *param) {
245 * *(uint32_t *) param += value;
246 * }
247 *
248 */
249 // we can also iterate the C++ way
250 counter = 0;
251 for (Roaring::const_iterator i = t.begin(); i != t.end(); i++) {
252 ++counter;
253 }
254 assert_true(counter == t.cardinality());
255
256 // we can move iterators
257 const uint32_t manyvalues[] = {2, 3, 4, 7, 8};
258 Roaring rogue(5, manyvalues);
259 Roaring::const_iterator j = rogue.begin();
260 j.equalorlarger(4);
261 assert_true(*j == 4);
262
263
264 // test move constructor
265 {
266 Roaring b;
267 b.add(10);
268 b.add(20);
269
270 Roaring a(std::move(b));
271 assert_true(a.cardinality() == 2);
272 assert_true(a.contains(10));
273 assert_true(a.contains(20));
274
275 // b should be destroyed without any errors
276 assert_true(b.cardinality() == 0);
277 }
278
279 // test move operator
280 {
281 Roaring b;
282 b.add(10);
283 b.add(20);
284
285 Roaring a;
286
287 a = std::move(b);
288 assert_int_equal(2, a.cardinality());
289 assert_true(a.contains(10));
290 assert_true(a.contains(20));
291
292 // b should be destroyed without any errors
293 assert_int_equal(0, b.cardinality());
294 }
295
296 // test toString
297 {
298 Roaring a;
299 a.add(1);
300 a.add(2);
301 a.add(3);
302 a.add(4);
303
304 assert_string_equal("{1,2,3,4}", a.toString().c_str());
305 }
306}
307
308void test_example_cpp_64(bool copy_on_write) {
309 // create a new empty bitmap
310 Roaring64Map r1;
311 r1.setCopyOnWrite(copy_on_write);
312 // then we can add values
313 for (uint64_t i = 100; i < 1000; i++) {
314 r1.add(i);
315 }
316 for (uint64_t i = 14000000000000000100ull; i < 14000000000000001000ull;
317 i++) {
318 r1.add(i);
319 }
320
321 // check whether a value is contained
322 assert_true(r1.contains((uint64_t)14000000000000000500ull));
323
324 // compute how many bits there are:
325 uint64_t cardinality = r1.cardinality();
326 std::cout << "Cardinality = " << cardinality << std::endl;
327
328 // if your bitmaps have long runs, you can compress them by calling
329 // run_optimize
330 uint64_t size = r1.getSizeInBytes();
331 r1.runOptimize();
332 uint64_t compact_size = r1.getSizeInBytes();
333
334 std::cout << "size before run optimize " << size << " bytes, and after "
335 << compact_size << " bytes." << std::endl;
336
337 // create a new bitmap with varargs
338 Roaring64Map r2 =
339 Roaring64Map::bitmapOf(5, 1ull, 2ull, 234294967296ull, 195839473298ull,
340 14000000000000000100ull);
341
342 r2.printf();
343 printf("\n");
344
345 // test select
346 uint64_t element;
347 r2.select(4, &element);
348 assert_true(element == 14000000000000000100ull);
349
350 assert_true(r2.minimum() == 1ull);
351
352 assert_true(r2.maximum() == 14000000000000000100ull);
353
354 assert_true(r2.rank(234294967296ull) == 4ull);
355
356 // we can also create a bitmap from a pointer to 32-bit integers
357 const uint32_t values[] = {2, 3, 4};
358 Roaring64Map r3(3, values);
359 r3.setCopyOnWrite(copy_on_write);
360
361 // we can also go in reverse and go from arrays to bitmaps
362 uint64_t card1 = r1.cardinality();
363 uint64_t *arr1 = new uint64_t[card1];
364 assert_true(arr1 != NULL);
365 r1.toUint64Array(arr1);
366 Roaring64Map r1f(card1, arr1);
367 delete[] arr1;
368
369 // bitmaps shall be equal
370 assert_true(r1 == r1f);
371
372 // we can copy and compare bitmaps
373 Roaring64Map z(r3);
374 z.setCopyOnWrite(copy_on_write);
375 assert_true(r3 == z);
376
377 // we can compute union two-by-two
378 Roaring64Map r1_2_3 = r1 | r2;
379 r1_2_3.setCopyOnWrite(copy_on_write);
380 r1_2_3 |= r3;
381
382 // we can compute a big union
383 const Roaring64Map *allmybitmaps[] = {&r1, &r2, &r3};
384 Roaring64Map bigunion = Roaring64Map::fastunion(3, allmybitmaps);
385 assert_true(r1_2_3 == bigunion);
386
387 // we can compute intersection two-by-two
388 Roaring64Map i1_2 = r1 & r2;
389
390 // we can write a bitmap to a pointer and recover it later
391 size_t expectedsize = r1.getSizeInBytes();
392 char *serializedbytes = new char[expectedsize];
393 r1.write(serializedbytes);
394 Roaring64Map t = Roaring64Map::read(serializedbytes);
395 assert_true(expectedsize == t.getSizeInBytes());
396 assert_true(r1 == t);
397 delete[] serializedbytes;
398
399 // we can iterate over all values using custom functions
400 uint64_t counter = 0;
401 r1.iterate(roaring_iterator_sumall64, &counter);
402 /**
403 * void roaring_iterator_sumall64(uint64_t value, void *param) {
404 * *(uint64_t *) param += value;
405 * }
406 *
407 */
408 // we can also iterate the C++ way
409 counter = 0;
410 for (Roaring64Map::const_iterator i = t.begin(); i != t.end(); i++) {
411 ++counter;
412 }
413 assert_true(counter == t.cardinality());
414
415 {
416 Roaring64Map b;
417 b.add(1u);
418 b.add(2u);
419 b.add(3u);
420 assert_int_equal(3, b.cardinality());
421
422 Roaring64Map a(std::move(b));
423 assert_int_equal(3, a.cardinality());
424 // assert_int_equal(0, b.cardinality()); // no: b is now unspecified.
425 }
426
427 {
428 Roaring64Map a, b;
429 b.add(1u);
430 b.add(2u);
431 b.add(3u);
432 assert_int_equal(3, b.cardinality());
433
434 a = std::move(b);
435 assert_int_equal(3, a.cardinality());
436 // assert_int_equal(0, b.cardinality()); // no: b is unspecified
437 }
438}
439
440void test_example_true(void **) { test_example(true); }
441
442void test_example_false(void **) { test_example(false); }
443
444void test_example_cpp_true(void **) { test_example_cpp(true); }
445
446void test_example_cpp_false(void **) { test_example_cpp(false); }
447
448void test_example_cpp_64_true(void **) { test_example_cpp_64(true); }
449
450void test_example_cpp_64_false(void **) { test_example_cpp_64(false); }
451
452void test_cpp_add_remove_checked(void **) {
453 Roaring roaring;
454 uint32_t values[4] = { 123, 9999, 0xFFFFFFF7, 0xFFFFFFFF};
455 for (int i = 0; i < 4; ++i) {
456 assert_true(roaring.addChecked(values[i]));
457 assert_false(roaring.addChecked(values[i]));
458 }
459 for (int i = 0; i < 4; ++i) {
460 assert_true(roaring.removeChecked(values[i]));
461 assert_false(roaring.removeChecked(values[i]));
462 }
463 assert_true(roaring.isEmpty());
464}
465
466void test_cpp_add_remove_checked_64(void **) {
467 Roaring64Map roaring;
468
469 uint32_t values32[4] = { 123, 9999, 0xFFFFFFF7, 0xFFFFFFFF};
470 for (int i = 0; i < 4; ++i) {
471 assert_true(roaring.addChecked(values32[i]));
472 assert_false(roaring.addChecked(values32[i]));
473 }
474 for (int i = 0; i < 4; ++i) {
475 assert_true(roaring.removeChecked(values32[i]));
476 assert_false(roaring.removeChecked(values32[i]));
477 }
478
479 uint64_t values64[4] = { 123ULL, 0xA00000000AULL, 0xAFFFFFFF7ULL, 0xFFFFFFFFFULL};
480 for (int i = 0; i < 4; ++i) {
481 assert_true(roaring.addChecked(values64[i]));
482 assert_false(roaring.addChecked(values64[i]));
483 }
484 for (int i = 0; i < 4; ++i) {
485 assert_true(roaring.removeChecked(values64[i]));
486 assert_false(roaring.removeChecked(values64[i]));
487 }
488 assert_true(roaring.isEmpty());
489}
490
491void test_cpp_clear_64(void **) {
492 Roaring64Map roaring;
493
494 uint64_t values64[4] = { 123ULL, 0xA00000000AULL, 0xAFFFFFFF7ULL, 0xFFFFFFFFFULL};
495 for (int i = 0; i < 4; ++i) {
496 assert_true(roaring.addChecked(values64[i]));
497 }
498
499 roaring.clear();
500
501 assert_true(roaring.isEmpty());
502}
503
504void test_cpp_move_64(void **) {
505 Roaring64Map roaring;
506
507 uint64_t values64[4] = { 123ULL, 0xA00000000AULL, 0xAFFFFFFF7ULL, 0xFFFFFFFFFULL};
508 for (int i = 0; i < 4; ++i) {
509 assert_true(roaring.addChecked(values64[i]));
510 }
511
512 Roaring64Map::const_iterator i(roaring);
513 i.move(123ULL);
514 assert_true(*i == 123ULL);
515 i.move(0xAFFFFFFF8ULL);
516 assert_true(*i == 0xFFFFFFFFFULL);
517 assert_false(i.move(0xFFFFFFFFFFULL));
518}
519
520void test_cpp_bidirectional_iterator_64(void **) {
521 Roaring64Map roaring;
522
523 uint64_t values64[4] = { 123ULL, 0xA00000000AULL, 0xAFFFFFFF7ULL, 0xFFFFFFFFFULL};
524 for (int i = 0; i < 4; ++i) {
525 assert_true(roaring.addChecked(values64[i]));
526 }
527
528 Roaring64Map::const_bidirectional_iterator i(roaring);
529 i = roaring.begin();
530 assert_true(*i++ == 123ULL);
531 assert_true(*i++ == 0xAFFFFFFF7ULL);
532 assert_true(*i++ == 0xFFFFFFFFFULL);
533 assert_true(*i++ == 0xA00000000AULL);
534 assert_true(i == roaring.end());
535 assert_true(*--i == 0xA00000000AULL);
536 assert_true(*--i == 0xFFFFFFFFFULL);
537 assert_true(*--i == 0xAFFFFFFF7ULL);
538 assert_true(*--i == 123ULL);
539 assert_true(i == roaring.begin());
540 i = roaring.end();
541 i--;
542 assert_true(*i-- == 0xA00000000AULL);
543 assert_true(*i-- == 0xFFFFFFFFFULL);
544 assert_true(*i-- == 0xAFFFFFFF7ULL);
545 assert_true(*i == 123ULL);
546 assert_true(i == roaring.begin());
547}
548
549int main() {
550 const struct CMUnitTest tests[] = {
551 cmocka_unit_test(serial_test),
552 cmocka_unit_test(test_example_true),
553 cmocka_unit_test(test_example_false),
554 cmocka_unit_test(test_example_cpp_true),
555 cmocka_unit_test(test_example_cpp_false),
556 cmocka_unit_test(test_example_cpp_64_true),
557 cmocka_unit_test(test_example_cpp_64_false),
558 cmocka_unit_test(test_cpp_add_remove_checked),
559 cmocka_unit_test(test_cpp_add_remove_checked_64),
560 cmocka_unit_test(test_cpp_clear_64),
561 cmocka_unit_test(test_cpp_move_64),
562 cmocka_unit_test(test_cpp_bidirectional_iterator_64)};
563
564 return cmocka_run_group_tests(tests, NULL, NULL);
565}
566