LCOV - differential code coverage report
Current view: top level - src/test/modules/test_bitmapset - test_bitmapset.c (source / functions) Coverage Total Hit UNC LBC UBC GNC CBC
Current: f76c13edadc2b319036e0d238703ed56bb23f934 vs 9e17d25e79d4756be08b4a5521b4b58450217137 Lines: 95.9 % 366 351 6 9 55 296
Current Date: 2026-09-20 14:13:17 +0900 Functions: 100.0 % 72 72 5 67
Baseline: lcov-20260920-baseline Branches: 71.7 % 276 198 25 1 52 39 159
Baseline Date: 2026-09-20 14:13:13 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 90.7 % 43 39 2 2 28 11
(30,360] days: 93.0 % 158 147 4 7 27 120
(360..) days: 100.0 % 165 165 165
Function coverage date bins:
(7,30] days: 100.0 % 1 1 1
(30,360] days: 100.0 % 6 6 4 2
(360..) days: 100.0 % 65 65 65
Branch coverage date bins:
(7,30] days: 58.1 % 62 36 15 11 29 7
(30,360] days: 76.5 % 170 130 10 1 29 10 120
(360..) days: 72.7 % 44 32 12 32

 Age         Owner                    Branch data    TLA  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 "fmgr.h"
                                 23                 :                : #include "miscadmin.h"
                                 24                 :                : #include "nodes/bitmapset.h"
                                 25                 :                : #include "nodes/nodes.h"
                                 26                 :                : #include "nodes/pg_list.h"
                                 27                 :                : #include "nodes/readfuncs.h"
                                 28                 :                : #include "utils/array.h"
                                 29                 :                : #include "utils/builtins.h"
                                 30                 :                : #include "utils/timestamp.h"
                                 31                 :                : 
  363 michael@paquier.xyz        32                 :CBC           1 : PG_MODULE_MAGIC;
                                 33                 :                : 
                                 34                 :                : /* Bitmapset API functions in order of appearance in bitmapset.c */
                                 35                 :              2 : PG_FUNCTION_INFO_V1(test_bms_make_singleton);
                                 36                 :              2 : PG_FUNCTION_INFO_V1(test_bms_add_member);
                                 37                 :              2 : PG_FUNCTION_INFO_V1(test_bms_del_member);
                                 38                 :              2 : PG_FUNCTION_INFO_V1(test_bms_is_member);
                                 39                 :              2 : PG_FUNCTION_INFO_V1(test_bms_num_members);
                                 40                 :              2 : PG_FUNCTION_INFO_V1(test_bms_copy);
                                 41                 :              2 : PG_FUNCTION_INFO_V1(test_bms_equal);
                                 42                 :              2 : PG_FUNCTION_INFO_V1(test_bms_compare);
                                 43                 :              2 : PG_FUNCTION_INFO_V1(test_bms_is_subset);
                                 44                 :              2 : PG_FUNCTION_INFO_V1(test_bms_subset_compare);
                                 45                 :              2 : PG_FUNCTION_INFO_V1(test_bms_union);
                                 46                 :              2 : PG_FUNCTION_INFO_V1(test_bms_intersect);
                                 47                 :              2 : PG_FUNCTION_INFO_V1(test_bms_difference);
   73 drowley@postgresql.o       48                 :GNC           2 : PG_FUNCTION_INFO_V1(test_bms_offset_members);
  363 michael@paquier.xyz        49                 :CBC           2 : PG_FUNCTION_INFO_V1(test_bms_is_empty);
                                 50                 :              2 : PG_FUNCTION_INFO_V1(test_bms_membership);
                                 51                 :              2 : PG_FUNCTION_INFO_V1(test_bms_singleton_member);
                                 52                 :              2 : PG_FUNCTION_INFO_V1(test_bms_get_singleton_member);
                                 53                 :              2 : PG_FUNCTION_INFO_V1(test_bms_next_member);
                                 54                 :              2 : PG_FUNCTION_INFO_V1(test_bms_prev_member);
                                 55                 :              2 : PG_FUNCTION_INFO_V1(test_bms_hash_value);
                                 56                 :              2 : PG_FUNCTION_INFO_V1(test_bms_overlap);
                                 57                 :              2 : PG_FUNCTION_INFO_V1(test_bms_overlap_list);
                                 58                 :              2 : PG_FUNCTION_INFO_V1(test_bms_nonempty_difference);
                                 59                 :              2 : PG_FUNCTION_INFO_V1(test_bms_member_index);
                                 60                 :              2 : PG_FUNCTION_INFO_V1(test_bms_add_range);
                                 61                 :              2 : PG_FUNCTION_INFO_V1(test_bms_add_members);
                                 62                 :              2 : PG_FUNCTION_INFO_V1(test_bms_int_members);
  356                            63                 :              2 : PG_FUNCTION_INFO_V1(test_bms_del_members);
  363                            64                 :              2 : PG_FUNCTION_INFO_V1(test_bms_replace_members);
                                 65                 :              2 : PG_FUNCTION_INFO_V1(test_bms_join);
                                 66                 :              2 : PG_FUNCTION_INFO_V1(test_bitmap_hash);
                                 67                 :              2 : PG_FUNCTION_INFO_V1(test_bitmap_match);
                                 68                 :                : 
                                 69                 :                : /* Test utility functions */
                                 70                 :              2 : PG_FUNCTION_INFO_V1(test_random_operations);
   73 drowley@postgresql.o       71                 :GNC           2 : PG_FUNCTION_INFO_V1(test_random_offset_operations);
                                 72                 :                : 
                                 73                 :                : /* Convenient macros to test results */
                                 74                 :                : #define EXPECT_TRUE(expr)   \
                                 75                 :                :     do { \
                                 76                 :                :         if (!(expr)) \
                                 77                 :                :             elog(ERROR, \
                                 78                 :                :                  "%s was unexpectedly false in file \"%s\" line %u", \
                                 79                 :                :                  #expr, __FILE__, __LINE__); \
                                 80                 :                :     } while (0)
                                 81                 :                : 
                                 82                 :                : #define EXPECT_NOT_NULL(expr)   \
                                 83                 :                :     do { \
                                 84                 :                :         if ((expr) == NULL) \
                                 85                 :                :             elog(ERROR, \
                                 86                 :                :                  "%s was unexpectedly true in file \"%s\" line %u", \
                                 87                 :                :                  #expr, __FILE__, __LINE__); \
                                 88                 :                :     } while (0)
                                 89                 :                : 
                                 90                 :                : /* Encode Bitmapset to TEXT */
                                 91                 :                : #define BITMAPSET_TO_TEXT(bms) cstring_to_text(nodeToString(bms))
                                 92                 :                : 
                                 93                 :                : /*
                                 94                 :                :  * Decode Bitmapset from text
                                 95                 :                :  */
                                 96                 :                : static Bitmapset *
   10 michael@paquier.xyz        97                 :            347 : text_to_bitmapset(text *txt)
                                 98                 :                : {
                                 99                 :            347 :     char       *str = text_to_cstring(txt);
                                100                 :                :     ReadNodeContext ctx;
                                101                 :                :     const char *token;
                                102                 :                :     int         length;
                                103                 :            347 :     bool        is_bitmapset = false;
                                104                 :                :     Node       *node;
                                105                 :                : 
                                106                 :            347 :     ctx.str = str;
                                107                 :                : 
                                108                 :            347 :     token = pg_strtok(&ctx, &length);
                                109                 :                : 
                                110                 :                :     /* Check empty case, translated to "<>". */
                                111   [ +  +  +  + ]:            347 :     if (token != NULL && length == 0)
                                112                 :              2 :         return NULL;
                                113                 :                : 
                                114                 :                :     /* First token has to be a single '('. */
                                115   [ +  +  +  +  :            345 :     if (token != NULL && length == 1 && token[0] == '(')
                                              +  + ]
                                116                 :                :     {
                                117                 :                :         /* Second token has to be a single 'b'. */
                                118                 :            342 :         token = pg_strtok(&ctx, &length);
                                119   [ +  -  +  -  :            342 :         is_bitmapset = (token != NULL && length == 1 && token[0] == 'b');
                                              +  + ]
                                120                 :                :     }
                                121                 :                : 
                                122         [ +  + ]:            345 :     if (!is_bitmapset)
                                123         [ +  - ]:              5 :         elog(ERROR, "argument is not a Bitmapset");
                                124                 :                : 
                                125                 :            340 :     node = stringToNode(str);
                                126   [ +  +  -  + ]:            340 :     Assert(node == NULL || IsA(node, Bitmapset));
                                127                 :                : 
                                128                 :            340 :     return (Bitmapset *) node;
                                129                 :                : }
                                130                 :                : 
                                131                 :                : /*
                                132                 :                :  * Helper macro to fetch text parameters as Bitmapsets. SQL-NULL means empty
                                133                 :                :  * set.
                                134                 :                :  */
                                135                 :                : #define PG_ARG_GETBITMAPSET(n) \
                                136                 :                :     (PG_ARGISNULL(n) ? NULL : text_to_bitmapset(PG_GETARG_TEXT_PP(n)))
                                137                 :                : 
                                138                 :                : /*
                                139                 :                :  * Helper macro to handle converting sets back to text, returning the
                                140                 :                :  * resulting text representation of the set.
                                141                 :                :  */
                                142                 :                : #define PG_RETURN_BITMAPSET_AS_TEXT(bms) \
                                143                 :                :     PG_RETURN_TEXT_P(BITMAPSET_TO_TEXT(bms))
                                144                 :                : 
                                145                 :                : /*
                                146                 :                :  * Individual test functions for each bitmapset API function
                                147                 :                :  *
                                148                 :                :  * Primarily, we aim to keep these as close to simple wrapper functions as
                                149                 :                :  * possible in order to publish the functions of bitmapset.c to the SQL layer
                                150                 :                :  * with as little interference as possible.  We opt to return SQL NULL in
                                151                 :                :  * cases where the input given to the SQL function isn't valid to pass to the
                                152                 :                :  * underlying bitmapset.c function.  For example we cannot do much useful
                                153                 :                :  * testing if someone calls test_bms_make_singleton(NULL) since
                                154                 :                :  * bms_make_singleton() expects an integer argument.
                                155                 :                :  *
                                156                 :                :  * For function arguments which are to be converted to Bitmapsets, we accept
                                157                 :                :  * SQL NULL as a valid argument to mean an empty set.  Optionally callers may
                                158                 :                :  * pass '(b)'.
                                159                 :                :  *
                                160                 :                :  * For the test functions which return a Bitmapset, these are converted back
                                161                 :                :  * to text with result generated by nodeToString().
                                162                 :                :  */
                                163                 :                : 
                                164                 :                : Datum
  363 michael@paquier.xyz       165                 :CBC           7 : test_bms_add_member(PG_FUNCTION_ARGS)
                                166                 :                : {
                                167                 :                :     Bitmapset  *bms;
                                168                 :                :     int         member;
                                169                 :                : 
                                170         [ +  + ]:              7 :     if (PG_ARGISNULL(1))
  354                           171                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                172                 :                : 
                                173         [ +  - ]:              6 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           174                 :              6 :     member = PG_GETARG_INT32(1);
                                175                 :                : 
  354                           176                 :              6 :     bms = bms_add_member(bms, member);
                                177                 :                : 
                                178                 :              4 :     PG_RETURN_BITMAPSET_AS_TEXT(bms);
                                179                 :                : }
                                180                 :                : 
                                181                 :                : Datum
  363                           182                 :              3 : test_bms_add_members(PG_FUNCTION_ARGS)
                                183                 :                : {
  354                           184         [ +  - ]:              3 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                185         [ +  - ]:              3 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                186                 :                : 
                                187                 :                :     /* left input is recycled */
  363                           188                 :              3 :     bms1 = bms_add_members(bms1, bms2);
                                189                 :                : 
  354                           190                 :              3 :     PG_RETURN_BITMAPSET_AS_TEXT(bms1);
                                191                 :                : }
                                192                 :                : 
                                193                 :                : Datum
  363                           194                 :             12 : test_bms_del_member(PG_FUNCTION_ARGS)
                                195                 :                : {
                                196                 :                :     Bitmapset  *bms;
                                197                 :                :     int32       member;
                                198                 :                : 
                                199         [ +  + ]:             12 :     if (PG_ARGISNULL(1))
  354                           200                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                201                 :                : 
                                202         [ +  - ]:             11 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           203                 :             11 :     member = PG_GETARG_INT32(1);
                                204                 :                : 
  354                           205                 :             11 :     bms = bms_del_member(bms, member);
                                206                 :                : 
                                207                 :             10 :     PG_RETURN_BITMAPSET_AS_TEXT(bms);
                                208                 :                : }
                                209                 :                : 
                                210                 :                : Datum
  363                           211                 :              6 : test_bms_is_member(PG_FUNCTION_ARGS)
                                212                 :                : {
                                213                 :                :     Bitmapset  *bms;
                                214                 :                :     int32       member;
                                215                 :                :     bool        result;
                                216                 :                : 
                                217         [ +  + ]:              6 :     if (PG_ARGISNULL(1))
  354                           218                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                219                 :                : 
                                220         [ +  - ]:              5 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           221                 :              5 :     member = PG_GETARG_INT32(1);
                                222                 :                : 
  354                           223                 :              5 :     result = bms_is_member(member, bms);
                                224                 :                : 
  363                           225                 :              4 :     PG_RETURN_BOOL(result);
                                226                 :                : }
                                227                 :                : 
                                228                 :                : Datum
                                229                 :              9 : test_bms_num_members(PG_FUNCTION_ARGS)
                                230                 :                : {
  354                           231         [ +  - ]:              9 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                232                 :                :     int         result;
                                233                 :                : 
  363                           234                 :              4 :     result = bms_num_members(bms);
                                235                 :                : 
                                236                 :              4 :     PG_RETURN_INT32(result);
                                237                 :                : }
                                238                 :                : 
                                239                 :                : Datum
                                240                 :              4 : test_bms_make_singleton(PG_FUNCTION_ARGS)
                                241                 :                : {
                                242                 :                :     Bitmapset  *bms;
                                243                 :                :     int32       member;
                                244                 :                : 
                                245                 :              4 :     member = PG_GETARG_INT32(0);
                                246                 :              4 :     bms = bms_make_singleton(member);
                                247                 :                : 
  354                           248                 :              3 :     PG_RETURN_BITMAPSET_AS_TEXT(bms);
                                249                 :                : }
                                250                 :                : 
                                251                 :                : Datum
  363                           252                 :              3 : test_bms_copy(PG_FUNCTION_ARGS)
                                253                 :                : {
  354                           254         [ +  + ]:              3 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                255                 :                :     Bitmapset  *copy_bms;
                                256                 :                : 
  363                           257                 :              3 :     copy_bms = bms_copy(bms);
                                258                 :                : 
  354                           259                 :              3 :     PG_RETURN_BITMAPSET_AS_TEXT(copy_bms);
                                260                 :                : }
                                261                 :                : 
                                262                 :                : Datum
  363                           263                 :             13 : test_bms_equal(PG_FUNCTION_ARGS)
                                264                 :                : {
  354                           265         [ +  + ]:             13 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                266         [ +  + ]:             13 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                267                 :                :     bool        result;
                                268                 :                : 
  363                           269                 :             13 :     result = bms_equal(bms1, bms2);
                                270                 :                : 
                                271                 :             13 :     PG_RETURN_BOOL(result);
                                272                 :                : }
                                273                 :                : 
                                274                 :                : Datum
                                275                 :              9 : test_bms_union(PG_FUNCTION_ARGS)
                                276                 :                : {
  354                           277         [ +  + ]:              9 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                278         [ +  + ]:              9 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                279                 :                :     Bitmapset  *result_bms;
                                280                 :                : 
  363                           281                 :              9 :     result_bms = bms_union(bms1, bms2);
                                282                 :                : 
  354                           283                 :              9 :     PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
                                284                 :                : }
                                285                 :                : 
                                286                 :                : Datum
  363                           287                 :              4 : test_bms_membership(PG_FUNCTION_ARGS)
                                288                 :                : {
  354                           289         [ +  + ]:              4 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                290                 :                :     BMS_Membership result;
                                291                 :                : 
  363                           292                 :              4 :     result = bms_membership(bms);
                                293                 :                : 
                                294                 :              4 :     PG_RETURN_INT32((int32) result);
                                295                 :                : }
                                296                 :                : 
                                297                 :                : Datum
                                298                 :              6 : test_bms_next_member(PG_FUNCTION_ARGS)
                                299                 :                : {
                                300                 :                :     Bitmapset  *bms;
                                301                 :                :     int32       prevmember;
                                302                 :                :     int         result;
                                303                 :                : 
  354                           304         [ +  + ]:              6 :     if (PG_ARGISNULL(1))
                                305                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                306                 :                : 
                                307         [ +  + ]:              5 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           308                 :              5 :     prevmember = PG_GETARG_INT32(1);
                                309                 :                : 
  354                           310                 :              5 :     result = bms_next_member(bms, prevmember);
                                311                 :                : 
  363                           312                 :              5 :     PG_RETURN_INT32(result);
                                313                 :                : }
                                314                 :                : 
                                315                 :                : Datum
                                316                 :              8 : test_bms_intersect(PG_FUNCTION_ARGS)
                                317                 :                : {
  354                           318         [ +  + ]:              8 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                319         [ +  + ]:              8 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                320                 :                :     Bitmapset  *result_bms;
                                321                 :                : 
  363                           322                 :              8 :     result_bms = bms_intersect(bms1, bms2);
                                323                 :                : 
  354                           324                 :              8 :     PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
                                325                 :                : }
                                326                 :                : 
                                327                 :                : Datum
  363                           328                 :             10 : test_bms_difference(PG_FUNCTION_ARGS)
                                329                 :                : {
  354                           330         [ +  + ]:             10 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                331         [ +  + ]:             10 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                332                 :                :     Bitmapset  *result_bms;
                                333                 :                : 
  363                           334                 :             10 :     result_bms = bms_difference(bms1, bms2);
                                335                 :                : 
  354                           336                 :             10 :     PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
                                337                 :                : }
                                338                 :                : 
                                339                 :                : Datum
   73 drowley@postgresql.o      340                 :GNC          13 : test_bms_offset_members(PG_FUNCTION_ARGS)
                                341                 :                : {
                                342         [ +  - ]:             13 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                343                 :             13 :     int         offset = PG_GETARG_INT32(1);
                                344                 :                : 
                                345                 :             13 :     bms = bms_offset_members(bms, offset);
                                346                 :                : 
                                347                 :             11 :     PG_RETURN_BITMAPSET_AS_TEXT(bms);
                                348                 :                : }
                                349                 :                : 
                                350                 :                : Datum
  363 michael@paquier.xyz       351                 :CBC          10 : test_bms_compare(PG_FUNCTION_ARGS)
                                352                 :                : {
  354                           353         [ +  + ]:             10 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                354         [ +  + ]:             10 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                355                 :                :     int         result;
                                356                 :                : 
  363                           357                 :             10 :     result = bms_compare(bms1, bms2);
                                358                 :                : 
                                359                 :             10 :     PG_RETURN_INT32(result);
                                360                 :                : }
                                361                 :                : 
                                362                 :                : Datum
                                363                 :              3 : test_bms_is_empty(PG_FUNCTION_ARGS)
                                364                 :                : {
  354                           365         [ +  + ]:              3 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                366                 :                :     bool        result;
                                367                 :                : 
  363                           368                 :              3 :     result = bms_is_empty(bms);
                                369                 :                : 
                                370                 :              3 :     PG_RETURN_BOOL(result);
                                371                 :                : }
                                372                 :                : 
                                373                 :                : Datum
                                374                 :             10 : test_bms_is_subset(PG_FUNCTION_ARGS)
                                375                 :                : {
  354                           376         [ +  + ]:             10 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                377         [ +  + ]:             10 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                378                 :                :     bool        result;
                                379                 :                : 
  363                           380                 :             10 :     result = bms_is_subset(bms1, bms2);
                                381                 :                : 
                                382                 :             10 :     PG_RETURN_BOOL(result);
                                383                 :                : }
                                384                 :                : 
                                385                 :                : Datum
                                386                 :             23 : test_bms_subset_compare(PG_FUNCTION_ARGS)
                                387                 :                : {
  354                           388         [ +  + ]:             23 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                389         [ +  + ]:             23 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                390                 :                :     BMS_Comparison result;
                                391                 :                : 
  363                           392                 :             23 :     result = bms_subset_compare(bms1, bms2);
                                393                 :                : 
                                394                 :             23 :     PG_RETURN_INT32((int32) result);
                                395                 :                : }
                                396                 :                : 
                                397                 :                : Datum
                                398                 :              3 : test_bms_singleton_member(PG_FUNCTION_ARGS)
                                399                 :                : {
  354                           400         [ +  - ]:              3 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                401                 :                :     int         result;
                                402                 :                : 
  363                           403                 :              3 :     result = bms_singleton_member(bms);
                                404                 :                : 
                                405                 :              1 :     PG_RETURN_INT32(result);
                                406                 :                : }
                                407                 :                : 
                                408                 :                : Datum
                                409                 :              4 : test_bms_get_singleton_member(PG_FUNCTION_ARGS)
                                410                 :                : {
  354                           411         [ +  + ]:              4 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                412                 :                :     int         member;
                                413                 :                : 
                                414                 :                :     /*
                                415                 :                :      * Keep this simple.  Return -1 when we detect the set is not a singleton
                                416                 :                :      * set, otherwise return the singleton member.
                                417                 :                :      */
                                418         [ +  + ]:              4 :     if (!bms_get_singleton_member(bms, &member))
                                419                 :              3 :         member = -1;
                                420                 :                : 
                                421                 :              4 :     PG_RETURN_INT32(member);
                                422                 :                : }
                                423                 :                : 
                                424                 :                : Datum
  363                           425                 :              7 : test_bms_prev_member(PG_FUNCTION_ARGS)
                                426                 :                : {
                                427                 :                :     Bitmapset  *bms;
                                428                 :                :     int32       prevmember;
                                429                 :                :     int         result;
                                430                 :                : 
  354                           431         [ +  + ]:              7 :     if (PG_ARGISNULL(1))
                                432                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                433                 :                : 
                                434         [ +  + ]:              6 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           435                 :              6 :     prevmember = PG_GETARG_INT32(1);
                                436                 :                : 
                                437                 :              6 :     result = bms_prev_member(bms, prevmember);
                                438                 :                : 
                                439                 :              6 :     PG_RETURN_INT32(result);
                                440                 :                : }
                                441                 :                : 
                                442                 :                : Datum
                                443                 :              6 : test_bms_overlap(PG_FUNCTION_ARGS)
                                444                 :                : {
  354                           445         [ +  + ]:              6 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                446         [ +  + ]:              6 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                447                 :                :     bool        result;
                                448                 :                : 
  363                           449                 :              6 :     result = bms_overlap(bms1, bms2);
                                450                 :                : 
                                451                 :              6 :     PG_RETURN_BOOL(result);
                                452                 :                : }
                                453                 :                : 
                                454                 :                : Datum
                                455                 :             11 : test_bms_overlap_list(PG_FUNCTION_ARGS)
                                456                 :                : {
                                457                 :                :     Bitmapset  *bms;
                                458                 :                :     ArrayType  *array;
                                459                 :             11 :     List       *int_list = NIL;
                                460                 :                :     bool        result;
  354                           461                 :             11 :     Datum      *elem_datums = NULL;
                                462                 :             11 :     bool       *elem_nulls = NULL;
                                463                 :                :     int         elem_count;
                                464                 :                :     int         i;
                                465                 :                : 
                                466         [ +  + ]:             11 :     bms = PG_ARG_GETBITMAPSET(0);
                                467                 :                : 
                                468         [ +  + ]:             11 :     if (!PG_ARGISNULL(1))
                                469                 :                :     {
                                470                 :              9 :         array = PG_GETARG_ARRAYTYPE_P(1);
                                471                 :                : 
                                472                 :              9 :         deconstruct_array(array,
                                473                 :                :                           INT4OID, sizeof(int32), true, 'i',
                                474                 :                :                           &elem_datums, &elem_nulls, &elem_count);
                                475                 :                : 
                                476         [ +  + ]:             31 :         for (i = 0; i < elem_count; i++)
                                477                 :                :         {
                                478         [ +  - ]:             22 :             if (!elem_nulls[i])
                                479                 :                :             {
                                480                 :             22 :                 int32       member = DatumGetInt32(elem_datums[i]);
                                481                 :                : 
                                482                 :             22 :                 int_list = lappend_int(int_list, member);
                                483                 :                :             }
                                484                 :                :         }
                                485                 :                :     }
                                486                 :                : 
  363                           487                 :             11 :     result = bms_overlap_list(bms, int_list);
                                488                 :                : 
                                489                 :              9 :     list_free(int_list);
                                490                 :                : 
  354                           491         [ +  + ]:              9 :     if (elem_datums)
                                492                 :              7 :         pfree(elem_datums);
                                493                 :                : 
                                494         [ +  + ]:              9 :     if (elem_nulls)
                                495                 :              7 :         pfree(elem_nulls);
                                496                 :                : 
  363                           497                 :              9 :     PG_RETURN_BOOL(result);
                                498                 :                : }
                                499                 :                : 
                                500                 :                : Datum
                                501                 :              9 : test_bms_nonempty_difference(PG_FUNCTION_ARGS)
                                502                 :                : {
  354                           503         [ +  + ]:              9 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                504         [ +  + ]:              9 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                505                 :                :     bool        result;
                                506                 :                : 
  363                           507                 :              9 :     result = bms_nonempty_difference(bms1, bms2);
                                508                 :                : 
                                509                 :              9 :     PG_RETURN_BOOL(result);
                                510                 :                : }
                                511                 :                : 
                                512                 :                : Datum
                                513                 :              8 : test_bms_member_index(PG_FUNCTION_ARGS)
                                514                 :                : {
                                515                 :                :     Bitmapset  *bms;
                                516                 :                :     int32       member;
                                517                 :                :     int         result;
                                518                 :                : 
  354                           519         [ +  + ]:              8 :     if (PG_ARGISNULL(1))
                                520                 :              1 :         PG_RETURN_NULL();       /* invalid input */
                                521                 :                : 
                                522         [ +  + ]:              7 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           523                 :              7 :     member = PG_GETARG_INT32(1);
                                524                 :                : 
                                525                 :              7 :     result = bms_member_index(bms, member);
                                526                 :                : 
                                527                 :              7 :     PG_RETURN_INT32(result);
                                528                 :                : }
                                529                 :                : 
                                530                 :                : Datum
                                531                 :             25 : test_bms_add_range(PG_FUNCTION_ARGS)
                                532                 :                : {
                                533                 :                :     Bitmapset  *bms;
                                534                 :                :     int32       lower,
                                535                 :                :                 upper;
                                536                 :                : 
                                537   [ +  +  +  + ]:             25 :     if (PG_ARGISNULL(1) || PG_ARGISNULL(2))
  354                           538                 :              3 :         PG_RETURN_NULL();       /* invalid input */
                                539                 :                : 
                                540         [ +  + ]:             22 :     bms = PG_ARG_GETBITMAPSET(0);
  363                           541                 :             22 :     lower = PG_GETARG_INT32(1);
                                542                 :             22 :     upper = PG_GETARG_INT32(2);
                                543                 :                : 
                                544                 :             22 :     bms = bms_add_range(bms, lower, upper);
                                545                 :                : 
  354                           546                 :             21 :     PG_RETURN_BITMAPSET_AS_TEXT(bms);
                                547                 :                : }
                                548                 :                : 
                                549                 :                : Datum
  363                           550                 :              7 : test_bms_int_members(PG_FUNCTION_ARGS)
                                551                 :                : {
  354                           552         [ +  + ]:              7 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                553         [ +  + ]:              7 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                554                 :                : 
                                555                 :                :     /* left input gets recycled */
  363                           556                 :              7 :     bms1 = bms_int_members(bms1, bms2);
                                557                 :                : 
  354                           558                 :              7 :     PG_RETURN_BITMAPSET_AS_TEXT(bms1);
                                559                 :                : }
                                560                 :                : 
                                561                 :                : Datum
  356                           562                 :             10 : test_bms_del_members(PG_FUNCTION_ARGS)
                                563                 :                : {
  354                           564         [ +  + ]:             10 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                565         [ +  + ]:             10 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                566                 :                : 
                                567                 :                :     /* left input gets recycled */
                                568                 :             10 :     bms1 = bms_del_members(bms1, bms2);
                                569                 :                : 
                                570                 :             10 :     PG_RETURN_BITMAPSET_AS_TEXT(bms1);
                                571                 :                : }
                                572                 :                : 
                                573                 :                : Datum
  363                           574                 :              6 : test_bms_replace_members(PG_FUNCTION_ARGS)
                                575                 :                : {
  354                           576         [ +  + ]:              6 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                577         [ +  + ]:              6 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                578                 :                : 
                                579                 :                :     /* left input gets recycled */
                                580                 :              6 :     bms1 = bms_replace_members(bms1, bms2);
                                581                 :                : 
                                582                 :              6 :     PG_RETURN_BITMAPSET_AS_TEXT(bms1);
                                583                 :                : }
                                584                 :                : 
                                585                 :                : Datum
  363                           586                 :              9 : test_bms_join(PG_FUNCTION_ARGS)
                                587                 :                : {
  354                           588         [ +  + ]:              9 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                589         [ +  + ]:              9 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                590                 :                :     Bitmapset  *result_bms;
                                591                 :                : 
                                592                 :                :     /* either input can be recycled */
  363                           593                 :              9 :     result_bms = bms_join(bms1, bms2);
                                594                 :                : 
  354                           595                 :              9 :     PG_RETURN_BITMAPSET_AS_TEXT(result_bms);
                                596                 :                : }
                                597                 :                : 
                                598                 :                : Datum
  363                           599                 :              7 : test_bms_hash_value(PG_FUNCTION_ARGS)
                                600                 :                : {
  354                           601         [ +  + ]:              7 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                602                 :                :     uint32      hash_result;
                                603                 :                : 
  363                           604                 :              7 :     hash_result = bms_hash_value(bms);
                                605                 :                : 
                                606                 :              7 :     PG_RETURN_INT32(hash_result);
                                607                 :                : }
                                608                 :                : 
                                609                 :                : Datum
                                610                 :              7 : test_bitmap_hash(PG_FUNCTION_ARGS)
                                611                 :                : {
  354                           612         [ +  + ]:              7 :     Bitmapset  *bms = PG_ARG_GETBITMAPSET(0);
                                613                 :                :     uint32      hash_result;
                                614                 :                : 
                                615                 :                :     /* Call bitmap_hash */
                                616                 :              7 :     hash_result = bitmap_hash(&bms, sizeof(Bitmapset *));
                                617                 :                : 
  363                           618                 :              7 :     PG_RETURN_INT32(hash_result);
                                619                 :                : }
                                620                 :                : 
                                621                 :                : Datum
                                622                 :             12 : test_bitmap_match(PG_FUNCTION_ARGS)
                                623                 :                : {
  354                           624         [ +  + ]:             12 :     Bitmapset  *bms1 = PG_ARG_GETBITMAPSET(0);
                                625         [ +  + ]:             12 :     Bitmapset  *bms2 = PG_ARG_GETBITMAPSET(1);
                                626                 :                :     int         match_result;
                                627                 :                : 
                                628                 :                :     /* Call bitmap_match with addresses of the Bitmapset pointers */
                                629                 :             12 :     match_result = bitmap_match(&bms1, &bms2, sizeof(Bitmapset *));
                                630                 :                : 
  363                           631                 :             12 :     PG_RETURN_INT32(match_result);
                                632                 :                : }
                                633                 :                : 
                                634                 :                : /*
                                635                 :                :  * Contrary to most of the other functions which are one-one mappings with the
                                636                 :                :  * equivalent C functions, this stresses Bitmapsets in a random fashion for
                                637                 :                :  * various operations.
                                638                 :                :  *
                                639                 :                :  * Arguments:
                                640                 :                :  *  arg1: optional random seed.  NULL autoselects the seed.
                                641                 :                :  *  arg2: defines the number of times each operation is done.
                                642                 :                :  *  arg3: the minimum bitmapset member number to use in the random set.
                                643                 :                :  *  arg4: the maximum bitmapset member number to use in the random set.
                                644                 :                :  *
                                645                 :                :  * The return value is the number of times all operations have been executed.
                                646                 :                :  */
                                647                 :                : Datum
                                648                 :              1 : test_random_operations(PG_FUNCTION_ARGS)
                                649                 :                : {
                                650                 :              1 :     Bitmapset  *bms1 = NULL;
                                651                 :              1 :     Bitmapset  *bms2 = NULL;
                                652                 :              1 :     Bitmapset  *bms = NULL;
                                653                 :              1 :     Bitmapset  *result = NULL;
                                654                 :                :     pg_prng_state state;
                                655                 :              1 :     uint64      seed = GetCurrentTimestamp();
                                656                 :                :     int         num_ops;
                                657                 :                :     int         min_value;
                                658                 :                :     int         max_value;
                                659                 :                :     int         member;
                                660                 :                :     uint32      range;
                                661                 :                :     int        *members;
                                662                 :              1 :     int         num_members = 0;
  352 drowley@postgresql.o      663                 :              1 :     int         total_ops = 0;
                                664                 :                : 
  153                           665         [ -  + ]:              1 :     if (!PG_ARGISNULL(0))
  153 drowley@postgresql.o      666                 :UBC           0 :         seed = PG_GETARG_INT64(0);
                                667                 :                : 
   26 drowley@postgresql.o      668   [ +  -  -  + ]:CBC           1 :     if (PG_ARGISNULL(1) || PG_GETARG_INT32(1) <= 0)
  153 drowley@postgresql.o      669         [ #  # ]:UBC           0 :         elog(ERROR, "invalid number of operations");
   26 drowley@postgresql.o      670   [ +  -  -  + ]:CBC           1 :     if (PG_ARGISNULL(2) || PG_GETARG_INT32(2) < 0)
  153 drowley@postgresql.o      671         [ #  # ]:UBC           0 :         elog(ERROR, "invalid minimum value");
   26 drowley@postgresql.o      672   [ +  -  -  + ]:CBC           1 :     if (PG_ARGISNULL(3) || PG_GETARG_INT32(3) < 0)
   26 drowley@postgresql.o      673         [ #  # ]:UBC           0 :         elog(ERROR, "invalid maximum value");
                                674                 :                : 
   26 drowley@postgresql.o      675                 :CBC           1 :     num_ops = PG_GETARG_INT32(1);
                                676                 :              1 :     min_value = PG_GETARG_INT32(2);
                                677                 :              1 :     max_value = PG_GETARG_INT32(3);
                                678                 :                : 
                                679         [ -  + ]:              1 :     if (max_value < min_value)
   26 drowley@postgresql.o      680         [ #  # ]:UBC           0 :         elog(ERROR, "maximum value must be greater than or equal to minimum value");
                                681                 :                : 
  363 michael@paquier.xyz       682                 :CBC           1 :     pg_prng_seed(&state, seed);
   26 drowley@postgresql.o      683                 :              1 :     range = (uint32) max_value - (uint32) min_value + 1;
                                684                 :                : 
                                685                 :                :     /*
                                686                 :                :      * There can be up to "num_ops" members added.  This is very unlikely,
                                687                 :                :      * still possible if all the operations hit the "0" case during phase 4
                                688                 :                :      * where multiple operation types are mixed together.
                                689                 :                :      */
  285 michael@paquier.xyz       690                 :              1 :     members = palloc_array(int, num_ops);
                                691                 :                : 
                                692                 :                :     /* Phase 1: Random insertions in first set */
  363                           693         [ +  + ]:           5001 :     for (int i = 0; i < num_ops / 2; i++)
                                694                 :                :     {
  153 drowley@postgresql.o      695         [ -  + ]:           5000 :         CHECK_FOR_INTERRUPTS();
                                696                 :                : 
   26                           697                 :           5000 :         member = min_value + (pg_prng_uint32(&state) % range);
                                698                 :                : 
  363 michael@paquier.xyz       699         [ +  + ]:           5000 :         if (!bms_is_member(member, bms1))
                                700                 :           4863 :             members[num_members++] = member;
  345                           701                 :           5000 :         bms1 = bms_add_member(bms1, member);
                                702                 :                :     }
                                703                 :                : 
                                704                 :                :     /* Phase 2: Random insertions in second set */
  363                           705         [ +  + ]:           2501 :     for (int i = 0; i < num_ops / 4; i++)
                                706                 :                :     {
  153 drowley@postgresql.o      707         [ -  + ]:           2500 :         CHECK_FOR_INTERRUPTS();
                                708                 :                : 
   26                           709                 :           2500 :         member = min_value + (pg_prng_uint32(&state) % range);
                                710                 :                : 
  345 michael@paquier.xyz       711         [ +  + ]:           2500 :         if (!bms_is_member(member, bms2))
                                712                 :           2462 :             members[num_members++] = member;
  363                           713                 :           2500 :         bms2 = bms_add_member(bms2, member);
                                714                 :                :     }
                                715                 :                : 
                                716                 :                :     /* Test union */
                                717                 :              1 :     result = bms_union(bms1, bms2);
                                718   [ -  +  -  - ]:              1 :     EXPECT_NOT_NULL(result);
                                719                 :                : 
                                720                 :                :     /* Verify union contains all members from first and second sets */
                                721         [ +  + ]:           7326 :     for (int i = 0; i < num_members; i++)
                                722                 :                :     {
  153 drowley@postgresql.o      723         [ -  + ]:           7325 :         CHECK_FOR_INTERRUPTS();
                                724                 :                : 
  363 michael@paquier.xyz       725         [ -  + ]:           7325 :         if (!bms_is_member(members[i], result))
  104 peter@eisentraut.org      726         [ #  # ]:UBC           0 :             elog(ERROR, "union missing member %d, seed " UINT64_FORMAT,
                                727                 :                :                  members[i], seed);
                                728                 :                :     }
  363 michael@paquier.xyz       729                 :CBC           1 :     bms_free(result);
                                730                 :                : 
                                731                 :                :     /*
                                732                 :                :      * Test intersection, checking that all the members in the result are from
                                733                 :                :      * both the first and second sets.
                                734                 :                :      */
                                735                 :              1 :     result = bms_intersect(bms1, bms2);
                                736         [ +  - ]:              1 :     if (result != NULL)
                                737                 :                :     {
                                738                 :              1 :         member = -1;
                                739                 :                : 
                                740         [ +  + ]:            169 :         while ((member = bms_next_member(result, member)) >= 0)
                                741                 :                :         {
  153 drowley@postgresql.o      742         [ -  + ]:            168 :             CHECK_FOR_INTERRUPTS();
                                743                 :                : 
  363 michael@paquier.xyz       744   [ +  -  -  + ]:            168 :             if (!bms_is_member(member, bms1) || !bms_is_member(member, bms2))
  104 peter@eisentraut.org      745         [ #  # ]:UBC           0 :                 elog(ERROR, "intersection contains invalid member %d, seed " UINT64_FORMAT,
                                746                 :                :                      member, seed);
                                747                 :                :         }
  363 michael@paquier.xyz       748                 :CBC           1 :         bms_free(result);
                                749                 :                :     }
                                750                 :                : 
                                751                 :                :     /* Phase 3: Test range operations */
                                752                 :              1 :     result = NULL;
                                753         [ +  + ]:          10001 :     for (int i = 0; i < num_ops; i++)
                                754                 :                :     {
                                755                 :          10000 :         int         lower = pg_prng_uint32(&state) % 100;
                                756                 :          10000 :         int         upper = lower + (pg_prng_uint32(&state) % 20);
                                757                 :                : 
  153 drowley@postgresql.o      758         [ -  + ]:          10000 :         CHECK_FOR_INTERRUPTS();
                                759                 :                : 
  363 michael@paquier.xyz       760                 :          10000 :         result = bms_add_range(result, lower, upper);
                                761                 :                :     }
                                762         [ +  - ]:              1 :     if (result != NULL)
                                763                 :                :     {
                                764   [ -  +  -  - ]:              1 :         EXPECT_TRUE(bms_num_members(result) > 0);
                                765                 :              1 :         bms_free(result);
                                766                 :                :     }
                                767                 :                : 
                                768                 :              1 :     bms_free(bms1);
                                769                 :              1 :     bms_free(bms2);
                                770                 :                : 
                                771                 :                :     /*
                                772                 :                :      * Phase 4: mix of operations on a single set, cross-checking a bitmap
                                773                 :                :      * with a secondary state, "members".
                                774                 :                :      */
  345                           775                 :              1 :     num_members = 0;
                                776                 :                : 
                                777         [ +  + ]:          10001 :     for (int op = 0; op < num_ops; op++)
                                778                 :                :     {
  153 drowley@postgresql.o      779         [ -  + ]:          10000 :         CHECK_FOR_INTERRUPTS();
                                780                 :                : 
  363 michael@paquier.xyz       781   [ +  +  +  - ]:          10000 :         switch (pg_prng_uint32(&state) % 3)
                                782                 :                :         {
                                783                 :           3310 :             case 0:             /* add */
   26 drowley@postgresql.o      784                 :           3310 :                 member = min_value + (pg_prng_uint32(&state) % range);
  345 michael@paquier.xyz       785         [ +  - ]:           3310 :                 if (!bms_is_member(member, bms))
                                786                 :           3310 :                     members[num_members++] = member;
  363                           787                 :           3310 :                 bms = bms_add_member(bms, member);
                                788                 :           3310 :                 break;
                                789                 :           3331 :             case 1:             /* delete */
  345                           790         [ +  + ]:           3331 :                 if (num_members > 0)
                                791                 :                :                 {
                                792                 :           3225 :                     int         pos = pg_prng_uint32(&state) % num_members;
                                793                 :                : 
                                794                 :           3225 :                     member = members[pos];
                                795         [ -  + ]:           3225 :                     if (!bms_is_member(member, bms))
  104 peter@eisentraut.org      796         [ #  # ]:UBC           0 :                         elog(ERROR, "expected %d to be a valid member, seed " UINT64_FORMAT,
                                797                 :                :                              member, seed);
                                798                 :                : 
  363 michael@paquier.xyz       799                 :CBC        3225 :                     bms = bms_del_member(bms, member);
                                800                 :                : 
                                801                 :                :                     /*
                                802                 :                :                      * Move the final array member at the position of the
                                803                 :                :                      * member just deleted, reducing the array size by one.
                                804                 :                :                      */
  345                           805                 :           3225 :                     members[pos] = members[--num_members];
                                806                 :                :                 }
  363                           807                 :           3331 :                 break;
                                808                 :           3359 :             case 2:             /* test membership */
                                809                 :                :                 /* Verify that bitmap contains all members */
  345                           810         [ +  + ]:         174209 :                 for (int i = 0; i < num_members; i++)
                                811                 :                :                 {
                                812         [ -  + ]:         170850 :                     if (!bms_is_member(members[i], bms))
  104 peter@eisentraut.org      813         [ #  # ]:UBC           0 :                         elog(ERROR, "missing member %d, seed " UINT64_FORMAT,
                                814                 :                :                              members[i], seed);
                                815                 :                :                 }
  363 michael@paquier.xyz       816                 :CBC        3359 :                 break;
                                817                 :                :         }
                                818                 :          10000 :         total_ops++;
                                819                 :                :     }
                                820                 :                : 
  354                           821                 :              1 :     bms_free(bms);
  345                           822                 :              1 :     pfree(members);
                                823                 :                : 
  363                           824                 :              1 :     PG_RETURN_INT32(total_ops);
                                825                 :                : }
                                826                 :                : 
                                827                 :                : /*
                                828                 :                :  * Random testing for bms_offset_members().  Generates a random set and then
                                829                 :                :  * picks a number to offset the members by.  We then create another set, which
                                830                 :                :  * is built by looping over the members of the random set and performing
                                831                 :                :  * bms_add_member and adding on the offset to create a known good set to
                                832                 :                :  * compare the result of bms_offset_members() to.
                                833                 :                :  *
                                834                 :                :  * Arguments:
                                835                 :                :  *  arg1: optional random seed.  NULL means use a random seed.
                                836                 :                :  *  arg2: the number of operations to perform.
                                837                 :                :  *  arg3: the minimum bitmapset member number to use in the random set.
                                838                 :                :  *  arg4: the maximum bitmapset member number to use in the random set.
                                839                 :                :  */
                                840                 :                : Datum
   73 drowley@postgresql.o      841                 :GNC           1 : test_random_offset_operations(PG_FUNCTION_ARGS)
                                842                 :                : {
                                843                 :                :     pg_prng_state state;
                                844                 :                :     int64       seed;
                                845                 :                :     int         num_ops;
                                846                 :                :     int         min_value;
                                847                 :                :     int         max_value;
                                848                 :                :     int         member;
                                849                 :                :     uint32      range;
                                850                 :                : 
                                851         [ +  - ]:              1 :     if (PG_ARGISNULL(0))
                                852                 :              1 :         seed = GetCurrentTimestamp();
                                853                 :                :     else
   73 drowley@postgresql.o      854                 :UNC           0 :         seed = PG_GETARG_INT64(0);
                                855                 :                : 
   27 drowley@postgresql.o      856   [ +  -  -  + ]:GNC           1 :     if (PG_ARGISNULL(1) || PG_GETARG_INT32(1) <= 0)
   73 drowley@postgresql.o      857         [ #  # ]:UNC           0 :         elog(ERROR, "invalid number of operations");
   27 drowley@postgresql.o      858   [ +  -  -  + ]:GNC           1 :     if (PG_ARGISNULL(2) || PG_GETARG_INT32(2) < 0)
   73 drowley@postgresql.o      859         [ #  # ]:UNC           0 :         elog(ERROR, "invalid minimum value");
   27 drowley@postgresql.o      860   [ +  -  -  + ]:GNC           1 :     if (PG_ARGISNULL(3) || PG_GETARG_INT32(3) < 0)
   27 drowley@postgresql.o      861         [ #  # ]:UNC           0 :         elog(ERROR, "invalid maximum value");
                                862                 :                : 
   27 drowley@postgresql.o      863                 :GNC           1 :     num_ops = PG_GETARG_INT32(1);
                                864                 :              1 :     min_value = PG_GETARG_INT32(2);
                                865                 :              1 :     max_value = PG_GETARG_INT32(3);
                                866                 :                : 
                                867         [ -  + ]:              1 :     if (max_value < min_value)
   27 drowley@postgresql.o      868         [ #  # ]:UNC           0 :         elog(ERROR, "maximum value must be greater than or equal to minimum value");
                                869                 :                : 
   73 drowley@postgresql.o      870                 :GNC           1 :     pg_prng_seed(&state, (uint64) seed);
   27                           871                 :              1 :     range = (uint32) max_value - (uint32) min_value + 1;
                                872                 :                : 
   73                           873         [ +  + ]:           1001 :     for (int op = 0; op < num_ops; op++)
                                874                 :                :     {
                                875                 :           1000 :         Bitmapset  *random_bms = NULL;
                                876                 :                :         Bitmapset  *offset_bms1;
                                877                 :           1000 :         Bitmapset  *offset_bms2 = NULL;
                                878                 :                :         int         offset;
                                879                 :                :         uint32      nmembers;
                                880                 :                : 
                                881         [ -  + ]:           1000 :         CHECK_FOR_INTERRUPTS();
                                882                 :                : 
                                883                 :                :         /*
                                884                 :                :          * Choose a random offset for passing to bms_offset_members().  We
                                885                 :                :          * want a number between -max_value and max_value so we test both left
                                886                 :                :          * and right shifting and also test cases that push members,
                                887                 :                :          * occasionally all of them, off the bottom of the set.
                                888                 :                :          */
   27                           889                 :           1000 :         offset = (int) (pg_prng_uint32(&state) % ((uint32) max_value + 1));
                                890                 :           1000 :         offset -= (int) (pg_prng_uint32(&state) % ((uint32) max_value + 1));
                                891                 :                : 
                                892                 :                :         /* decide how many members to add */
                                893                 :           1000 :         nmembers = pg_prng_uint32(&state) % range;
                                894                 :                : 
                                895                 :                :         /*
                                896                 :                :          * Add a random number of members with values between the minimum and
                                897                 :                :          * maximum values.
                                898                 :                :          */
                                899         [ +  + ]:         511709 :         for (uint32 i = 0; i < nmembers; i++)
                                900                 :                :         {
                                901                 :         510709 :             member = min_value + (pg_prng_uint32(&state) % range);
   73                           902                 :         510709 :             random_bms = bms_add_member(random_bms, member);
                                903                 :                :         }
                                904                 :                : 
                                905                 :                :         /* create a known-good set the old fashioned way */
                                906                 :           1000 :         offset_bms2 = NULL;
                                907                 :           1000 :         member = -1;
                                908         [ +  + ]:         377873 :         while ((member = bms_next_member(random_bms, member)) >= 0)
                                909                 :                :         {
                                910         [ +  + ]:         376873 :             if (member + offset >= 0)
                                911                 :         313465 :                 offset_bms2 = bms_add_member(offset_bms2, member + offset);
                                912                 :                :         }
                                913                 :                : 
                                914                 :                :         /* do the offsetting */
                                915                 :           1000 :         offset_bms1 = bms_offset_members(random_bms, offset);
                                916                 :                : 
                                917                 :                :         /* check against the known-good set */
                                918         [ -  + ]:           1000 :         if (!bms_equal(offset_bms1, offset_bms2))
   73 drowley@postgresql.o      919         [ #  # ]:UNC           0 :             elog(ERROR, "bms_offset_members failed with offset %d seed " INT64_FORMAT, offset, seed);
                                920                 :                : 
                                921                 :                :         /* Cleanup before the next loop */
   73 drowley@postgresql.o      922                 :GNC        1000 :         bms_free(random_bms);
                                923                 :           1000 :         bms_free(offset_bms1);
                                924                 :           1000 :         bms_free(offset_bms2);
                                925                 :                :     }
                                926                 :                : 
                                927                 :              1 :     PG_RETURN_INT32(num_ops);
                                928                 :                : }
        

Generated by: LCOV version 2.0-1