Add tap test for pg_signal_autovacuum role
This commit provides testig coverage for ccd38024bc3c, checking that a role granted pg_signal_autovacuum_worker is able to stop a vacuum worker. An injection point with a wait is placed at the beginning of autovacuum worker startup to make sure that a worker is still alive when sending and processing the signal sent. Author: Anthony Leung, Michael Paquier, Kirill Reshke Reviewed-by: Andrey Borodin, Nathan Bossart Discussion: https://postgr.es/m/CALdSSPiQPuuQpOkF7x0g2QkA5eE-3xXt7hiJFvShV1bHKDvf8w@mail.gmail.com
This commit is contained in:
parent
47ecbfdfcc
commit
d2b74882ca
@ -100,6 +100,7 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/fmgrprotos.h"
|
||||
#include "utils/guc_hooks.h"
|
||||
#include "utils/injection_point.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
@ -1902,6 +1903,12 @@ do_autovacuum(void)
|
||||
/* Start a transaction so our commands have one to play into. */
|
||||
StartTransactionCommand();
|
||||
|
||||
/*
|
||||
* This injection point is put in a transaction block to work with a wait
|
||||
* that uses a condition variable.
|
||||
*/
|
||||
INJECTION_POINT("autovacuum-worker-start");
|
||||
|
||||
/*
|
||||
* Compute the multixact age for which freezing is urgent. This is
|
||||
* normally autovacuum_multixact_freeze_max_age, but may be less if we are
|
||||
|
@ -13,7 +13,8 @@ tests += {
|
||||
't/002_tablespace.pl',
|
||||
't/003_check_guc.pl',
|
||||
't/004_io_direct.pl',
|
||||
't/005_timeouts.pl'
|
||||
't/005_timeouts.pl',
|
||||
't/006_signal_autovacuum.pl',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
95
src/test/modules/test_misc/t/006_signal_autovacuum.pl
Normal file
95
src/test/modules/test_misc/t/006_signal_autovacuum.pl
Normal file
@ -0,0 +1,95 @@
|
||||
# Copyright (c) 2024, PostgreSQL Global Development Group
|
||||
|
||||
# Test signaling autovacuum worker with pg_signal_autovacuum_worker.
|
||||
#
|
||||
# Only roles with privileges of pg_signal_autovacuum_worker are allowed to
|
||||
# signal autovacuum workers. This test uses an injection point located
|
||||
# at the beginning of the autovacuum worker startup.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use PostgreSQL::Test::Cluster;
|
||||
use Test::More;
|
||||
|
||||
if ($ENV{enable_injection_points} ne 'yes')
|
||||
{
|
||||
plan skip_all => 'Injection points not supported by this build';
|
||||
}
|
||||
|
||||
# Initialize postgres
|
||||
my $psql_err = '';
|
||||
my $psql_out = '';
|
||||
my $node = PostgreSQL::Test::Cluster->new('node');
|
||||
$node->init;
|
||||
|
||||
# This ensures a quick worker spawn.
|
||||
$node->append_conf('postgresql.conf', 'autovacuum_naptime = 1');
|
||||
$node->start;
|
||||
$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;');
|
||||
|
||||
$node->safe_psql(
|
||||
'postgres', qq(
|
||||
CREATE ROLE regress_regular_role;
|
||||
CREATE ROLE regress_worker_role;
|
||||
GRANT pg_signal_autovacuum_worker TO regress_worker_role;
|
||||
));
|
||||
|
||||
# From this point, autovacuum worker will wait at startup.
|
||||
$node->safe_psql('postgres',
|
||||
"SELECT injection_points_attach('autovacuum-worker-start', 'wait');");
|
||||
|
||||
# Accelerate worker creation in case we reach this point before the naptime
|
||||
# ends.
|
||||
$node->reload();
|
||||
|
||||
# Wait until an autovacuum worker starts.
|
||||
$node->wait_for_event('autovacuum worker', 'autovacuum-worker-start');
|
||||
|
||||
# And grab one of them.
|
||||
my $av_pid = $node->safe_psql(
|
||||
'postgres', qq(
|
||||
SELECT pid FROM pg_stat_activity WHERE backend_type = 'autovacuum worker' AND wait_event = 'autovacuum-worker-start' LIMIT 1;
|
||||
));
|
||||
|
||||
# Regular role cannot terminate autovacuum worker.
|
||||
my $terminate_with_no_pg_signal_av = $node->psql(
|
||||
'postgres', qq(
|
||||
SET ROLE regress_regular_role;
|
||||
SELECT pg_terminate_backend('$av_pid');
|
||||
),
|
||||
stdout => \$psql_out,
|
||||
stderr => \$psql_err);
|
||||
|
||||
like(
|
||||
$psql_err,
|
||||
qr/ERROR: permission denied to terminate process\nDETAIL: Only roles with privileges of the "pg_signal_autovacuum_worker" role may terminate autovacuum workers./,
|
||||
"autovacuum worker not signaled with regular role");
|
||||
|
||||
my $offset = -s $node->logfile;
|
||||
|
||||
# Role with pg_signal_autovacuum can terminate autovacuum worker.
|
||||
my $terminate_with_pg_signal_av = $node->psql(
|
||||
'postgres', qq(
|
||||
SET ROLE regress_worker_role;
|
||||
SELECT pg_terminate_backend('$av_pid');
|
||||
),
|
||||
stdout => \$psql_out,
|
||||
stderr => \$psql_err);
|
||||
|
||||
# Wait for the autovacuum worker to exit before scanning the logs.
|
||||
$node->poll_query_until('postgres',
|
||||
"SELECT count(*) = 0 FROM pg_stat_activity "
|
||||
. "WHERE pid = '$av_pid' AND backend_type = 'autovacuum worker';");
|
||||
|
||||
# Check that the primary server logs a FATAL indicating that autovacuum
|
||||
# is terminated.
|
||||
ok( $node->log_contains(
|
||||
qr/FATAL: terminating autovacuum process due to administrator command/,
|
||||
$offset),
|
||||
"autovacuum worker signaled with pg_signal_autovacuum_worker granted");
|
||||
|
||||
# Release injection point.
|
||||
$node->safe_psql('postgres',
|
||||
"SELECT injection_points_detach('autovacuum-worker-start');");
|
||||
|
||||
done_testing();
|
Loading…
x
Reference in New Issue
Block a user