1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-15 05:46:52 +03:00

Add a test module for Bitmapset

Bitmapset has a complex set of APIs, defined in bitmapset.h, and it can
be hard to test edge cases with the backend core code only.

This test module is aimed at closing the gap, and implements a set of
SQL functions that act as wrappers of the low-level C functions of the
same names.  These functions rely on text as data type for the input and
the output as Bitmapset as a node has support for these.  An extra
function, named test_random_operations(), can be used to stress bitmaps
with random member values and a defined number of operations potentially
useful for other purposes than only tests.

The coverage increases from 85.2% to 93.4%.  It should be possible to
cover more code paths, but at least it's a beginning.

Author: Greg Burd <greg@burd.me>
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/7BD1ABDB-B03A-464A-9BA9-A73B55AD8A1F@getmailspring.com
This commit is contained in:
Michael Paquier
2025-09-22 16:53:00 +09:00
parent 9fc7f6ab72
commit 00c3d87a5c
10 changed files with 2387 additions and 0 deletions

View File

@@ -16,6 +16,7 @@ SUBDIRS = \
spgist_name_ops \
test_aio \
test_binaryheap \
test_bitmapset \
test_bloomfilter \
test_copy_callbacks \
test_custom_rmgrs \

View File

@@ -15,6 +15,7 @@ subdir('spgist_name_ops')
subdir('ssl_passphrase_callback')
subdir('test_aio')
subdir('test_binaryheap')
subdir('test_bitmapset')
subdir('test_bloomfilter')
subdir('test_copy_callbacks')
subdir('test_custom_rmgrs')

View File

@@ -0,0 +1,4 @@
# Generated subdirectories
/log/
/results/
/tmp_check/

View File

@@ -0,0 +1,23 @@
# src/test/modules/test_bitmapset/Makefile
MODULE_big = test_bitmapset
OBJS = \
$(WIN32RES) \
test_bitmapset.o
PGFILEDESC = "test_bitmapset - test code for bitmapset"
EXTENSION = test_bitmapset
DATA = test_bitmapset--1.0.sql
REGRESS = test_bitmapset
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = src/test/modules/test_bitmapset
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@@ -0,0 +1,907 @@
-- Tests for Bitmapsets
CREATE EXTENSION test_bitmapset;
-- bms_make_singleton()
SELECT test_bms_make_singleton(-1);
ERROR: negative bitmapset member not allowed
SELECT test_bms_make_singleton(42) AS result;
result
--------
(b 42)
(1 row)
SELECT test_bms_make_singleton(0) AS result;
result
--------
(b 0)
(1 row)
SELECT test_bms_make_singleton(1000) AS result;
result
----------
(b 1000)
(1 row)
-- bms_add_member()
SELECT test_bms_add_member('(b 1)', -1); -- error
ERROR: negative bitmapset member not allowed
SELECT test_bms_add_member('(b)', -10); -- error
ERROR: negative bitmapset member not allowed
SELECT test_bms_add_member('(b)', 10) AS result;
result
--------
(b 10)
(1 row)
SELECT test_bms_add_member('(b 5)', 10) AS result;
result
----------
(b 5 10)
(1 row)
-- sort check
SELECT test_bms_add_member('(b 10)', 5) AS result;
result
----------
(b 5 10)
(1 row)
-- idempotent change
SELECT test_bms_add_member('(b 10)', 10) AS result;
result
--------
(b 10)
(1 row)
-- bms_replace_members()
SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result;
result
-----------
(b 1 2 3)
(1 row)
SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result;
result
--------
(1 row)
SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result;
result
-----------
(b 3 5 6)
(1 row)
SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5)') AS result;
result
---------
(b 3 5)
(1 row)
SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result;
result
-----------
(b 3 5 7)
(1 row)
-- bms_del_member()
SELECT test_bms_del_member('(b)', -20); -- error
ERROR: negative bitmapset member not allowed
SELECT test_bms_del_member('(b)', 10) AS result;
result
--------
(1 row)
SELECT test_bms_del_member('(b 10)', 10) AS result;
result
--------
(1 row)
SELECT test_bms_del_member('(b 10)', 5) AS result;
result
--------
(b 10)
(1 row)
SELECT test_bms_del_member('(b 1 2 3)', 2) AS result;
result
---------
(b 1 3)
(1 row)
-- Reallocation check
SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result;
result
-------------
(b 0 31 64)
(1 row)
-- Word boundary
SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result;
result
-----------------
(b 30 31 33 34)
(1 row)
-- bms_join()
SELECT test_bms_join('(b 1 3 5)', NULL) AS result;
result
-----------
(b 1 3 5)
(1 row)
SELECT test_bms_join(NULL, '(b 2 4 6)') AS result;
result
-----------
(b 2 4 6)
(1 row)
SELECT test_bms_join('(b 1 3 5)', '(b 2 4 6)') AS result;
result
-----------------
(b 1 2 3 4 5 6)
(1 row)
SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result;
result
-------------
(b 1 3 4 5)
(1 row)
-- bms_union()
-- Overlapping sets.
SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result;
result
-------------
(b 1 3 5 7)
(1 row)
-- Union with NULL
SELECT test_bms_union('(b 1 3 5)', '(b)') AS result;
result
-----------
(b 1 3 5)
(1 row)
-- Union of empty with empty
SELECT test_bms_union('(b)', '(b)') AS result;
result
--------
(1 row)
-- Overlapping ranges
SELECT test_bms_union(
test_bms_add_range('(b)', 0, 15),
test_bms_add_range('(b)', 10, 20)
) AS result;
result
----------------------------------------------------------
(b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
(1 row)
-- bms_intersect()
-- Overlapping sets
SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result;
result
---------
(b 3 5)
(1 row)
-- Disjoint sets
SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
(1 row)
-- Intersect with empty.
SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result;
result
--------
(1 row)
-- bms_int_members()
-- Overlapping sets
SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result;
result
---------
(b 3 5)
(1 row)
-- Disjoint sets
SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
(1 row)
-- Intersect with empty.
SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result;
result
--------
(1 row)
-- Multiple members
SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result;
result
--------------
(b 31 32 64)
(1 row)
-- bms_difference()
-- Overlapping sets
SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result;
result
--------
(b 1)
(1 row)
-- Disjoint sets
SELECT test_bms_difference('(b 1 3 5)', '(b 2 4 6)') AS result;
result
-----------
(b 1 3 5)
(1 row)
-- Identical sets
SELECT test_bms_difference('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
(1 row)
-- Substraction to empty
SELECT test_bms_difference('(b 42)', '(b 42)') AS result;
result
--------
(1 row)
-- Subtraction edge case
SELECT test_bms_difference(
test_bms_add_range('(b)', 0, 100),
test_bms_add_range('(b)', 50, 150)
) AS result;
result
-------------------------------------------------------------------------------------------------------------------------------------------------
(b 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49)
(1 row)
-- bms_is_member()
SELECT test_bms_is_member('(b)', -5); -- error
ERROR: negative bitmapset member not allowed
SELECT test_bms_is_member('(b 1 3 5)', 1) AS result;
result
--------
t
(1 row)
SELECT test_bms_is_member('(b 1 3 5)', 2) AS result;
result
--------
f
(1 row)
SELECT test_bms_is_member('(b 1 3 5)', 3) AS result;
result
--------
t
(1 row)
SELECT test_bms_is_member('(b)', 1) AS result;
result
--------
f
(1 row)
-- bms_member_index()
SELECT test_bms_member_index(NULL, 1) AS result;
result
--------
-1
(1 row)
SELECT test_bms_member_index('(b 1 3 5)', 2) AS result;
result
--------
-1
(1 row)
SELECT test_bms_member_index('(b 1 3 5)', 1) AS result;
result
--------
0
(1 row)
SELECT test_bms_member_index('(b 1 3 5)', 3) AS result;
result
--------
1
(1 row)
-- bms_num_members()
SELECT test_bms_num_members('(b)') AS result;
result
--------
0
(1 row)
SELECT test_bms_num_members('(b 1 3 5)') AS result;
result
--------
3
(1 row)
SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result;
result
--------
5
(1 row)
-- test_bms_equal()
SELECT test_bms_equal('(b)', '(b)') AS result;
result
--------
t
(1 row)
SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result;
result
--------
f
(1 row)
SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result;
result
--------
f
(1 row)
SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
f
(1 row)
-- bms_compare()
SELECT test_bms_compare('(b)', '(b)') AS result;
result
--------
0
(1 row)
SELECT test_bms_compare('(b)', '(b 1 3)') AS result;
result
--------
-1
(1 row)
SELECT test_bms_compare('(b 1 3)', '(b)') AS result;
result
--------
1
(1 row)
SELECT test_bms_compare('(b 1 3)', '(b 1 3)') AS result;
result
--------
0
(1 row)
SELECT test_bms_compare('(b 1 3)', '(b 1 3 5)') AS result;
result
--------
-1
(1 row)
SELECT test_bms_compare('(b 1 3 5)', '(b 1 3)') AS result;
result
--------
1
(1 row)
SELECT test_bms_compare(
test_bms_add_range('(b)', 0, 63),
test_bms_add_range('(b)', 0, 64)
) AS result;
result
--------
-1
(1 row)
-- bms_add_range()
SELECT test_bms_add_range('(b)', -5, 10); -- error
ERROR: negative bitmapset member not allowed
SELECT test_bms_add_range('(b)', 5, 7) AS result;
result
-----------
(b 5 6 7)
(1 row)
SELECT test_bms_add_range('(b)', 5, 5) AS result;
result
--------
(b 5)
(1 row)
SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result;
result
----------------
(b 1 5 6 7 10)
(1 row)
-- Word boundary of 31
SELECT test_bms_add_range('(b)', 30, 34) AS result;
result
--------------------
(b 30 31 32 33 34)
(1 row)
-- Word boundary of 63
SELECT test_bms_add_range('(b)', 62, 66) AS result;
result
--------------------
(b 62 63 64 65 66)
(1 row)
-- Large range
SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result;
result
--------
3898
(1 row)
-- Force reallocations
SELECT length(test_bms_add_range('(b)', 0, 200)) AS result;
result
--------
697
(1 row)
SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result;
result
--------
508
(1 row)
-- bms_membership()
SELECT test_bms_membership('(b)') AS result;
result
--------
0
(1 row)
SELECT test_bms_membership('(b 42)') AS result;
result
--------
1
(1 row)
SELECT test_bms_membership('(b 1 2)') AS result;
result
--------
2
(1 row)
-- bms_is_empty()
SELECT test_bms_is_empty(NULL) AS result;
result
--------
t
(1 row)
SELECT test_bms_is_empty('(b)') AS result;
result
--------
t
(1 row)
SELECT test_bms_is_empty('(b 1)') AS result;
result
--------
f
(1 row)
-- bms_singleton_member()
SELECT test_bms_singleton_member('(b 1 2)'); -- error
ERROR: bitmapset has multiple members
SELECT test_bms_singleton_member('(b 42)') AS result;
result
--------
42
(1 row)
-- bms_get_singleton_member()
-- Not a singleton, returns input default
SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result;
result
--------
1000
(1 row)
-- Singletone, returns sole member
SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result;
result
--------
400
(1 row)
-- bms_next_member() and bms_prev_member()
-- First member
SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result;
result
--------
5
(1 row)
-- Second member
SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result;
result
--------
10
(1 row)
-- Member past the end
SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result;
result
--------
-2
(1 row)
-- Empty set
SELECT test_bms_next_member('(b)', -1) AS result;
result
--------
-2
(1 row)
-- Last member
SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result;
result
--------
20
(1 row)
-- Penultimate member
SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result;
result
--------
15
(1 row)
-- Past beginning member
SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result;
result
--------
-2
(1 row)
-- Empty set
SELECT test_bms_prev_member('(b)', 100) AS result;
result
--------
-2
(1 row)
-- bms_hash_value()
SELECT test_bms_hash_value('(b)') = 0 AS result;
result
--------
t
(1 row)
SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result;
result
--------
t
(1 row)
-- bms_overlap()
SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result;
result
--------
t
(1 row)
SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
f
(1 row)
SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result;
result
--------
f
(1 row)
-- bms_is_subset()
SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result;
result
--------
f
(1 row)
SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result;
result
--------
f
(1 row)
SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31),
test_bms_add_range(NULL, 0, 63)) AS result;
result
--------
t
(1 row)
-- bms_subset_compare()
SELECT test_bms_subset_compare(NULL, NULL) AS result;
result
--------
0
(1 row)
SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
result
--------
2
(1 row)
SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result;
result
--------
1
(1 row)
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
result
--------
2
(1 row)
SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
result
--------
1
(1 row)
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
0
(1 row)
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
3
(1 row)
-- bms_copy()
SELECT test_bms_copy(NULL) AS result;
result
--------
(1 row)
SELECT test_bms_copy('(b 1 3 5 7)') AS result;
result
-------------
(b 1 3 5 7)
(1 row)
-- bms_add_members()
SELECT test_bms_add_member('(b)', 1000); -- error
test_bms_add_member
---------------------
(b 1000)
(1 row)
SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result;
result
-------------
(b 1 3 5 7)
(1 row)
SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 7)') AS result;
result
---------------
(b 1 2 3 5 7)
(1 row)
SELECT test_bms_add_members('(b 1 3 5)', '(b 100 200 300)') AS result;
result
-----------------------
(b 1 3 5 100 200 300)
(1 row)
-- bitmap_hash()
SELECT test_bitmap_hash('(b)') = 0 AS result;
result
--------
t
(1 row)
SELECT test_bitmap_hash('(b 1 3 5)') = test_bitmap_hash('(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bitmap_hash('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result;
result
--------
t
(1 row)
-- bitmap_match()
SELECT test_bitmap_match('(b)', '(b)') AS result;
result
--------
0
(1 row)
SELECT test_bitmap_match('(b)', '(b 1 3 5)') AS result;
result
--------
1
(1 row)
SELECT test_bitmap_match('(b 1 3 5)', '(b)') AS result;
result
--------
1
(1 row)
SELECT test_bitmap_match('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
0
(1 row)
SELECT test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
1
(1 row)
SELECT test_bitmap_match('(b 1 3)', '(b 1 3 5)') AS result;
result
--------
1
(1 row)
-- Check relationship of bitmap_match() with bms_equal()
SELECT (test_bitmap_match('(b 1 3 5)', '(b 1 3 5)') = 0) =
test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
t
(1 row)
SELECT (test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') = 0) =
test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
t
(1 row)
SELECT (test_bitmap_match('(b)', '(b)') = 0) =
test_bms_equal('(b)', '(b)') AS result;
result
--------
t
(1 row)
-- bms_overlap_list()
SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result;
result
--------
t
(1 row)
SELECT test_bms_overlap_list('(b 2 3)', ARRAY[1,2]) AS result;
result
--------
t
(1 row)
SELECT test_bms_overlap_list('(b 3 4)', ARRAY[3,4,5]) AS result;
result
--------
t
(1 row)
SELECT test_bms_overlap_list('(b 7 10)', ARRAY[6,7,8,9]) AS result;
result
--------
t
(1 row)
SELECT test_bms_overlap_list('(b 1 5)', ARRAY[6,7,8,9]) AS result;
result
--------
f
(1 row)
-- Empty list
SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result;
result
--------
f
(1 row)
-- bms_nonempty_difference()
SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result;
result
--------
f
(1 row)
SELECT test_bms_nonempty_difference('(b 1 3 5)', NULL) AS result;
result
--------
t
(1 row)
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 2 4 6)') AS result;
result
--------
t
(1 row)
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 5)') AS result;
result
--------
t
(1 row)
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result;
result
--------
f
(1 row)
-- random operations
SELECT test_random_operations(-1, 10000, 81920, 0) > 0 AS result;
result
--------
t
(1 row)
DROP EXTENSION test_bitmapset;

View File

@@ -0,0 +1,33 @@
# Copyright (c) 2025, PostgreSQL Global Development Group
test_bitmapset_sources = files(
'test_bitmapset.c',
)
if host_system == 'windows'
test_bitmapset_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
'--NAME', 'test_bitmapset',
'--FILEDESC', 'test_bitmapset - test code for src/include/nodes/bitmapset.h',])
endif
test_bitmapset = shared_module('test_bitmapset',
test_bitmapset_sources,
kwargs: pg_test_mod_args,
)
test_install_libs += test_bitmapset
test_install_data += files(
'test_bitmapset.control',
'test_bitmapset--1.0.sql',
)
tests += {
'name': 'test_bitmapset',
'sd': meson.current_source_dir(),
'bd': meson.current_build_dir(),
'regress': {
'sql': [
'test_bitmapset',
],
},
}

View File

@@ -0,0 +1,257 @@
-- Tests for Bitmapsets
CREATE EXTENSION test_bitmapset;
-- bms_make_singleton()
SELECT test_bms_make_singleton(-1);
SELECT test_bms_make_singleton(42) AS result;
SELECT test_bms_make_singleton(0) AS result;
SELECT test_bms_make_singleton(1000) AS result;
-- bms_add_member()
SELECT test_bms_add_member('(b 1)', -1); -- error
SELECT test_bms_add_member('(b)', -10); -- error
SELECT test_bms_add_member('(b)', 10) AS result;
SELECT test_bms_add_member('(b 5)', 10) AS result;
-- sort check
SELECT test_bms_add_member('(b 10)', 5) AS result;
-- idempotent change
SELECT test_bms_add_member('(b 10)', 10) AS result;
-- bms_replace_members()
SELECT test_bms_replace_members(NULL, '(b 1 2 3)') AS result;
SELECT test_bms_replace_members('(b 1 2 3)', NULL) AS result;
SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5 6)') AS result;
SELECT test_bms_replace_members('(b 1 2 3)', '(b 3 5)') AS result;
SELECT test_bms_replace_members('(b 1 2)', '(b 3 5 7)') AS result;
-- bms_del_member()
SELECT test_bms_del_member('(b)', -20); -- error
SELECT test_bms_del_member('(b)', 10) AS result;
SELECT test_bms_del_member('(b 10)', 10) AS result;
SELECT test_bms_del_member('(b 10)', 5) AS result;
SELECT test_bms_del_member('(b 1 2 3)', 2) AS result;
-- Reallocation check
SELECT test_bms_del_member(test_bms_del_member('(b 0 31 32 63 64)', 32), 63) AS result;
-- Word boundary
SELECT test_bms_del_member(test_bms_add_range('(b)', 30, 34), 32) AS result;
-- bms_join()
SELECT test_bms_join('(b 1 3 5)', NULL) AS result;
SELECT test_bms_join(NULL, '(b 2 4 6)') AS result;
SELECT test_bms_join('(b 1 3 5)', '(b 2 4 6)') AS result;
SELECT test_bms_join('(b 1 3 5)', '(b 1 4 5)') AS result;
-- bms_union()
-- Overlapping sets.
SELECT test_bms_union('(b 1 3 5)', '(b 3 5 7)') AS result;
-- Union with NULL
SELECT test_bms_union('(b 1 3 5)', '(b)') AS result;
-- Union of empty with empty
SELECT test_bms_union('(b)', '(b)') AS result;
-- Overlapping ranges
SELECT test_bms_union(
test_bms_add_range('(b)', 0, 15),
test_bms_add_range('(b)', 10, 20)
) AS result;
-- bms_intersect()
-- Overlapping sets
SELECT test_bms_intersect('(b 1 3 5)', '(b 3 5 7)') AS result;
-- Disjoint sets
SELECT test_bms_intersect('(b 1 3 5)', '(b 2 4 6)') AS result;
-- Intersect with empty.
SELECT test_bms_intersect('(b 1 3 5)', '(b)') AS result;
-- bms_int_members()
-- Overlapping sets
SELECT test_bms_int_members('(b 1 3 5)', '(b 3 5 7)') AS result;
-- Disjoint sets
SELECT test_bms_int_members('(b 1 3 5)', '(b 2 4 6)') AS result;
-- Intersect with empty.
SELECT test_bms_int_members('(b 1 3 5)', '(b)') AS result;
-- Multiple members
SELECT test_bms_int_members('(b 0 31 32 63 64)', '(b 31 32 64 65)') AS result;
-- bms_difference()
-- Overlapping sets
SELECT test_bms_difference('(b 1 3 5)', '(b 3 5 7)') AS result;
-- Disjoint sets
SELECT test_bms_difference('(b 1 3 5)', '(b 2 4 6)') AS result;
-- Identical sets
SELECT test_bms_difference('(b 1 3 5)', '(b 1 3 5)') AS result;
-- Substraction to empty
SELECT test_bms_difference('(b 42)', '(b 42)') AS result;
-- Subtraction edge case
SELECT test_bms_difference(
test_bms_add_range('(b)', 0, 100),
test_bms_add_range('(b)', 50, 150)
) AS result;
-- bms_is_member()
SELECT test_bms_is_member('(b)', -5); -- error
SELECT test_bms_is_member('(b 1 3 5)', 1) AS result;
SELECT test_bms_is_member('(b 1 3 5)', 2) AS result;
SELECT test_bms_is_member('(b 1 3 5)', 3) AS result;
SELECT test_bms_is_member('(b)', 1) AS result;
-- bms_member_index()
SELECT test_bms_member_index(NULL, 1) AS result;
SELECT test_bms_member_index('(b 1 3 5)', 2) AS result;
SELECT test_bms_member_index('(b 1 3 5)', 1) AS result;
SELECT test_bms_member_index('(b 1 3 5)', 3) AS result;
-- bms_num_members()
SELECT test_bms_num_members('(b)') AS result;
SELECT test_bms_num_members('(b 1 3 5)') AS result;
SELECT test_bms_num_members('(b 2 4 6 8 10)') AS result;
-- test_bms_equal()
SELECT test_bms_equal('(b)', '(b)') AS result;
SELECT test_bms_equal('(b)', '(b 1 3 5)') AS result;
SELECT test_bms_equal('(b 1 3 5)', '(b)') AS result;
SELECT test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
SELECT test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result;
-- bms_compare()
SELECT test_bms_compare('(b)', '(b)') AS result;
SELECT test_bms_compare('(b)', '(b 1 3)') AS result;
SELECT test_bms_compare('(b 1 3)', '(b)') AS result;
SELECT test_bms_compare('(b 1 3)', '(b 1 3)') AS result;
SELECT test_bms_compare('(b 1 3)', '(b 1 3 5)') AS result;
SELECT test_bms_compare('(b 1 3 5)', '(b 1 3)') AS result;
SELECT test_bms_compare(
test_bms_add_range('(b)', 0, 63),
test_bms_add_range('(b)', 0, 64)
) AS result;
-- bms_add_range()
SELECT test_bms_add_range('(b)', -5, 10); -- error
SELECT test_bms_add_range('(b)', 5, 7) AS result;
SELECT test_bms_add_range('(b)', 5, 5) AS result;
SELECT test_bms_add_range('(b 1 10)', 5, 7) AS result;
-- Word boundary of 31
SELECT test_bms_add_range('(b)', 30, 34) AS result;
-- Word boundary of 63
SELECT test_bms_add_range('(b)', 62, 66) AS result;
-- Large range
SELECT length(test_bms_add_range('(b)', 0, 1000)) AS result;
-- Force reallocations
SELECT length(test_bms_add_range('(b)', 0, 200)) AS result;
SELECT length(test_bms_add_range('(b)', 1000, 1100)) AS result;
-- bms_membership()
SELECT test_bms_membership('(b)') AS result;
SELECT test_bms_membership('(b 42)') AS result;
SELECT test_bms_membership('(b 1 2)') AS result;
-- bms_is_empty()
SELECT test_bms_is_empty(NULL) AS result;
SELECT test_bms_is_empty('(b)') AS result;
SELECT test_bms_is_empty('(b 1)') AS result;
-- bms_singleton_member()
SELECT test_bms_singleton_member('(b 1 2)'); -- error
SELECT test_bms_singleton_member('(b 42)') AS result;
-- bms_get_singleton_member()
-- Not a singleton, returns input default
SELECT test_bms_get_singleton_member('(b 3 6)', 1000) AS result;
-- Singletone, returns sole member
SELECT test_bms_get_singleton_member('(b 400)', 1000) AS result;
-- bms_next_member() and bms_prev_member()
-- First member
SELECT test_bms_next_member('(b 5 10 15 20)', -1) AS result;
-- Second member
SELECT test_bms_next_member('(b 5 10 15 20)', 5) AS result;
-- Member past the end
SELECT test_bms_next_member('(b 5 10 15 20)', 20) AS result;
-- Empty set
SELECT test_bms_next_member('(b)', -1) AS result;
-- Last member
SELECT test_bms_prev_member('(b 5 10 15 20)', 21) AS result;
-- Penultimate member
SELECT test_bms_prev_member('(b 5 10 15 20)', 20) AS result;
-- Past beginning member
SELECT test_bms_prev_member('(b 5 10 15 20)', 5) AS result;
-- Empty set
SELECT test_bms_prev_member('(b)', 100) AS result;
-- bms_hash_value()
SELECT test_bms_hash_value('(b)') = 0 AS result;
SELECT test_bms_hash_value('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
SELECT test_bms_hash_value('(b 1 3 5)') != test_bms_hash_value('(b 2 4 6)') AS result;
-- bms_overlap()
SELECT test_bms_overlap('(b 1 3 5)', '(b 3 5 7)') AS result;
SELECT test_bms_overlap('(b 1 3 5)', '(b 2 4 6)') AS result;
SELECT test_bms_overlap('(b)', '(b 1 3 5)') AS result;
-- bms_is_subset()
SELECT test_bms_is_subset('(b)', '(b 1 3 5)') AS result;
SELECT test_bms_is_subset('(b 1 3)', '(b 1 3 5)') AS result;
SELECT test_bms_is_subset('(b 1 3 5)', '(b 1 3)') AS result;
SELECT test_bms_is_subset('(b 1 3)', '(b 2 4)') AS result;
SELECT test_bms_is_subset(test_bms_add_range(NULL, 0, 31),
test_bms_add_range(NULL, 0, 63)) AS result;
-- bms_subset_compare()
SELECT test_bms_subset_compare(NULL, NULL) AS result;
SELECT test_bms_subset_compare('(b 1 3)', NULL) AS result;
SELECT test_bms_subset_compare(NULL, '(b 1 3)') AS result;
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3)') AS result;
SELECT test_bms_subset_compare('(b 1 3)', '(b 1 3 5)') AS result;
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 1 3 5)') AS result;
SELECT test_bms_subset_compare('(b 1 3 5)', '(b 2 4 6)') AS result;
-- bms_copy()
SELECT test_bms_copy(NULL) AS result;
SELECT test_bms_copy('(b 1 3 5 7)') AS result;
-- bms_add_members()
SELECT test_bms_add_member('(b)', 1000); -- error
SELECT test_bms_add_members('(b 1 3)', '(b 5 7)') AS result;
SELECT test_bms_add_members('(b 1 3 5)', '(b 2 5 7)') AS result;
SELECT test_bms_add_members('(b 1 3 5)', '(b 100 200 300)') AS result;
-- bitmap_hash()
SELECT test_bitmap_hash('(b)') = 0 AS result;
SELECT test_bitmap_hash('(b 1 3 5)') = test_bitmap_hash('(b 1 3 5)') AS result;
SELECT test_bitmap_hash('(b 1 3 5)') = test_bms_hash_value('(b 1 3 5)') AS result;
SELECT test_bitmap_hash('(b 1 3 5)') != test_bitmap_hash('(b 2 4 6)') AS result;
-- bitmap_match()
SELECT test_bitmap_match('(b)', '(b)') AS result;
SELECT test_bitmap_match('(b)', '(b 1 3 5)') AS result;
SELECT test_bitmap_match('(b 1 3 5)', '(b)') AS result;
SELECT test_bitmap_match('(b 1 3 5)', '(b 1 3 5)') AS result;
SELECT test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') AS result;
SELECT test_bitmap_match('(b 1 3)', '(b 1 3 5)') AS result;
-- Check relationship of bitmap_match() with bms_equal()
SELECT (test_bitmap_match('(b 1 3 5)', '(b 1 3 5)') = 0) =
test_bms_equal('(b 1 3 5)', '(b 1 3 5)') AS result;
SELECT (test_bitmap_match('(b 1 3 5)', '(b 2 4 6)') = 0) =
test_bms_equal('(b 1 3 5)', '(b 2 4 6)') AS result;
SELECT (test_bitmap_match('(b)', '(b)') = 0) =
test_bms_equal('(b)', '(b)') AS result;
-- bms_overlap_list()
SELECT test_bms_overlap_list('(b 0)', ARRAY[0]) AS result;
SELECT test_bms_overlap_list('(b 2 3)', ARRAY[1,2]) AS result;
SELECT test_bms_overlap_list('(b 3 4)', ARRAY[3,4,5]) AS result;
SELECT test_bms_overlap_list('(b 7 10)', ARRAY[6,7,8,9]) AS result;
SELECT test_bms_overlap_list('(b 1 5)', ARRAY[6,7,8,9]) AS result;
-- Empty list
SELECT test_bms_overlap_list('(b 1)', ARRAY[]::integer[]) AS result;
-- bms_nonempty_difference()
SELECT test_bms_nonempty_difference(NULL, '(b 1 3 5)') AS result;
SELECT test_bms_nonempty_difference('(b 1 3 5)', NULL) AS result;
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 2 4 6)') AS result;
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 5)') AS result;
SELECT test_bms_nonempty_difference('(b 1 3 5)', '(b 1 3 5)') AS result;
-- random operations
SELECT test_random_operations(-1, 10000, 81920, 0) > 0 AS result;
DROP EXTENSION test_bitmapset;

View File

@@ -0,0 +1,136 @@
/* src/test/modules/test_bitmapset/test_bitmapset--1.0.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_bitmapset" to load this file. \quit
-- Bitmapset API functions
CREATE FUNCTION test_bms_make_singleton(integer)
RETURNS text STRICT
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_add_member(text, integer)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_del_member(text, integer)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_is_member(text, integer)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_num_members(text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_copy(text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_equal(text, text)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_compare(text, text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_is_subset(text, text)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_subset_compare(text, text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_union(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_intersect(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_difference(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_is_empty(text)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_membership(text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_singleton_member(text)
RETURNS integer STRICT
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_get_singleton_member(text, integer)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_next_member(text, integer)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_prev_member(text, integer)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_hash_value(text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_overlap(text, text)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_overlap_list(text, int4[])
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_nonempty_difference(text, text)
RETURNS boolean
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_member_index(text, integer)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_add_range(text, integer, integer)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_add_members(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_int_members(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_replace_members(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bms_join(text, text)
RETURNS text
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bitmap_hash(text)
RETURNS integer
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_bitmap_match(text, text)
RETURNS int
AS 'MODULE_PATHNAME' LANGUAGE C;
-- Test utility functions
CREATE FUNCTION test_random_operations(integer, integer, integer, integer)
RETURNS integer STRICT
AS 'MODULE_PATHNAME' LANGUAGE C;
COMMENT ON EXTENSION test_bitmapset IS 'Test code for Bitmapset';

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
comment = 'Test code for Bitmapset'
default_version = '1.0'
module_pathname = '$libdir/test_bitmapset'
relocatable = true