2 # Copyright (c) 2021-2024, PostgreSQL Global Development Group
8 PostgreSQL::Test::Cluster - class representing PostgreSQL server instance
12 use PostgreSQL::Test::Cluster;
14 my $node = PostgreSQL::Test::Cluster->new('mynode');
16 # Create a data directory with initdb
19 # Start the PostgreSQL server
22 # Add a setting and restart
23 $node->append_conf('postgresql.conf', 'hot_standby = on');
26 # Modify or delete an existing setting
27 $node->adjust_conf('postgresql.conf', 'max_wal_senders', '10');
29 # get pg_config settings
30 # all the settings in one string
31 $pgconfig = $node->config_data;
32 # all the settings as a map
33 %config_map = ($node->config_data);
35 ($incdir, $sharedir) = $node->config_data(qw(--includedir --sharedir));
37 # run a query with psql, like:
38 # echo 'SELECT 1' | psql -qAXt postgres -v ON_ERROR_STOP=1
39 $psql_stdout = $node->safe_psql('postgres', 'SELECT 1');
41 # Run psql with a timeout, capturing stdout and stderr
42 # as well as the psql exit code. Pass some extra psql
43 # options. If there's an error from psql raise an exception.
44 my ($stdout, $stderr, $timed_out);
45 my $cmdret = $node->psql('postgres', 'SELECT pg_sleep(600)',
46 stdout => \$stdout, stderr => \$stderr,
47 timeout => $PostgreSQL::Test::Utils::timeout_default,
48 timed_out => \$timed_out,
49 extra_params => ['--single-transaction'],
51 print "Sleep timed out" if $timed_out;
53 # Similar thing, more convenient in common cases
54 my ($cmdret, $stdout, $stderr) =
55 $node->psql('postgres', 'SELECT 1');
57 # run query every second until it returns 't'
59 $node->poll_query_until('postgres', q|SELECT random() < 0.1;|')
62 # Do an online pg_basebackup
63 my $ret = $node->backup('testbackup1');
65 # Take a backup of a running server
66 my $ret = $node->backup_fs_hot('testbackup2');
68 # Take a backup of a stopped server
70 my $ret = $node->backup_fs_cold('testbackup3')
72 # Restore it to create a new independent node (not a replica)
73 my $other_node = PostgreSQL::Test::Cluster->new('mycopy');
74 $other_node->init_from_backup($node, 'testbackup');
80 # Find a free, unprivileged TCP port to bind some other service to
81 my $port = PostgreSQL::Test::Cluster::get_free_port();
85 PostgreSQL::Test::Cluster contains a set of routines able to work on a PostgreSQL node,
86 allowing to start, stop, backup and initialize it with various options.
87 The set of nodes managed by a given test is also managed by this module.
89 In addition to node management, PostgreSQL::Test::Cluster instances have some wrappers
90 around Test::More functions to run commands with an environment set up to
91 point to the instance.
93 The IPC::Run module is required.
97 package PostgreSQL::Test::Cluster;
100 use warnings FATAL => 'all';
104 use Fcntl qw(:mode :flock :seek :DEFAULT);
106 use File::Path qw(rmtree mkpath);
108 use File::stat qw(stat);
111 use PostgreSQL::Version;
112 use PostgreSQL::Test::RecursiveCopy;
115 use PostgreSQL::Test::Utils ();
116 use PostgreSQL::Test::BackgroundPsql ();
117 use Time::HiRes qw(usleep);
118 use Scalar::Util qw(blessed);
120 our ($use_tcp, $test_localhost, $test_pghost, $last_host_assigned,
121 $last_port_assigned, @all_nodes, $died, $portdir);
123 # the minimum version we believe to be compatible with this package without
125 our $min_compat = 12;
127 # list of file reservations made by get_free_port
128 my @port_reservation_files;
133 # Set PGHOST for backward compatibility. This doesn't work for own_host
134 # nodes, so prefer to not rely on this when writing new tests.
135 $use_tcp = !$PostgreSQL::Test::Utils::use_unix_sockets;
136 $test_localhost = "127.0.0.1";
137 $last_host_assigned = 1;
140 $test_pghost = $test_localhost;
144 # On windows, replace windows-style \ path separators with / when
145 # putting socket directories either in postgresql.conf or libpq
146 # connection strings, otherwise they are interpreted as escapes.
147 $test_pghost = PostgreSQL::Test::Utils::tempdir_short;
148 $test_pghost =~ s!\\!/!g if $PostgreSQL::Test::Utils::windows_os;
150 $ENV{PGHOST} = $test_pghost;
151 $ENV{PGDATABASE} = 'postgres';
153 # Tracking of last port value assigned to accelerate free port lookup.
154 $last_port_assigned = int(rand() * 16384) + 49152;
156 # Set the port lock directory
158 # If we're told to use a directory (e.g. from a buildfarm client)
159 # explicitly, use that
160 $portdir = $ENV{PG_TEST_PORT_DIR};
161 # Otherwise, try to use a directory at the top of the build tree
162 # or as a last resort use the tmp_check directory
164 $ENV{MESON_BUILD_ROOT}
165 || $ENV{top_builddir}
166 || $PostgreSQL::Test::Utils::tmp_check;
167 $portdir ||= "$build_dir/portlock";
168 $portdir =~ s!\\!/!g;
169 # Make sure the directory exists
170 mkpath($portdir) unless -d $portdir;
181 Get the port number assigned to the host. This won't necessarily be a TCP port
182 open on the local host since we prefer to use unix sockets if possible.
184 Use $node->connstr() if you want a connection string.
191 return $self->{_port};
198 Return the host (like PGHOST) for this instance. May be a UNIX socket path.
200 Use $node->connstr() if you want a connection string.
207 return $self->{_host};
212 =item $node->basedir()
214 The directory all the node's files will be within - datadir, archive directory,
222 return $self->{_basedir};
229 The name assigned to the node at creation time.
236 return $self->{_name};
241 =item $node->logfile()
243 Path to the PostgreSQL log file for this instance.
250 return $self->{_logfile};
255 =item $node->connstr()
257 Get a libpq connection string that will establish a connection to
258 this node. Suitable for passing to psql, DBD::Pg, etc.
264 my ($self, $dbname) = @_;
265 my $pgport = $self->port;
266 my $pghost = $self->host;
267 if (!defined($dbname))
269 return "port=$pgport host=$pghost";
272 # Escape properly the database string before using it, only
273 # single quotes and backslashes need to be treated this way.
274 $dbname =~ s#\\#\\\\#g;
275 $dbname =~ s#\'#\\\'#g;
277 return "port=$pgport host=$pghost dbname='$dbname'";
282 =item $node->group_access()
284 Does the data dir allow group access?
292 my $dir_stat = stat($self->data_dir);
295 or die('unable to stat ' . $self->data_dir);
297 return (S_IMODE($dir_stat->mode) == 0750);
302 =item $node->data_dir()
304 Returns the path to the data directory. postgresql.conf and pg_hba.conf are
312 my $res = $self->basedir;
313 return "$res/pgdata";
318 =item $node->archive_dir()
320 If archiving is enabled, WAL files go here.
327 my $basedir = $self->basedir;
328 return "$basedir/archives";
333 =item $node->backup_dir()
335 The output path for backups taken with $node->backup()
342 my $basedir = $self->basedir;
343 return "$basedir/backup";
348 =item $node->install_path()
350 The configured install path (if any) for the node.
357 return $self->{_install_path};
362 =item $node->pg_version()
364 The version number for the node, from PostgreSQL::Version.
371 return $self->{_pg_version};
376 =item $node->config_data( option ...)
378 Return configuration data from pg_config, using options (if supplied).
379 The options will be things like '--sharedir'.
381 If no options are supplied, return a string in scalar context or a map in
384 If options are supplied, return the list of values.
390 my ($self, @options) = @_;
391 local %ENV = $self->_get_env();
393 my ($stdout, $stderr);
395 IPC::Run::run [ $self->installed_command('pg_config'), @options ],
396 '>', \$stdout, '2>', \$stderr
397 or die "could not execute pg_config";
398 # standardize line endings
399 $stdout =~ s/\r(?=\n)//g;
400 # no options, scalar context: just hand back the output
401 return $stdout unless (wantarray || @options);
403 # exactly one option: hand back the output (minus LF)
404 return $stdout if (@options == 1);
405 my @lines = split(/\n/, $stdout);
406 # more than one option: hand back the list of values;
407 return @lines if (@options);
408 # no options, array context: return a map
410 foreach my $line (@lines)
412 my ($k, $v) = split(/ = /, $line, 2);
422 Return a string containing human-readable diagnostic information (paths, etc)
431 open my $fh, '>', \$_info or die;
432 print $fh "Name: " . $self->name . "\n";
433 print $fh "Version: " . $self->{_pg_version} . "\n"
434 if $self->{_pg_version};
435 print $fh "Data directory: " . $self->data_dir . "\n";
436 print $fh "Backup directory: " . $self->backup_dir . "\n";
437 print $fh "Archive directory: " . $self->archive_dir . "\n";
438 print $fh "Connection string: " . $self->connstr . "\n";
439 print $fh "Log file: " . $self->logfile . "\n";
440 print $fh "Install Path: ", $self->{_install_path} . "\n"
441 if $self->{_install_path};
448 =item $node->dump_info()
462 # Internal method to set up trusted pg_hba.conf for replication. Not
463 # documented because you shouldn't use it, it's called automatically if needed.
464 sub set_replication_conf
467 my $pgdata = $self->data_dir;
469 $self->host eq $test_pghost
470 or croak "set_replication_conf only works with the default host";
472 open my $hba, '>>', "$pgdata/pg_hba.conf";
474 "\n# Allow replication (set up by PostgreSQL::Test::Cluster.pm)\n";
475 if ($PostgreSQL::Test::Utils::windows_os
476 && !$PostgreSQL::Test::Utils::use_unix_sockets)
479 "host replication all $test_localhost/32 sspi include_realm=1 map=regress\n";
487 =item $node->init(...)
489 Initialize a new cluster for testing.
491 Authentication is set up so that only the current OS user can access the
492 cluster. On Unix, we use Unix domain socket connections, with the socket in
493 a directory that's only accessible to the current user to ensure that.
494 On Windows, we use SSPI authentication to ensure the same (by pg_regress
497 WAL archiving can be enabled on this node by passing the keyword parameter
498 has_archiving => 1. This is disabled by default.
500 postgresql.conf can be set up for replication by passing the keyword
501 parameter allows_streaming => 'logical' or 'physical' (passing 1 will also
502 suffice for physical replication) depending on type of replication that
503 should be enabled. This is disabled by default.
505 The new node is set up in a fast but unsafe configuration where fsync is
512 my ($self, %params) = @_;
513 my $port = $self->port;
514 my $pgdata = $self->data_dir;
515 my $host = $self->host;
517 local %ENV = $self->_get_env();
519 $params{allows_streaming} = 0 unless defined $params{allows_streaming};
520 $params{has_archiving} = 0 unless defined $params{has_archiving};
522 mkdir $self->backup_dir;
523 mkdir $self->archive_dir;
525 # If available and if there aren't any parameters, use a previously
526 # initdb'd cluster as a template by copying it. For a lot of tests, that's
527 # substantially cheaper. Do so only if there aren't parameters, it doesn't
528 # seem worth figuring out whether they affect compatibility.
530 # There's very similar code in pg_regress.c, but we can't easily
531 # deduplicate it until we require perl at build time.
532 if (defined $params{extra} or !defined $ENV{INITDB_TEMPLATE})
534 note("initializing database system by running initdb");
535 PostgreSQL::Test::Utils::system_or_bail('initdb', '-D', $pgdata, '-A',
536 'trust', '-N', @{ $params{extra} });
541 my $expected_exitcode;
543 note("initializing database system by copying initdb template");
545 if ($PostgreSQL::Test::Utils::windows_os)
547 @copycmd = qw(robocopy /E /NJS /NJH /NFL /NDL /NP);
548 $expected_exitcode = 1; # 1 denotes files were copied
552 @copycmd = qw(cp -RPp);
553 $expected_exitcode = 0;
556 @copycmd = (@copycmd, $ENV{INITDB_TEMPLATE}, $pgdata);
558 my $ret = PostgreSQL::Test::Utils::system_log(@copycmd);
560 # See http://perldoc.perl.org/perlvar.html#%24CHILD_ERROR
561 if ($ret & 127 or $ret >> 8 != $expected_exitcode)
564 sprintf("failed to execute command \"%s\": $ret",
565 join(" ", @copycmd)));
569 PostgreSQL::Test::Utils::system_or_bail($ENV{PG_REGRESS},
570 '--config-auth', $pgdata, @{ $params{auth_extra} });
572 open my $conf, '>>', "$pgdata/postgresql.conf";
573 print $conf "\n# Added by PostgreSQL::Test::Cluster.pm\n";
574 print $conf "fsync = off\n";
575 print $conf "restart_after_crash = off\n";
576 print $conf "log_line_prefix = '%m [%p] %q%a '\n";
577 print $conf "log_statement = all\n";
578 print $conf "log_replication_commands = on\n";
579 print $conf "wal_retrieve_retry_interval = '500ms'\n";
581 # If a setting tends to affect whether tests pass or fail, print it after
582 # TEMP_CONFIG. Otherwise, print it before TEMP_CONFIG, thereby permitting
583 # overrides. Settings that merely improve performance or ease debugging
584 # belong before TEMP_CONFIG.
585 print $conf PostgreSQL::Test::Utils::slurp_file($ENV{TEMP_CONFIG})
586 if defined $ENV{TEMP_CONFIG};
588 if ($params{allows_streaming})
590 if ($params{allows_streaming} eq "logical")
592 print $conf "wal_level = logical\n";
596 print $conf "wal_level = replica\n";
598 print $conf "max_wal_senders = 10\n";
599 print $conf "max_replication_slots = 10\n";
600 print $conf "wal_log_hints = on\n";
601 print $conf "hot_standby = on\n";
602 # conservative settings to ensure we can run multiple postmasters:
603 print $conf "shared_buffers = 1MB\n";
604 print $conf "max_connections = 10\n";
605 # limit disk space consumption, too:
606 print $conf "max_wal_size = 128MB\n";
610 print $conf "wal_level = minimal\n";
611 print $conf "max_wal_senders = 0\n";
614 print $conf "port = $port\n";
617 print $conf "unix_socket_directories = ''\n";
618 print $conf "listen_addresses = '$host'\n";
622 print $conf "unix_socket_directories = '$host'\n";
623 print $conf "listen_addresses = ''\n";
627 chmod($self->group_access ? 0640 : 0600, "$pgdata/postgresql.conf")
628 or die("unable to set permissions for $pgdata/postgresql.conf");
630 $self->set_replication_conf if $params{allows_streaming};
631 $self->enable_archiving if $params{has_archiving};
637 =item $node->append_conf(filename, str)
639 A shortcut method to append to files like pg_hba.conf and postgresql.conf.
641 Does no validation or sanity checking. Does not reload the configuration
644 A newline is automatically appended to the string.
650 my ($self, $filename, $str) = @_;
652 my $conffile = $self->data_dir . '/' . $filename;
654 PostgreSQL::Test::Utils::append_to_file($conffile, $str . "\n");
656 chmod($self->group_access() ? 0640 : 0600, $conffile)
657 or die("unable to set permissions for $conffile");
664 =item $node->adjust_conf(filename, setting, value, skip_equals)
666 Modify the named config file setting with the value. If the value is undefined,
667 instead delete the setting. If the setting is not present no action is taken.
669 This will write "$setting = $value\n" in place of the existing line,
670 unless skip_equals is true, in which case it will write
671 "$setting $value\n". If the value needs to be quoted it is the caller's
672 responsibility to do that.
678 my ($self, $filename, $setting, $value, $skip_equals) = @_;
680 my $conffile = $self->data_dir . '/' . $filename;
682 my $contents = PostgreSQL::Test::Utils::slurp_file($conffile);
683 my @lines = split(/\n/, $contents);
685 my $eq = $skip_equals ? '' : '= ';
686 foreach my $line (@lines)
688 if ($line !~ /^$setting\W/)
690 push(@result, "$line\n");
692 elsif (defined $value)
694 push(@result, "$setting $eq$value\n");
697 open my $fh, ">", $conffile
698 or croak "could not write \"$conffile\": $!";
702 chmod($self->group_access() ? 0640 : 0600, $conffile)
703 or die("unable to set permissions for $conffile");
708 =item $node->backup(backup_name)
710 Create a hot backup with B<pg_basebackup> in subdirectory B<backup_name> of
711 B<< $node->backup_dir >>, including the WAL.
713 By default, WAL files are fetched at the end of the backup, not streamed.
714 You can adjust that and other things by passing an array of additional
715 B<pg_basebackup> command line options in the keyword parameter backup_options.
717 You'll have to configure a suitable B<max_wal_senders> on the
718 target server since it isn't done by default.
724 my ($self, $backup_name, %params) = @_;
725 my $backup_path = $self->backup_dir . '/' . $backup_name;
726 my $name = $self->name;
728 local %ENV = $self->_get_env();
730 print "# Taking pg_basebackup $backup_name from node \"$name\"\n";
731 PostgreSQL::Test::Utils::system_or_bail(
732 'pg_basebackup', '-D',
735 $self->port, '--checkpoint',
737 @{ $params{backup_options} });
738 print "# Backup finished\n";
742 =item $node->backup_fs_cold(backup_name)
744 Create a backup with a filesystem level copy in subdirectory B<backup_name> of
745 B<< $node->backup_dir >>, including WAL. The server must be
746 stopped as no attempt to handle concurrent writes is made.
748 Use B<backup> or B<backup_fs_hot> if you want to back up a running server.
754 my ($self, $backup_name) = @_;
756 PostgreSQL::Test::RecursiveCopy::copypath(
758 $self->backup_dir . '/' . $backup_name,
761 return ($src ne 'log' and $src ne 'postmaster.pid');
769 =item $node->init_from_backup(root_node, backup_name)
771 Initialize a node from a backup, which may come from this node or a different
772 node. root_node must be a PostgreSQL::Test::Cluster reference, backup_name the string name
773 of a backup previously created on that node with $node->backup.
775 Does not start the node after initializing it.
777 By default, the backup is assumed to be plain format. To restore from
778 a tar-format backup, pass the name of the tar program to use in the
779 keyword parameter tar_program. Note that tablespace tar files aren't
782 To restore from an incremental backup, pass the parameter combine_with_prior
783 as a reference to an array of prior backup names with which this backup
784 is to be combined using pg_combinebackup.
786 Streaming replication can be enabled on this node by passing the keyword
787 parameter has_streaming => 1. This is disabled by default.
789 Restoring WAL segments from archives using restore_command can be enabled
790 by passing the keyword parameter has_restoring => 1. This is disabled by
793 If has_restoring is used, standby mode is used by default. To use
794 recovery mode instead, pass the keyword parameter standby => 0.
796 The backup is copied, leaving the original unmodified. pg_hba.conf is
797 unconditionally set to enable replication connections.
803 my ($self, $root_node, $backup_name, %params) = @_;
804 my $backup_path = $root_node->backup_dir . '/' . $backup_name;
805 my $host = $self->host;
806 my $port = $self->port;
807 my $node_name = $self->name;
808 my $root_name = $root_node->name;
810 $params{has_streaming} = 0 unless defined $params{has_streaming};
811 $params{has_restoring} = 0 unless defined $params{has_restoring};
812 $params{standby} = 1 unless defined $params{standby};
815 "# Initializing node \"$node_name\" from backup \"$backup_name\" of node \"$root_name\"\n";
816 croak "Backup \"$backup_name\" does not exist at $backup_path"
817 unless -d $backup_path;
819 mkdir $self->backup_dir;
820 mkdir $self->archive_dir;
822 my $data_path = $self->data_dir;
823 if (defined $params{combine_with_prior})
825 my @prior_backups = @{$params{combine_with_prior}};
826 my @prior_backup_path;
828 for my $prior_backup_name (@prior_backups)
830 push @prior_backup_path,
831 $root_node->backup_dir . '/' . $prior_backup_name;
834 local %ENV = $self->_get_env();
835 PostgreSQL::Test::Utils::system_or_bail('pg_combinebackup', '-d',
836 @prior_backup_path, $backup_path, '-o', $data_path);
838 elsif (defined $params{tar_program})
841 PostgreSQL::Test::Utils::system_or_bail($params{tar_program}, 'xf',
842 $backup_path . '/base.tar',
844 PostgreSQL::Test::Utils::system_or_bail(
845 $params{tar_program}, 'xf',
846 $backup_path . '/pg_wal.tar', '-C',
847 $data_path . '/pg_wal');
852 PostgreSQL::Test::RecursiveCopy::copypath($backup_path, $data_path);
854 chmod(0700, $data_path);
856 # Base configuration for this node
864 $self->append_conf('postgresql.conf', "listen_addresses = '$host'");
868 $self->append_conf('postgresql.conf',
869 "unix_socket_directories = '$host'");
871 $self->enable_streaming($root_node) if $params{has_streaming};
872 $self->enable_restoring($root_node, $params{standby})
873 if $params{has_restoring};
879 =item $node->rotate_logfile()
881 Switch to a new PostgreSQL log file. This does not alter any running
882 PostgreSQL process. Subsequent method calls, including pg_ctl invocations,
883 will use the new name. Return the new name.
890 $self->{_logfile} = sprintf('%s_%d.log',
891 $self->{_logfile_base},
892 ++$self->{_logfile_generation});
893 return $self->{_logfile};
898 =item $node->start(%params) => success_or_failure
900 Wrapper for pg_ctl start
902 Start the node and wait until it is ready to accept connections.
908 By default, failure terminates the entire F<prove> invocation. If given,
909 instead return a true or false value to indicate success or failure.
917 my ($self, %params) = @_;
918 my $port = $self->port;
919 my $pgdata = $self->data_dir;
920 my $name = $self->name;
923 BAIL_OUT("node \"$name\" is already running") if defined $self->{_pid};
925 print("### Starting node \"$name\"\n");
927 # Temporarily unset PGAPPNAME so that the server doesn't
928 # inherit it. Otherwise this could affect libpqwalreceiver
929 # connections in confusing ways.
930 local %ENV = $self->_get_env(PGAPPNAME => undef);
932 # Note: We set the cluster_name here, not in postgresql.conf (in
933 # sub init) so that it does not get copied to standbys.
934 # -w is now the default but having it here does no harm and helps
935 # compatibility with older versions.
936 $ret = PostgreSQL::Test::Utils::system_log(
937 'pg_ctl', '-w', '-D', $self->data_dir,
938 '-l', $self->logfile, '-o', "--cluster-name=$name",
943 print "# pg_ctl start failed; logfile:\n";
944 print PostgreSQL::Test::Utils::slurp_file($self->logfile);
946 # pg_ctl could have timed out, so check to see if there's a pid file;
947 # otherwise our END block will fail to shut down the new postmaster.
948 $self->_update_pid(-1);
950 BAIL_OUT("pg_ctl start failed") unless $params{fail_ok};
954 $self->_update_pid(1);
962 Send SIGKILL (signal 9) to the postmaster.
964 Note: if the node is already known stopped, this does nothing.
965 However, if we think it's running and it's not, it's important for
966 this to fail. Otherwise, tests might fail to detect server crashes.
973 my $name = $self->name;
974 return unless defined $self->{_pid};
976 local %ENV = $self->_get_env();
978 print "### Killing node \"$name\" using signal 9\n";
979 kill(9, $self->{_pid});
980 $self->{_pid} = undef;
986 =item $node->stop(mode)
988 Stop the node using pg_ctl -m $mode and wait for it to stop.
990 Note: if the node is already known stopped, this does nothing.
991 However, if we think it's running and it's not, it's important for
992 this to fail. Otherwise, tests might fail to detect server crashes.
994 With optional extra param fail_ok => 1, returns 0 for failure
995 instead of bailing out.
1001 my ($self, $mode, %params) = @_;
1002 my $pgdata = $self->data_dir;
1003 my $name = $self->name;
1006 local %ENV = $self->_get_env();
1008 $mode = 'fast' unless defined $mode;
1009 return 1 unless defined $self->{_pid};
1011 print "### Stopping node \"$name\" using mode $mode\n";
1012 $ret = PostgreSQL::Test::Utils::system_log('pg_ctl', '-D', $pgdata,
1013 '-m', $mode, 'stop');
1017 print "# pg_ctl stop failed: $ret\n";
1019 # Check to see if we still have a postmaster or not.
1020 $self->_update_pid(-1);
1022 BAIL_OUT("pg_ctl stop failed") unless $params{fail_ok};
1026 $self->_update_pid(0);
1032 =item $node->reload()
1034 Reload configuration parameters on the node.
1041 my $port = $self->port;
1042 my $pgdata = $self->data_dir;
1043 my $name = $self->name;
1045 local %ENV = $self->_get_env();
1047 print "### Reloading node \"$name\"\n";
1048 PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata,
1055 =item $node->restart()
1057 Wrapper for pg_ctl restart.
1059 With optional extra param fail_ok => 1, returns 0 for failure
1060 instead of bailing out.
1066 my ($self, %params) = @_;
1067 my $name = $self->name;
1070 local %ENV = $self->_get_env(PGAPPNAME => undef);
1072 print "### Restarting node \"$name\"\n";
1074 # -w is now the default but having it here does no harm and helps
1075 # compatibility with older versions.
1076 $ret = PostgreSQL::Test::Utils::system_log(
1077 'pg_ctl', '-w', '-D', $self->data_dir,
1078 '-l', $self->logfile, 'restart');
1082 print "# pg_ctl restart failed; logfile:\n";
1083 print PostgreSQL::Test::Utils::slurp_file($self->logfile);
1085 # pg_ctl could have timed out, so check to see if there's a pid file;
1086 # otherwise our END block will fail to shut down the new postmaster.
1087 $self->_update_pid(-1);
1089 BAIL_OUT("pg_ctl restart failed") unless $params{fail_ok};
1093 $self->_update_pid(1);
1099 =item $node->promote()
1101 Wrapper for pg_ctl promote
1108 my $port = $self->port;
1109 my $pgdata = $self->data_dir;
1110 my $logfile = $self->logfile;
1111 my $name = $self->name;
1113 local %ENV = $self->_get_env();
1115 print "### Promoting node \"$name\"\n";
1116 PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata, '-l',
1117 $logfile, 'promote');
1123 =item $node->logrotate()
1125 Wrapper for pg_ctl logrotate
1132 my $port = $self->port;
1133 my $pgdata = $self->data_dir;
1134 my $logfile = $self->logfile;
1135 my $name = $self->name;
1137 local %ENV = $self->_get_env();
1139 print "### Rotating log in node \"$name\"\n";
1140 PostgreSQL::Test::Utils::system_or_bail('pg_ctl', '-D', $pgdata, '-l',
1141 $logfile, 'logrotate');
1145 # Internal routine to enable streaming replication on a standby node.
1146 sub enable_streaming
1148 my ($self, $root_node) = @_;
1149 my $root_connstr = $root_node->connstr;
1150 my $name = $self->name;
1152 print "### Enabling streaming replication for node \"$name\"\n";
1154 $self->_recovery_file, qq(
1155 primary_conninfo='$root_connstr'
1157 $self->set_standby_mode();
1161 # Internal routine to enable archive recovery command on a standby node
1162 sub enable_restoring
1164 my ($self, $root_node, $standby) = @_;
1165 my $path = $root_node->archive_dir;
1166 my $name = $self->name;
1168 print "### Enabling WAL restore for node \"$name\"\n";
1170 # On Windows, the path specified in the restore command needs to use
1171 # double back-slashes to work properly and to be able to detect properly
1172 # the file targeted by the copy command, so the directory value used
1173 # in this routine, using only one back-slash, need to be properly changed
1174 # first. Paths also need to be double-quoted to prevent failures where
1175 # the path contains spaces.
1176 $path =~ s{\\}{\\\\}g if ($PostgreSQL::Test::Utils::windows_os);
1178 $PostgreSQL::Test::Utils::windows_os
1179 ? qq{copy "$path\\\\%f" "%p"}
1180 : qq{cp "$path/%f" "%p"};
1183 $self->_recovery_file, qq(
1184 restore_command = '$copy_command'
1188 $self->set_standby_mode();
1192 $self->set_recovery_mode();
1197 sub _recovery_file { return "postgresql.conf"; }
1201 =item $node->set_recovery_mode()
1203 Place recovery.signal file.
1207 sub set_recovery_mode
1211 $self->append_conf('recovery.signal', '');
1217 =item $node->set_standby_mode()
1219 Place standby.signal file.
1223 sub set_standby_mode
1227 $self->append_conf('standby.signal', '');
1231 # Internal routine to enable archiving
1232 sub enable_archiving
1235 my $path = $self->archive_dir;
1236 my $name = $self->name;
1238 print "### Enabling WAL archiving for node \"$name\"\n";
1240 # On Windows, the path specified in the restore command needs to use
1241 # double back-slashes to work properly and to be able to detect properly
1242 # the file targeted by the copy command, so the directory value used
1243 # in this routine, using only one back-slash, need to be properly changed
1244 # first. Paths also need to be double-quoted to prevent failures where
1245 # the path contains spaces.
1246 $path =~ s{\\}{\\\\}g if ($PostgreSQL::Test::Utils::windows_os);
1248 $PostgreSQL::Test::Utils::windows_os
1249 ? qq{copy "%p" "$path\\\\%f"}
1250 : qq{cp "%p" "$path/%f"};
1252 # Enable archive_mode and archive_command on node
1254 'postgresql.conf', qq(
1256 archive_command = '$copy_command'
1261 # Internal method to update $self->{_pid}
1262 # $is_running = 1: pid file should be there
1263 # $is_running = 0: pid file should NOT be there
1264 # $is_running = -1: we aren't sure
1267 my ($self, $is_running) = @_;
1268 my $name = $self->name;
1270 # If we can open the PID file, read its first line and that's the PID we
1272 if (open my $pidfile, '<', $self->data_dir . "/postmaster.pid")
1274 chomp($self->{_pid} = <$pidfile>);
1277 # If we aren't sure what to expect, validate the PID using kill().
1278 # This protects against stale PID files left by crashed postmasters.
1279 if ($is_running == -1 && kill(0, $self->{_pid}) == 0)
1282 "# Stale postmaster.pid file for node \"$name\": PID $self->{_pid} no longer exists\n";
1283 $self->{_pid} = undef;
1287 print "# Postmaster PID for node \"$name\" is $self->{_pid}\n";
1289 # If we found a pidfile when there shouldn't be one, complain.
1290 BAIL_OUT("postmaster.pid unexpectedly present") if $is_running == 0;
1294 $self->{_pid} = undef;
1295 print "# No postmaster PID for node \"$name\"\n";
1297 # Complain if we expected to find a pidfile.
1298 BAIL_OUT("postmaster.pid unexpectedly not present") if $is_running == 1;
1304 =item PostgreSQL::Test::Cluster->new(node_name, %params)
1306 Build a new object of class C<PostgreSQL::Test::Cluster> (or of a subclass, if you have
1307 one), assigning a free port number. Remembers the node, to prevent its port
1308 number from being reused for another node, and to ensure that it gets
1309 shut down when the test script exits.
1313 =item port => [1,65535]
1315 By default, this function assigns a port number to each node. Specify this to
1316 force a particular port number. The caller is responsible for evaluating
1317 potential conflicts and privilege requirements.
1321 By default, all nodes use the same PGHOST value. If specified, generate a
1322 PGHOST specific to this node. This allows multiple nodes to use the same
1325 =item install_path => '/path/to/postgres/installation'
1327 Using this parameter is it possible to have nodes pointing to different
1328 installations, for testing different versions together or the same version
1329 with different build parameters. The provided path must be the parent of the
1330 installation's 'bin' and 'lib' directories. In the common case where this is
1331 not provided, Postgres binaries will be found in the caller's PATH.
1340 my ($name, %params) = @_;
1344 if (defined $params{port})
1346 $port = $params{port};
1350 # When selecting a port, we look for an unassigned TCP port number,
1351 # even if we intend to use only Unix-domain sockets. This is clearly
1352 # necessary on $use_tcp (Windows) configurations, and it seems like a
1353 # good idea on Unixen as well.
1354 $port = get_free_port();
1358 my $host = $test_pghost;
1359 if ($params{own_host})
1363 $last_host_assigned++;
1364 $last_host_assigned > 254 and BAIL_OUT("too many own_host nodes");
1365 $host = '127.0.0.' . $last_host_assigned;
1369 $host = "$test_pghost/$name"; # Assume $name =~ /^[-_a-zA-Z0-9]+$/
1374 my $testname = basename($0);
1375 $testname =~ s/\.[^.]+$//;
1380 "$PostgreSQL::Test::Utils::tmp_check/t_${testname}_${name}_data",
1382 _logfile_generation => 0,
1384 "$PostgreSQL::Test::Utils::log_path/${testname}_${name}",
1386 "$PostgreSQL::Test::Utils::log_path/${testname}_${name}.log"
1389 if ($params{install_path})
1391 $node->{_install_path} = $params{install_path};
1394 bless $node, $class;
1395 mkdir $node->{_basedir}
1397 BAIL_OUT("could not create data directory \"$node->{_basedir}\": $!");
1401 $node->_set_pg_version;
1403 my $ver = $node->{_pg_version};
1405 # Use a subclass as defined below (or elsewhere) if this version
1406 # isn't fully compatible. Warn if the version is too old and thus we don't
1407 # have a subclass of this class.
1408 if (ref $ver && $ver < $min_compat)
1410 my $maj = $ver->major(separator => '_');
1411 my $subclass = $class . "::V_$maj";
1412 if ($subclass->isa($class))
1414 bless $node, $subclass;
1419 "PostgreSQL::Test::Cluster isn't fully compatible with version $ver";
1423 # Add node to list of nodes
1424 push(@all_nodes, $node);
1429 # Private routine to run the pg_config binary found in our environment (or in
1430 # our install_path, if we have one), and set the version from it
1435 my $inst = $self->{_install_path};
1436 my $pg_config = "pg_config";
1440 # If the _install_path is invalid, our PATH variables might find an
1441 # unrelated pg_config executable elsewhere. Sanity check the
1443 BAIL_OUT("directory not found: $inst")
1446 # If the directory exists but is not the root of a postgresql
1447 # installation, or if the user configured using
1448 # --bindir=$SOMEWHERE_ELSE, we're not going to find pg_config, so
1449 # complain about that, too.
1450 $pg_config = "$inst/bin/pg_config";
1451 BAIL_OUT("pg_config not found: $pg_config")
1452 unless -e $pg_config
1453 or ($PostgreSQL::Test::Utils::windows_os and -e "$pg_config.exe");
1454 BAIL_OUT("pg_config not executable: $pg_config")
1455 unless $PostgreSQL::Test::Utils::windows_os or -x $pg_config;
1457 # Leave $pg_config install_path qualified, to be sure we get the right
1458 # version information, below, or die trying
1461 local %ENV = $self->_get_env();
1463 # We only want the version field
1464 my $version_line = qx{$pg_config --version};
1465 BAIL_OUT("$pg_config failed: $!") if $?;
1467 $self->{_pg_version} = PostgreSQL::Version->new($version_line);
1469 BAIL_OUT("could not parse pg_config --version output: $version_line")
1470 unless defined $self->{_pg_version};
1473 # Private routine to return a copy of the environment with the PATH and
1474 # (DY)LD_LIBRARY_PATH correctly set when there is an install path set for
1477 # Routines that call Postgres binaries need to call this routine like this:
1479 # local %ENV = $self->_get_env([%extra_settings]);
1481 # A copy of the environment is taken and node's host and port settings are
1482 # added as PGHOST and PGPORT, then the extra settings (if any) are applied.
1483 # Any setting in %extra_settings with a value that is undefined is deleted;
1484 # the remainder are set. Then the PATH and (DY)LD_LIBRARY_PATH are adjusted
1485 # if the node's install path is set, and the copy environment is returned.
1487 # The install path set in new() needs to be a directory containing
1488 # bin and lib subdirectories as in a standard PostgreSQL installation, so this
1489 # can't be used with installations where the bin and lib directories don't have
1490 # a common parent directory.
1494 my %inst_env = (%ENV, PGHOST => $self->{_host}, PGPORT => $self->{_port});
1495 # the remaining arguments are modifications to make to the environment
1497 while (my ($k, $v) = each %mods)
1501 $inst_env{$k} = "$v";
1505 delete $inst_env{$k};
1508 # now fix up the new environment for the install path
1509 my $inst = $self->{_install_path};
1512 if ($PostgreSQL::Test::Utils::windows_os)
1514 # Windows picks up DLLs from the PATH rather than *LD_LIBRARY_PATH
1515 # choose the right path separator
1516 if ($Config{osname} eq 'MSWin32')
1518 $inst_env{PATH} = "$inst/bin;$inst/lib;$ENV{PATH}";
1522 $inst_env{PATH} = "$inst/bin:$inst/lib:$ENV{PATH}";
1528 $Config{osname} eq 'darwin'
1529 ? "DYLD_LIBRARY_PATH"
1530 : "LD_LIBRARY_PATH";
1531 $inst_env{PATH} = "$inst/bin:$ENV{PATH}";
1532 if (exists $ENV{$dylib_name})
1534 $inst_env{$dylib_name} = "$inst/lib:$ENV{$dylib_name}";
1538 $inst_env{$dylib_name} = "$inst/lib";
1545 # Private routine to get an installation path qualified command.
1547 # IPC::Run maintains a cache, %cmd_cache, mapping commands to paths. Tests
1548 # which use nodes spanning more than one postgres installation path need to
1549 # avoid confusing which installation's binaries get run. Setting $ENV{PATH} is
1550 # insufficient, as IPC::Run does not check to see if the path has changed since
1551 # caching a command.
1552 sub installed_command
1554 my ($self, $cmd) = @_;
1556 # Nodes using alternate installation locations use their installation's
1557 # bin/ directory explicitly
1558 return join('/', $self->{_install_path}, 'bin', $cmd)
1559 if defined $self->{_install_path};
1561 # Nodes implicitly using the default installation location rely on IPC::Run
1562 # to find the right binary, which should not cause %cmd_cache confusion,
1563 # because no nodes with other installation paths do it that way.
1569 =item get_free_port()
1571 Locate an unprivileged (high) TCP port that's not currently bound to
1572 anything. This is used by C<new()>, and also by some test cases that need to
1573 start other, non-Postgres servers.
1575 Ports assigned to existing PostgreSQL::Test::Cluster objects are automatically
1576 excluded, even if those servers are not currently running.
1578 The port number is reserved so that other concurrent test programs will not
1579 try to use the same port.
1581 Note: this is not an instance method. As it's not exported it should be
1582 called from outside the module as C<PostgreSQL::Test::Cluster::get_free_port()>.
1589 my $port = $last_port_assigned;
1594 # advance $port, wrapping correctly around range end
1595 $port = 49152 if ++$port >= 65536;
1596 print "# Checking port $port\n";
1598 # Check first that candidate port number is not included in
1599 # the list of already-registered nodes.
1601 foreach my $node (@all_nodes)
1603 $found = 0 if ($node->port == $port);
1606 # Check to see if anything else is listening on this TCP port.
1607 # Seek a port available for all possible listen_addresses values,
1608 # so callers can harness this port for the widest range of purposes.
1609 # The 0.0.0.0 test achieves that for MSYS, which automatically sets
1610 # SO_EXCLUSIVEADDRUSE. Testing 0.0.0.0 is insufficient for Windows
1611 # native Perl (https://stackoverflow.com/a/14388707), so we also
1612 # have to test individual addresses. Doing that for 127.0.0/24
1613 # addresses other than 127.0.0.1 might fail with EADDRNOTAVAIL on
1614 # non-Linux, non-Windows kernels.
1616 # Thus, 0.0.0.0 and individual 127.0.0/24 addresses are tested
1617 # only on Windows and only when TCP usage is requested.
1620 foreach my $addr (qw(127.0.0.1),
1621 ($use_tcp && $PostgreSQL::Test::Utils::windows_os)
1622 ? qw(127.0.0.2 127.0.0.3 0.0.0.0)
1625 if (!can_bind($addr, $port))
1631 $found = _reserve_port($port) if $found;
1635 print "# Found port $port\n";
1637 # Update port for next time
1638 $last_port_assigned = $port;
1643 # Internal routine to check whether a host:port is available to bind
1646 my ($host, $port) = @_;
1647 my $iaddr = inet_aton($host);
1648 my $paddr = sockaddr_in($port, $iaddr);
1650 socket(SOCK, PF_INET, SOCK_STREAM, 0)
1651 or die "socket failed: $!";
1653 # As in postmaster, don't use SO_REUSEADDR on Windows
1654 setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
1655 unless $PostgreSQL::Test::Utils::windows_os;
1656 my $ret = bind(SOCK, $paddr) && listen(SOCK, SOMAXCONN);
1661 # Internal routine to reserve a port number
1662 # Returns 1 if successful, 0 if port is already reserved.
1666 # open in rw mode so we don't have to reopen it and lose the lock
1667 my $filename = "$portdir/$port.rsv";
1668 sysopen(my $portfile, $filename, O_RDWR | O_CREAT)
1669 || die "opening port file $filename: $!";
1670 # take an exclusive lock to avoid concurrent access
1671 flock($portfile, LOCK_EX) || die "locking port file $filename: $!";
1672 # see if someone else has or had a reservation of this port
1673 my $pid = <$portfile> || "0";
1679 # process exists and is owned by us, so we can't reserve this port
1680 flock($portfile, LOCK_UN);
1685 # All good, go ahead and reserve the port
1686 seek($portfile, 0, SEEK_SET);
1687 # print the pid with a fixed width so we don't leave any trailing junk
1688 print $portfile sprintf("%10d\n", $$);
1689 flock($portfile, LOCK_UN);
1691 push(@port_reservation_files, $filename);
1695 # Automatically shut down any still-running nodes (in the same order the nodes
1696 # were created in) when the test script exits.
1700 # take care not to change the script's exit value
1703 foreach my $node (@all_nodes)
1705 # During unclean termination (which could be a signal or some
1706 # other failure), we're not sure that the status of our nodes
1707 # has been correctly set up already, so try and update it to
1708 # improve our chances of shutting them down.
1709 $node->_update_pid(-1) if $exit_code != 0;
1711 # If that fails, don't let that foil other nodes' shutdown
1712 $node->teardown_node(fail_ok => 1);
1714 # skip clean if we are requested to retain the basedir
1715 next if defined $ENV{'PG_TEST_NOCLEAN'};
1717 # clean basedir on clean test invocation
1719 if $exit_code == 0 && PostgreSQL::Test::Utils::all_tests_passing();
1722 unlink @port_reservation_files;
1729 =item $node->teardown_node()
1731 Do an immediate stop of the node
1733 Any optional extra parameter is passed to ->stop.
1739 my ($self, %params) = @_;
1741 $self->stop('immediate', %params);
1747 =item $node->clean_node()
1749 Remove the base directory of the node if the node has been stopped.
1757 rmtree $self->{_basedir} unless defined $self->{_pid};
1763 =item $node->safe_psql($dbname, $sql) => stdout
1765 Invoke B<psql> to run B<sql> on B<dbname> and return its stdout on success.
1766 Die if the SQL produces an error. Runs with B<ON_ERROR_STOP> set.
1768 Takes optional extra params like timeout and timed_out parameters with the same
1775 my ($self, $dbname, $sql, %params) = @_;
1777 local %ENV = $self->_get_env();
1779 my ($stdout, $stderr);
1781 my $ret = $self->psql(
1787 on_error_stop => 1);
1789 # psql can emit stderr from NOTICEs etc
1792 print "#### Begin standard error\n";
1794 print "\n#### End standard error\n";
1802 =item $node->psql($dbname, $sql, %params) => psql_retval
1804 Invoke B<psql> to execute B<$sql> on B<$dbname> and return the return value
1805 from B<psql>, which is run with on_error_stop by default so that it will
1806 stop running sql and return 3 if the passed SQL results in an error.
1808 As a convenience, if B<psql> is called in array context it returns an
1809 array containing ($retval, $stdout, $stderr).
1811 psql is invoked in tuples-only unaligned mode with reading of B<.psqlrc>
1812 disabled. That may be overridden by passing extra psql parameters.
1814 stdout and stderr are transformed to UNIX line endings if on Windows. Any
1815 trailing newline is removed.
1817 Dies on failure to invoke psql but not if psql exits with a nonzero
1818 return code (unless on_error_die specified).
1820 If psql exits because of a signal, an exception is raised.
1824 =item stdout => \$stdout
1826 B<stdout>, if given, must be a scalar reference to which standard output is
1827 written. If not given, standard output is not redirected and will be printed
1828 unless B<psql> is called in array context, in which case it's captured and
1831 =item stderr => \$stderr
1833 Same as B<stdout> but gets standard error. If the same scalar is passed for
1834 both B<stdout> and B<stderr> the results may be interleaved unpredictably.
1836 =item on_error_stop => 1
1838 By default, the B<psql> method invokes the B<psql> program with ON_ERROR_STOP=1
1839 set, so SQL execution is stopped at the first error and exit code 3 is
1840 returned. Set B<on_error_stop> to 0 to ignore errors instead.
1842 =item on_error_die => 0
1844 By default, this method returns psql's result code. Pass on_error_die to
1845 instead die with an informative message.
1847 =item timeout => 'interval'
1849 Set a timeout for the psql call as an interval accepted by B<IPC::Run::timer>
1850 (integer seconds is fine). This method raises an exception on timeout, unless
1851 the B<timed_out> parameter is also given.
1853 =item timed_out => \$timed_out
1855 If B<timeout> is set and this parameter is given, the scalar it references
1856 is set to true if the psql call times out.
1858 =item connstr => B<value>
1860 If set, use this as the connection string for the connection to the
1863 =item replication => B<value>
1865 If set, add B<replication=value> to the conninfo string.
1866 Passing the literal value C<database> results in a logical replication
1869 =item extra_params => ['--single-transaction']
1871 If given, it must be an array reference containing additional parameters to B<psql>.
1877 my ($stdout, $stderr, $timed_out);
1878 my $cmdret = $node->psql('postgres', 'SELECT pg_sleep(600)',
1879 stdout => \$stdout, stderr => \$stderr,
1880 timeout => $PostgreSQL::Test::Utils::timeout_default,
1881 timed_out => \$timed_out,
1882 extra_params => ['--single-transaction'])
1884 will set $cmdret to undef and $timed_out to a true value.
1886 $node->psql('postgres', $sql, on_error_die => 1);
1888 dies with an informative message if $sql fails.
1894 my ($self, $dbname, $sql, %params) = @_;
1896 local %ENV = $self->_get_env();
1898 my $stdout = $params{stdout};
1899 my $stderr = $params{stderr};
1900 my $replication = $params{replication};
1901 my $timeout = undef;
1902 my $timeout_exception = 'psql timed out';
1904 # Build the connection string.
1906 if (defined $params{connstr})
1908 $psql_connstr = $params{connstr};
1912 $psql_connstr = $self->connstr($dbname);
1914 $psql_connstr .= defined $replication ? " replication=$replication" : "";
1917 $self->installed_command('psql'),
1918 '-XAtq', '-d', $psql_connstr, '-f', '-');
1920 # If the caller wants an array and hasn't passed stdout/stderr
1921 # references, allocate temporary ones to capture them so we
1922 # can return them. Otherwise we won't redirect them at all.
1925 if (!defined($stdout))
1927 my $temp_stdout = "";
1928 $stdout = \$temp_stdout;
1930 if (!defined($stderr))
1932 my $temp_stderr = "";
1933 $stderr = \$temp_stderr;
1937 $params{on_error_stop} = 1 unless defined $params{on_error_stop};
1938 $params{on_error_die} = 0 unless defined $params{on_error_die};
1940 push @psql_params, '-v', 'ON_ERROR_STOP=1' if $params{on_error_stop};
1941 push @psql_params, @{ $params{extra_params} }
1942 if defined $params{extra_params};
1945 IPC::Run::timeout($params{timeout}, exception => $timeout_exception)
1946 if (defined($params{timeout}));
1948 ${ $params{timed_out} } = 0 if defined $params{timed_out};
1950 # IPC::Run would otherwise append to existing contents:
1951 $$stdout = "" if ref($stdout);
1952 $$stderr = "" if ref($stderr);
1956 # Run psql and capture any possible exceptions. If the exception is
1957 # because of a timeout and the caller requested to handle that, just return
1958 # and set the flag. Otherwise, and for any other exception, rethrow.
1960 # For background, see
1961 # https://metacpan.org/release/ETHER/Try-Tiny-0.24/view/lib/Try/Tiny.pm
1966 my @ipcrun_opts = (\@psql_params, '<', \$sql);
1967 push @ipcrun_opts, '>', $stdout if defined $stdout;
1968 push @ipcrun_opts, '2>', $stderr if defined $stderr;
1969 push @ipcrun_opts, $timeout if defined $timeout;
1971 IPC::Run::run @ipcrun_opts;
1978 # IPC::Run::run threw an exception. re-throw unless it's a
1979 # timeout, which we'll handle by testing is_expired
1981 if (blessed($exc_save)
1982 || $exc_save !~ /^\Q$timeout_exception\E/);
1986 die "Got timeout exception '$exc_save' but timer not expired?!"
1987 unless $timeout->is_expired;
1989 if (defined($params{timed_out}))
1991 ${ $params{timed_out} } = 1;
1995 die "psql timed out: stderr: '$$stderr'\n"
1996 . "while running '@psql_params'";
2001 if (defined $$stdout)
2006 if (defined $$stderr)
2011 # See http://perldoc.perl.org/perlvar.html#%24CHILD_ERROR
2012 # We don't use IPC::Run::Simple to limit dependencies.
2014 # We always die on signal.
2015 my $core = $ret & 128 ? " (core dumped)" : "";
2016 die "psql exited with signal "
2018 . "$core: '$$stderr' while running '@psql_params'"
2022 if ($ret && $params{on_error_die})
2024 die "psql error: stderr: '$$stderr'\nwhile running '@psql_params'"
2026 die "connection error: '$$stderr'\nwhile running '@psql_params'"
2029 "error running SQL: '$$stderr'\nwhile running '@psql_params' with sql '$sql'"
2031 die "psql returns $ret: '$$stderr'\nwhile running '@psql_params'";
2036 return ($ret, $$stdout, $$stderr);
2046 =item $node->background_psql($dbname, %params) => PostgreSQL::Test::BackgroundPsql instance
2048 Invoke B<psql> on B<$dbname> and return a BackgroundPsql object.
2050 psql is invoked in tuples-only unaligned mode with reading of B<.psqlrc>
2051 disabled. That may be overridden by passing extra psql parameters.
2053 Dies on failure to invoke psql, or if psql fails to connect. Errors occurring
2054 later are the caller's problem. psql runs with on_error_stop by default so
2055 that it will stop running sql and return 3 if passed SQL results in an error.
2057 Be sure to "quit" the returned object when done with it.
2061 =item on_error_stop => 1
2063 By default, the B<psql> method invokes the B<psql> program with ON_ERROR_STOP=1
2064 set, so SQL execution is stopped at the first error and exit code 3 is
2065 returned. Set B<on_error_stop> to 0 to ignore errors instead.
2067 =item timeout => 'interval'
2069 Set a timeout for a background psql session. By default, timeout of
2070 $PostgreSQL::Test::Utils::timeout_default is set up.
2072 =item replication => B<value>
2074 If set, add B<replication=value> to the conninfo string.
2075 Passing the literal value C<database> results in a logical replication
2078 =item extra_params => ['--single-transaction']
2080 If given, it must be an array reference containing additional parameters to B<psql>.
2088 my ($self, $dbname, %params) = @_;
2090 local %ENV = $self->_get_env();
2092 my $replication = $params{replication};
2093 my $timeout = undef;
2096 $self->installed_command('psql'),
2099 $self->connstr($dbname)
2100 . (defined $replication ? " replication=$replication" : ""),
2104 $params{on_error_stop} = 1 unless defined $params{on_error_stop};
2105 $timeout = $params{timeout} if defined $params{timeout};
2107 push @psql_params, '-v', 'ON_ERROR_STOP=1' if $params{on_error_stop};
2108 push @psql_params, @{ $params{extra_params} }
2109 if defined $params{extra_params};
2111 return PostgreSQL::Test::BackgroundPsql->new(0, \@psql_params, $timeout);
2116 =item $node->interactive_psql($dbname, %params) => BackgroundPsql instance
2118 Invoke B<psql> on B<$dbname> and return a BackgroundPsql object, which the
2119 caller may use to send interactive input to B<psql>.
2121 A timeout of $PostgreSQL::Test::Utils::timeout_default is set up.
2123 psql is invoked in tuples-only unaligned mode with reading of B<.psqlrc>
2124 disabled. That may be overridden by passing extra psql parameters.
2126 Dies on failure to invoke psql, or if psql fails to connect.
2127 Errors occurring later are the caller's problem.
2129 Be sure to "quit" the returned object when done with it.
2133 =item extra_params => ['--single-transaction']
2135 If given, it must be an array reference containing additional parameters to B<psql>.
2137 =item history_file => B<path>
2139 Cause the interactive B<psql> session to write its command history to B<path>.
2140 If not given, the history is sent to B</dev/null>.
2144 This requires IO::Pty in addition to IPC::Run.
2148 sub interactive_psql
2150 my ($self, $dbname, %params) = @_;
2152 local %ENV = $self->_get_env();
2154 # Since the invoked psql will believe it's interactive, it will use
2155 # readline/libedit if available. We need to adjust some environment
2156 # settings to prevent unwanted side-effects.
2158 # Developers would not appreciate tests adding a bunch of junk to
2159 # their ~/.psql_history, so redirect readline history somewhere else.
2160 # If the calling script doesn't specify anything, just bit-bucket it.
2161 $ENV{PSQL_HISTORY} = $params{history_file} || '/dev/null';
2163 # Another pitfall for developers is that they might have a ~/.inputrc
2164 # file that changes readline's behavior enough to affect the test.
2165 # So ignore any such file.
2166 $ENV{INPUTRC} = '/dev/null';
2168 # Unset TERM so that readline/libedit won't use any terminal-dependent
2169 # escape sequences; that leads to way too many cross-version variations
2172 # Some versions of readline inspect LS_COLORS, so for luck unset that too.
2173 delete $ENV{LS_COLORS};
2176 $self->installed_command('psql'),
2177 '-XAt', '-d', $self->connstr($dbname));
2179 push @psql_params, @{ $params{extra_params} }
2180 if defined $params{extra_params};
2182 return PostgreSQL::Test::BackgroundPsql->new(1, \@psql_params);
2185 # Common sub of pgbench-invoking interfaces. Makes any requested script files
2186 # and returns pgbench command-line options causing use of those files.
2187 sub _pgbench_make_files
2189 my ($self, $files) = @_;
2195 # note: files are ordered for determinism
2196 for my $fn (sort keys %$files)
2198 my $filename = $self->basedir . '/' . $fn;
2199 push @file_opts, '-f', $filename;
2201 # cleanup file weight
2202 $filename =~ s/\@\d+$//;
2204 # filenames are expected to be unique on a test
2207 ok(0, "$filename must not already exist");
2208 unlink $filename or die "cannot unlink $filename: $!";
2210 PostgreSQL::Test::Utils::append_to_file($filename, $$files{$fn});
2219 =item $node->pgbench($opts, $stat, $out, $err, $name, $files, @args)
2221 Invoke B<pgbench>, with parameters and files.
2227 Options as a string to be split on spaces.
2231 Expected exit status.
2235 Reference to a regexp list that must match stdout.
2239 Reference to a regexp list that must match stderr.
2243 Name of test for error messages.
2247 Reference to filename/contents dictionary.
2251 Further raw options or arguments.
2259 local $Test::Builder::Level = $Test::Builder::Level + 1;
2261 my ($self, $opts, $stat, $out, $err, $name, $files, @args) = @_;
2264 split(/\s+/, $opts),
2265 $self->_pgbench_make_files($files), @args);
2267 $self->command_checks_all(\@cmd, $stat, $out, $err, $name);
2272 =item $node->connect_ok($connstr, $test_name, %params)
2274 Attempt a connection with a custom connection string. This is expected
2279 =item sql => B<value>
2281 If this parameter is set, this query is used for the connection attempt
2282 instead of the default.
2284 =item expected_stdout => B<value>
2286 If this regular expression is set, matches it with the output generated.
2288 =item log_like => [ qr/required message/ ]
2290 =item log_unlike => [ qr/prohibited message/ ]
2292 See C<log_check(...)>.
2300 local $Test::Builder::Level = $Test::Builder::Level + 1;
2301 my ($self, $connstr, $test_name, %params) = @_;
2304 if (defined($params{sql}))
2306 $sql = $params{sql};
2310 $sql = "SELECT \$\$connected with $connstr\$\$";
2313 my $log_location = -s $self->logfile;
2315 # Never prompt for a password, any callers of this routine should
2316 # have set up things properly, and this should not block.
2317 my ($ret, $stdout, $stderr) = $self->psql(
2320 extra_params => ['-w'],
2321 connstr => "$connstr",
2322 on_error_stop => 0);
2324 is($ret, 0, $test_name);
2326 if (defined($params{expected_stdout}))
2328 like($stdout, $params{expected_stdout}, "$test_name: stdout matches");
2331 is($stderr, "", "$test_name: no stderr");
2333 $self->log_check($test_name, $log_location, %params);
2338 =item $node->connect_fails($connstr, $test_name, %params)
2340 Attempt a connection with a custom connection string. This is expected
2345 =item expected_stderr => B<value>
2347 If this regular expression is set, matches it with the output generated.
2349 =item log_like => [ qr/required message/ ]
2351 =item log_unlike => [ qr/prohibited message/ ]
2353 See C<log_check(...)>.
2361 local $Test::Builder::Level = $Test::Builder::Level + 1;
2362 my ($self, $connstr, $test_name, %params) = @_;
2364 my $log_location = -s $self->logfile;
2366 # Never prompt for a password, any callers of this routine should
2367 # have set up things properly, and this should not block.
2368 my ($ret, $stdout, $stderr) = $self->psql(
2371 extra_params => ['-w'],
2372 connstr => "$connstr");
2374 isnt($ret, 0, $test_name);
2376 if (defined($params{expected_stderr}))
2378 like($stderr, $params{expected_stderr}, "$test_name: matches");
2381 $self->log_check($test_name, $log_location, %params);
2386 =item $node->poll_query_until($dbname, $query [, $expected ])
2388 Run B<$query> repeatedly, until it returns the B<$expected> result
2389 ('t', or SQL boolean true, by default).
2390 Continues polling if B<psql> returns an error result.
2391 Times out after $PostgreSQL::Test::Utils::timeout_default seconds.
2392 Returns 1 if successful, 0 if timed out.
2396 sub poll_query_until
2398 my ($self, $dbname, $query, $expected) = @_;
2400 local %ENV = $self->_get_env();
2402 $expected = 't' unless defined($expected); # default value
2405 $self->installed_command('psql'), '-XAt',
2406 '-d', $self->connstr($dbname)
2408 my ($stdout, $stderr);
2409 my $max_attempts = 10 * $PostgreSQL::Test::Utils::timeout_default;
2412 while ($attempts < $max_attempts)
2414 my $result = IPC::Run::run $cmd, '<', \$query,
2415 '>', \$stdout, '2>', \$stderr;
2420 if ($stdout eq $expected && $stderr eq '')
2425 # Wait 0.1 second before retrying.
2431 # Give up. Print the output from the last attempt, hopefully that's useful
2433 diag qq(poll_query_until timed out executing this query:
2435 expecting this output:
2437 last actual query output:
2446 =item $node->command_ok(...)
2448 Runs a shell command like PostgreSQL::Test::Utils::command_ok, but with PGHOST and PGPORT set
2449 so that the command will default to connecting to this PostgreSQL::Test::Cluster.
2455 local $Test::Builder::Level = $Test::Builder::Level + 1;
2459 local %ENV = $self->_get_env();
2461 PostgreSQL::Test::Utils::command_ok(@_);
2467 =item $node->command_fails(...)
2469 PostgreSQL::Test::Utils::command_fails with our connection parameters. See command_ok(...)
2475 local $Test::Builder::Level = $Test::Builder::Level + 1;
2479 local %ENV = $self->_get_env();
2481 PostgreSQL::Test::Utils::command_fails(@_);
2487 =item $node->command_like(...)
2489 PostgreSQL::Test::Utils::command_like with our connection parameters. See command_ok(...)
2495 local $Test::Builder::Level = $Test::Builder::Level + 1;
2499 local %ENV = $self->_get_env();
2501 PostgreSQL::Test::Utils::command_like(@_);
2507 =item $node->command_fails_like(...)
2509 PostgreSQL::Test::Utils::command_fails_like with our connection parameters. See command_ok(...)
2513 sub command_fails_like
2515 local $Test::Builder::Level = $Test::Builder::Level + 1;
2519 local %ENV = $self->_get_env();
2521 PostgreSQL::Test::Utils::command_fails_like(@_);
2527 =item $node->command_checks_all(...)
2529 PostgreSQL::Test::Utils::command_checks_all with our connection parameters. See
2534 sub command_checks_all
2536 local $Test::Builder::Level = $Test::Builder::Level + 1;
2540 local %ENV = $self->_get_env();
2542 PostgreSQL::Test::Utils::command_checks_all(@_);
2548 =item $node->issues_sql_like(cmd, expected_sql, test_name)
2550 Run a command on the node, then verify that $expected_sql appears in the
2557 local $Test::Builder::Level = $Test::Builder::Level + 1;
2559 my ($self, $cmd, $expected_sql, $test_name) = @_;
2561 local %ENV = $self->_get_env();
2563 my $log_location = -s $self->logfile;
2565 my $result = PostgreSQL::Test::Utils::run_log($cmd);
2566 ok($result, "@$cmd exit code 0");
2568 PostgreSQL::Test::Utils::slurp_file($self->logfile, $log_location);
2569 like($log, $expected_sql, "$test_name: SQL found in server log");
2575 =item $node->log_content()
2577 Returns the contents of log of the node
2584 return PostgreSQL::Test::Utils::slurp_file($self->logfile);
2589 =item $node->log_check($offset, $test_name, %parameters)
2591 Check contents of server logs.
2597 Name of test for error messages.
2601 Offset of the log file.
2603 =item log_like => [ qr/required message/ ]
2605 If given, it must be an array reference containing a list of regular
2606 expressions that must match against the server log, using
2607 C<Test::More::like()>.
2609 =item log_unlike => [ qr/prohibited message/ ]
2611 If given, it must be an array reference containing a list of regular
2612 expressions that must NOT match against the server log. They will be
2613 passed to C<Test::More::unlike()>.
2621 my ($self, $test_name, $offset, %params) = @_;
2623 my (@log_like, @log_unlike);
2624 if (defined($params{log_like}))
2626 @log_like = @{ $params{log_like} };
2628 if (defined($params{log_unlike}))
2630 @log_unlike = @{ $params{log_unlike} };
2633 if (@log_like or @log_unlike)
2636 PostgreSQL::Test::Utils::slurp_file($self->logfile, $offset);
2638 while (my $regex = shift @log_like)
2640 like($log_contents, $regex, "$test_name: log matches");
2642 while (my $regex = shift @log_unlike)
2644 unlike($log_contents, $regex, "$test_name: log does not match");
2651 =item log_contains(pattern, offset)
2653 Find pattern in logfile of node after offset byte.
2659 my ($self, $pattern, $offset) = @_;
2661 return PostgreSQL::Test::Utils::slurp_file($self->logfile, $offset) =~
2667 =item $node->run_log(...)
2669 Runs a shell command like PostgreSQL::Test::Utils::run_log, but with connection parameters set
2670 so that the command will default to connecting to this PostgreSQL::Test::Cluster.
2678 local %ENV = $self->_get_env();
2680 return PostgreSQL::Test::Utils::run_log(@_);
2685 =item $node->lsn(mode)
2687 Look up WAL locations on the server:
2689 * insert location (primary only, error on replica)
2690 * write location (primary only, error on replica)
2691 * flush location (primary only, error on replica)
2692 * receive location (always undef on primary)
2693 * replay location (always undef on primary)
2695 mode must be specified.
2701 my ($self, $mode) = @_;
2703 'insert' => 'pg_current_wal_insert_lsn()',
2704 'flush' => 'pg_current_wal_flush_lsn()',
2705 'write' => 'pg_current_wal_lsn()',
2706 'receive' => 'pg_last_wal_receive_lsn()',
2707 'replay' => 'pg_last_wal_replay_lsn()');
2709 $mode = '<undef>' if !defined($mode);
2710 croak "unknown mode for 'lsn': '$mode', valid modes are "
2711 . join(', ', keys %modes)
2712 if !defined($modes{$mode});
2714 my $result = $self->safe_psql('postgres', "SELECT $modes{$mode}");
2728 =item $node->wait_for_catchup(standby_name, mode, target_lsn)
2730 Wait for the replication connection with application_name standby_name until
2731 its 'mode' replication column in pg_stat_replication equals or passes the
2732 specified or default target_lsn. By default the replay_lsn is waited for,
2733 but 'mode' may be specified to wait for any of sent|write|flush|replay.
2734 The replication connection must be in a streaming state.
2736 When doing physical replication, the standby is usually identified by
2737 passing its PostgreSQL::Test::Cluster instance. When doing logical
2738 replication, standby_name identifies a subscription.
2740 When not in recovery, the default value of target_lsn is $node->lsn('write'),
2741 which ensures that the standby has caught up to what has been committed on
2744 When in recovery, the default value of target_lsn is $node->lsn('replay')
2745 instead which ensures that the cascaded standby has caught up to what has been
2746 replayed on the standby.
2748 If you pass an explicit value of target_lsn, it should almost always be
2749 the primary's write LSN; so this parameter is seldom needed except when
2750 querying some intermediate replication node rather than the primary.
2752 If there is no active replication connection from this peer, waits until
2753 poll_query_until timeout.
2755 Requires that the 'postgres' db exists and is accessible.
2757 This is not a test. It die()s on failure.
2761 sub wait_for_catchup
2763 my ($self, $standby_name, $mode, $target_lsn) = @_;
2764 $mode = defined($mode) ? $mode : 'replay';
2766 ('sent' => 1, 'write' => 1, 'flush' => 1, 'replay' => 1);
2767 croak "unknown mode $mode for 'wait_for_catchup', valid modes are "
2768 . join(', ', keys(%valid_modes))
2769 unless exists($valid_modes{$mode});
2771 # Allow passing of a PostgreSQL::Test::Cluster instance as shorthand
2772 if (blessed($standby_name)
2773 && $standby_name->isa("PostgreSQL::Test::Cluster"))
2775 $standby_name = $standby_name->name;
2777 if (!defined($target_lsn))
2780 $self->safe_psql('postgres', "SELECT pg_is_in_recovery()");
2782 if ($isrecovery eq 't')
2784 $target_lsn = $self->lsn('replay');
2788 $target_lsn = $self->lsn('write');
2791 print "Waiting for replication conn "
2792 . $standby_name . "'s "
2795 . $target_lsn . " on "
2796 . $self->name . "\n";
2797 # Before release 12 walreceiver just set the application name to
2799 my $query = qq[SELECT '$target_lsn' <= ${mode}_lsn AND state = 'streaming'
2800 FROM pg_catalog.pg_stat_replication
2801 WHERE application_name IN ('$standby_name', 'walreceiver')];
2802 if (!$self->poll_query_until('postgres', $query))
2804 if (PostgreSQL::Test::Utils::has_wal_read_bug)
2806 # Mimic having skipped the test file. If >0 tests have run, the
2807 # harness won't accept a skip; otherwise, it won't accept
2808 # done_testing(). Force a nonzero count by running one test.
2809 ok(1, 'dummy test before skip for filesystem bug');
2810 carp "skip rest: timed out waiting for catchup & filesystem bug";
2816 croak "timed out waiting for catchup";
2825 =item $node->wait_for_replay_catchup($standby_name [, $base_node ])
2827 Wait for the replication connection with application_name I<$standby_name>
2828 until its B<replay> replication column in pg_stat_replication in I<$node>
2829 equals or passes the I<$base_node>'s B<replay_lsn>. If I<$base_node> is
2830 omitted, the LSN to wait for is obtained from I<$node>.
2832 The replication connection must be in a streaming state.
2834 Requires that the 'postgres' db exists and is accessible.
2836 This is not a test. It die()s on failure.
2840 sub wait_for_replay_catchup
2842 my ($self, $standby_name, $node) = @_;
2843 $node = defined($node) ? $node : $self;
2845 $self->wait_for_catchup($standby_name, 'replay', $node->lsn('flush'));
2848 =item $node->wait_for_slot_catchup(slot_name, mode, target_lsn)
2850 Wait for the named replication slot to equal or pass the supplied target_lsn.
2851 The location used is the restart_lsn unless mode is given, in which case it may
2852 be 'restart' or 'confirmed_flush'.
2854 Requires that the 'postgres' db exists and is accessible.
2856 This is not a test. It die()s on failure.
2858 If the slot is not active, will time out after poll_query_until's timeout.
2860 target_lsn may be any arbitrary lsn, but is typically $primary_node->lsn('insert').
2862 Note that for logical slots, restart_lsn is held down by the oldest in-progress tx.
2866 sub wait_for_slot_catchup
2868 my ($self, $slot_name, $mode, $target_lsn) = @_;
2869 $mode = defined($mode) ? $mode : 'restart';
2870 if (!($mode eq 'restart' || $mode eq 'confirmed_flush'))
2872 croak "valid modes are restart, confirmed_flush";
2874 croak 'target lsn must be specified' unless defined($target_lsn);
2875 print "Waiting for replication slot "
2876 . $slot_name . "'s "
2879 . $target_lsn . " on "
2880 . $self->name . "\n";
2882 qq[SELECT '$target_lsn' <= ${mode}_lsn FROM pg_catalog.pg_replication_slots WHERE slot_name = '$slot_name';];
2883 $self->poll_query_until('postgres', $query)
2884 or croak "timed out waiting for catchup";
2891 =item $node->wait_for_subscription_sync(publisher, subname, dbname)
2893 Wait for all tables in pg_subscription_rel to complete the initial
2894 synchronization (i.e to be either in 'syncdone' or 'ready' state).
2896 If the publisher node is given, additionally, check if the subscriber has
2897 caught up to what has been committed on the primary. This is useful to
2898 ensure that the initial data synchronization has been completed after
2899 creating a new subscription.
2901 If there is no active replication connection from this peer, wait until
2902 poll_query_until timeout.
2904 This is not a test. It die()s on failure.
2908 sub wait_for_subscription_sync
2910 my ($self, $publisher, $subname, $dbname) = @_;
2911 my $name = $self->name;
2913 $dbname = defined($dbname) ? $dbname : 'postgres';
2915 # Wait for all tables to finish initial sync.
2916 print "Waiting for all subscriptions in \"$name\" to synchronize data\n";
2918 qq[SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');];
2919 $self->poll_query_until($dbname, $query)
2920 or croak "timed out waiting for subscriber to synchronize data";
2922 # Then, wait for the replication to catchup if required.
2923 if (defined($publisher))
2925 croak 'subscription name must be specified' unless defined($subname);
2926 $publisher->wait_for_catchup($subname);
2935 =item $node->wait_for_log(regexp, offset)
2937 Waits for the contents of the server log file, starting at the given offset, to
2938 match the supplied regular expression. Checks the entire log if no offset is
2939 given. Times out after $PostgreSQL::Test::Utils::timeout_default seconds.
2941 If successful, returns the length of the entire log file, in bytes.
2947 my ($self, $regexp, $offset) = @_;
2948 $offset = 0 unless defined $offset;
2950 my $max_attempts = 10 * $PostgreSQL::Test::Utils::timeout_default;
2953 while ($attempts < $max_attempts)
2956 PostgreSQL::Test::Utils::slurp_file($self->logfile, $offset);
2958 return $offset + length($log) if ($log =~ m/$regexp/);
2960 # Wait 0.1 second before retrying.
2966 croak "timed out waiting for match: $regexp";
2971 =item $node->query_hash($dbname, $query, @columns)
2973 Execute $query on $dbname, replacing any appearance of the string __COLUMNS__
2974 within the query with a comma-separated list of @columns.
2976 If __COLUMNS__ does not appear in the query, its result columns must EXACTLY
2977 match the order and number (but not necessarily alias) of supplied @columns.
2979 The query must return zero or one rows.
2981 Return a hash-ref representation of the results of the query, with any empty
2982 or null results as defined keys with an empty-string value. There is no way
2983 to differentiate between null and empty-string result fields.
2985 If the query returns zero rows, return a hash with all columns empty. There
2986 is no way to differentiate between zero rows returned and a row with only
2993 my ($self, $dbname, $query, @columns) = @_;
2994 croak 'calls in array context for multi-row results not supported yet'
2997 # Replace __COLUMNS__ if found
2998 substr($query, index($query, '__COLUMNS__'), length('__COLUMNS__')) =
2999 join(', ', @columns)
3000 if index($query, '__COLUMNS__') >= 0;
3001 my $result = $self->safe_psql($dbname, $query);
3003 # hash slice, see http://stackoverflow.com/a/16755894/398670 .
3005 # Fills the hash with empty strings produced by x-operator element
3006 # duplication if result is an empty row
3010 $result ne '' ? split(qr/\|/, $result, -1) : ('',) x scalar(@columns);
3016 =item $node->slot(slot_name)
3018 Return hash-ref of replication slot data for the named slot, or a hash-ref with
3019 all values '' if not found. Does not differentiate between null and empty string
3020 for fields, no field is ever undef.
3022 The restart_lsn and confirmed_flush_lsn fields are returned verbatim, and also
3023 as a 2-list of [highword, lowword] integer. Since we rely on Perl 5.14 we can't
3024 "use bigint", it's from 5.20, and we can't assume we have Math::Bigint from CPAN
3031 my ($self, $slot_name) = @_;
3033 'plugin', 'slot_type', 'datoid', 'database',
3034 'active', 'active_pid', 'xmin', 'catalog_xmin',
3036 return $self->query_hash(
3038 "SELECT __COLUMNS__ FROM pg_catalog.pg_replication_slots WHERE slot_name = '$slot_name'",
3044 =item $node->pg_recvlogical_upto(self, dbname, slot_name, endpos, timeout_secs, ...)
3046 Invoke pg_recvlogical to read from slot_name on dbname until LSN endpos, which
3047 corresponds to pg_recvlogical --endpos. Gives up after timeout (if nonzero).
3049 Disallows pg_recvlogical from internally retrying on error by passing --no-loop.
3051 Plugin options are passed as additional keyword arguments.
3053 If called in scalar context, returns stdout, and die()s on timeout or nonzero return.
3055 If called in array context, returns a tuple of (retval, stdout, stderr, timeout).
3056 timeout is the IPC::Run::Timeout object whose is_expired method can be tested
3057 to check for timeout. retval is undef on timeout.
3061 sub pg_recvlogical_upto
3063 my ($self, $dbname, $slot_name, $endpos, $timeout_secs, %plugin_options)
3066 local %ENV = $self->_get_env();
3068 my ($stdout, $stderr);
3070 my $timeout_exception = 'pg_recvlogical timed out';
3072 croak 'slot name must be specified' unless defined($slot_name);
3073 croak 'endpos must be specified' unless defined($endpos);
3076 $self->installed_command('pg_recvlogical'),
3077 '-S', $slot_name, '--dbname', $self->connstr($dbname));
3078 push @cmd, '--endpos', $endpos;
3079 push @cmd, '-f', '-', '--no-loop', '--start';
3081 while (my ($k, $v) = each %plugin_options)
3083 croak "= is not permitted to appear in replication option name"
3085 push @cmd, "-o", "$k=$v";
3090 IPC::Run::timeout($timeout_secs, exception => $timeout_exception)
3098 IPC::Run::run(\@cmd, ">", \$stdout, "2>", \$stderr, $timeout);
3105 # IPC::Run::run threw an exception. re-throw unless it's a
3106 # timeout, which we'll handle by testing is_expired
3108 if (blessed($exc_save) || $exc_save !~ qr/$timeout_exception/);
3112 die "Got timeout exception '$exc_save' but timer not expired?!"
3113 unless $timeout->is_expired;
3116 "$exc_save waiting for endpos $endpos with stdout '$stdout', stderr '$stderr'"
3123 return ($ret, $stdout, $stderr, $timeout);
3128 "pg_recvlogical exited with code '$ret', stdout '$stdout' and stderr '$stderr'"
3136 =item $node->corrupt_page_checksum(self, file, page_offset)
3138 Intentionally corrupt the checksum field of one page in a file.
3139 The server must be stopped for this to work reliably.
3141 The file name should be specified relative to the cluster datadir.
3142 page_offset had better be a multiple of the cluster's block size.
3146 sub corrupt_page_checksum
3148 my ($self, $file, $page_offset) = @_;
3149 my $pgdata = $self->data_dir;
3152 open my $fh, '+<', "$pgdata/$file" or die "open($file) failed: $!";
3154 sysseek($fh, $page_offset, 0) or die "sysseek failed: $!";
3155 sysread($fh, $pageheader, 24) or die "sysread failed: $!";
3156 # This inverts the pd_checksum field (only); see struct PageHeaderData
3157 $pageheader ^= "\0\0\0\0\0\0\0\0\xff\xff";
3158 sysseek($fh, $page_offset, 0) or die "sysseek failed: $!";
3159 syswrite($fh, $pageheader) or die "syswrite failed: $!";
3168 $SIG{TERM} = $SIG{INT} = sub {
3169 die "death by signal";
3174 =item $node->create_logical_slot_on_standby(self, primary, slot_name, dbname)
3176 Create logical replication slot on given standby
3180 sub create_logical_slot_on_standby
3182 my ($self, $primary, $slot_name, $dbname) = @_;
3183 my ($stdout, $stderr);
3187 $handle = IPC::Run::start(
3189 'pg_recvlogical', '-d',
3190 $self->connstr($dbname), '-P',
3191 'test_decoding', '-S',
3192 $slot_name, '--create-slot'
3199 # Once the slot's restart_lsn is determined, the standby looks for
3200 # xl_running_xacts WAL record from the restart_lsn onwards. First wait
3201 # until the slot restart_lsn is determined.
3203 $self->poll_query_until(
3205 SELECT restart_lsn IS NOT NULL
3206 FROM pg_catalog.pg_replication_slots WHERE slot_name = '$slot_name'
3209 "timed out waiting for logical slot to calculate its restart_lsn";
3211 # Then arrange for the xl_running_xacts record for which pg_recvlogical is
3213 $primary->safe_psql('postgres', 'SELECT pg_log_standby_snapshot()');
3217 is($self->slot($slot_name)->{'slot_type'},
3218 'logical', $slot_name . ' on standby created')
3219 or die "could not create slot" . $slot_name;
3224 =item $node->advance_wal(num)
3226 Advance WAL of node by given number of segments.
3232 my ($self, $num) = @_;
3234 # Advance by $n segments (= (wal_segment_size * $num) bytes).
3235 # pg_switch_wal() forces a WAL flush, making pg_logical_emit_message()
3236 # safe to use in non-transactional mode.
3237 for (my $i = 0; $i < $num; $i++)
3241 SELECT pg_logical_emit_message(false, '', 'foo');
3242 SELECT pg_switch_wal();
3253 ##########################################################################
3255 package PostgreSQL::Test::Cluster::V_11
3256 ; ## no critic (ProhibitMultiplePackages)
3258 use parent -norequire, qw(PostgreSQL::Test::Cluster);
3260 # https://www.postgresql.org/docs/11/release-11.html
3262 # max_wal_senders + superuser_reserved_connections must be < max_connections
3263 # uses recovery.conf
3265 sub _recovery_file { return "recovery.conf"; }
3267 sub set_standby_mode
3270 $self->append_conf("recovery.conf", "standby_mode = on\n");
3275 my ($self, %params) = @_;
3276 $self->SUPER::init(%params);
3277 $self->adjust_conf('postgresql.conf', 'max_wal_senders',
3278 $params{allows_streaming} ? 5 : 0);
3281 ##########################################################################
3283 package PostgreSQL::Test::Cluster::V_10
3284 ; ## no critic (ProhibitMultiplePackages)
3286 use parent -norequire, qw(PostgreSQL::Test::Cluster::V_11);
3288 # https://www.postgresql.org/docs/10/release-10.html
3290 ########################################################################