1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-24 00:23:06 +03:00

Refactor background psql TAP functions

This breaks out the background and interactive psql functionality into a
new class, PostgreSQL::Test::BackgroundPsql.  Sessions are still initiated
via PostgreSQL::Test::Cluster, but once started they can be manipulated by
the new helper functions which intend to make querying easier.  A sample
session for a command which can be expected to finish at a later time can
be seen below.

  my $session = $node->background_psql('postgres');
  $bsession->query_until(qr/start/, q(
    \echo start
	CREATE INDEX CONCURRENTLY idx ON t(a);
  ));
  $bsession->quit;

Patch by Andres Freund with some additional hacking by me.

Author: Andres Freund <andres@anarazel.de>
Reviewed-by: Andrew Dunstan <andrew@dunslane.net>
Discussion: https://postgr.es/m/20230130194350.zj5v467x4jgqt3d6@awork3.anarazel.de
This commit is contained in:
Daniel Gustafsson
2023-04-07 22:14:20 +02:00
parent 32bc0d022d
commit 664d757531
7 changed files with 386 additions and 240 deletions

View File

@@ -113,6 +113,7 @@ use PostgreSQL::Test::RecursiveCopy;
use Socket;
use Test::More;
use PostgreSQL::Test::Utils ();
use PostgreSQL::Test::BackgroundPsql ();
use Time::HiRes qw(usleep);
use Scalar::Util qw(blessed);
@@ -1966,18 +1967,12 @@ sub psql
=pod
=item $node->background_psql($dbname, \$stdin, \$stdout, $timer, %params) => harness
=item $node->background_psql($dbname, %params) => PostgreSQL::Test::BackgroundPsql instance
Invoke B<psql> on B<$dbname> and return an IPC::Run harness object, which the
caller may use to send input to B<psql>. The process's stdin is sourced from
the $stdin scalar reference, and its stdout and stderr go to the $stdout
scalar reference. This allows the caller to act on other parts of the system
while idling this backend.
Invoke B<psql> on B<$dbname> and return a BackgroundPsql object.
The specified timer object is attached to the harness, as well. It's caller's
responsibility to set the timeout length (usually
$PostgreSQL::Test::Utils::timeout_default), and to restart the timer after
each command if the timeout is per-command.
A default timeout of $PostgreSQL::Test::Utils::timeout_default is set up,
which can be modified later.
psql is invoked in tuples-only unaligned mode with reading of B<.psqlrc>
disabled. That may be overridden by passing extra psql parameters.
@@ -1986,7 +1981,7 @@ Dies on failure to invoke psql, or if psql fails to connect. Errors occurring
later are the caller's problem. psql runs with on_error_stop by default so
that it will stop running sql and return 3 if passed SQL results in an error.
Be sure to "finish" the harness when done with it.
Be sure to "quit" the returned object when done with it.
=over
@@ -2012,7 +2007,7 @@ If given, it must be an array reference containing additional parameters to B<ps
sub background_psql
{
my ($self, $dbname, $stdin, $stdout, $timer, %params) = @_;
my ($self, $dbname, %params) = @_;
local %ENV = $self->_get_env();
@@ -2033,41 +2028,18 @@ sub background_psql
push @psql_params, @{ $params{extra_params} }
if defined $params{extra_params};
# Ensure there is no data waiting to be sent:
$$stdin = "" if ref($stdin);
# IPC::Run would otherwise append to existing contents:
$$stdout = "" if ref($stdout);
my $harness = IPC::Run::start \@psql_params,
'<', $stdin, '>', $stdout, $timer;
# Request some output, and pump until we see it. This means that psql
# connection failures are caught here, relieving callers of the need to
# handle those. (Right now, we have no particularly good handling for
# errors anyway, but that might be added later.)
my $banner = "background_psql: ready";
$$stdin = "\\echo $banner\n";
pump $harness until $$stdout =~ /$banner/ || $timer->is_expired;
die "psql startup timed out" if $timer->is_expired;
return $harness;
return PostgreSQL::Test::BackgroundPsql->new(0, \@psql_params);
}
=pod
=item $node->interactive_psql($dbname, \$stdin, \$stdout, $timer, %params) => harness
=item $node->interactive_psql($dbname, %params) => BackgroundPsql instance
Invoke B<psql> on B<$dbname> and return an IPC::Run harness object,
which the caller may use to send interactive input to B<psql>.
The process's stdin is sourced from the $stdin scalar reference,
and its stdout and stderr go to the $stdout scalar reference.
ptys are used so that psql thinks it's being called interactively.
Invoke B<psql> on B<$dbname> and return a BackgroundPsql object, which the
caller may use to send interactive input to B<psql>.
The specified timer object is attached to the harness, as well. It's caller's
responsibility to set the timeout length (usually
$PostgreSQL::Test::Utils::timeout_default), and to restart the timer after
each command if the timeout is per-command.
A default timeout of $PostgreSQL::Test::Utils::timeout_default is set up,
which can be modified later.
psql is invoked in tuples-only unaligned mode with reading of B<.psqlrc>
disabled. That may be overridden by passing extra psql parameters.
@@ -2075,7 +2047,7 @@ disabled. That may be overridden by passing extra psql parameters.
Dies on failure to invoke psql, or if psql fails to connect.
Errors occurring later are the caller's problem.
Be sure to "finish" the harness when done with it.
Be sure to "quit" the returned object when done with it.
The only extra parameter currently accepted is
@@ -2093,7 +2065,7 @@ This requires IO::Pty in addition to IPC::Run.
sub interactive_psql
{
my ($self, $dbname, $stdin, $stdout, $timer, %params) = @_;
my ($self, $dbname, %params) = @_;
local %ENV = $self->_get_env();
@@ -2104,26 +2076,7 @@ sub interactive_psql
push @psql_params, @{ $params{extra_params} }
if defined $params{extra_params};
# Ensure there is no data waiting to be sent:
$$stdin = "" if ref($stdin);
# IPC::Run would otherwise append to existing contents:
$$stdout = "" if ref($stdout);
my $harness = IPC::Run::start \@psql_params,
'<pty<', $stdin, '>pty>', $stdout, $timer;
# Pump until we see psql's help banner. This ensures that callers
# won't write anything to the pty before it's ready, avoiding an
# implementation issue in IPC::Run. Also, it means that psql
# connection failures are caught here, relieving callers of
# the need to handle those. (Right now, we have no particularly
# good handling for errors anyway, but that might be added later.)
pump $harness
until $$stdout =~ /Type "help" for help/ || $timer->is_expired;
die "psql startup timed out" if $timer->is_expired;
return $harness;
return PostgreSQL::Test::BackgroundPsql->new(1, \@psql_params);
}
# Common sub of pgbench-invoking interfaces. Makes any requested script files