v1-0001-Extending-PostgresNode-cross-version-functionalit.patch
application/octet-stream
Filename: v1-0001-Extending-PostgresNode-cross-version-functionalit.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: Extending PostgresNode cross-version functionality
| File | + | − |
|---|---|---|
| src/test/perl/PostgresNode.pm | 188 | 10 |
From 4f2930b883e8180523da1140b6c54fdf2d502be6 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 31 Mar 2021 19:14:31 -0700
Subject: [PATCH v1 1/2] Extending PostgresNode cross-version functionality
Extending the recently introduced functionality that allows a
PostgresNode to be formed using an older installation. First,
adding functions that allow nodes to be compared, such as
if ($some_node->newer_than_version($some_other_node)) { ... }
if ($node_node->at_least_version("12.2")) { ... }
Fixing PostgresNode::init() to work with versions older than 9.3.
Sanity check the install_path argument.
Fixing PostgresNode::start() to work with versions old than 10.
---
src/test/perl/PostgresNode.pm | 198 ++++++++++++++++++++++++++++++++--
1 file changed, 188 insertions(+), 10 deletions(-)
diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm
index d6e10544bb..c64380d608 100644
--- a/src/test/perl/PostgresNode.pm
+++ b/src/test/perl/PostgresNode.pm
@@ -438,7 +438,8 @@ sub init
mkdir $self->backup_dir;
mkdir $self->archive_dir;
- TestLib::system_or_bail('initdb', '-D', $pgdata, '-A', 'trust', '-N',
+ TestLib::system_or_bail('initdb', '-D', $pgdata, '-A', 'trust',
+ $self->at_least_version("9.3") ? '-N' : (),
@{ $params{extra} });
TestLib::system_or_bail($ENV{PG_REGRESS}, '--config-auth', $pgdata,
@{ $params{auth_extra} });
@@ -446,11 +447,14 @@ sub init
open my $conf, '>>', "$pgdata/postgresql.conf";
print $conf "\n# Added by PostgresNode.pm\n";
print $conf "fsync = off\n";
- print $conf "restart_after_crash = off\n";
+ print $conf "restart_after_crash = off\n"
+ if $self->at_least_version("9.1");
print $conf "log_line_prefix = '%m [%p] %q%a '\n";
print $conf "log_statement = all\n";
- print $conf "log_replication_commands = on\n";
- print $conf "wal_retrieve_retry_interval = '500ms'\n";
+ print $conf "log_replication_commands = on\n"
+ if $self->at_least_version("9.5");
+ print $conf "wal_retrieve_retry_interval = '500ms'\n"
+ if $self->at_least_version("9.5");
# If a setting tends to affect whether tests pass or fail, print it after
# TEMP_CONFIG. Otherwise, print it before TEMP_CONFIG, thereby permitting
@@ -492,12 +496,14 @@ sub init
print $conf "port = $port\n";
if ($use_tcp)
{
- print $conf "unix_socket_directories = ''\n";
+ print $conf "unix_socket_directories = ''\n"
+ if $self->at_least_version("9.3");
print $conf "listen_addresses = '$host'\n";
}
else
{
- print $conf "unix_socket_directories = '$host'\n";
+ print $conf "unix_socket_directories = '$host'\n"
+ if $self->at_least_version("9.3");
print $conf "listen_addresses = ''\n";
}
close $conf;
@@ -732,7 +738,8 @@ port = $port
else
{
$self->append_conf('postgresql.conf',
- "unix_socket_directories = '$host'");
+ "unix_socket_directories = '$host'")
+ if $self->at_least_version("9.3");
}
$self->enable_streaming($root_node) if $params{has_streaming};
$self->enable_restoring($root_node, $params{standby})
@@ -797,8 +804,12 @@ sub start
# Note: We set the cluster_name here, not in postgresql.conf (in
# sub init) so that it does not get copied to standbys.
- $ret = TestLib::system_log('pg_ctl', '-D', $self->data_dir, '-l',
- $self->logfile, '-o', "--cluster-name=$name", 'start');
+ $ret = TestLib::system_log('pg_ctl',
+ $self->older_than_version('10') ? '-w' : (),
+ '-D', $self->data_dir, '-l',
+ $self->logfile,
+ $self->at_least_version('9.5') ? ('-o', "--cluster-name=$name") : (),
+ 'start');
if ($ret != 0)
{
@@ -911,7 +922,9 @@ sub restart
print "### Restarting node \"$name\"\n";
- TestLib::system_or_bail('pg_ctl', '-D', $pgdata, '-l', $logfile,
+ TestLib::system_or_bail('pg_ctl',
+ $self->older_than_version('10') ? '-w' : (),
+ '-D', $pgdata, '-l', $logfile,
'restart');
$self->_update_pid(1);
@@ -1196,9 +1209,174 @@ sub get_new_node
# Add node to list of nodes
push(@all_nodes, $node);
+ # Get information about the node
+ $node->_read_pg_config;
+
return $node;
}
+# Private routine to run the pg_config binary found in our environment (or in
+# our install_path, if we have one), and collect all fields that matter to us.
+#
+sub _read_pg_config
+{
+ my ($self) = @_;
+ my $inst = $self->{_install_path};
+ my $pg_config = "pg_config";
+
+ if (defined $inst)
+ {
+ # If the _install_path is invalid, our PATH variables might find an
+ # unrelated pg_config executable elsewhere. Sanity check the
+ # directory.
+ BAIL_OUT("directory not found: $inst")
+ unless -d $inst;
+
+ # If the directory exists but is not the root of a postgresql
+ # installation, or if the user configured using
+ # --bindir=$SOMEWHERE_ELSE, we're not going to find pg_config, so
+ # complain about that, too.
+ $pg_config = "$inst/bin/pg_config";
+ BAIL_OUT("pg_config not found: $pg_config")
+ unless -e $pg_config;
+ BAIL_OUT("pg_config not executable: $pg_config")
+ unless -x $pg_config;
+
+ # Leave $pg_config install_path qualified, to be sure we get the right
+ # version information, below, or die trying
+ }
+
+ local %ENV = $self->_get_env();
+
+ # We only want the version field
+ open my $fh, "-|", $pg_config, "--version"
+ or
+ BAIL_OUT("$pg_config failed: $!");
+ my $version_line = <$fh>;
+ close $fh or die;
+
+ $self->{_pg_version} = _pg_version_array($version_line);
+
+ BAIL_OUT("could not parse pg_config --version output: $version_line")
+ unless defined $self->{_pg_version};
+}
+
+# Private routine which returns a reference to an array of integers
+# representing the pg_version of a PostgresNode, or parsed from a postgres
+# version string. Development versions (such as "14devel") are converted
+# to an array with minus one as the last value (such as [14, -1]).
+#
+# For idempotency, will return the argument back to the caller if handed an
+# array reference.
+sub _pg_version_array
+{
+ my ($arg) = @_;
+
+ # accept node arguments
+ return _pg_version_array($arg->{_pg_version})
+ if (blessed($arg) && $arg->isa("PostgresNode"));
+
+ # idempotency
+ return $arg
+ if (ref($arg) && ref($arg) =~ /ARRAY/);
+
+ # Accept standard formats, in case caller has handed us the output of a
+ # postgres command line tool
+ $arg = $1
+ if ($arg =~ m/\(?PostgreSQL\)? (\d+(?:\.\d+)*(?:devel)?)/);
+
+ # Split into an array
+ my @result = split(/\./, $arg);
+
+ # Treat development versions as having a minor/micro version one less than
+ # the first released version of that branch.
+ if ($result[$#result] =~ m/^(\d+)devel$/)
+ {
+ pop(@result);
+ push(@result, $1, -1);
+ }
+
+ # Return an array reference
+ [ @result ];
+}
+
+# Private routine which compares the _pg_version_array obtained for the two
+# arguments and returns -1, 0, or 1, allowing comparison between two
+# PostgresNodes or a PostgresNode and a version string.
+#
+# To achieve intuitive behavior when comparing a PostgresNode against a version
+# string, "X" is equal to "X.Y" for any value of Y. This allows calls like
+#
+# $node->newer_than_version("14")
+#
+# to return true starting with "15devel", but false for "14devel", "14.0",
+# "14.1", etc. It also allows
+#
+# $node->at_least_version("14")
+#
+# to work for a node of version "14devel", where comparing against "14.0" would
+# fail.
+#
+sub _pg_version_cmp
+{
+ my ($a, $b) = @_;
+
+ $a = _pg_version_array($a);
+ $b = _pg_version_array($b);
+
+ for (my $idx = 0; ; $idx++)
+ {
+ return 0 unless (defined $a->[$idx] && defined $b->[$idx]);
+ return $a->[$idx] <=> $b->[$idx]
+ if ($a->[$idx] <=> $b->[$idx]);
+ }
+}
+
+=pod
+
+=item $node->older_than_version(other)
+
+Returns whether this node's postgres version is older than "other", which can be
+either another PostgresNode or a version string.
+
+=cut
+
+sub older_than_version
+{
+ my ($node, $pg_version) = @_;
+ return _pg_version_cmp($node->{_pg_version}, $pg_version) < 0;
+}
+
+=pod
+
+=item $node->newer_than_version(other)
+
+Returns whether this node's postgres version is newer than "other", which can
+be either another PostgresNode or a version string.
+
+=cut
+
+sub newer_than_version
+{
+ my ($node, $pg_version) = @_;
+ return _pg_version_cmp($node->{_pg_version}, $pg_version) > 0;
+}
+
+=pod
+
+=item $node->at_least_version(other)
+
+Returns whether this node's postgres version is at least as new as "other",
+which can be either another PostgresNode or a version string.
+
+=cut
+
+sub at_least_version
+{
+ my ($node, $pg_version) = @_;
+ return _pg_version_cmp($node->{_pg_version}, $pg_version) >= 0;
+}
+
# Private routine to return a copy of the environment with the PATH and
# (DY)LD_LIBRARY_PATH correctly set when there is an install path set for
# the node.
--
2.21.1 (Apple Git-122.3)