0002-Add-test_scram-module-for-direct-unit-tests-of-SCRAM.patch
text/x-patch
Filename: 0002-Add-test_scram-module-for-direct-unit-tests-of-SCRAM.patch
Type: text/x-patch
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0002
Subject: Add test_scram module for direct unit tests of SCRAM helpers
| File | + | − |
|---|---|---|
| src/test/modules/Makefile | 1 | 0 |
| src/test/modules/meson.build | 1 | 0 |
| src/test/modules/test_scram/expected/test_scram.out | 122 | 0 |
| src/test/modules/test_scram/Makefile | 23 | 0 |
| src/test/modules/test_scram/meson.build | 33 | 0 |
| src/test/modules/test_scram/README | 18 | 0 |
| src/test/modules/test_scram/sql/test_scram.sql | 31 | 0 |
| src/test/modules/test_scram/test_scram--1.0.sql | 16 | 0 |
| src/test/modules/test_scram/test_scram.c | 45 | 0 |
| src/test/modules/test_scram/test_scram.control | 5 | 0 |
From 473f9de901867e529d065c198195553f00e8047e Mon Sep 17 00:00:00 2001
From: Sehrope Sarkuni <sehrope@jackdb.com>
Date: Sun, 24 May 2026 12:19:35 -0400
Subject: [PATCH 2/6] Add test_scram module for direct unit tests of SCRAM
helpers
Adds src/test/modules/test_scram/, mirroring the layout of the
existing test_saslprep module, with one SQL-callable wrapper around
scram_parse_iterations() and a regression test that exercises the
parser directly rather than only through a SCRAM authentication
exchange.
Coverage is organized by why the input is accepted or rejected.
Wires the new module into src/test/modules/Makefile and
src/test/modules/meson.build so it runs under check-world.
---
src/test/modules/Makefile | 1 +
src/test/modules/meson.build | 1 +
src/test/modules/test_scram/Makefile | 23 ++++
src/test/modules/test_scram/README | 18 +++
.../test_scram/expected/test_scram.out | 122 ++++++++++++++++++
src/test/modules/test_scram/meson.build | 33 +++++
.../modules/test_scram/sql/test_scram.sql | 31 +++++
.../modules/test_scram/test_scram--1.0.sql | 16 +++
src/test/modules/test_scram/test_scram.c | 45 +++++++
.../modules/test_scram/test_scram.control | 5 +
10 files changed, 295 insertions(+)
create mode 100644 src/test/modules/test_scram/Makefile
create mode 100644 src/test/modules/test_scram/README
create mode 100644 src/test/modules/test_scram/expected/test_scram.out
create mode 100644 src/test/modules/test_scram/meson.build
create mode 100644 src/test/modules/test_scram/sql/test_scram.sql
create mode 100644 src/test/modules/test_scram/test_scram--1.0.sql
create mode 100644 src/test/modules/test_scram/test_scram.c
create mode 100644 src/test/modules/test_scram/test_scram.control
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 0a74ab5c86f..dc010fb111f 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -49,6 +49,7 @@ SUBDIRS = \
test_resowner \
test_rls_hooks \
test_saslprep \
+ test_scram \
test_shmem \
test_shm_mq \
test_slru \
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
index 4bca42bb370..a8019538ef0 100644
--- a/src/test/modules/meson.build
+++ b/src/test/modules/meson.build
@@ -50,6 +50,7 @@ subdir('test_regex')
subdir('test_resowner')
subdir('test_rls_hooks')
subdir('test_saslprep')
+subdir('test_scram')
subdir('test_shmem')
subdir('test_shm_mq')
subdir('test_slru')
diff --git a/src/test/modules/test_scram/Makefile b/src/test/modules/test_scram/Makefile
new file mode 100644
index 00000000000..b597ca5035a
--- /dev/null
+++ b/src/test/modules/test_scram/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_scram/Makefile
+
+MODULE_big = test_scram
+OBJS = \
+ $(WIN32RES) \
+ test_scram.o
+PGFILEDESC = "test_scram - test SCRAM helpers in src/common"
+
+EXTENSION = test_scram
+DATA = test_scram--1.0.sql
+
+REGRESS = test_scram
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_scram
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_scram/README b/src/test/modules/test_scram/README
new file mode 100644
index 00000000000..549571245e3
--- /dev/null
+++ b/src/test/modules/test_scram/README
@@ -0,0 +1,18 @@
+src/test/modules/test_scram
+
+Direct tests for SCRAM helpers
+==============================
+
+This module provides SQL-callable wrappers around helper functions in
+src/common/scram-common.c so they can be exercised in isolation by a
+regression test, without going through a real SCRAM authentication
+exchange.
+
+Currently it covers scram_parse_iterations().
+
+Running the tests
+=================
+
+ make check
+or
+ make installcheck
diff --git a/src/test/modules/test_scram/expected/test_scram.out b/src/test/modules/test_scram/expected/test_scram.out
new file mode 100644
index 00000000000..70a6e5bdadf
--- /dev/null
+++ b/src/test/modules/test_scram/expected/test_scram.out
@@ -0,0 +1,122 @@
+--
+-- Direct tests for scram_parse_iterations() in src/common/scram-common.c.
+--
+CREATE EXTENSION test_scram;
+-- Accepted: non-empty digit-only strings whose value is in [1, INT_MAX].
+SELECT test_scram_parse_iterations('1');
+ test_scram_parse_iterations
+-----------------------------
+ 1
+(1 row)
+
+SELECT test_scram_parse_iterations('4096');
+ test_scram_parse_iterations
+-----------------------------
+ 4096
+(1 row)
+
+SELECT test_scram_parse_iterations('999999999');
+ test_scram_parse_iterations
+-----------------------------
+ 999999999
+(1 row)
+
+SELECT test_scram_parse_iterations('2147483647'); -- INT_MAX on every supported platform
+ test_scram_parse_iterations
+-----------------------------
+ 2147483647
+(1 row)
+
+SELECT test_scram_parse_iterations('0042'); -- leading zeros are still digits
+ test_scram_parse_iterations
+-----------------------------
+ 42
+(1 row)
+
+-- Rejected: value below 1 (RFC 5802 requires a positive count).
+SELECT test_scram_parse_iterations('0');
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+-- Rejected: anything that is not a pure digit string.
+SELECT test_scram_parse_iterations(''); -- empty string
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('-1'); -- sign character
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('+1'); -- sign character
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations(' 1'); -- leading whitespace
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('1 '); -- trailing whitespace
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('1.0'); -- decimal point
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('1a'); -- digit then letter
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('a1'); -- letter then digit
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('abc'); -- all letters
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('0x10'); -- hex prefix is not digits-only
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+-- Rejected: out-of-range values that would otherwise narrow to a bogus int.
+SELECT test_scram_parse_iterations('2147483648'); -- INT_MAX + 1
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('9999999999'); -- > INT_MAX on every supported platform
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
+SELECT test_scram_parse_iterations('99999999999999999999'); -- overflows long on every supported platform
+ test_scram_parse_iterations
+-----------------------------
+ invalid
+(1 row)
+
diff --git a/src/test/modules/test_scram/meson.build b/src/test/modules/test_scram/meson.build
new file mode 100644
index 00000000000..4039ae5b2af
--- /dev/null
+++ b/src/test/modules/test_scram/meson.build
@@ -0,0 +1,33 @@
+# Copyright (c) 2026, PostgreSQL Global Development Group
+
+test_scram_sources = files(
+ 'test_scram.c',
+)
+
+if host_system == 'windows'
+ test_scram_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
+ '--NAME', 'test_scram',
+ '--FILEDESC', 'test_scram - test SCRAM helpers in src/common',])
+endif
+
+test_scram = shared_module('test_scram',
+ test_scram_sources,
+ kwargs: pg_test_mod_args,
+)
+test_install_libs += test_scram
+
+test_install_data += files(
+ 'test_scram.control',
+ 'test_scram--1.0.sql',
+)
+
+tests += {
+ 'name': 'test_scram',
+ 'sd': meson.current_source_dir(),
+ 'bd': meson.current_build_dir(),
+ 'regress': {
+ 'sql': [
+ 'test_scram',
+ ],
+ },
+}
diff --git a/src/test/modules/test_scram/sql/test_scram.sql b/src/test/modules/test_scram/sql/test_scram.sql
new file mode 100644
index 00000000000..113b92a9736
--- /dev/null
+++ b/src/test/modules/test_scram/sql/test_scram.sql
@@ -0,0 +1,31 @@
+--
+-- Direct tests for scram_parse_iterations() in src/common/scram-common.c.
+--
+CREATE EXTENSION test_scram;
+
+-- Accepted: non-empty digit-only strings whose value is in [1, INT_MAX].
+SELECT test_scram_parse_iterations('1');
+SELECT test_scram_parse_iterations('4096');
+SELECT test_scram_parse_iterations('999999999');
+SELECT test_scram_parse_iterations('2147483647'); -- INT_MAX on every supported platform
+SELECT test_scram_parse_iterations('0042'); -- leading zeros are still digits
+
+-- Rejected: value below 1 (RFC 5802 requires a positive count).
+SELECT test_scram_parse_iterations('0');
+
+-- Rejected: anything that is not a pure digit string.
+SELECT test_scram_parse_iterations(''); -- empty string
+SELECT test_scram_parse_iterations('-1'); -- sign character
+SELECT test_scram_parse_iterations('+1'); -- sign character
+SELECT test_scram_parse_iterations(' 1'); -- leading whitespace
+SELECT test_scram_parse_iterations('1 '); -- trailing whitespace
+SELECT test_scram_parse_iterations('1.0'); -- decimal point
+SELECT test_scram_parse_iterations('1a'); -- digit then letter
+SELECT test_scram_parse_iterations('a1'); -- letter then digit
+SELECT test_scram_parse_iterations('abc'); -- all letters
+SELECT test_scram_parse_iterations('0x10'); -- hex prefix is not digits-only
+
+-- Rejected: out-of-range values that would otherwise narrow to a bogus int.
+SELECT test_scram_parse_iterations('2147483648'); -- INT_MAX + 1
+SELECT test_scram_parse_iterations('9999999999'); -- > INT_MAX on every supported platform
+SELECT test_scram_parse_iterations('99999999999999999999'); -- overflows long on every supported platform
diff --git a/src/test/modules/test_scram/test_scram--1.0.sql b/src/test/modules/test_scram/test_scram--1.0.sql
new file mode 100644
index 00000000000..363e2a267b9
--- /dev/null
+++ b/src/test/modules/test_scram/test_scram--1.0.sql
@@ -0,0 +1,16 @@
+/* src/test/modules/test_scram/test_scram--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_scram" to load this file. \quit
+
+--
+-- test_scram_parse_iterations(text) -> text
+--
+-- Returns the parsed iteration count as text, or 'invalid' if the
+-- parser rejects the input. Used to exercise scram_parse_iterations()
+-- in src/common/scram-common.c.
+--
+CREATE FUNCTION test_scram_parse_iterations(IN input text)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
diff --git a/src/test/modules/test_scram/test_scram.c b/src/test/modules/test_scram/test_scram.c
new file mode 100644
index 00000000000..681536e70d3
--- /dev/null
+++ b/src/test/modules/test_scram/test_scram.c
@@ -0,0 +1,45 @@
+/*--------------------------------------------------------------------------
+ *
+ * test_scram.c
+ * Test harness for SCRAM helpers in src/common/scram-common.c.
+ *
+ * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/test_scram/test_scram.c
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "common/scram-common.h"
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+PG_MODULE_MAGIC;
+
+/*
+ * Wrapper around scram_parse_iterations() for direct testing.
+ *
+ * Returns 'invalid' when the parser rejects the input, otherwise the
+ * parsed integer value as text. Returning text rather than a record
+ * keeps the regression output one column wide and easy to read.
+ */
+PG_FUNCTION_INFO_V1(test_scram_parse_iterations);
+Datum
+test_scram_parse_iterations(PG_FUNCTION_ARGS)
+{
+ text *input = PG_GETARG_TEXT_PP(0);
+ char *cstr = text_to_cstring(input);
+ int iter = -1;
+ char buf[32];
+
+ if (scram_parse_iterations(cstr, &iter))
+ snprintf(buf, sizeof(buf), "%d", iter);
+ else
+ snprintf(buf, sizeof(buf), "invalid");
+
+ pfree(cstr);
+ PG_RETURN_TEXT_P(cstring_to_text(buf));
+}
diff --git a/src/test/modules/test_scram/test_scram.control b/src/test/modules/test_scram/test_scram.control
new file mode 100644
index 00000000000..c25017b9d81
--- /dev/null
+++ b/src/test/modules/test_scram/test_scram.control
@@ -0,0 +1,5 @@
+# test_scram extension
+comment = 'Test SCRAM helpers in src/common'
+default_version = '1.0'
+module_pathname = '$libdir/test_scram'
+relocatable = true
--
2.43.0