aboutsummaryrefslogtreecommitdiff
path: root/src/test/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/modules')
-rw-r--r--src/test/modules/Makefile1
-rw-r--r--src/test/modules/meson.build1
-rw-r--r--src/test/modules/test_int128/.gitignore2
-rw-r--r--src/test/modules/test_int128/Makefile23
-rw-r--r--src/test/modules/test_int128/meson.build33
-rw-r--r--src/test/modules/test_int128/t/001_test_int128.pl27
-rw-r--r--src/test/modules/test_int128/test_int128.c190
-rw-r--r--src/test/modules/test_radixtree/test_radixtree.c2
8 files changed, 278 insertions, 1 deletions
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 7d3d3d52b45..903a8ac151a 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -25,6 +25,7 @@ SUBDIRS = \
test_escape \
test_extensions \
test_ginpostinglist \
+ test_int128 \
test_integerset \
test_json_parser \
test_lfind \
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index dd5cd065ba1..93be0f57289 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -24,6 +24,7 @@ subdir('test_dsm_registry')
subdir('test_escape')
subdir('test_extensions')
subdir('test_ginpostinglist')
+subdir('test_int128')
subdir('test_integerset')
subdir('test_json_parser')
subdir('test_lfind')
diff --git a/src/test/modules/test_int128/.gitignore b/src/test/modules/test_int128/.gitignore
new file mode 100644
index 00000000000..277fec6ed2c
--- /dev/null
+++ b/src/test/modules/test_int128/.gitignore
@@ -0,0 +1,2 @@
+/tmp_check/
+/test_int128
diff --git a/src/test/modules/test_int128/Makefile b/src/test/modules/test_int128/Makefile
new file mode 100644
index 00000000000..2e86ee93a9d
--- /dev/null
+++ b/src/test/modules/test_int128/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_int128/Makefile
+
+PGFILEDESC = "test_int128 - test 128-bit integer arithmetic"
+
+PROGRAM = test_int128
+OBJS = $(WIN32RES) test_int128.o
+
+PG_CPPFLAGS = -I$(libpq_srcdir)
+PG_LIBS_INTERNAL += $(libpq_pgport)
+
+NO_INSTALL = 1
+TAP_TESTS = 1
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_int128
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_int128/meson.build b/src/test/modules/test_int128/meson.build
new file mode 100644
index 00000000000..4c2be7a0326
--- /dev/null
+++ b/src/test/modules/test_int128/meson.build
@@ -0,0 +1,33 @@
+# Copyright (c) 2025, PostgreSQL Global Development Group
+
+test_int128_sources = files(
+ 'test_int128.c',
+)
+
+if host_system == 'windows'
+ test_int128_sources += rc_bin_gen.process(win32ver_rc, extra_args: [
+ '--NAME', 'test_int128',
+ '--FILEDESC', 'test int128 program',])
+endif
+
+test_int128 = executable('test_int128',
+ test_int128_sources,
+ dependencies: [frontend_code, libpq],
+ kwargs: default_bin_args + {
+ 'install': false,
+ },
+)
+testprep_targets += test_int128
+
+
+tests += {
+ 'name': 'test_int128',
+ 'sd': meson.current_source_dir(),
+ 'bd': meson.current_build_dir(),
+ 'tap': {
+ 'tests': [
+ 't/001_test_int128.pl',
+ ],
+ 'deps': [test_int128],
+ },
+}
diff --git a/src/test/modules/test_int128/t/001_test_int128.pl b/src/test/modules/test_int128/t/001_test_int128.pl
new file mode 100644
index 00000000000..0c683869f34
--- /dev/null
+++ b/src/test/modules/test_int128/t/001_test_int128.pl
@@ -0,0 +1,27 @@
+# Copyright (c) 2025, PostgreSQL Global Development Group
+
+# Test 128-bit integer arithmetic code in int128.h
+
+use strict;
+use warnings FATAL => 'all';
+
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Run the test program with 1M iterations
+my $exe = "test_int128";
+my $size = 1_000_000;
+
+note "testing executable $exe";
+
+my ($stdout, $stderr) = run_command([ $exe, $size ]);
+
+SKIP:
+{
+ skip "no native int128 type", 2 if $stdout =~ /skipping tests/;
+
+ is($stdout, "", "test_int128: no stdout");
+ is($stderr, "", "test_int128: no stderr");
+}
+
+done_testing();
diff --git a/src/test/modules/test_int128/test_int128.c b/src/test/modules/test_int128/test_int128.c
new file mode 100644
index 00000000000..caa06541a1f
--- /dev/null
+++ b/src/test/modules/test_int128/test_int128.c
@@ -0,0 +1,190 @@
+/*-------------------------------------------------------------------------
+ *
+ * test_int128.c
+ * Testbed for roll-our-own 128-bit integer arithmetic.
+ *
+ * This is a standalone test program that compares the behavior of an
+ * implementation in int128.h to an (assumed correct) int128 native type.
+ *
+ * Copyright (c) 2017-2025, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_int128/test_int128.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <time.h>
+
+/* Require a native int128 type */
+#ifdef HAVE_INT128
+
+/*
+ * By default, we test the non-native implementation in int128.h; but
+ * by predefining USE_NATIVE_INT128 to 1, you can test the native
+ * implementation, just to be sure.
+ */
+#ifndef USE_NATIVE_INT128
+#define USE_NATIVE_INT128 0
+#endif
+
+#include "common/int128.h"
+#include "common/pg_prng.h"
+
+/*
+ * We assume the parts of this union are laid out compatibly.
+ */
+typedef union
+{
+ int128 i128;
+ INT128 I128;
+ struct
+ {
+#ifdef WORDS_BIGENDIAN
+ int64 hi;
+ uint64 lo;
+#else
+ uint64 lo;
+ int64 hi;
+#endif
+ } hl;
+} test128;
+
+#define INT128_HEX_FORMAT "%016" PRIx64 "%016" PRIx64
+
+/*
+ * Control version of comparator.
+ */
+static inline int
+my_int128_compare(int128 x, int128 y)
+{
+ if (x < y)
+ return -1;
+ if (x > y)
+ return 1;
+ return 0;
+}
+
+/*
+ * Main program.
+ *
+ * Generates a lot of random numbers and tests the implementation for each.
+ * The results should be reproducible, since we use a fixed PRNG seed.
+ *
+ * You can give a loop count if you don't like the default 1B iterations.
+ */
+int
+main(int argc, char **argv)
+{
+ long count;
+
+ pg_prng_seed(&pg_global_prng_state, (uint64) time(NULL));
+
+ if (argc >= 2)
+ count = strtol(argv[1], NULL, 0);
+ else
+ count = 1000000000;
+
+ while (count-- > 0)
+ {
+ int64 x = pg_prng_uint64(&pg_global_prng_state);
+ int64 y = pg_prng_uint64(&pg_global_prng_state);
+ int64 z = pg_prng_uint64(&pg_global_prng_state);
+ test128 t1;
+ test128 t2;
+
+ /* check unsigned addition */
+ t1.hl.hi = x;
+ t1.hl.lo = y;
+ t2 = t1;
+ t1.i128 += (int128) (uint64) z;
+ int128_add_uint64(&t2.I128, (uint64) z);
+
+ if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
+ {
+ printf(INT128_HEX_FORMAT " + unsigned %016" PRIx64 "\n", x, y, z);
+ printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
+ printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
+ return 1;
+ }
+
+ /* check signed addition */
+ t1.hl.hi = x;
+ t1.hl.lo = y;
+ t2 = t1;
+ t1.i128 += (int128) z;
+ int128_add_int64(&t2.I128, z);
+
+ if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
+ {
+ printf(INT128_HEX_FORMAT " + signed %016" PRIx64 "\n", x, y, z);
+ printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
+ printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
+ return 1;
+ }
+
+ /* check multiplication */
+ t1.i128 = (int128) x * (int128) y;
+
+ t2.hl.hi = t2.hl.lo = 0;
+ int128_add_int64_mul_int64(&t2.I128, x, y);
+
+ if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
+ {
+ printf("%016" PRIx64 " * %016" PRIx64 "\n", x, y);
+ printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
+ printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
+ return 1;
+ }
+
+ /* check comparison */
+ t1.hl.hi = x;
+ t1.hl.lo = y;
+ t2.hl.hi = z;
+ t2.hl.lo = pg_prng_uint64(&pg_global_prng_state);
+
+ if (my_int128_compare(t1.i128, t2.i128) !=
+ int128_compare(t1.I128, t2.I128))
+ {
+ printf("comparison failure: %d vs %d\n",
+ my_int128_compare(t1.i128, t2.i128),
+ int128_compare(t1.I128, t2.I128));
+ printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
+ printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
+ return 1;
+ }
+
+ /* check case with identical hi parts; above will hardly ever hit it */
+ t2.hl.hi = x;
+
+ if (my_int128_compare(t1.i128, t2.i128) !=
+ int128_compare(t1.I128, t2.I128))
+ {
+ printf("comparison failure: %d vs %d\n",
+ my_int128_compare(t1.i128, t2.i128),
+ int128_compare(t1.I128, t2.I128));
+ printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
+ printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#else /* ! HAVE_INT128 */
+
+/*
+ * For now, do nothing if we don't have a native int128 type.
+ */
+int
+main(int argc, char **argv)
+{
+ printf("skipping tests: no native int128 type\n");
+ return 0;
+}
+
+#endif
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index 32de6a3123e..80ad0296164 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -44,7 +44,7 @@
uint64 _expected = (expected_expr); \
if (_result != _expected) \
elog(ERROR, \
- "%s yielded " UINT64_HEX_FORMAT ", expected " UINT64_HEX_FORMAT " (%s) in file \"%s\" line %u", \
+ "%s yielded %" PRIx64 ", expected %" PRIx64 " (%s) in file \"%s\" line %u", \
#result_expr, _result, _expected, #expected_expr, __FILE__, __LINE__); \
} while (0)