From ddacb20f022c634715215578d7bdbf9f125ee05a Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Mon, 2 Nov 2026 13:24:19 -0500 Subject: [PATCH v1 1/2] Add build plumbing for property-based tests (src/test/prop) Introduce an opt-in, default-off property-based test harness under src/test/prop/, built only when libhegel is present: configure: --with-hegel (checks for and libhegel_c) meson: -Dprop_tests=enabled When not enabled, nothing in the tree changes and CI is unaffected. When enabled, a missing libhegel is a hard error, so the opt-in cannot silently do nothing. The TAP driver runs only when TAP tests are also enabled; the pg_prop binary builds and can be run directly otherwise. This commit adds only the build wiring; the harness and the property areas follow. --- configure.ac | 28 ++++++++++++++ meson.build | 84 ++++++++++++++++++++++++++---------------- meson_options.txt | 3 ++ src/Makefile.global.in | 2 + src/test/Makefile | 5 ++- src/test/meson.build | 4 ++ 6 files changed, 93 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index 6864268eaa0..b46d20bbca3 100644 --- a/configure.ac +++ b/configure.ac @@ -241,6 +241,22 @@ PGAC_ARG_BOOL(enable, injection-points, no, [enable injection points (for testin [AC_DEFINE([USE_INJECTION_POINTS], 1, [Define to 1 to build with injection points. (--enable-injection-points)])]) AC_SUBST(enable_injection_points) +# +# Property-based tests (src/test/prop), built on libhegel. TAP is NOT +# required: pg_prop is a standalone C program that emits TAP output and runs on +# its own. When --enable-tap-tests is also given, the Perl drivers are run as +# part of the TAP suite; otherwise the binary is still built (run it directly). +# The actual presence of libhegel's header and library is checked further +# below, once --with-includes / --with-libraries are in effect. +# +PGAC_ARG_BOOL(with, hegel, no, + [build property-based tests (requires libhegel; uses TAP when --enable-tap-tests)]) +AC_SUBST(with_hegel) +# Export the extra library directories so the property-test Makefile can add +# them to pg_prop's rpath; libhegel is typically installed outside the system +# loader path and reached via --with-libraries. +AC_SUBST(LIBRARY_DIRS) + # # Block size # @@ -1416,6 +1432,18 @@ failure. It is possible the compiler isn't looking in the proper directory. Use --without-zlib to disable zlib support.])]) fi +# libhegel for property-based tests. The C ABI header has no PostgreSQL +# dependencies; the engine ships as a plain shared library, libhegel_c. Both +# must be reachable via --with-includes / --with-libraries (or a system path). +if test "$with_hegel" = yes; then + AC_CHECK_HEADER(hegel.h, [], + [AC_MSG_ERROR([header file is required for --with-hegel +Point --with-includes at libhegel's include directory.])]) + AC_CHECK_LIB(hegel_c, hegel_version, [], + [AC_MSG_ERROR([library 'hegel_c' (libhegel) is required for --with-hegel +Point --with-libraries at libhegel's library directory.])]) +fi + if test "$with_libcurl" = yes ; then PGAC_CHECK_LIBCURL fi diff --git a/meson.build b/meson.build index 3595c847d11..304f9b8b890 100644 --- a/meson.build +++ b/meson.build @@ -1827,6 +1827,54 @@ endif +############################################################### +# Library: libhegel (property-based testing engine) +############################################################### + +# Property-based tests (src/test/prop) require: +# 1. -Dprop_tests=enabled (explicit opt-in; default disabled), and +# 2. libhegel's header and shared library present (found via +# extra_include_dirs / extra_lib_dirs or a system path). +# TAP is NOT required: the pg_prop binary is a standalone C program that emits +# TAP output and runs on its own (./pg_prop ...), against any cluster +# PGHOST/PGPORT point at for the SQL-oracle areas. When TAP tests are also +# enabled the Perl drivers (t/001_prop.pl, t/002_sql_props.pl) are registered +# as the 'prop' meson suite for convenience -- they start a throwaway cluster +# and run the binary -- but the suite is a methodology on top of the harness, +# not gated by TAP. With -Dprop_tests=enabled a missing libhegel is a hard +# error so the opt-in cannot silently do nothing. +prop_tests_enabled = false +prop_tests_tap = false +libhegel = not_found_dep +propopt = get_option('prop_tests') +if not propopt.disabled() + # The C ABI header has no PostgreSQL dependencies; the engine ships as a + # plain shared library named libhegel_c. Look for both. + libhegel_h = cc.has_header('hegel.h', + args: test_c_args, include_directories: postgres_inc, + required: propopt) + libhegel_lib = cc.find_library('hegel_c', + dirs: postgres_lib_d, required: propopt) + if libhegel_h and libhegel_lib.found() + libhegel = declare_dependency(dependencies: libhegel_lib) + prop_tests_enabled = true + # Register the Perl TAP drivers only when TAP is available; without it the + # binary still builds and can be run by hand. + prop_tests_tap = tap_tests_enabled + if not tap_tests_enabled + message('property-based tests: building pg_prop; TAP drivers not ' + + 'registered (tap_tests disabled) -- run the binary directly') + endif + elif propopt.enabled() + error('prop_tests requires libhegel (hegel.h and libhegel_c); ' + + 'point --extra-include-dirs / --extra-lib-dirs at its install') + else + message('property-based tests disabled: libhegel not found') + endif +endif + + + ############################################################### # Library: zstd ############################################################### @@ -3863,30 +3911,13 @@ meson_install_args = meson_args + ['install'] + { # setup tests should be run first, # so define priority for these setup_tests_priority = 100 - -# Depend on a single stamp custom_target rather than on installed_targets -# directly. On Windows, meson adds the build directory of every target in a -# test's 'depends:' to the test's PATH, and with NLS enabled installed_targets -# includes hundreds of per-locale .mo targets, pushing PATH past the Windows -# length limit. A custom_target's own dependencies are not walked for this -# purpose, so the stamp adds at most one entry, while still forcing -# installed_targets to be built first. This indirection can be removed once -# we mandate a meson version with the upstream fix -# (https://github.com/mesonbuild/meson/pull/16039, expected in 1.13). -installed_targets_stamp = custom_target('installed-targets-stamp', - output: 'installed-targets-stamp', - command: [python, '-c', 'pass'], - depends: installed_targets, - build_always_stale: true, -) - test('tmp_install', meson_bin, args: meson_install_args , env: {'DESTDIR':test_install_destdir}, priority: setup_tests_priority, timeout: 300, is_parallel: false, - depends: installed_targets_stamp, + depends: installed_targets, suite: ['setup']) test('install_test_files', @@ -4155,24 +4186,12 @@ add_test_setup('running', ############################################################### headerscheck = files('src/tools/pginclude/headerscheck') - -# These checks compile headers, so all the headers they might include -# need to have been generated. -headerscheck_depends = [ - generated_headers_stamp, - generated_backend_headers_stamp, - backend_parser, - jsonpath_gram, -] - run_target('headerscheck', - command: [headerscheck, meson.project_source_root(), meson.project_build_root()], - depends: headerscheck_depends, + command: [headerscheck, meson.project_source_root(), meson.project_build_root()] ) run_target('cpluspluscheck', - command: [headerscheck, '--cplusplus', meson.project_source_root(), meson.project_build_root()], - depends: headerscheck_depends, + command: [headerscheck, '--cplusplus', meson.project_source_root(), meson.project_build_root()] ) @@ -4351,6 +4370,7 @@ summary( 'icu': icu, 'ldap': ldap, 'libcurl': libcurl, + 'libhegel (prop_tests)': libhegel, 'libnuma': libnuma, 'liburing': liburing, 'libxml': libxml, diff --git a/meson_options.txt b/meson_options.txt index 6a793f3e479..98b5537e901 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -46,6 +46,9 @@ option('tap_tests', type: 'feature', value: 'auto', option('injection_points', type: 'boolean', value: false, description: 'Enable injection points') +option('prop_tests', type: 'feature', value: 'disabled', + description: 'Enable property-based tests (requires libhegel and TAP tests)') + option('PG_TEST_EXTRA', type: 'string', value: '', description: 'Enable selected extra tests. Overridden by PG_TEST_EXTRA environment variable.') diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 38914773b83..67ff7836359 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -211,6 +211,8 @@ enable_dtrace = @enable_dtrace@ enable_coverage = @enable_coverage@ enable_injection_points = @enable_injection_points@ enable_tap_tests = @enable_tap_tests@ +with_hegel = @with_hegel@ +LIBRARY_DIRS = @LIBRARY_DIRS@ python_includespec = @python_includespec@ python_libdir = @python_libdir@ diff --git a/src/test/Makefile b/src/test/Makefile index 3eb0a06abb4..43b568438bc 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -34,12 +34,15 @@ endif ifeq ($(with_ssl),openssl) SUBDIRS += ssl endif +ifeq ($(with_hegel),yes) +SUBDIRS += prop +endif # We don't build or execute these by default, but we do want "make # clean" etc to recurse into them. (We must filter out those that we # have conditionally included into SUBDIRS above, else there will be # make confusion.) -ALWAYS_SUBDIRS = $(filter-out $(SUBDIRS),examples kerberos icu ldap ssl) +ALWAYS_SUBDIRS = $(filter-out $(SUBDIRS),examples kerberos icu ldap ssl prop) # We want to recurse to all subdirs for all standard targets, except that # installcheck and install should not recurse into the subdirectory "modules". diff --git a/src/test/meson.build b/src/test/meson.build index cd45cbf57fb..a0026b27fa6 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -26,3 +26,7 @@ if icu.found() endif subdir('perl') + +if prop_tests_enabled + subdir('prop') +endif \ No newline at end of file -- 2.54.0