From 720cac3ae8907d9bdc8eb09cbe2117c07d4e0053 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Sun, 21 Jan 2018 23:41:35 +0100
Subject: [PATCH 2/3] Allow running SSL tests against different binaries

In order to be able to test work on SSL frontends, or backends,
against a stock installation, allow a pgpath setting to override
the path to the binaries. The SSLTEST_SERVER_BIN environment var
will be used, if set, for which set of server binaries to run.

  SSLTEST_SERVER_BIN=/path/bin/ make -C src/test/ssl/ check

This is intended for testing during development in order to test
a new frontend against a known backend for example.
---
 src/test/perl/PostgresNode.pm  | 77 ++++++++++++++++++++++++++++++++----------
 src/test/ssl/t/001_ssltests.pl |  2 +-
 2 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm
index 1d5ac4ee35..41c980ee0c 100644
--- a/src/test/perl/PostgresNode.pm
+++ b/src/test/perl/PostgresNode.pm
@@ -133,7 +133,7 @@ INIT
 
 =over
 
-=item PostgresNode::new($class, $name, $pghost, $pgport)
+=item PostgresNode::new($class, $name, $pghost, $pgport, $pgpath)
 
 Create a new PostgresNode instance. Does not initdb or start it.
 
@@ -144,12 +144,14 @@ of finding port numbers, registering instances for cleanup, etc.
 
 sub new
 {
-	my ($class, $name, $pghost, $pgport) = @_;
+	my ($class, $name, $pghost, $pgport, $pgpath) = @_;
 	my $testname = basename($0);
 	$testname =~ s/\.[^.]+$//;
+	$pgpath = '' unless defined $pgpath;
 	my $self = {
 		_port    => $pgport,
 		_host    => $pghost,
+		_pgpath  => $pgpath,
 		_basedir => "$TestLib::tmp_check/t_${testname}_${name}_data",
 		_name    => $name,
 		_logfile => "$TestLib::log_path/${testname}_${name}.log" };
@@ -227,6 +229,21 @@ sub name
 
 =pod
 
+=item $node->pgpath()
+
+Path to the PostgreSQL binaries to run, if empty then the installation in PATH
+is assumed.
+
+=cut
+
+sub pgpath
+{
+	my ($self) = @_;
+	return $self->{_pgpath};
+}
+
+=pod
+
 =item $node->logfile()
 
 Path to the PostgreSQL log file for this instance.
@@ -327,6 +344,7 @@ sub info
 	my $_info = '';
 	open my $fh, '>', \$_info or die;
 	print $fh "Name: " . $self->name . "\n";
+	print $fh "Binary directory: " . $self->pgpath . "\n";
 	print $fh "Data directory: " . $self->data_dir . "\n";
 	print $fh "Backup directory: " . $self->backup_dir . "\n";
 	print $fh "Archive directory: " . $self->archive_dir . "\n";
@@ -402,6 +420,7 @@ sub init
 	my $port   = $self->port;
 	my $pgdata = $self->data_dir;
 	my $host   = $self->host;
+	my $pgpath = $self->pgpath;
 
 	$params{allows_streaming} = 0 unless defined $params{allows_streaming};
 	$params{has_archiving}    = 0 unless defined $params{has_archiving};
@@ -409,7 +428,7 @@ sub init
 	mkdir $self->backup_dir;
 	mkdir $self->archive_dir;
 
-	TestLib::system_or_bail('initdb', '-D', $pgdata, '-A', 'trust', '-N',
+	TestLib::system_or_bail($pgpath . 'initdb', '-D', $pgdata, '-A', 'trust', '-N',
 		@{ $params{extra} });
 	TestLib::system_or_bail($ENV{PG_REGRESS}, '--config-auth', $pgdata);
 
@@ -504,9 +523,10 @@ sub backup
 	my $backup_path = $self->backup_dir . '/' . $backup_name;
 	my $port        = $self->port;
 	my $name        = $self->name;
+	my $pgpath      = $self->pgpath;
 
 	print "# Taking pg_basebackup $backup_name from node \"$name\"\n";
-	TestLib::system_or_bail('pg_basebackup', '-D', $backup_path, '-p', $port,
+	TestLib::system_or_bail($pgpath . 'pg_basebackup', '-D', $backup_path, '-p', $port,
 		'--no-sync');
 	print "# Backup finished\n";
 }
@@ -662,8 +682,9 @@ sub start
 	my $pgdata = $self->data_dir;
 	my $name   = $self->name;
 	BAIL_OUT("node \"$name\" is already running") if defined $self->{_pid};
+	my $pgpath = $self->pgpath;
 	print("### Starting node \"$name\"\n");
-	my $ret = TestLib::system_log('pg_ctl', '-D', $self->data_dir, '-l',
+	my $ret = TestLib::system_log($pgpath . 'pg_ctl', '-D', $self->data_dir, '-l',
 		$self->logfile, 'start');
 
 	if ($ret != 0)
@@ -694,10 +715,11 @@ sub stop
 	my $port   = $self->port;
 	my $pgdata = $self->data_dir;
 	my $name   = $self->name;
+	my $pgpath = $self->pgpath;
 	$mode = 'fast' unless defined $mode;
 	return unless defined $self->{_pid};
 	print "### Stopping node \"$name\" using mode $mode\n";
-	TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-m', $mode, 'stop');
+	TestLib::system_or_bail($pgpath . 'pg_ctl', '-D', $pgdata, '-m', $mode, 'stop');
 	$self->_update_pid(0);
 }
 
@@ -715,8 +737,10 @@ sub reload
 	my $port   = $self->port;
 	my $pgdata = $self->data_dir;
 	my $name   = $self->name;
+	my $pgpath = $self->pgpath;
 	print "### Reloading node \"$name\"\n";
-	TestLib::system_or_bail('pg_ctl', '-D', $pgdata, 'reload');
+	TestLib::system_or_bail($pgpath . 'pg_ctl', '-D', $pgdata, 'reload');
+
 }
 
 =pod
@@ -734,8 +758,9 @@ sub restart
 	my $pgdata  = $self->data_dir;
 	my $logfile = $self->logfile;
 	my $name    = $self->name;
+	my $pgpath  = $self->pgpath;
 	print "### Restarting node \"$name\"\n";
-	TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
+	TestLib::system_or_bail($pgpath . 'pg_ctl', '-D', $pgdata, '-l', $logfile,
 		'restart');
 	$self->_update_pid(1);
 }
@@ -755,8 +780,9 @@ sub promote
 	my $pgdata  = $self->data_dir;
 	my $logfile = $self->logfile;
 	my $name    = $self->name;
+	my $pgpath  = $self->pgpath;
 	print "### Promoting node \"$name\"\n";
-	TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
+	TestLib::system_or_bail($pgpath . 'pg_ctl', '-D', $pgdata, '-l', $logfile,
 		'promote');
 }
 
@@ -860,12 +886,15 @@ sub _update_pid
 
 =pod
 
-=item PostgresNode->get_new_node(node_name)
+=item PostgresNode->get_new_node(node_name, pgpath)
 
 Build a new object of class C<PostgresNode> (or of a subclass, if you have
 one), assigning a free port number.  Remembers the node, to prevent its port
 number from being reused for another node, and to ensure that it gets
-shut down when the test script exits.
+shut down when the test script exits. If the pgpath parameter is defined then
+the path is tested for containing a PostgreSQL installation with the correct
+permissions for execution.
+
 
 You should generally use this instead of C<PostgresNode::new(...)>.
 
@@ -877,8 +906,8 @@ which can only create objects of class C<PostgresNode>.
 sub get_new_node
 {
 	my $class = 'PostgresNode';
-	$class = shift if 1 < scalar @_;
-	my $name  = shift;
+	$class = shift if 2 < scalar @_;
+	my ($name, $pgpath) = @_;
 	my $found = 0;
 	my $port  = $last_port_assigned;
 
@@ -921,8 +950,19 @@ sub get_new_node
 
 	print "# Found free port $port\n";
 
+	# If a separate path to the binaries was specified then we do rudimentary
+	# checks for a sane installation. If an executable copy of initdb is there
+	# then let's go ahead.
+	if (defined $pgpath)
+	{
+		$pgpath =~ s!/*$!/!;
+		die "initdb missing in $pgpath" unless -x $pgpath . 'initdb';
+
+		print "# Found PostgreSQL installation in $pgpath\n";
+	}
+
 	# Lock port number found by creating a new node
-	my $node = $class->new($name, $test_pghost, $port);
+	my $node = $class->new($name, $test_pghost, $port, $pgpath);
 
 	# Add node to list of nodes
 	push(@all_nodes, $node);
@@ -1129,8 +1169,9 @@ sub psql
 	my $stderr            = $params{stderr};
 	my $timeout           = undef;
 	my $timeout_exception = 'psql timed out';
+	my $pgpath            = $self->pgpath;
 	my @psql_params =
-	  ('psql', '-XAtq', '-d', $self->connstr($dbname), '-f', '-');
+	  ($pgpath . 'psql', '-XAtq', '-d', $self->connstr($dbname), '-f', '-');
 
 	# If the caller wants an array and hasn't passed stdout/stderr
 	# references, allocate temporary ones to capture them so we
@@ -1272,11 +1313,11 @@ Returns 1 if successful, 0 if timed out.
 
 sub poll_query_until
 {
-	my ($self, $dbname, $query, $expected) = @_;
+	my ($self, $dbname, $query, $expected, $pgpath) = @_;
 
 	$expected = 't' unless defined($expected);    # default value
 
-	my $cmd = [ 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ];
+	my $cmd = [ $pgpath . 'psql', '-XAt', '-c', $query, '-d', $self->connstr($dbname) ];
 	my ($stdout, $stderr);
 	my $max_attempts = 180 * 10;
 	my $attempts     = 0;
@@ -1516,7 +1557,7 @@ sub wait_for_catchup
 	  . $self->name . "\n";
 	my $query =
 qq[SELECT $lsn_expr <= ${mode}_lsn FROM pg_catalog.pg_stat_replication WHERE application_name = '$standby_name';];
-	$self->poll_query_until('postgres', $query)
+	$self->poll_query_until('postgres', $query, $self->pgpath)
 	  or die "timed out waiting for catchup";
 	print "done\n";
 }
diff --git a/src/test/ssl/t/001_ssltests.pl b/src/test/ssl/t/001_ssltests.pl
index a858344329..6061838a20 100644
--- a/src/test/ssl/t/001_ssltests.pl
+++ b/src/test/ssl/t/001_ssltests.pl
@@ -45,7 +45,7 @@ else
 #### Part 0. Set up the server.
 
 note "setting up data directory";
-my $node = get_new_node('master');
+my $node = get_new_node('master', $ENV{SSLTEST_SERVER_BIN});
 $node->init;
 
 # PGHOST is enforced here to set up the node, subsequent connections
-- 
2.14.1.145.gb3622a4ee

