1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-25 01:39:28 +03:00

Fix incorrect nmembers calculation in test_bitmapset

This calculation was failing to correctly account for the min_value when
calculating how many random members to add to the Bitmapset.  What the
code was meant to do was add a random number of members between the
minimum and maximum values.  The code failed to account for the minimum
value being non-zero, which could result in too many members being added
to the set, which could reduce the effectiveness of the test.  In reality,
the only caller to this function did pass 0 as the min_value, so there is
no live bug being fixed here.

Fix this so that the Bitmapset is more sparsely populated with members
between the minimum and maximum values.  In passing, swap the order of the
min_value and max_value parameters.  Having the minimum value appear
before the maximum value makes more sense.  Also align the names of both
parameters, and adjust the 'offset' calculation to widen the offset range
by 1 so that the possible range for that random value is -max_value to
max_value.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Greg Burd <greg@burd.me>
Discussion: https://postgr.es/m/CAApHDvpfZqdMRmR-6W9UXb+Tanex5wK6PsL=XzYCV4P3pD36Ng@mail.gmail.com
This commit is contained in:
David Rowley
2026-08-24 22:43:27 +12:00
parent 8646214ee2
commit 53a981ed5b
3 changed files with 36 additions and 19 deletions

View File

@@ -1650,7 +1650,7 @@ SELECT test_random_operations(NULL, 10000, 81920, 0) > 0 AS result;
(1 row)
-- perform some random tests on bms_offset_members()
SELECT test_random_offset_operations(NULL, 1000, 1024, 0) AS result;
SELECT test_random_offset_operations(NULL, 1000, 0, 1024) AS result;
result
--------
1000

View File

@@ -424,6 +424,6 @@ SELECT test_bms_nonempty_difference('(b 1 2)', '(b 50 100)') AS result;
SELECT test_random_operations(NULL, 10000, 81920, 0) > 0 AS result;
-- perform some random tests on bms_offset_members()
SELECT test_random_offset_operations(NULL, 1000, 1024, 0) AS result;
SELECT test_random_offset_operations(NULL, 1000, 0, 1024) AS result;
DROP EXTENSION test_bitmapset;

View File

@@ -790,8 +790,8 @@ test_random_operations(PG_FUNCTION_ARGS)
* Arguments:
* arg1: optional random seed. NULL means use a random seed.
* arg2: the number of operations to perform.
* arg3: the maximum bitmapset member number to use in the random set.
* arg4: the minimum bitmapset member number to use in the random set.
* arg3: the minimum bitmapset member number to use in the random set.
* arg4: the maximum bitmapset member number to use in the random set.
*/
Datum
test_random_offset_operations(PG_FUNCTION_ARGS)
@@ -799,27 +799,32 @@ test_random_offset_operations(PG_FUNCTION_ARGS)
pg_prng_state state;
int64 seed;
int num_ops;
int max_range;
int min_value;
int max_value;
int member;
uint32 range;
if (PG_ARGISNULL(0))
seed = GetCurrentTimestamp();
else
seed = PG_GETARG_INT64(0);
num_ops = PG_GETARG_INT32(1);
max_range = PG_GETARG_INT32(2);
min_value = PG_GETARG_INT32(3);
if (PG_ARGISNULL(1) || num_ops <= 0)
if (PG_ARGISNULL(1) || PG_GETARG_INT32(1) <= 0)
elog(ERROR, "invalid number of operations");
if (PG_ARGISNULL(2) || max_range <= 0)
elog(ERROR, "invalid maximum range");
if (PG_ARGISNULL(3) || min_value < 0)
if (PG_ARGISNULL(2) || PG_GETARG_INT32(2) < 0)
elog(ERROR, "invalid minimum value");
if (PG_ARGISNULL(3) || PG_GETARG_INT32(3) < 0)
elog(ERROR, "invalid maximum value");
num_ops = PG_GETARG_INT32(1);
min_value = PG_GETARG_INT32(2);
max_value = PG_GETARG_INT32(3);
if (max_value < min_value)
elog(ERROR, "maximum value must be greater than or equal to minimum value");
pg_prng_seed(&state, (uint64) seed);
range = (uint32) max_value - (uint32) min_value + 1;
for (int op = 0; op < num_ops; op++)
{
@@ -827,17 +832,29 @@ test_random_offset_operations(PG_FUNCTION_ARGS)
Bitmapset *offset_bms1;
Bitmapset *offset_bms2 = NULL;
int offset;
int nmembers;
uint32 nmembers;
CHECK_FOR_INTERRUPTS();
/* Figure out a random offset and how many members to add */
offset = (pg_prng_uint32(&state) % max_range) - (pg_prng_uint32(&state) % max_range);
nmembers = pg_prng_uint32(&state) % max_range + min_value;
/*
* Choose a random offset for passing to bms_offset_members(). We
* want a number between -max_value and max_value so we test both left
* and right shifting and also test cases that push members,
* occasionally all of them, off the bottom of the set.
*/
offset = (int) (pg_prng_uint32(&state) % ((uint32) max_value + 1));
offset -= (int) (pg_prng_uint32(&state) % ((uint32) max_value + 1));
for (int i = 0; i < nmembers; i++)
/* decide how many members to add */
nmembers = pg_prng_uint32(&state) % range;
/*
* Add a random number of members with values between the minimum and
* maximum values.
*/
for (uint32 i = 0; i < nmembers; i++)
{
member = pg_prng_uint32(&state) % max_range + min_value;
member = min_value + (pg_prng_uint32(&state) % range);
random_bms = bms_add_member(random_bms, member);
}