Add test_dsa module.

This covers basic calls within a single backend process, and also
calling dsa_allocate() or dsa_get_address() while in a different
resource owners. The latter case was fixed by the previous commit.

Discussion: https://www.postgresql.org/message-id/11b70743-c5f3-3910-8e5b-dd6c115ff829%40gmail.com
This commit is contained in:
Heikki Linnakangas 2023-11-15 10:34:31 +01:00
parent a8b330ffb6
commit 325f54033e
9 changed files with 204 additions and 0 deletions

View File

@ -17,6 +17,7 @@ SUBDIRS = \
test_copy_callbacks \
test_custom_rmgrs \
test_ddl_deparse \
test_dsa \
test_extensions \
test_ginpostinglist \
test_integerset \

View File

@ -14,6 +14,7 @@ subdir('test_bloomfilter')
subdir('test_copy_callbacks')
subdir('test_custom_rmgrs')
subdir('test_ddl_deparse')
subdir('test_dsa')
subdir('test_extensions')
subdir('test_ginpostinglist')
subdir('test_integerset')

View File

@ -0,0 +1,23 @@
# src/test/modules/test_dsa/Makefile
MODULE_big = test_dsa
OBJS = \
$(WIN32RES) \
test_dsa.o
PGFILEDESC = "test_dsa - test code for dynamic shared memory areas"
EXTENSION = test_dsa
DATA = test_dsa--1.0.sql
REGRESS = test_dsa
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = src/test/modules/test_dsa
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

View File

@ -0,0 +1,13 @@
CREATE EXTENSION test_dsa;
SELECT test_dsa_basic();
test_dsa_basic
----------------
(1 row)
SELECT test_dsa_resowners();
test_dsa_resowners
--------------------
(1 row)

View File

@ -0,0 +1,33 @@
# Copyright (c) 2022-2023, PostgreSQL Global Development Group
test_dsa_sources = files(
'test_dsa.c',
)
if host_system == 'windows'
test_dsa_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
'--NAME', 'test_dsa',
'--FILEDESC', 'test_dsa - test code for dynamic shared memory areas',])
endif
test_dsa = shared_module('test_dsa',
test_dsa_sources,
kwargs: pg_test_mod_args,
)
test_install_libs += test_dsa
test_install_data += files(
'test_dsa.control',
'test_dsa--1.0.sql',
)
tests += {
'name': 'test_dsa',
'sd': meson.current_source_dir(),
'bd': meson.current_build_dir(),
'regress': {
'sql': [
'test_dsa',
],
},
}

View File

@ -0,0 +1,4 @@
CREATE EXTENSION test_dsa;
SELECT test_dsa_basic();
SELECT test_dsa_resowners();

View File

@ -0,0 +1,12 @@
/* src/test/modules/test_dsa/test_dsa--1.0.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_dsa" to load this file. \quit
CREATE FUNCTION test_dsa_basic()
RETURNS pg_catalog.void
AS 'MODULE_PATHNAME' LANGUAGE C;
CREATE FUNCTION test_dsa_resowners()
RETURNS pg_catalog.void
AS 'MODULE_PATHNAME' LANGUAGE C;

View File

@ -0,0 +1,113 @@
/*--------------------------------------------------------------------------
*
* test_dsa.c
* Test dynamic shared memory areas (DSAs)
*
* Copyright (c) 2022-2023, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/test/modules/test_dsa/test_dsa.c
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "fmgr.h"
#include "utils/dsa.h"
#include "storage/lwlock.h"
#include "utils/resowner.h"
PG_MODULE_MAGIC;
/* Test basic DSA functionality */
PG_FUNCTION_INFO_V1(test_dsa_basic);
Datum
test_dsa_basic(PG_FUNCTION_ARGS)
{
int tranche_id;
dsa_area *a;
dsa_pointer p[100];
/* XXX: this tranche is leaked */
tranche_id = LWLockNewTrancheId();
LWLockRegisterTranche(tranche_id, "test_dsa");
a = dsa_create(tranche_id);
for (int i = 0; i < 100; i++)
{
p[i] = dsa_allocate(a, 1000);
snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
}
for (int i = 0; i < 100; i++)
{
char buf[100];
snprintf(buf, 100, "foobar%d", i);
if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
elog(ERROR, "no match");
}
for (int i = 0; i < 100; i++)
{
dsa_free(a, p[i]);
}
dsa_detach(a);
PG_RETURN_VOID();
}
/* Test using DSA across different resource owners */
PG_FUNCTION_INFO_V1(test_dsa_resowners);
Datum
test_dsa_resowners(PG_FUNCTION_ARGS)
{
int tranche_id;
dsa_area *a;
dsa_pointer p[10000];
ResourceOwner oldowner;
ResourceOwner childowner;
/* XXX: this tranche is leaked */
tranche_id = LWLockNewTrancheId();
LWLockRegisterTranche(tranche_id, "test_dsa");
/* Create DSA in parent resource owner */
a = dsa_create(tranche_id);
/*
* Switch to child resource owner, and do a bunch of allocations in the
* DSA
*/
oldowner = CurrentResourceOwner;
childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
CurrentResourceOwner = childowner;
for (int i = 0; i < 10000; i++)
{
p[i] = dsa_allocate(a, 1000);
snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
}
/* Also test freeing, by freeing some of the allocations. */
for (int i = 0; i < 500; i++)
dsa_free(a, p[i]);
/* Release the child resource owner */
CurrentResourceOwner = oldowner;
ResourceOwnerRelease(childowner,
RESOURCE_RELEASE_BEFORE_LOCKS,
true, false);
ResourceOwnerRelease(childowner,
RESOURCE_RELEASE_LOCKS,
true, false);
ResourceOwnerRelease(childowner,
RESOURCE_RELEASE_AFTER_LOCKS,
true, false);
ResourceOwnerDelete(childowner);
dsa_detach(a);
PG_RETURN_VOID();
}

View File

@ -0,0 +1,4 @@
comment = 'Test code for dynamic shared memory areas'
default_version = '1.0'
module_pathname = '$libdir/test_dsa'
relocatable = true