1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-18 04:29:09 +03:00

Add a test harness for the LWLock tranche code.

This code is heavily used and already has decent test coverage, but
it lacks a dedicated test suite.  This commit changes that.

Author: Sami Imseih <samimseih@gmail.com>
Co-authored-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Discussion: https://postgr.es/m/CAA5RZ0tQ%2BEYSTOd2hQ8RXdsNfGBLAtOe-YmnsTE6ZVg0E-4qew%40mail.gmail.com
Discussion: https://postgr.es/m/CAA5RZ0vpr0P2rbA%3D_K0_SCHM7bmfVX4wEO9FAyopN1eWCYORhA%40mail.gmail.com
This commit is contained in:
Nathan Bossart
2025-09-18 15:23:11 -05:00
parent c3cc2ab87d
commit 16607718c0
11 changed files with 243 additions and 0 deletions

View File

@@ -29,6 +29,7 @@ SUBDIRS = \
test_integerset \
test_json_parser \
test_lfind \
test_lwlock_tranches \
test_misc \
test_oat_hooks \
test_parser \

View File

@@ -28,6 +28,7 @@ subdir('test_int128')
subdir('test_integerset')
subdir('test_json_parser')
subdir('test_lfind')
subdir('test_lwlock_tranches')
subdir('test_misc')
subdir('test_oat_hooks')
subdir('test_parser')

View File

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

View File

@@ -0,0 +1,25 @@
# src/test/modules/test_lwlock_tranches/Makefile
MODULE_big = test_lwlock_tranches
OBJS = \
$(WIN32RES) \
test_lwlock_tranches.o
PGFILEDESC = "test_lwlock_tranches - test code for LWLock tranches allocated by extensions"
EXTENSION = test_lwlock_tranches
DATA = test_lwlock_tranches--1.0.sql
REGRESS_OPTS = --temp-config $(top_srcdir)/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.conf
REGRESS = test_lwlock_tranches
NO_INSTALLCHECK = 1
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = src/test/modules/test_lwlock_tranches
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@@ -0,0 +1,25 @@
CREATE EXTENSION test_lwlock_tranches;
SELECT test_lwlock_tranches();
test_lwlock_tranches
----------------------
(1 row)
SELECT test_lwlock_tranche_creation(NULL);
ERROR: tranche name cannot be NULL
SELECT test_lwlock_tranche_creation(repeat('a', 64));
ERROR: tranche name too long
DETAIL: LWLock tranche names must be no longer than 63 bytes.
SELECT test_lwlock_tranche_creation('test');
ERROR: maximum number of tranches already registered
DETAIL: No more than 256 tranches may be registered.
SELECT test_lwlock_tranche_lookup('test_lwlock_tranches_startup');
test_lwlock_tranche_lookup
----------------------------
(1 row)
SELECT test_lwlock_tranche_lookup('bogus');
ERROR: requested tranche is not registered
SELECT test_lwlock_initialize(65535);
ERROR: tranche 65535 is not registered

View File

@@ -0,0 +1,35 @@
# Copyright (c) 2025, PostgreSQL Global Development Group
test_lwlock_tranches_sources = files(
'test_lwlock_tranches.c',
)
if host_system == 'windows'
test_lwlock_tranches_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
'--NAME', 'test_lwlock_tranches',
'--FILEDESC', 'test_lwlock_tranches - test code for LWLock tranches allocated by extensions',])
endif
test_lwlock_tranches = shared_module('test_lwlock_tranches',
test_lwlock_tranches_sources,
kwargs: pg_test_mod_args,
)
test_install_libs += test_lwlock_tranches
test_install_data += files(
'test_lwlock_tranches.control',
'test_lwlock_tranches--1.0.sql',
)
tests += {
'name': 'test_lwlock_tranches',
'sd': meson.current_source_dir(),
'bd': meson.current_build_dir(),
'regress': {
'sql': [
'test_lwlock_tranches',
],
'regress_args': ['--temp-config', files('test_lwlock_tranches.conf')],
'runningcheck': false,
},
}

View File

@@ -0,0 +1,8 @@
CREATE EXTENSION test_lwlock_tranches;
SELECT test_lwlock_tranches();
SELECT test_lwlock_tranche_creation(NULL);
SELECT test_lwlock_tranche_creation(repeat('a', 64));
SELECT test_lwlock_tranche_creation('test');
SELECT test_lwlock_tranche_lookup('test_lwlock_tranches_startup');
SELECT test_lwlock_tranche_lookup('bogus');
SELECT test_lwlock_initialize(65535);

View File

@@ -0,0 +1,16 @@
/* src/test/modules/test_lwlock_tranches/test_lwlock_tranches--1.0.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_lwlock_tranches" to load this file. \quit
CREATE FUNCTION test_lwlock_tranches() RETURNS VOID
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_lwlock_tranche_creation(tranche_name TEXT) RETURNS VOID
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_lwlock_tranche_lookup(tranche_name TEXT) RETURNS VOID
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_lwlock_initialize(tranche_id INT) RETURNS VOID
AS 'MODULE_PATHNAME' LANGUAGE C;

View File

@@ -0,0 +1,123 @@
/*--------------------------------------------------------------------------
*
* test_lwlock_tranches.c
* Test code for LWLock tranches allocated by extensions.
*
* Copyright (c) 2025, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "fmgr.h"
#include "miscadmin.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/wait_classes.h"
PG_MODULE_MAGIC;
#define STARTUP_TRANCHE_NAME "test_lwlock_tranches_startup"
#define DYNAMIC_TRANCHE_NAME "test_lwlock_tranches_dynamic"
#define NUM_STARTUP_TRANCHES (32)
#define NUM_DYNAMIC_TRANCHES (256 - NUM_STARTUP_TRANCHES)
#define GET_TRANCHE_NAME(a) GetLWLockIdentifier(PG_WAIT_LWLOCK, (a))
static shmem_request_hook_type prev_shmem_request_hook;
static void test_lwlock_tranches_shmem_request(void);
void
_PG_init(void)
{
prev_shmem_request_hook = shmem_request_hook;
shmem_request_hook = test_lwlock_tranches_shmem_request;
}
static void
test_lwlock_tranches_shmem_request(void)
{
if (prev_shmem_request_hook)
prev_shmem_request_hook();
for (int i = 0; i < NUM_STARTUP_TRANCHES; i++)
RequestNamedLWLockTranche(STARTUP_TRANCHE_NAME, 1);
}
/*
* Checks that GetLWLockIdentifier() returns the expected value for tranches
* registered via RequestNamedLWLockTranche() and LWLockNewTrancheId().
*/
PG_FUNCTION_INFO_V1(test_lwlock_tranches);
Datum
test_lwlock_tranches(PG_FUNCTION_ARGS)
{
int dynamic_tranches[NUM_DYNAMIC_TRANCHES];
for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++)
dynamic_tranches[i] = LWLockNewTrancheId(DYNAMIC_TRANCHE_NAME);
for (int i = 0; i < NUM_STARTUP_TRANCHES; i++)
{
if (strcmp(GET_TRANCHE_NAME(LWTRANCHE_FIRST_USER_DEFINED + i),
STARTUP_TRANCHE_NAME) != 0)
elog(ERROR, "incorrect startup lock tranche name");
}
for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++)
{
if (strcmp(GET_TRANCHE_NAME(dynamic_tranches[i]),
DYNAMIC_TRANCHE_NAME) != 0)
elog(ERROR, "incorrect dynamic lock tranche name");
}
PG_RETURN_VOID();
}
/*
* Wrapper for LWLockNewTrancheId().
*/
PG_FUNCTION_INFO_V1(test_lwlock_tranche_creation);
Datum
test_lwlock_tranche_creation(PG_FUNCTION_ARGS)
{
char *tranche_name = PG_ARGISNULL(0) ? NULL : TextDatumGetCString(PG_GETARG_DATUM(0));
(void) LWLockNewTrancheId(tranche_name);
PG_RETURN_VOID();
}
/*
* Wrapper for GetNamedLWLockTranche().
*/
PG_FUNCTION_INFO_V1(test_lwlock_tranche_lookup);
Datum
test_lwlock_tranche_lookup(PG_FUNCTION_ARGS)
{
char *tranche_name = TextDatumGetCString(PG_GETARG_DATUM(0));
(void) GetNamedLWLockTranche(tranche_name);
PG_RETURN_VOID();
}
/*
* Wrapper for LWLockInitialize().
*/
PG_FUNCTION_INFO_V1(test_lwlock_initialize);
Datum
test_lwlock_initialize(PG_FUNCTION_ARGS)
{
int tranche_id = PG_GETARG_INT32(0);
LWLock lock;
LWLockInitialize(&lock, tranche_id);
PG_RETURN_VOID();
}

View File

@@ -0,0 +1 @@
shared_preload_libraries = 'test_lwlock_tranches'

View File

@@ -0,0 +1,4 @@
comment = 'Test code for LWLock tranches allocated by extensions'
default_version = '1.0'
module_pathname = '$libdir/test_lwlock_tranches'
relocatable = true