Skip to content

Commit b34ca59

Browse files
committed
Allow for installation-aware instances of PostgresNode
Currently instances of PostgresNode find their Postgres executables in the PATH of the caller. This modification allows for instances that know the installation path they are supposed to use, and the module adjusts the environment of methods that call Postgres executables appropriately. This facility is activated by passing the installation path to the constructor: my $node = PostgresNode->get_new_node('mynode', installation_path => '/path/to/installation'); This makes a number of things substantially easier, including . testing third party modules . testing different versions of postgres together . testing different builds of postgres together Discussion: https://postgr.es/m/a94c74f9-6b71-1957-7973-a734ea3cbef1@dunslane.net Reviewed-By: Alvaro Herrera, Michael Paquier, Dagfinn Ilmari Mannsåker
1 parent 65c2ec6 commit b34ca59

File tree

1 file changed

+138
-31
lines changed

1 file changed

+138
-31
lines changed

src/test/perl/PostgresNode.pm

+138-31
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ sub info
355355
print $fh "Archive directory: " . $self->archive_dir . "\n";
356356
print $fh "Connection string: " . $self->connstr . "\n";
357357
print $fh "Log file: " . $self->logfile . "\n";
358+
print $fh "Install Path: ", $self->{_install_path} . "\n"
359+
if $self->{_install_path};
358360
close $fh or die;
359361
return $_info;
360362
}
@@ -428,6 +430,8 @@ sub init
428430
my $pgdata = $self->data_dir;
429431
my $host = $self->host;
430432

433+
local %ENV = $self->_get_env();
434+
431435
$params{allows_streaming} = 0 unless defined $params{allows_streaming};
432436
$params{has_archiving} = 0 unless defined $params{has_archiving};
433437

@@ -555,6 +559,8 @@ sub backup
555559
my $backup_path = $self->backup_dir . '/' . $backup_name;
556560
my $name = $self->name;
557561

562+
local %ENV = $self->_get_env();
563+
558564
print "# Taking pg_basebackup $backup_name from node \"$name\"\n";
559565
TestLib::system_or_bail(
560566
'pg_basebackup', '-D', $backup_path, '-h',
@@ -784,18 +790,15 @@ sub start
784790

785791
print("### Starting node \"$name\"\n");
786792

787-
{
788-
# Temporarily unset PGAPPNAME so that the server doesn't
789-
# inherit it. Otherwise this could affect libpqwalreceiver
790-
# connections in confusing ways.
791-
local %ENV = %ENV;
792-
delete $ENV{PGAPPNAME};
793-
794-
# Note: We set the cluster_name here, not in postgresql.conf (in
795-
# sub init) so that it does not get copied to standbys.
796-
$ret = TestLib::system_log('pg_ctl', '-D', $self->data_dir, '-l',
797-
$self->logfile, '-o', "--cluster-name=$name", 'start');
798-
}
793+
# Temporarily unset PGAPPNAME so that the server doesn't
794+
# inherit it. Otherwise this could affect libpqwalreceiver
795+
# connections in confusing ways.
796+
local %ENV = $self->_get_env(PGAPPNAME => undef);
797+
798+
# Note: We set the cluster_name here, not in postgresql.conf (in
799+
# sub init) so that it does not get copied to standbys.
800+
$ret = TestLib::system_log('pg_ctl', '-D', $self->data_dir, '-l',
801+
$self->logfile, '-o', "--cluster-name=$name", 'start');
799802

800803
if ($ret != 0)
801804
{
@@ -826,6 +829,9 @@ sub kill9
826829
my ($self) = @_;
827830
my $name = $self->name;
828831
return unless defined $self->{_pid};
832+
833+
local %ENV = $self->_get_env();
834+
829835
print "### Killing node \"$name\" using signal 9\n";
830836
# kill(9, ...) fails under msys Perl 5.8.8, so fall back on pg_ctl.
831837
kill(9, $self->{_pid})
@@ -852,6 +858,9 @@ sub stop
852858
my $port = $self->port;
853859
my $pgdata = $self->data_dir;
854860
my $name = $self->name;
861+
862+
local %ENV = $self->_get_env();
863+
855864
$mode = 'fast' unless defined $mode;
856865
return unless defined $self->{_pid};
857866
print "### Stopping node \"$name\" using mode $mode\n";
@@ -874,6 +883,9 @@ sub reload
874883
my $port = $self->port;
875884
my $pgdata = $self->data_dir;
876885
my $name = $self->name;
886+
887+
local %ENV = $self->_get_env();
888+
877889
print "### Reloading node \"$name\"\n";
878890
TestLib::system_or_bail('pg_ctl', '-D', $pgdata, 'reload');
879891
return;
@@ -895,15 +907,12 @@ sub restart
895907
my $logfile = $self->logfile;
896908
my $name = $self->name;
897909

898-
print "### Restarting node \"$name\"\n";
910+
local %ENV = $self->_get_env(PGAPPNAME => undef);
899911

900-
{
901-
local %ENV = %ENV;
902-
delete $ENV{PGAPPNAME};
912+
print "### Restarting node \"$name\"\n";
903913

904-
TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
905-
'restart');
906-
}
914+
TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
915+
'restart');
907916

908917
$self->_update_pid(1);
909918
return;
@@ -924,6 +933,9 @@ sub promote
924933
my $pgdata = $self->data_dir;
925934
my $logfile = $self->logfile;
926935
my $name = $self->name;
936+
937+
local %ENV = $self->_get_env();
938+
927939
print "### Promoting node \"$name\"\n";
928940
TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
929941
'promote');
@@ -945,6 +957,9 @@ sub logrotate
945957
my $pgdata = $self->data_dir;
946958
my $logfile = $self->logfile;
947959
my $name = $self->name;
960+
961+
local %ENV = $self->_get_env();
962+
948963
print "### Rotating log in node \"$name\"\n";
949964
TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
950965
'logrotate');
@@ -1117,6 +1132,14 @@ By default, all nodes use the same PGHOST value. If specified, generate a
11171132
PGHOST specific to this node. This allows multiple nodes to use the same
11181133
port.
11191134
1135+
=item install_path => '/path/to/postgres/installation'
1136+
1137+
Using this parameter is it possible to have nodes pointing to different
1138+
installations, for testing different versions together or the same version
1139+
with different build parameters. The provided path must be the parent of the
1140+
installation's 'bin' and 'lib' directories. In the common case where this is
1141+
not provided, Postgres binaries will be found in the caller's PATH.
1142+
11201143
=back
11211144
11221145
For backwards compatibility, it is also exported as a standalone function,
@@ -1165,12 +1188,89 @@ sub get_new_node
11651188
# Lock port number found by creating a new node
11661189
my $node = $class->new($name, $host, $port);
11671190

1191+
if ($params{install_path})
1192+
{
1193+
$node->{_install_path} = $params{install_path};
1194+
}
1195+
11681196
# Add node to list of nodes
11691197
push(@all_nodes, $node);
11701198

11711199
return $node;
11721200
}
11731201

1202+
# Private routine to return a copy of the environment with the PATH and
1203+
# (DY)LD_LIBRARY_PATH correctly set when there is an install path set for
1204+
# the node.
1205+
#
1206+
# Routines that call Postgres binaries need to call this routine like this:
1207+
#
1208+
# local %ENV = $self->_get_env{[%extra_settings]);
1209+
#
1210+
# A copy of the environment is taken and node's host and port settings are
1211+
# added as PGHOST and PGPORT, Then the extra settings (if any) are applied.
1212+
# Any setting in %extra_settings with a value that is undefined is deleted
1213+
# the remainder are# set. Then the PATH and (DY)LD_LIBRARY_PATH are adjusted
1214+
# if the node's install path is set, and the copy environment is returned.
1215+
#
1216+
# The install path set in get_new_node needs to be a directory containing
1217+
# bin and lib subdirectories as in a standard PostgreSQL installation, so this
1218+
# can't be used with installations where the bin and lib directories don't have
1219+
# a common parent directory.
1220+
sub _get_env
1221+
{
1222+
my $self = shift;
1223+
my %inst_env = (%ENV, PGHOST => $self->{_host}, PGPORT => $self->{_port});
1224+
# the remaining arguments are modifications to make to the environment
1225+
my %mods = (@_);
1226+
while (my ($k, $v) = each %mods)
1227+
{
1228+
if (defined $v)
1229+
{
1230+
$inst_env{$k} = "$v";
1231+
}
1232+
else
1233+
{
1234+
delete $inst_env{$k};
1235+
}
1236+
}
1237+
# now fix up the new environment for the install path
1238+
my $inst = $self->{_install_path};
1239+
if ($inst)
1240+
{
1241+
if ($TestLib::windows_os)
1242+
{
1243+
# Windows picks up DLLs from the PATH rather than *LD_LIBRARY_PATH
1244+
# choose the right path separator
1245+
if ($Config{osname} eq 'MSWin32')
1246+
{
1247+
$inst_env{PATH} = "$inst/bin;$inst/lib;$ENV{PATH}";
1248+
}
1249+
else
1250+
{
1251+
$inst_env{PATH} = "$inst/bin:$inst/lib:$ENV{PATH}";
1252+
}
1253+
}
1254+
else
1255+
{
1256+
my $dylib_name =
1257+
$Config{osname} eq 'darwin'
1258+
? "DYLD_LIBRARY_PATH"
1259+
: "LD_LIBRARY_PATH";
1260+
$inst_env{PATH} = "$inst/bin:$ENV{PATH}";
1261+
if (exists $ENV{$dylib_name})
1262+
{
1263+
$inst_env{$dylib_name} = "$inst/lib:$ENV{$dylib_name}";
1264+
}
1265+
else
1266+
{
1267+
$inst_env{$dylib_name} = "$inst/lib";
1268+
}
1269+
}
1270+
}
1271+
return (%inst_env);
1272+
}
1273+
11741274
=pod
11751275
11761276
=item get_free_port()
@@ -1330,6 +1430,8 @@ sub safe_psql
13301430
{
13311431
my ($self, $dbname, $sql, %params) = @_;
13321432

1433+
local %ENV = $self->_get_env();
1434+
13331435
my ($stdout, $stderr);
13341436

13351437
my $ret = $self->psql(
@@ -1441,6 +1543,8 @@ sub psql
14411543
{
14421544
my ($self, $dbname, $sql, %params) = @_;
14431545

1546+
local %ENV = $self->_get_env();
1547+
14441548
my $stdout = $params{stdout};
14451549
my $stderr = $params{stderr};
14461550
my $replication = $params{replication};
@@ -1634,6 +1738,8 @@ sub background_psql
16341738
{
16351739
my ($self, $dbname, $stdin, $stdout, $timer, %params) = @_;
16361740

1741+
local %ENV = $self->_get_env();
1742+
16371743
my $replication = $params{replication};
16381744

16391745
my @psql_params = (
@@ -1712,6 +1818,8 @@ sub interactive_psql
17121818
{
17131819
my ($self, $dbname, $stdin, $stdout, $timer, %params) = @_;
17141820

1821+
local %ENV = $self->_get_env();
1822+
17151823
my @psql_params = ('psql', '-XAt', '-d', $self->connstr($dbname));
17161824

17171825
push @psql_params, @{ $params{extra_params} }
@@ -1755,6 +1863,8 @@ sub poll_query_until
17551863
{
17561864
my ($self, $dbname, $query, $expected) = @_;
17571865

1866+
local %ENV = $self->_get_env();
1867+
17581868
$expected = 't' unless defined($expected); # default value
17591869

17601870
my $cmd = [ 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ];
@@ -1810,8 +1920,7 @@ sub command_ok
18101920

18111921
my $self = shift;
18121922

1813-
local $ENV{PGHOST} = $self->host;
1814-
local $ENV{PGPORT} = $self->port;
1923+
local %ENV = $self->_get_env();
18151924

18161925
TestLib::command_ok(@_);
18171926
return;
@@ -1831,8 +1940,7 @@ sub command_fails
18311940

18321941
my $self = shift;
18331942

1834-
local $ENV{PGHOST} = $self->host;
1835-
local $ENV{PGPORT} = $self->port;
1943+
local %ENV = $self->_get_env();
18361944

18371945
TestLib::command_fails(@_);
18381946
return;
@@ -1852,8 +1960,7 @@ sub command_like
18521960

18531961
my $self = shift;
18541962

1855-
local $ENV{PGHOST} = $self->host;
1856-
local $ENV{PGPORT} = $self->port;
1963+
local %ENV = $self->_get_env();
18571964

18581965
TestLib::command_like(@_);
18591966
return;
@@ -1874,8 +1981,7 @@ sub command_checks_all
18741981

18751982
my $self = shift;
18761983

1877-
local $ENV{PGHOST} = $self->host;
1878-
local $ENV{PGPORT} = $self->port;
1984+
local %ENV = $self->_get_env();
18791985

18801986
TestLib::command_checks_all(@_);
18811987
return;
@@ -1899,8 +2005,7 @@ sub issues_sql_like
18992005

19002006
my ($self, $cmd, $expected_sql, $test_name) = @_;
19012007

1902-
local $ENV{PGHOST} = $self->host;
1903-
local $ENV{PGPORT} = $self->port;
2008+
local %ENV = $self->_get_env();
19042009

19052010
truncate $self->logfile, 0;
19062011
my $result = TestLib::run_log($cmd);
@@ -1923,8 +2028,7 @@ sub run_log
19232028
{
19242029
my $self = shift;
19252030

1926-
local $ENV{PGHOST} = $self->host;
1927-
local $ENV{PGPORT} = $self->port;
2031+
local %ENV = $self->_get_env();
19282032

19292033
TestLib::run_log(@_);
19302034
return;
@@ -2174,6 +2278,9 @@ sub pg_recvlogical_upto
21742278
{
21752279
my ($self, $dbname, $slot_name, $endpos, $timeout_secs, %plugin_options)
21762280
= @_;
2281+
2282+
local %ENV = $self->_get_env();
2283+
21772284
my ($stdout, $stderr);
21782285

21792286
my $timeout_exception = 'pg_recvlogical timed out';

0 commit comments

Comments
 (0)