LCOV - code coverage report
Current view: top level - src/test/modules/test_bitmapset - test_bitmapset.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 382 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 67 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * test_bitmapset.c
       4              :  *      Test the Bitmapset data structure.
       5              :  *
       6              :  * This module tests the Bitmapset implementation in PostgreSQL, covering
       7              :  * all public API functions.
       8              :  *
       9              :  * Copyright (c) 2025-2026, PostgreSQL Global Development Group
      10              :  *
      11              :  * IDENTIFICATION
      12              :  *              src/test/modules/test_bitmapset/test_bitmapset.c
      13              :  *
      14              :  *-------------------------------------------------------------------------
      15              :  */
      16              : 
      17              : #include "postgres.h"
      18              : 
      19              : #include <stddef.h>
      20              : #include "catalog/pg_type.h"
      21              : #include "common/pg_prng.h"
      22              : #include "utils/array.h"
      23              : #include "fmgr.h"
      24              : #include "nodes/bitmapset.h"
      25              : #include "nodes/nodes.h"
      26              : #include "nodes/pg_list.h"
      27              : #include "utils/builtins.h"
      28              : #include "utils/timestamp.h"
      29              : 
      30            0 : PG_MODULE_MAGIC;
      31              : 
      32              : /* Bitmapset API functions in order of appearance in bitmapset.c */
      33            0 : PG_FUNCTION_INFO_V1(test_bms_make_singleton);
      34            0 : PG_FUNCTION_INFO_V1(test_bms_add_member);
      35            0 : PG_FUNCTION_INFO_V1(test_bms_del_member);
      36            0 : PG_FUNCTION_INFO_V1(test_bms_is_member);
      37            0 : PG_FUNCTION_INFO_V1(test_bms_num_members);
      38            0 : PG_FUNCTION_INFO_V1(test_bms_copy);
      39            0 : PG_FUNCTION_INFO_V1(test_bms_equal);
      40            0 : PG_FUNCTION_INFO_V1(test_bms_compare);
      41            0 : PG_FUNCTION_INFO_V1(test_bms_is_subset);
      42            0 : PG_FUNCTION_INFO_V1(test_bms_subset_compare);
      43            0 : PG_FUNCTION_INFO_V1(test_bms_union);
      44            0 : PG_FUNCTION_INFO_V1(test_bms_intersect);
      45            0 : PG_FUNCTION_INFO_V1(test_bms_difference);
      46            0 : PG_FUNCTION_INFO_V1(test_bms_is_empty);
      47            0 : PG_FUNCTION_INFO_V1(test_bms_membership);
      48            0 : PG_FUNCTION_INFO_V1(test_bms_singleton_member);
      49            0 : PG_FUNCTION_INFO_V1(test_bms_get_singleton_member);
      50            0 : PG_FUNCTION_INFO_V1(test_bms_next_member);
      51            0 : PG_FUNCTION_INFO_V1(test_bms_prev_member);
      52            0 : PG_FUNCTION_INFO_V1(test_bms_hash_value);
      53            0 : PG_FUNCTION_INFO_V1(test_bms_overlap);
      54            0 : PG_FUNCTION_INFO_V1(test_bms_overlap_list);
      55            0 : PG_FUNCTION_INFO_V1(test_bms_nonempty_difference);
      56            0 : PG_FUNCTION_INFO_V1(test_bms_member_index);
      57            0 : PG_FUNCTION_INFO_V1(test_bms_add_range);
      58            0 : PG_FUNCTION_INFO_V1(test_bms_add_members);
      59            0 : PG_FUNCTION_INFO_V1(test_bms_int_members);
      60            0 : PG_FUNCTION_INFO_V1(test_bms_del_members);
      61            0 : PG_FUNCTION_INFO_V1(test_bms_replace_members);
      62            0 : PG_FUNCTION_INFO_V1(test_bms_join);
      63            0 : PG_FUNCTION_INFO_V1(test_bitmap_hash);
      64            0 : PG_FUNCTION_INFO_V1(test_bitmap_match);
      65              : 
      66              : /* Test utility functions */
      67            0 : PG_FUNCTION_INFO_V1(test_random_operations);
      68              : 
      69              : /* Convenient macros to test results */
      70              : #define EXPECT_TRUE(expr)       \
      71              :         do { \
      72              :                 if (!(expr)) \
      73              :                         elog(ERROR, \
      74              :                                  "%s was unexpectedly false in file \"%s\" line %u", \
      75              :                                  #expr, __FILE__, __LINE__); \
      76              :         } while (0)
      77              : 
      78              : #define EXPECT_NOT_NULL(expr)   \
      79              :         do { \
      80              :                 if ((expr) == NULL) \
      81              :                         elog(ERROR, \
      82              :                                  "%s was unexpectedly true in file \"%s\" line %u", \
      83              :                                  #expr, __FILE__, __LINE__); \
      84              :         } while (0)
      85              : 
      86              : /* Encode/Decode to/from TEXT and Bitmapset */
      87              : #define BITMAPSET_TO_TEXT(bms) cstring_to_text(nodeToString(bms))
      88              : #define TEXT_TO_BITMAPSET(str) ((Bitmapset *) stringToNode(text_to_cstring(str)))
      89              : 
      90              : /*
      91              :  * Helper macro to fetch text parameters as Bitmapsets. SQL-NULL means empty
      92              :  * set.
      93              :  */
      94              : #define PG_ARG_GETBITMAPSET(n) \
      95              :         (PG_ARGISNULL(n) ? NULL : TEXT_TO_BITMAPSET(PG_GETARG_TEXT_PP(n)))
      96              : 
      97              : /*
      98              :  * Helper macro to handle converting sets back to text, returning the
      99              :  * resulting text representation of the set.
     100              :  */
     101              : #define PG_RETURN_BITMAPSET_AS_TEXT(bms) \
     102              :         PG_RETURN_TEXT_P(BITMAPSET_TO_TEXT(bms))
     103              : 
     104              : /*
     105              :  * Individual test functions for each bitmapset API function
     106              :  *
     107              :  * Primarily, we aim to keep these as close to simple wrapper functions as
     108              :  * possible in order to publish the functions of bitmapset.c to the SQL layer
     109              :  * with as little interference as possible.  We opt to return SQL NULL in
     110              :  * cases where the input given to the SQL function isn't valid to pass to the
     111              :  * underlying bitmapset.c function.  For example we cannot do much useful
     112              :  * testing if someone calls test_bms_make_singleton(NULL) since
     113              :  * bms_make_singleton() expects an integer argument.
     114              :  *
     115              :  * For function arguments which are to be converted to Bitmapsets, we accept
     116              :  * SQL NULL as a valid argument to mean an empty set.  Optionally callers may
     117              :  * pass '(b)'.
     118              :  *
     119              :  * For the test functions which return a Bitmapset, these are converted back
     120              :  * to text with result generated by nodeToString().
     121              :  */
     122              : 
     123              : Datum
     124            0 : test_bms_add_member(PG_FUNCTION_ARGS)
     125              : {
     126            0 :         Bitmapset  *bms;
     127            0 :         int                     member;
     128              : 
     129            0 :         if (PG_ARGISNULL(1))
     130            0 :                 PG_RETURN_NULL();               /* invalid input */
     131              : 
     132            0 :         bms = PG_ARG_GETBITMAPSET(0);
     133            0 :         member = PG_GETARG_INT32(1);
     134              : 
     135            0 :         bms = bms_add_member(bms, member);
     136              : 
     137            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms);
     138            0 : }
     139              : 
     140              : Datum
     141            0 : test_bms_add_members(PG_FUNCTION_ARGS)
     142              : {
     143            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     144            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     145              : 
     146              :         /* left input is recycled */
     147            0 :         bms1 = bms_add_members(bms1, bms2);
     148              : 
     149            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms1);
     150            0 : }
     151              : 
     152              : Datum
     153            0 : test_bms_del_member(PG_FUNCTION_ARGS)
     154              : {
     155            0 :         Bitmapset  *bms;
     156            0 :         int32           member;
     157              : 
     158            0 :         if (PG_ARGISNULL(1))
     159            0 :                 PG_RETURN_NULL();               /* invalid input */
     160              : 
     161            0 :         bms = PG_ARG_GETBITMAPSET(0);
     162            0 :         member = PG_GETARG_INT32(1);
     163              : 
     164            0 :         bms = bms_del_member(bms, member);
     165              : 
     166            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms);
     167            0 : }
     168              : 
     169              : Datum
     170            0 : test_bms_is_member(PG_FUNCTION_ARGS)
     171              : {
     172            0 :         Bitmapset  *bms;
     173            0 :         int32           member;
     174            0 :         bool            result;
     175              : 
     176            0 :         if (PG_ARGISNULL(1))
     177            0 :                 PG_RETURN_NULL();               /* invalid input */
     178              : 
     179            0 :         bms = PG_ARG_GETBITMAPSET(0);
     180            0 :         member = PG_GETARG_INT32(1);
     181              : 
     182            0 :         result = bms_is_member(member, bms);
     183              : 
     184            0 :         PG_RETURN_BOOL(result);
     185            0 : }
     186              : 
     187              : Datum
     188            0 : test_bms_num_members(PG_FUNCTION_ARGS)
     189              : {
     190            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     191            0 :         int                     result;
     192              : 
     193            0 :         result = bms_num_members(bms);
     194              : 
     195            0 :         PG_RETURN_INT32(result);
     196            0 : }
     197              : 
     198              : Datum
     199            0 : test_bms_make_singleton(PG_FUNCTION_ARGS)
     200              : {
     201            0 :         Bitmapset  *bms;
     202            0 :         int32           member;
     203              : 
     204            0 :         member = PG_GETARG_INT32(0);
     205            0 :         bms = bms_make_singleton(member);
     206              : 
     207            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms);
     208            0 : }
     209              : 
     210              : Datum
     211            0 : test_bms_copy(PG_FUNCTION_ARGS)
     212              : {
     213            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     214            0 :         Bitmapset  *copy_bms;
     215              : 
     216            0 :         copy_bms = bms_copy(bms);
     217              : 
     218            0 :         PG_RETURN_BITMAPSET_AS_TEXT(copy_bms);
     219            0 : }
     220              : 
     221              : Datum
     222            0 : test_bms_equal(PG_FUNCTION_ARGS)
     223              : {
     224            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     225            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     226            0 :         bool            result;
     227              : 
     228            0 :         result = bms_equal(bms1, bms2);
     229              : 
     230            0 :         PG_RETURN_BOOL(result);
     231            0 : }
     232              : 
     233              : Datum
     234            0 : test_bms_union(PG_FUNCTION_ARGS)
     235              : {
     236            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     237            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     238            0 :         Bitmapset  *result_bms;
     239              : 
     240            0 :         result_bms = bms_union(bms1, bms2);
     241              : 
     242            0 :         PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
     243            0 : }
     244              : 
     245              : Datum
     246            0 : test_bms_membership(PG_FUNCTION_ARGS)
     247              : {
     248            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     249            0 :         BMS_Membership result;
     250              : 
     251            0 :         result = bms_membership(bms);
     252              : 
     253            0 :         PG_RETURN_INT32((int32) result);
     254            0 : }
     255              : 
     256              : Datum
     257            0 : test_bms_next_member(PG_FUNCTION_ARGS)
     258              : {
     259            0 :         Bitmapset  *bms;
     260            0 :         int32           prevmember;
     261            0 :         int                     result;
     262              : 
     263            0 :         if (PG_ARGISNULL(1))
     264            0 :                 PG_RETURN_NULL();               /* invalid input */
     265              : 
     266            0 :         bms = PG_ARG_GETBITMAPSET(0);
     267            0 :         prevmember = PG_GETARG_INT32(1);
     268              : 
     269            0 :         result = bms_next_member(bms, prevmember);
     270              : 
     271            0 :         PG_RETURN_INT32(result);
     272            0 : }
     273              : 
     274              : Datum
     275            0 : test_bms_intersect(PG_FUNCTION_ARGS)
     276              : {
     277            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     278            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     279            0 :         Bitmapset  *result_bms;
     280              : 
     281            0 :         result_bms = bms_intersect(bms1, bms2);
     282              : 
     283            0 :         PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
     284            0 : }
     285              : 
     286              : Datum
     287            0 : test_bms_difference(PG_FUNCTION_ARGS)
     288              : {
     289            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     290            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     291            0 :         Bitmapset  *result_bms;
     292              : 
     293            0 :         result_bms = bms_difference(bms1, bms2);
     294              : 
     295            0 :         PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
     296            0 : }
     297              : 
     298              : Datum
     299            0 : test_bms_compare(PG_FUNCTION_ARGS)
     300              : {
     301            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     302            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     303            0 :         int                     result;
     304              : 
     305            0 :         result = bms_compare(bms1, bms2);
     306              : 
     307            0 :         PG_RETURN_INT32(result);
     308            0 : }
     309              : 
     310              : Datum
     311            0 : test_bms_is_empty(PG_FUNCTION_ARGS)
     312              : {
     313            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     314            0 :         bool            result;
     315              : 
     316            0 :         result = bms_is_empty(bms);
     317              : 
     318            0 :         PG_RETURN_BOOL(result);
     319            0 : }
     320              : 
     321              : Datum
     322            0 : test_bms_is_subset(PG_FUNCTION_ARGS)
     323              : {
     324            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     325            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     326            0 :         bool            result;
     327              : 
     328            0 :         result = bms_is_subset(bms1, bms2);
     329              : 
     330            0 :         PG_RETURN_BOOL(result);
     331            0 : }
     332              : 
     333              : Datum
     334            0 : test_bms_subset_compare(PG_FUNCTION_ARGS)
     335              : {
     336            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     337            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     338            0 :         BMS_Comparison result;
     339              : 
     340            0 :         result = bms_subset_compare(bms1, bms2);
     341              : 
     342            0 :         PG_RETURN_INT32((int32) result);
     343            0 : }
     344              : 
     345              : Datum
     346            0 : test_bms_singleton_member(PG_FUNCTION_ARGS)
     347              : {
     348            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     349            0 :         int                     result;
     350              : 
     351            0 :         result = bms_singleton_member(bms);
     352              : 
     353            0 :         PG_RETURN_INT32(result);
     354            0 : }
     355              : 
     356              : Datum
     357            0 : test_bms_get_singleton_member(PG_FUNCTION_ARGS)
     358              : {
     359            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     360            0 :         int                     member;
     361              : 
     362              :         /*
     363              :          * Keep this simple.  Return -1 when we detect the set is not a singleton
     364              :          * set, otherwise return the singleton member.
     365              :          */
     366            0 :         if (!bms_get_singleton_member(bms, &member))
     367            0 :                 member = -1;
     368              : 
     369            0 :         PG_RETURN_INT32(member);
     370            0 : }
     371              : 
     372              : Datum
     373            0 : test_bms_prev_member(PG_FUNCTION_ARGS)
     374              : {
     375            0 :         Bitmapset  *bms;
     376            0 :         int32           prevmember;
     377            0 :         int                     result;
     378              : 
     379            0 :         if (PG_ARGISNULL(1))
     380            0 :                 PG_RETURN_NULL();               /* invalid input */
     381              : 
     382            0 :         bms = PG_ARG_GETBITMAPSET(0);
     383            0 :         prevmember = PG_GETARG_INT32(1);
     384              : 
     385            0 :         result = bms_prev_member(bms, prevmember);
     386              : 
     387            0 :         PG_RETURN_INT32(result);
     388            0 : }
     389              : 
     390              : Datum
     391            0 : test_bms_overlap(PG_FUNCTION_ARGS)
     392              : {
     393            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     394            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     395            0 :         bool            result;
     396              : 
     397            0 :         result = bms_overlap(bms1, bms2);
     398              : 
     399            0 :         PG_RETURN_BOOL(result);
     400            0 : }
     401              : 
     402              : Datum
     403            0 : test_bms_overlap_list(PG_FUNCTION_ARGS)
     404              : {
     405            0 :         Bitmapset  *bms;
     406            0 :         ArrayType  *array;
     407            0 :         List       *int_list = NIL;
     408            0 :         bool            result;
     409            0 :         Datum      *elem_datums = NULL;
     410            0 :         bool       *elem_nulls = NULL;
     411            0 :         int                     elem_count;
     412            0 :         int                     i;
     413              : 
     414            0 :         bms = PG_ARG_GETBITMAPSET(0);
     415              : 
     416            0 :         if (!PG_ARGISNULL(1))
     417              :         {
     418            0 :                 array = PG_GETARG_ARRAYTYPE_P(1);
     419              : 
     420            0 :                 deconstruct_array(array,
     421              :                                                   INT4OID, sizeof(int32), true, 'i',
     422              :                                                   &elem_datums, &elem_nulls, &elem_count);
     423              : 
     424            0 :                 for (i = 0; i < elem_count; i++)
     425              :                 {
     426            0 :                         if (!elem_nulls[i])
     427              :                         {
     428            0 :                                 int32           member = DatumGetInt32(elem_datums[i]);
     429              : 
     430            0 :                                 int_list = lappend_int(int_list, member);
     431            0 :                         }
     432            0 :                 }
     433            0 :         }
     434              : 
     435            0 :         result = bms_overlap_list(bms, int_list);
     436              : 
     437            0 :         list_free(int_list);
     438              : 
     439            0 :         if (elem_datums)
     440            0 :                 pfree(elem_datums);
     441              : 
     442            0 :         if (elem_nulls)
     443            0 :                 pfree(elem_nulls);
     444              : 
     445            0 :         PG_RETURN_BOOL(result);
     446            0 : }
     447              : 
     448              : Datum
     449            0 : test_bms_nonempty_difference(PG_FUNCTION_ARGS)
     450              : {
     451            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     452            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     453            0 :         bool            result;
     454              : 
     455            0 :         result = bms_nonempty_difference(bms1, bms2);
     456              : 
     457            0 :         PG_RETURN_BOOL(result);
     458            0 : }
     459              : 
     460              : Datum
     461            0 : test_bms_member_index(PG_FUNCTION_ARGS)
     462              : {
     463            0 :         Bitmapset  *bms;
     464            0 :         int32           member;
     465            0 :         int                     result;
     466              : 
     467            0 :         if (PG_ARGISNULL(1))
     468            0 :                 PG_RETURN_NULL();               /* invalid input */
     469              : 
     470            0 :         bms = PG_ARG_GETBITMAPSET(0);
     471            0 :         member = PG_GETARG_INT32(1);
     472              : 
     473            0 :         result = bms_member_index(bms, member);
     474              : 
     475            0 :         PG_RETURN_INT32(result);
     476            0 : }
     477              : 
     478              : Datum
     479            0 : test_bms_add_range(PG_FUNCTION_ARGS)
     480              : {
     481            0 :         Bitmapset  *bms;
     482            0 :         int32           lower,
     483              :                                 upper;
     484              : 
     485            0 :         if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
     486            0 :                 PG_RETURN_NULL();               /* invalid input */
     487              : 
     488            0 :         bms = PG_ARG_GETBITMAPSET(0);
     489            0 :         lower = PG_GETARG_INT32(1);
     490            0 :         upper = PG_GETARG_INT32(2);
     491              : 
     492            0 :         bms = bms_add_range(bms, lower, upper);
     493              : 
     494            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms);
     495            0 : }
     496              : 
     497              : Datum
     498            0 : test_bms_int_members(PG_FUNCTION_ARGS)
     499              : {
     500            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     501            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     502              : 
     503              :         /* left input gets recycled */
     504            0 :         bms1 = bms_int_members(bms1, bms2);
     505              : 
     506            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms1);
     507            0 : }
     508              : 
     509              : Datum
     510            0 : test_bms_del_members(PG_FUNCTION_ARGS)
     511              : {
     512            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     513            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     514              : 
     515              :         /* left input gets recycled */
     516            0 :         bms1 = bms_del_members(bms1, bms2);
     517              : 
     518            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms1);
     519            0 : }
     520              : 
     521              : Datum
     522            0 : test_bms_replace_members(PG_FUNCTION_ARGS)
     523              : {
     524            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     525            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     526              : 
     527              :         /* left input gets recycled */
     528            0 :         bms1 = bms_replace_members(bms1, bms2);
     529              : 
     530            0 :         PG_RETURN_BITMAPSET_AS_TEXT(bms1);
     531            0 : }
     532              : 
     533              : Datum
     534            0 : test_bms_join(PG_FUNCTION_ARGS)
     535              : {
     536            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     537            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     538            0 :         Bitmapset  *result_bms;
     539              : 
     540              :         /* either input can be recycled */
     541            0 :         result_bms = bms_join(bms1, bms2);
     542              : 
     543            0 :         PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
     544            0 : }
     545              : 
     546              : Datum
     547            0 : test_bms_hash_value(PG_FUNCTION_ARGS)
     548              : {
     549            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     550            0 :         uint32          hash_result;
     551              : 
     552            0 :         hash_result = bms_hash_value(bms);
     553              : 
     554            0 :         PG_RETURN_INT32(hash_result);
     555            0 : }
     556              : 
     557              : Datum
     558            0 : test_bitmap_hash(PG_FUNCTION_ARGS)
     559              : {
     560            0 :         Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
     561            0 :         uint32          hash_result;
     562              : 
     563              :         /* Call bitmap_hash */
     564            0 :         hash_result = bitmap_hash(&bms, sizeof(Bitmapset *));
     565              : 
     566            0 :         PG_RETURN_INT32(hash_result);
     567            0 : }
     568              : 
     569              : Datum
     570            0 : test_bitmap_match(PG_FUNCTION_ARGS)
     571              : {
     572            0 :         Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
     573            0 :         Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
     574            0 :         int                     match_result;
     575              : 
     576              :         /* Call bitmap_match with addresses of the Bitmapset pointers */
     577            0 :         match_result = bitmap_match(&bms1, &bms2, sizeof(Bitmapset *));
     578              : 
     579            0 :         PG_RETURN_INT32(match_result);
     580            0 : }
     581              : 
     582              : /*
     583              :  * Contrary to all the other functions which are one-one mappings with the
     584              :  * equivalent C functions, this stresses Bitmapsets in a random fashion for
     585              :  * various operations.
     586              :  *
     587              :  * "min_value" is the minimal value used for the members, that will stand
     588              :  * up to a range of "max_range".  "num_ops" defines the number of time each
     589              :  * operation is done.  "seed" is a random seed used to calculate the member
     590              :  * values.  When "seed" is <= 0, a random seed will be chosen automatically.
     591              :  *
     592              :  * The return value is the number of times all operations have been executed.
     593              :  */
     594              : Datum
     595            0 : test_random_operations(PG_FUNCTION_ARGS)
     596              : {
     597            0 :         Bitmapset  *bms1 = NULL;
     598            0 :         Bitmapset  *bms2 = NULL;
     599            0 :         Bitmapset  *bms = NULL;
     600            0 :         Bitmapset  *result = NULL;
     601            0 :         pg_prng_state state;
     602            0 :         uint64          seed = GetCurrentTimestamp();
     603            0 :         int                     num_ops;
     604            0 :         int                     max_range;
     605            0 :         int                     min_value;
     606            0 :         int                     member;
     607            0 :         int                *members;
     608            0 :         int                     num_members = 0;
     609            0 :         int                     total_ops = 0;
     610              : 
     611            0 :         if (PG_GETARG_INT32(0) > 0)
     612            0 :                 seed = PG_GETARG_INT32(0);
     613              : 
     614            0 :         num_ops = PG_GETARG_INT32(1);
     615            0 :         max_range = PG_GETARG_INT32(2);
     616            0 :         min_value = PG_GETARG_INT32(3);
     617              : 
     618            0 :         pg_prng_seed(&state, seed);
     619              : 
     620              :         /*
     621              :          * There can be up to "num_ops" members added.  This is very unlikely,
     622              :          * still possible if all the operations hit the "0" case during phase 4
     623              :          * where multiple operation types are mixed together.
     624              :          */
     625            0 :         members = palloc_array(int, num_ops);
     626              : 
     627              :         /* Phase 1: Random insertions in first set */
     628            0 :         for (int i = 0; i < num_ops / 2; i++)
     629              :         {
     630            0 :                 member = pg_prng_uint32(&state) % max_range + min_value;
     631              : 
     632            0 :                 if (!bms_is_member(member, bms1))
     633            0 :                         members[num_members++] = member;
     634            0 :                 bms1 = bms_add_member(bms1, member);
     635            0 :         }
     636              : 
     637              :         /* Phase 2: Random insertions in second set */
     638            0 :         for (int i = 0; i < num_ops / 4; i++)
     639              :         {
     640            0 :                 member = pg_prng_uint32(&state) % max_range + min_value;
     641              : 
     642            0 :                 if (!bms_is_member(member, bms2))
     643            0 :                         members[num_members++] = member;
     644            0 :                 bms2 = bms_add_member(bms2, member);
     645            0 :         }
     646              : 
     647              :         /* Test union */
     648            0 :         result = bms_union(bms1, bms2);
     649            0 :         EXPECT_NOT_NULL(result);
     650              : 
     651              :         /* Verify union contains all members from first and second sets */
     652            0 :         for (int i = 0; i < num_members; i++)
     653              :         {
     654            0 :                 if (!bms_is_member(members[i], result))
     655            0 :                         elog(ERROR, "union missing member %d", members[i]);
     656            0 :         }
     657            0 :         bms_free(result);
     658              : 
     659              :         /*
     660              :          * Test intersection, checking that all the members in the result are from
     661              :          * both the first and second sets.
     662              :          */
     663            0 :         result = bms_intersect(bms1, bms2);
     664            0 :         if (result != NULL)
     665              :         {
     666            0 :                 member = -1;
     667              : 
     668            0 :                 while ((member = bms_next_member(result, member)) >= 0)
     669              :                 {
     670            0 :                         if (!bms_is_member(member, bms1) || !bms_is_member(member, bms2))
     671            0 :                                 elog(ERROR, "intersection contains invalid member %d", member);
     672              :                 }
     673            0 :                 bms_free(result);
     674            0 :         }
     675              : 
     676              :         /* Phase 3: Test range operations */
     677            0 :         result = NULL;
     678            0 :         for (int i = 0; i < num_ops; i++)
     679              :         {
     680            0 :                 int                     lower = pg_prng_uint32(&state) % 100;
     681            0 :                 int                     upper = lower + (pg_prng_uint32(&state) % 20);
     682              : 
     683            0 :                 result = bms_add_range(result, lower, upper);
     684            0 :         }
     685            0 :         if (result != NULL)
     686              :         {
     687            0 :                 EXPECT_TRUE(bms_num_members(result) > 0);
     688            0 :                 bms_free(result);
     689            0 :         }
     690              : 
     691            0 :         bms_free(bms1);
     692            0 :         bms_free(bms2);
     693              : 
     694              :         /*
     695              :          * Phase 4: mix of operations on a single set, cross-checking a bitmap
     696              :          * with a secondary state, "members".
     697              :          */
     698            0 :         num_members = 0;
     699              : 
     700            0 :         for (int op = 0; op < num_ops; op++)
     701              :         {
     702            0 :                 switch (pg_prng_uint32(&state) % 3)
     703              :                 {
     704              :                         case 0:                         /* add */
     705            0 :                                 member = pg_prng_uint32(&state) % max_range + min_value;
     706            0 :                                 if (!bms_is_member(member, bms))
     707            0 :                                         members[num_members++] = member;
     708            0 :                                 bms = bms_add_member(bms, member);
     709            0 :                                 break;
     710              :                         case 1:                         /* delete */
     711            0 :                                 if (num_members > 0)
     712              :                                 {
     713            0 :                                         int                     pos = pg_prng_uint32(&state) % num_members;
     714              : 
     715            0 :                                         member = members[pos];
     716            0 :                                         if (!bms_is_member(member, bms))
     717            0 :                                                 elog(ERROR, "expected %d to be a valid member", member);
     718              : 
     719            0 :                                         bms = bms_del_member(bms, member);
     720              : 
     721              :                                         /*
     722              :                                          * Move the final array member at the position of the
     723              :                                          * member just deleted, reducing the array size by one.
     724              :                                          */
     725            0 :                                         members[pos] = members[--num_members];
     726            0 :                                 }
     727            0 :                                 break;
     728              :                         case 2:                         /* test membership */
     729              :                                 /* Verify that bitmap contains all members */
     730            0 :                                 for (int i = 0; i < num_members; i++)
     731              :                                 {
     732            0 :                                         if (!bms_is_member(members[i], bms))
     733            0 :                                                 elog(ERROR, "missing member %d", members[i]);
     734            0 :                                 }
     735            0 :                                 break;
     736              :                 }
     737            0 :                 total_ops++;
     738            0 :         }
     739              : 
     740            0 :         bms_free(bms);
     741            0 :         pfree(members);
     742              : 
     743            0 :         PG_RETURN_INT32(total_ops);
     744            0 : }
        

Generated by: LCOV version 2.3.2-1