Skip to content

Commit 8c7445a

Browse files
committed
Convert src/tools/testint128.c into a test module.
This creates a new test module src/test/modules/test_int128 and moves src/tools/testint128.c into it so that it can be built using the normal build system, allowing the 128-bit integer arithmetic functions in src/include/common/int128.h to be tested automatically. For now, the tests are skipped on platforms that don't have native int128 support. While at it, fix the test128 union in the test code: the "hl" member of test128 was incorrectly defined to be a union instead of a struct, which meant that the tests were only ever setting and checking half of each 128-bit integer value. Author: Dean Rasheed <dean.a.rasheed@gmail.com> Reviewed-by: John Naylor <johncnaylorls@gmail.com> Discussion: https://postgr.es/m/CAEZATCWgBMc9ZwKMYqQpaQz2X6gaamYRB+RnMsUNcdMcL2Mj_w@mail.gmail.com
1 parent 225ebfe commit 8c7445a

File tree

8 files changed

+125
-18
lines changed

8 files changed

+125
-18
lines changed

src/include/common/int128.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* We make use of the native int128 type if there is one, otherwise
77
* implement things the hard way based on two int64 halves.
88
*
9-
* See src/tools/testint128.c for a simple test harness for this file.
9+
* See src/test/modules/test_int128 for a simple test harness for this file.
1010
*
1111
* Copyright (c) 2017-2025, PostgreSQL Global Development Group
1212
*

src/test/modules/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ SUBDIRS = \
2525
test_escape \
2626
test_extensions \
2727
test_ginpostinglist \
28+
test_int128 \
2829
test_integerset \
2930
test_json_parser \
3031
test_lfind \

src/test/modules/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ subdir('test_dsm_registry')
2424
subdir('test_escape')
2525
subdir('test_extensions')
2626
subdir('test_ginpostinglist')
27+
subdir('test_int128')
2728
subdir('test_integerset')
2829
subdir('test_json_parser')
2930
subdir('test_lfind')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/tmp_check/
2+
/test_int128

src/test/modules/test_int128/Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# src/test/modules/test_int128/Makefile
2+
3+
PGFILEDESC = "test_int128 - test 128-bit integer arithmetic"
4+
5+
PROGRAM = test_int128
6+
OBJS = $(WIN32RES) test_int128.o
7+
8+
PG_CPPFLAGS = -I$(libpq_srcdir)
9+
PG_LIBS_INTERNAL += $(libpq_pgport)
10+
11+
NO_INSTALL = 1
12+
TAP_TESTS = 1
13+
14+
ifdef USE_PGXS
15+
PG_CONFIG = pg_config
16+
PGXS := $(shell $(PG_CONFIG) --pgxs)
17+
include $(PGXS)
18+
else
19+
subdir = src/test/modules/test_int128
20+
top_builddir = ../../../..
21+
include $(top_builddir)/src/Makefile.global
22+
include $(top_srcdir)/contrib/contrib-global.mk
23+
endif
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright (c) 2025, PostgreSQL Global Development Group
2+
3+
test_int128_sources = files(
4+
'test_int128.c',
5+
)
6+
7+
if host_system == 'windows'
8+
test_int128_sources += rc_bin_gen.process(win32ver_rc, extra_args: [
9+
'--NAME', 'test_int128',
10+
'--FILEDESC', 'test int128 program',])
11+
endif
12+
13+
test_int128 = executable('test_int128',
14+
test_int128_sources,
15+
dependencies: [frontend_code, libpq],
16+
kwargs: default_bin_args + {
17+
'install': false,
18+
},
19+
)
20+
testprep_targets += test_int128
21+
22+
23+
tests += {
24+
'name': 'test_int128',
25+
'sd': meson.current_source_dir(),
26+
'bd': meson.current_build_dir(),
27+
'tap': {
28+
'tests': [
29+
't/001_test_int128.pl',
30+
],
31+
'deps': [test_int128],
32+
},
33+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Copyright (c) 2025, PostgreSQL Global Development Group
2+
3+
# Test 128-bit integer arithmetic code in int128.h
4+
5+
use strict;
6+
use warnings FATAL => 'all';
7+
8+
use PostgreSQL::Test::Utils;
9+
use Test::More;
10+
11+
# Run the test program with 1M iterations
12+
my $exe = "test_int128";
13+
my $size = 1_000_000;
14+
15+
note "testing executable $exe";
16+
17+
my ($stdout, $stderr) = run_command([ $exe, $size ]);
18+
19+
SKIP:
20+
{
21+
skip "no native int128 type", 2 if $stdout =~ /skipping tests/;
22+
23+
is($stdout, "", "test_int128: no stdout");
24+
is($stderr, "", "test_int128: no stderr");
25+
}
26+
27+
done_testing();

src/tools/testint128.c renamed to src/test/modules/test_int128/test_int128.c

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* testint128.c
3+
* test_int128.c
44
* Testbed for roll-our-own 128-bit integer arithmetic.
55
*
66
* This is a standalone test program that compares the behavior of an
@@ -10,13 +10,18 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* src/tools/testint128.c
13+
* src/test/modules/test_int128/test_int128.c
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
1717

1818
#include "postgres_fe.h"
1919

20+
#include <time.h>
21+
22+
/* Require a native int128 type */
23+
#ifdef HAVE_INT128
24+
2025
/*
2126
* By default, we test the non-native implementation in int128.h; but
2227
* by predefining USE_NATIVE_INT128 to 1, you can test the native
@@ -36,7 +41,7 @@ typedef union
3641
{
3742
int128 i128;
3843
INT128 I128;
39-
union
44+
struct
4045
{
4146
#ifdef WORDS_BIGENDIAN
4247
int64 hi;
@@ -48,6 +53,7 @@ typedef union
4853
} hl;
4954
} test128;
5055

56+
#define INT128_HEX_FORMAT "%016" PRIx64 "%016" PRIx64
5157

5258
/*
5359
* Control version of comparator.
@@ -75,7 +81,7 @@ main(int argc, char **argv)
7581
{
7682
long count;
7783

78-
pg_prng_seed(&pg_global_prng_state, 0);
84+
pg_prng_seed(&pg_global_prng_state, (uint64) time(NULL));
7985

8086
if (argc >= 2)
8187
count = strtol(argv[1], NULL, 0);
@@ -99,9 +105,9 @@ main(int argc, char **argv)
99105

100106
if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
101107
{
102-
printf("%016lX%016lX + unsigned %lX\n", x, y, z);
103-
printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
104-
printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
108+
printf(INT128_HEX_FORMAT " + unsigned " PRIx64 "\n", x, y, z);
109+
printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
110+
printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
105111
return 1;
106112
}
107113

@@ -114,9 +120,9 @@ main(int argc, char **argv)
114120

115121
if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
116122
{
117-
printf("%016lX%016lX + signed %lX\n", x, y, z);
118-
printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
119-
printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
123+
printf(INT128_HEX_FORMAT " + signed " PRIx64 "\n", x, y, z);
124+
printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
125+
printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
120126
return 1;
121127
}
122128

@@ -128,9 +134,9 @@ main(int argc, char **argv)
128134

129135
if (t1.hl.hi != t2.hl.hi || t1.hl.lo != t2.hl.lo)
130136
{
131-
printf("%lX * %lX\n", x, y);
132-
printf("native = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
133-
printf("result = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
137+
printf(PRIx64 " * " PRIx64 "\n", x, y);
138+
printf("native = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
139+
printf("result = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
134140
return 1;
135141
}
136142

@@ -146,8 +152,8 @@ main(int argc, char **argv)
146152
printf("comparison failure: %d vs %d\n",
147153
my_int128_compare(t1.i128, t2.i128),
148154
int128_compare(t1.I128, t2.I128));
149-
printf("arg1 = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
150-
printf("arg2 = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
155+
printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
156+
printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
151157
return 1;
152158
}
153159

@@ -160,11 +166,25 @@ main(int argc, char **argv)
160166
printf("comparison failure: %d vs %d\n",
161167
my_int128_compare(t1.i128, t2.i128),
162168
int128_compare(t1.I128, t2.I128));
163-
printf("arg1 = %016lX%016lX\n", t1.hl.hi, t1.hl.lo);
164-
printf("arg2 = %016lX%016lX\n", t2.hl.hi, t2.hl.lo);
169+
printf("arg1 = " INT128_HEX_FORMAT "\n", t1.hl.hi, t1.hl.lo);
170+
printf("arg2 = " INT128_HEX_FORMAT "\n", t2.hl.hi, t2.hl.lo);
165171
return 1;
166172
}
167173
}
168174

169175
return 0;
170176
}
177+
178+
#else /* ! HAVE_INT128 */
179+
180+
/*
181+
* For now, do nothing if we don't have a native int128 type.
182+
*/
183+
int
184+
main(int argc, char **argv)
185+
{
186+
printf("skipping tests: no native int128 type\n");
187+
return 0;
188+
}
189+
190+
#endif

0 commit comments

Comments
 (0)