From fb3de11044fc712d83d1bda269c3daccd7abaac2 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 7 Jan 2015 15:22:07 +0200 Subject: [PATCH] Refactor the pg_rewind regression tests to use TAP --- contrib/pg_rewind/Makefile | 19 +- contrib/pg_rewind/RewindTest.pm | 238 ++++++++++++++++++++++ contrib/pg_rewind/expected/basictest.out | 27 --- contrib/pg_rewind/expected/databases.out | 24 --- contrib/pg_rewind/expected/extrafiles.out | 15 -- contrib/pg_rewind/launcher | 6 - contrib/pg_rewind/sql/basictest.sql | 53 ----- contrib/pg_rewind/sql/config_test.sh | 73 ------- contrib/pg_rewind/sql/databases.sql | 43 ---- contrib/pg_rewind/sql/extrafiles.sql | 52 ----- contrib/pg_rewind/sql/run_test.sh | 149 -------------- contrib/pg_rewind/t/001_basic.pl | 50 +++++ contrib/pg_rewind/t/002_databases.pl | 42 ++++ contrib/pg_rewind/t/003_extrafiles.pl | 61 ++++++ src/test/perl/TestLib.pm | 11 + 15 files changed, 406 insertions(+), 457 deletions(-) create mode 100644 contrib/pg_rewind/RewindTest.pm delete mode 100644 contrib/pg_rewind/expected/basictest.out delete mode 100644 contrib/pg_rewind/expected/databases.out delete mode 100644 contrib/pg_rewind/expected/extrafiles.out delete mode 100755 contrib/pg_rewind/launcher delete mode 100644 contrib/pg_rewind/sql/basictest.sql delete mode 100755 contrib/pg_rewind/sql/config_test.sh delete mode 100644 contrib/pg_rewind/sql/databases.sql delete mode 100644 contrib/pg_rewind/sql/extrafiles.sql delete mode 100755 contrib/pg_rewind/sql/run_test.sh create mode 100644 contrib/pg_rewind/t/001_basic.pl create mode 100644 contrib/pg_rewind/t/002_databases.pl create mode 100644 contrib/pg_rewind/t/003_extrafiles.pl diff --git a/contrib/pg_rewind/Makefile b/contrib/pg_rewind/Makefile index 241c775bf5..ab778002d0 100644 --- a/contrib/pg_rewind/Makefile +++ b/contrib/pg_rewind/Makefile @@ -10,8 +10,8 @@ PROGRAM = pg_rewind OBJS = pg_rewind.o parsexlog.o xlogreader.o util.o datapagemap.o timeline.o \ fetch.o copy_fetch.o libpq_fetch.o filemap.o -REGRESS = basictest extrafiles databases -REGRESS_OPTS=--use-existing --launcher=./launcher +#REGRESS = basictest extrafiles databases +#REGRESS_OPTS=--use-existing --launcher=./launcher PG_CPPFLAGS = -I$(libpq_srcdir) PG_LIBS = $(libpq_pgport) @@ -36,16 +36,5 @@ endif xlogreader.c: % : $(top_srcdir)/src/backend/access/transam/% rm -f $@ && $(LN_S) $< . -# The regression tests can be run separately against, using the libpq or local -# method to copy the files. For local mode, the makefile target is -# "check-local", and for libpq mode, "check-remote". The target check-both -# runs the tests in both modes. -check-local: - echo "Running tests against local data directory, in copy-mode" - bindir=$(bindir) TEST_SUITE="local" $(MAKE) installcheck - -check-remote: - echo "Running tests against a running standby, via libpq" - bindir=$(bindir) TEST_SUITE="remote" $(MAKE) installcheck - -check-both: check-local check-remote +check: all + $(prove_check) diff --git a/contrib/pg_rewind/RewindTest.pm b/contrib/pg_rewind/RewindTest.pm new file mode 100644 index 0000000000..2578464b97 --- /dev/null +++ b/contrib/pg_rewind/RewindTest.pm @@ -0,0 +1,238 @@ +package RewindTest; + +# Test driver for pg_rewind. Each test consists of a cycle where a new cluster +# is first created with initdb, and a streaming replication standby is set up +# to follow the master. Then the master is shut down and the standby is +# promoted, and finally pg_rewind is used to rewind the old master, using the +# standby as the source. Between the steps, test-specific actions are +# performed. +# +# To run a test, the test script (in t/ subdirectory) calls run_rewind_test +# function. All the test-specific actions that are run in different stages +# are defined as callback functions: +# +# before_standby - runs after initializing the master, before creating the +# standby +# standby_following_master - runs after standby has been created and started +# after_promotion - runs after standby has been promoted, but old master is +# still running +# after_rewind - runs after pg_rewind and after restarting the rewound +# old master +# +# The test script can use the helper functions master_psql and standby_psql +# to run psql against the master and standby servers, respectively. The +# test script can also use the $connstr_master and $connstr_standby global +# variables, which contain libpq connection strings for connecting to the +# master and standby servers. The data directories are also available +# in paths $test_master_datadir and $test_standby_datadir + +use TestLib; +use Test::More; + +use File::Copy; +use File::Path qw(remove_tree); +use IPC::Run qw(run start); + +use Exporter 'import'; +our @EXPORT = qw( + $connstr_master + $connstr_standby + $test_master_datadir + $test_standby_datadir + + append_to_file + master_psql + standby_psql + run_rewind_test +); + + +# Adjust these paths for your environment +my $testroot = "./tmp_check"; +$test_master_datadir="$testroot/data_master"; +$test_standby_datadir="$testroot/data_standby"; + +mkdir $testroot; + +# Log files are created here +mkdir "regress_log"; + +# Define non-conflicting ports for both nodes. +my $port_master=$ENV{PGPORT}; +my $port_standby=$port_master + 1; + +$connstr_master="port=$port_master"; +$connstr_standby="port=$port_standby"; + +$ENV{PGDATABASE} = "postgres"; + +sub master_psql +{ + my $cmd = shift; + + system_or_bail("psql -a --no-psqlrc -d $connstr_master -c \"$cmd\""); +} + +sub standby_psql +{ + my $cmd = shift; + + system_or_bail("psql -a --no-psqlrc -p$port_standby -c \"$cmd\""); +} + +sub append_to_file +{ + my($filename, $str) = @_; + + open my $fh, ">>", $filename or die "could not open file $filename"; + print $fh $str; + close $fh; +} + +sub run_rewind_test +{ + my($testname, $test_mode, %callbacks) = @_; + + my $log_path="regress_log/pg_rewind_log_${testname}_${test_mode}"; + + remove_tree $log_path; + diag "Running rewind test in $test_mode mode...\n"; + + # Initialize master, data checksums are mandatory + remove_tree($test_master_datadir); + system_or_bail("initdb -N -A trust -D $test_master_datadir >>$log_path"); + + # Custom parameters for master's postgresql.conf + append_to_file("$test_master_datadir/postgresql.conf", qq( +wal_level = hot_standby +max_wal_senders = 2 +wal_keep_segments = 20 +checkpoint_segments = 50 +shared_buffers = 1MB +wal_log_hints = on +log_line_prefix = 'M %m %p ' +hot_standby = on +autovacuum = off +max_connections = 50 +listen_addresses = '$LISTEN_ADDRESSES' +)); + + # Accept replication connections on master + append_to_file("$test_master_datadir/pg_hba.conf", qq( +local replication all trust +host replication all 127.0.0.1/32 trust +host replication all ::1/128 trust +)); + + system_or_bail("pg_ctl -w -D $test_master_datadir -o \"-p $port_master\" start >>$log_path 2>&1"); + + #### Now run the test-specific parts to initialize the master before setting + # up standby + diag "Master initialized and running.\n"; + + $callbacks{before_standby}(); + + # Set up standby with necessary parameter + remove_tree $test_standby_datadir; + + # Base backup is taken with xlog files included + system_or_bail("pg_basebackup -D $test_standby_datadir -p $port_master -x >>$log_path 2>&1"); + append_to_file("$test_standby_datadir/recovery.conf", qq( +primary_conninfo='$connstr_master' +standby_mode=on +recovery_target_timeline='latest' +)); + + # Start standby + system_or_bail("pg_ctl -w -D $test_standby_datadir start -o \"-p $port_standby\" >>$log_path 2>&1"); + + #### Now run the test-specific parts to run after standby has been started + # up standby + diag "Standby initialized and running.\n"; + $callbacks{standby_following_master}(); + + # sleep a bit to make sure the standby has caught up. + sleep 1; + + # Now promote slave and insert some new data on master, this will put + # the master out-of-sync with the standby. + system_or_bail("pg_ctl -w -D $test_standby_datadir promote >>$log_path 2>&1"); + sleep 1; + + #### Now run the test-specific parts to run after promotion + diag "Standby promoted.\n"; + $callbacks{after_promotion}(); + + # Stop the master and be ready to perform the rewind + system_or_bail("pg_ctl -w -D $test_master_datadir stop -m fast >>$log_path 2>&1"); + + # At this point, the rewind processing is ready to run. + # We now have a very simple scenario with a few diverged WAL record. + # The real testing begins really now with a bifurcation of the possible + # scenarios that pg_rewind supports. + + # Keep a temporary postgresql.conf for master node or it would be + # overwritten during the rewind. + copy("$test_master_datadir/postgresql.conf", "$testroot/master-postgresql.conf.tmp"); + # Now run pg_rewind + diag "Running pg_rewind...\n"; + if ($test_mode == "local") + { + # Do rewind using a local pgdata as source + my $result = + run(['./pg_rewind', + "--source-pgdata=$test_standby_datadir", + "--target-pgdata=$test_master_datadir"], + '>>', $log_path, '2>&1'); + ok ($result, 'pg_rewind local'); + } + elsif ($test_mode == "remote") + { + # Do rewind using a remote connection as source + my $result = + run(['./pg_rewind', + "--source-server=\"port=$port_standby dbname=postgres\"", + "--target-pgdata=$test_master_datadir"], + '>>', $log_path, '2>&1'); + ok ($result, 'pg_rewind remote'); + } else { + # Cannot come here normally + die("Incorrect test suite specified"); + } + + # Now move back postgresql.conf with old settings + move("$testroot/master-postgresql.conf.tmp", "$test_master_datadir/postgresql.conf"); + + # Plug-in rewound node to the now-promoted standby node + append_to_file("$test_master_datadir/recovery.conf", qq( +primary_conninfo='port=$port_standby' +standby_mode=on +recovery_target_timeline='latest' +)); + + # Restart the master to check that rewind went correctly + system_or_bail("pg_ctl -w -D $test_master_datadir start -o \"-p $port_master\" >>$log_path 2>&1"); + + #### Now run the test-specific parts to check the result + diag "Old master restarted after rewind.\n"; + $callbacks{after_rewind}(); + + # Stop remaining servers + system "pg_ctl stop -D $test_master_datadir -m fast -w >>$log_path 2>&1"; + system "pg_ctl stop -D $test_standby_datadir -m fast -w >>$log_path 2>&1"; +} + +# Clean up after the test. Stop both servers, if they're still running. +END +{ + if ($test_master_datadir) + { + system 'pg_ctl', '-D', $test_master_datadir, '-s', '-w', '-m', + 'immediate', 'stop'; + } + if ($test_standby_datadir) + { + system 'pg_ctl', '-D', $test_standby_datadir, '-s', '-w', '-m', + 'immediate', 'stop'; + } +} diff --git a/contrib/pg_rewind/expected/basictest.out b/contrib/pg_rewind/expected/basictest.out deleted file mode 100644 index b67ead527f..0000000000 --- a/contrib/pg_rewind/expected/basictest.out +++ /dev/null @@ -1,27 +0,0 @@ -Master initialized and running. -CREATE TABLE tbl1 (d text); -CREATE TABLE -INSERT INTO tbl1 VALUES ('in master'); -INSERT 0 1 -CHECKPOINT; -CHECKPOINT -Standby initialized and running. -INSERT INTO tbl1 values ('in master, before promotion'); -INSERT 0 1 -CHECKPOINT; -CHECKPOINT -Standby promoted. -INSERT INTO tbl1 VALUES ('in master, after promotion'); -INSERT 0 1 -INSERT INTO tbl1 VALUES ('in standby, after promotion'); -INSERT 0 1 -Running pg_rewind... -Old master restarted after rewind. -SELECT * from tbl1 - d ------------------------------ - in master - in master, before promotion - in standby, after promotion -(3 rows) - diff --git a/contrib/pg_rewind/expected/databases.out b/contrib/pg_rewind/expected/databases.out deleted file mode 100644 index e486107a6d..0000000000 --- a/contrib/pg_rewind/expected/databases.out +++ /dev/null @@ -1,24 +0,0 @@ -Master initialized and running. -CREATE DATABASE inmaster; -CREATE DATABASE -Standby initialized and running. -CREATE DATABASE beforepromotion -CREATE DATABASE -Standby promoted. -CREATE DATABASE master_afterpromotion -CREATE DATABASE -CREATE DATABASE standby_afterpromotion -CREATE DATABASE -Running pg_rewind... -Old master restarted after rewind. -SELECT datname from pg_database - datname ------------------------- - template1 - template0 - postgres - inmaster - beforepromotion - standby_afterpromotion -(6 rows) - diff --git a/contrib/pg_rewind/expected/extrafiles.out b/contrib/pg_rewind/expected/extrafiles.out deleted file mode 100644 index 8e3f3f1daf..0000000000 --- a/contrib/pg_rewind/expected/extrafiles.out +++ /dev/null @@ -1,15 +0,0 @@ -Master initialized and running. -Standby initialized and running. -Standby promoted. -Running pg_rewind... -Old master restarted after rewind. -tst_both_dir -tst_both_dir/both_file1 -tst_both_dir/both_file2 -tst_both_dir/both_subdir -tst_both_dir/both_subdir/both_file3 -tst_standby_dir -tst_standby_dir/standby_file1 -tst_standby_dir/standby_file2 -tst_standby_dir/standby_subdir -tst_standby_dir/standby_subdir/standby_file3 diff --git a/contrib/pg_rewind/launcher b/contrib/pg_rewind/launcher deleted file mode 100755 index 56f8cc0182..0000000000 --- a/contrib/pg_rewind/launcher +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# -# Normally, psql feeds the files in sql/ directory to psql, but we want to -# run them as shell scripts instead. - -bash diff --git a/contrib/pg_rewind/sql/basictest.sql b/contrib/pg_rewind/sql/basictest.sql deleted file mode 100644 index cee59c24f2..0000000000 --- a/contrib/pg_rewind/sql/basictest.sql +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# This file has the .sql extension, but it is actually launched as a shell -# script. This contortion is necessary because pg_regress normally uses -# psql to run the input scripts, and requires them to have the .sql -# extension, but we use a custom launcher script that runs the scripts using -# a shell instead. - -TESTNAME=basictest - -. sql/config_test.sh - -# Do an insert in master. -function before_standby -{ -$MASTER_PSQL <>$log_path 2>&1 - TEST_SUITE="remote" -elif [ "$TEST_SUITE" = 'local' ]; then - echo "Running tests with local data folder as source" >>$log_path 2>&1 - TEST_SUITE="local" -else - echo "TEST_SUITE environment variable must be set to either \"local\" or \"remote\"" - exit 1 -fi - -# Set listen_addresses desirably -testhost=`uname -s` -case $testhost in - MINGW*) LISTEN_ADDRESSES="localhost" ;; - *) LISTEN_ADDRESSES="" ;; -esac - -# Indicate of binaries -PATH=$bindir:$PATH -export PATH - -# Adjust these paths for your environment -TESTROOT=$PWD/tmp_check -TEST_MASTER=$TESTROOT/data_master -TEST_STANDBY=$TESTROOT/data_standby - -# Create the root folder for test data -mkdir -p $TESTROOT - -# Clear out any environment vars that might cause libpq to connect to -# the wrong postmaster (cf pg_regress.c) -# -# Some shells, such as NetBSD's, return non-zero from unset if the variable -# is already unset. Since we are operating under 'set -e', this causes the -# script to fail. To guard against this, set them all to an empty string first. -PGDATABASE=""; unset PGDATABASE -PGUSER=""; unset PGUSER -PGSERVICE=""; unset PGSERVICE -PGSSLMODE=""; unset PGSSLMODE -PGREQUIRESSL=""; unset PGREQUIRESSL -PGCONNECT_TIMEOUT=""; unset PGCONNECT_TIMEOUT -PGHOST=""; unset PGHOST -PGHOSTADDR=""; unset PGHOSTADDR - -export PGDATABASE="postgres" - -# Define non conflicting ports for both nodes, this could be a bit -# smarter with for example dynamic port recognition using psql but -# this will make it for now. -PG_VERSION_NUM=90401 -PORT_MASTER=`expr $PG_VERSION_NUM % 16384 + 49152` -PORT_STANDBY=`expr $PORT_MASTER + 1` - -MASTER_PSQL="psql -a --no-psqlrc -p $PORT_MASTER" -STANDBY_PSQL="psql -a --no-psqlrc -p $PORT_STANDBY" diff --git a/contrib/pg_rewind/sql/databases.sql b/contrib/pg_rewind/sql/databases.sql deleted file mode 100644 index 60520d25ec..0000000000 --- a/contrib/pg_rewind/sql/databases.sql +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# This file has the .sql extension, but it is actually launched as a shell -# script. This contortion is necessary because pg_regress normally uses -# psql to run the input scripts, and requires them to have the .sql -# extension, but we use a custom launcher script that runs the scripts using -# a shell instead. - -TESTNAME=databases - -. sql/config_test.sh - -# Create a database in master. -function before_standby -{ -$MASTER_PSQL < $TEST_MASTER/tst_both_dir/both_file1 - echo "in both2" > $TEST_MASTER/tst_both_dir/both_file2 - mkdir $TEST_MASTER/tst_both_dir/both_subdir/ - echo "in both3" > $TEST_MASTER/tst_both_dir/both_subdir/both_file3 -} - -# Create subdirs that will be present only in one data dir. -function standby_following_master -{ - mkdir $TEST_STANDBY/tst_standby_dir - echo "in standby1" > $TEST_STANDBY/tst_standby_dir/standby_file1 - echo "in standby2" > $TEST_STANDBY/tst_standby_dir/standby_file2 - mkdir $TEST_STANDBY/tst_standby_dir/standby_subdir/ - echo "in standby3" > $TEST_STANDBY/tst_standby_dir/standby_subdir/standby_file3 - mkdir $TEST_MASTER/tst_master_dir - echo "in master1" > $TEST_MASTER/tst_master_dir/master_file1 - echo "in master2" > $TEST_MASTER/tst_master_dir/master_file2 - mkdir $TEST_MASTER/tst_master_dir/master_subdir/ - echo "in master3" > $TEST_MASTER/tst_master_dir/master_subdir/master_file3 -} - -function after_promotion -{ - : -} - -# See what files and directories are present after rewind. -function after_rewind -{ - (cd $TEST_MASTER; find tst_* | sort) -} - -# Run the test -. sql/run_test.sh diff --git a/contrib/pg_rewind/sql/run_test.sh b/contrib/pg_rewind/sql/run_test.sh deleted file mode 100755 index a6b934cd1b..0000000000 --- a/contrib/pg_rewind/sql/run_test.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash -# -# pg_rewind.sh -# -# Test driver for pg_rewind. This test script initdb's and configures a -# cluster and creates a table with some data in it. Then, it makes a -# standby of it with pg_basebackup, and promotes the standby. -# -# The result is two clusters, so that the old "master" cluster can be -# resynchronized with pg_rewind to catch up with the new "standby" cluster. -# This test can be run with either a local data folder or a remote -# connection as source. -# -# Before running this script, the calling script should've included -# config_test.sh, and defined four functions to define the test case: -# -# before_standby - runs after initializing the master, before creating the -# standby -# standby_following_master - runs after standby has been created and started -# after_promotion - runs after standby has been promoted, but old master is -# still running -# after_rewind - runs after pg_rewind and after restarting the rewound -# old master -# -# In those functions, the test script can use $MASTER_PSQL and $STANDBY_PSQL -# to run psql against the master and standby servers, to cause the servers -# to diverge. - -PATH=$bindir:$PATH -export PATH - -# Initialize master, data checksums are mandatory -rm -rf $TEST_MASTER -initdb -N -A trust -D $TEST_MASTER >>$log_path - -# Custom parameters for master's postgresql.conf -cat >> $TEST_MASTER/postgresql.conf <> $TEST_MASTER/pg_hba.conf <>$log_path 2>&1 - -#### Now run the test-specific parts to initialize the master before setting -# up standby -echo "Master initialized and running." -before_standby - -# Set up standby with necessary parameter -rm -rf $TEST_STANDBY - -# Base backup is taken with xlog files included -pg_basebackup -D $TEST_STANDBY -p $PORT_MASTER -x >>$log_path 2>&1 -echo "port = $PORT_STANDBY" >> $TEST_STANDBY/postgresql.conf - -cat > $TEST_STANDBY/recovery.conf <>$log_path 2>&1 - -#### Now run the test-specific parts to run after standby has been started -# up standby -echo "Standby initialized and running." -standby_following_master - -# sleep a bit to make sure the standby has caught up. -sleep 1 - -# Now promote slave and insert some new data on master, this will put -# the master out-of-sync with the standby. -pg_ctl -w -D $TEST_STANDBY promote >>$log_path 2>&1 -sleep 1 - -#### Now run the test-specific parts to run after promotion -echo "Standby promoted." -after_promotion - -# Stop the master and be ready to perform the rewind -pg_ctl -w -D $TEST_MASTER stop -m fast >>$log_path 2>&1 - -# At this point, the rewind processing is ready to run. -# We now have a very simple scenario with a few diverged WAL record. -# The real testing begins really now with a bifurcation of the possible -# scenarios that pg_rewind supports. - -# Keep a temporary postgresql.conf for master node or it would be -# overwritten during the rewind. -cp $TEST_MASTER/postgresql.conf $TESTROOT/master-postgresql.conf.tmp - -# Now run pg_rewind -echo "Running pg_rewind..." -echo "Running pg_rewind..." >> $log_path -if [ $TEST_SUITE == "local" ]; then - # Do rewind using a local pgdata as source - pg_rewind \ - --source-pgdata=$TEST_STANDBY \ - --target-pgdata=$TEST_MASTER >>$log_path 2>&1 -elif [ $TEST_SUITE == "remote" ]; then - # Do rewind using a remote connection as source - pg_rewind \ - --source-server="port=$PORT_STANDBY dbname=postgres" \ - --target-pgdata=$TEST_MASTER >>$log_path 2>&1 -else - # Cannot come here normally - echo "Incorrect test suite specified" - exit 1 -fi - -# Now move back postgresql.conf with old settings -mv $TESTROOT/master-postgresql.conf.tmp $TEST_MASTER/postgresql.conf - -# Plug-in rewound node to the now-promoted standby node -cat > $TEST_MASTER/recovery.conf <>$log_path 2>&1 - -#### Now run the test-specific parts to check the result -echo "Old master restarted after rewind." -after_rewind - -# Stop remaining servers -pg_ctl stop -D $TEST_MASTER -m fast -w >>$log_path 2>&1 -pg_ctl stop -D $TEST_STANDBY -m fast -w >>$log_path 2>&1 diff --git a/contrib/pg_rewind/t/001_basic.pl b/contrib/pg_rewind/t/001_basic.pl new file mode 100644 index 0000000000..8786cf6875 --- /dev/null +++ b/contrib/pg_rewind/t/001_basic.pl @@ -0,0 +1,50 @@ +use strict; +use warnings; +use TestLib; +use Test::More tests => 8; + +use RewindTest; + +my %rewind_test_callbacks = ( + # Create a test table and insert a row in master. + 'before_standby' => sub { + master_psql("CREATE TABLE tbl1 (d text)"); + master_psql("INSERT INTO tbl1 VALUES ('in master')"); + master_psql("CHECKPOINT"); + }, + + # Create another database after promotion + standby_following_master => sub { + # Insert additional data on master that will be replicated to standby + master_psql("INSERT INTO tbl1 values ('in master, before promotion')"); + # Launch checkpoint after standby has been started + master_psql('CHECKPOINT'); + }, + + # This function runs after the standby has been promoted. Old Master is + # still running. + after_promotion => sub { + # Insert a row in the old master. This causes the master and standby + # to have "diverged", it's no longer possible to just apply the + # standy's logs over master directory - you need to rewind. + master_psql("INSERT INTO tbl1 VALUES ('in master, after promotion')"); + + # Also insert a new row in the standby, which won't be present in the + # old master. + standby_psql("INSERT INTO tbl1 VALUES ('in standby, after promotion')"); + }, + + # Compare results generated by querying new master after rewind + after_rewind => sub { + command_is(['psql', '-A', '-t', '--no-psqlrc', "-d $connstr_master", + '-c' , 'SELECT * FROM tbl1'], + qq(in master +in master, before promotion +in standby, after promotion +), + 'check_table_content'); + } +); + +RewindTest::run_rewind_test('basic', 'local', %rewind_test_callbacks); +RewindTest::run_rewind_test('basic', 'remote', %rewind_test_callbacks); diff --git a/contrib/pg_rewind/t/002_databases.pl b/contrib/pg_rewind/t/002_databases.pl new file mode 100644 index 0000000000..d90c90f680 --- /dev/null +++ b/contrib/pg_rewind/t/002_databases.pl @@ -0,0 +1,42 @@ +use strict; +use warnings; +use TestLib; +use Test::More tests => 8; + +use RewindTest; + +my %rewind_test_callbacks = ( + # Create a database in master. + 'before_standby' => sub { + master_psql('CREATE DATABASE inmaster'); + }, + + # Create another database after promotion + standby_following_master => sub { + master_psql('CREATE DATABASE beforepromotion'); + }, + + # This function runs after the standby has been promoted. Old Master is + # still running. + after_promotion => sub { + master_psql('CREATE DATABASE master_afterpromotion'); + standby_psql('CREATE DATABASE standby_afterpromotion'); + }, + + # Compare results generated by querying new master after rewind + after_rewind => sub { + command_is(['psql', '-A', '-t', '--no-psqlrc', "-c $connstr_master", + '-c' , 'SELECT datname FROM pg_database'], + qq(template1 +template0 +postgres +inmaster +beforepromotion +standby_afterpromotion +), + 'check_database_names'); + } +); + +RewindTest::run_rewind_test('databases', 'local', %rewind_test_callbacks); +RewindTest::run_rewind_test('databases', 'remote', %rewind_test_callbacks); diff --git a/contrib/pg_rewind/t/003_extrafiles.pl b/contrib/pg_rewind/t/003_extrafiles.pl new file mode 100644 index 0000000000..01751aee29 --- /dev/null +++ b/contrib/pg_rewind/t/003_extrafiles.pl @@ -0,0 +1,61 @@ +# Test how pg_rewind reacts to extra files and directories in the data dirs. + +use strict; +use warnings; +use TestLib; +use Test::More tests => 4; + +use File::Find; + +use RewindTest; + +my %rewind_test_callbacks = ( + # Create a subdir that will be present in both + 'before_standby' => sub { + mkdir "$test_master_datadir/tst_both_dir"; + append_to_file "$test_master_datadir/tst_both_dir/both_file1", "in both1"; + append_to_file "$test_master_datadir/tst_both_dir/both_file2", "in both2"; + mkdir "$test_master_datadir/tst_both_dir/both_subdir/"; + append_to_file "$test_master_datadir/tst_both_dir/both_subdir/both_file3", "in both3"; + }, + + # Create subdirs that will be present only in one data dir. + standby_following_master => sub { + mkdir "$test_standby_datadir/tst_standby_dir"; + append_to_file "$test_standby_datadir/tst_standby_dir/standby_file1", "in standby1"; + append_to_file "$test_standby_datadir/tst_standby_dir/standby_file2", "in standby2"; + mkdir "$test_standby_datadir/tst_standby_dir/standby_subdir/"; + append_to_file "$test_standby_datadir/tst_standby_dir/standby_subdir/standby_file3", "in standby3"; + + mkdir "$test_master_datadir/tst_master_dir"; + append_to_file "$test_master_datadir/tst_master_dir/master_file1", "in master1"; + append_to_file "$test_master_datadir/tst_master_dir/master_file2", "in master2"; + mkdir "$test_master_datadir/tst_master_dir/master_subdir/"; + append_to_file "$test_master_datadir/tst_master_dir/master_subdir/master_file3", "in master3"; + }, + + after_promotion => sub { }, + + # List files in the data directory after rewind. + after_rewind => sub { + my @paths; + find(sub {push @paths, $File::Find::name if $File::Find::name =~ m/.*tst_.*/}, + $test_master_datadir); + @paths = sort @paths; + is_deeply(\@paths, + ["$test_master_datadir/tst_both_dir", + "$test_master_datadir/tst_both_dir/both_file1", + "$test_master_datadir/tst_both_dir/both_file2", + "$test_master_datadir/tst_both_dir/both_subdir", + "$test_master_datadir/tst_both_dir/both_subdir/both_file3", + "$test_master_datadir/tst_standby_dir", + "$test_master_datadir/tst_standby_dir/standby_file1", + "$test_master_datadir/tst_standby_dir/standby_file2", + "$test_master_datadir/tst_standby_dir/standby_subdir", + "$test_master_datadir/tst_standby_dir/standby_subdir/standby_file3"], + "file lists match"); + }, +); + +RewindTest::run_rewind_test('extrafiles', 'local', %rewind_test_callbacks); +RewindTest::run_rewind_test('extrafiles', 'remote', %rewind_test_callbacks); diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm index 003cd9a2cc..a035472d83 100644 --- a/src/test/perl/TestLib.pm +++ b/src/test/perl/TestLib.pm @@ -20,6 +20,7 @@ our @EXPORT = qw( program_version_ok program_options_handling_ok command_like + command_is issues_sql_like ); @@ -200,6 +201,16 @@ sub command_like like($stdout, $expected_stdout, "$test_name: matches"); } +sub command_is +{ + my ($cmd, $expected_stdout, $test_name) = @_; + my ($stdout, $stderr); + my $result = run $cmd, '>', \$stdout, '2>', \$stderr; + ok($result, "@$cmd exit code 0"); + is($stderr, '', "@$cmd no stderr"); + is($stdout, $expected_stdout, "$test_name: matches"); +} + sub issues_sql_like { my ($cmd, $expected_sql, $test_name) = @_; -- 2.39.5