diff --git a/src/test/Makefile b/src/test/Makefile index dbd3192874..abdd6e5a98 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -12,7 +12,7 @@ subdir = src/test top_builddir = ../.. include $(top_builddir)/src/Makefile.global -SUBDIRS = perl regress isolation modules authentication recovery subscription +SUBDIRS = perl postmaster regress isolation modules authentication recovery subscription ifeq ($(with_icu),yes) SUBDIRS += icu diff --git a/src/test/meson.build b/src/test/meson.build index c3d0dfedf1..67376e4b7f 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -4,6 +4,7 @@ subdir('regress') subdir('isolation') subdir('authentication') +subdir('postmaster') subdir('recovery') subdir('subscription') subdir('modules') diff --git a/src/test/postmaster/Makefile b/src/test/postmaster/Makefile new file mode 100644 index 0000000000..dfcce9c9ee --- /dev/null +++ b/src/test/postmaster/Makefile @@ -0,0 +1,23 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/test/postmaster +# +# Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/test/postmaster/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/test/postmaster +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +check: + $(prove_check) + +installcheck: + $(prove_installcheck) + +clean distclean: + rm -rf tmp_check diff --git a/src/test/postmaster/README b/src/test/postmaster/README new file mode 100644 index 0000000000..7e47bf5cff --- /dev/null +++ b/src/test/postmaster/README @@ -0,0 +1,27 @@ +src/test/postmaster/README + +Regression tests for postmaster +=============================== + +This directory contains a test suite for postmaster's handling of +connections, connection limits, and startup/shutdown sequence. + + +Running the tests +================= + +NOTE: You must have given the --enable-tap-tests argument to configure. + +Run + make check +or + make installcheck +You can use "make installcheck" if you previously did "make install". +In that case, the code in the installation tree is tested. With +"make check", a temporary installation tree is built from the current +sources and then tested. + +Either way, this test initializes, starts, and stops a test Postgres +cluster. + +See src/test/perl/README for more info about running these tests. diff --git a/src/test/postmaster/meson.build b/src/test/postmaster/meson.build new file mode 100644 index 0000000000..c2de2e0eb5 --- /dev/null +++ b/src/test/postmaster/meson.build @@ -0,0 +1,12 @@ +# Copyright (c) 2022-2024, PostgreSQL Global Development Group + +tests += { + 'name': 'postmaster', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'tap': { + 'tests': [ + 't/001_connection_limits.pl', + ], + }, +} diff --git a/src/test/postmaster/t/001_connection_limits.pl b/src/test/postmaster/t/001_connection_limits.pl new file mode 100644 index 0000000000..f50aae4949 --- /dev/null +++ b/src/test/postmaster/t/001_connection_limits.pl @@ -0,0 +1,79 @@ + +# Copyright (c) 2021-2024, PostgreSQL Global Development Group + +# Test connection limits, i.e. max_connections, reserved_connections +# and superuser_reserved_connections. + +use strict; +use warnings FATAL => 'all'; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; + +# Initialize the server with specific low connection limits +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init; +$node->append_conf('postgresql.conf', "max_connections = 6"); +$node->append_conf('postgresql.conf', "reserved_connections = 2"); +$node->append_conf('postgresql.conf', "superuser_reserved_connections = 1"); +$node->append_conf('postgresql.conf', "log_connections = on"); +$node->start; + +$node->safe_psql( + 'postgres', qq{ +CREATE USER regress_regular LOGIN; +CREATE USER regress_reserved LOGIN; +GRANT pg_use_reserved_connections TO regress_reserved; +CREATE USER regress_superuser LOGIN SUPERUSER; +}); + +# With the limits we set in postgresql.conf, we can establish: +# - 3 connections for any user with no special privileges +# - 2 more connections for users belonging to "pg_use_reserved_connections" +# - 1 more connection for superuser + +sub background_psql_as_user +{ + my $user = shift; + + return $node->background_psql( + 'postgres', + on_error_die => 1, + extra_params => [ '-U', $user ]); +} + +my @sessions = (); + +push(@sessions, background_psql_as_user('regress_regular')); +push(@sessions, background_psql_as_user('regress_regular')); +push(@sessions, background_psql_as_user('regress_regular')); +$node->connect_fails( + "dbname=postgres user=regress_regular", + "reserved_connections limit", + expected_stderr => + qr/FATAL: remaining connection slots are reserved for roles with privileges of the "pg_use_reserved_connections" role/ +); + +push(@sessions, background_psql_as_user('regress_reserved')); +push(@sessions, background_psql_as_user('regress_reserved')); +$node->connect_fails( + "dbname=postgres user=regress_regular", + "reserved_connections limit", + expected_stderr => + qr/FATAL: remaining connection slots are reserved for roles with the SUPERUSER attribute/ +); + +push(@sessions, background_psql_as_user('regress_superuser')); +$node->connect_fails( + "dbname=postgres user=regress_superuser", + "superuser_reserved_connections limit", + expected_stderr => qr/FATAL: sorry, too many clients already/); + +# TODO: test that query cancellation is still possible + +foreach my $session (@sessions) +{ + $session->quit; +} + +done_testing();