diff --git a/src/bin/pg_rewind/Makefile b/src/bin/pg_rewind/Makefile index efd49888c51..e3400f5e812 100644 --- a/src/bin/pg_rewind/Makefile +++ b/src/bin/pg_rewind/Makefile @@ -47,6 +47,5 @@ clean distclean maintainer-clean: rm -f pg_rewind$(X) $(OBJS) xlogreader.c rm -rf tmp_check regress_log -check: all - $(prove_check) :: local - $(prove_check) :: remote +check: + $(prove_check) diff --git a/src/bin/pg_rewind/RewindTest.pm b/src/bin/pg_rewind/RewindTest.pm index 0f8f4ca7ce0..7a20e79be8b 100644 --- a/src/bin/pg_rewind/RewindTest.pm +++ b/src/bin/pg_rewind/RewindTest.pm @@ -29,6 +29,9 @@ package RewindTest; # master and standby servers. The data directories are also available # in paths $test_master_datadir and $test_standby_datadir +use strict; +use warnings; + use TestLib; use Test::More; @@ -58,8 +61,8 @@ our @EXPORT = qw( # Adjust these paths for your environment my $testroot = "./tmp_check"; -$test_master_datadir="$testroot/data_master"; -$test_standby_datadir="$testroot/data_standby"; +our $test_master_datadir="$testroot/data_master"; +our $test_standby_datadir="$testroot/data_standby"; mkdir $testroot; @@ -73,8 +76,8 @@ my $port_standby=$port_master + 1; my $log_path; my $tempdir_short; -$connstr_master="port=$port_master"; -$connstr_standby="port=$port_standby"; +my $connstr_master="port=$port_master"; +my $connstr_standby="port=$port_standby"; $ENV{PGDATABASE} = "postgres"; @@ -127,7 +130,8 @@ sub append_to_file sub init_rewind_test { - ($testname, $test_mode) = @_; + my $testname = shift; + my $test_mode = shift; $log_path="regress_log/pg_rewind_log_${testname}_${test_mode}"; @@ -195,11 +199,13 @@ sub promote_standby # 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; + sleep 2; } sub run_pg_rewind { + my $test_mode = shift; + # 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"); @@ -212,7 +218,7 @@ sub run_pg_rewind # overwritten during the rewind. copy("$test_master_datadir/postgresql.conf", "$testroot/master-postgresql.conf.tmp"); # Now run pg_rewind - if ($test_mode == "local") + if ($test_mode eq "local") { # Do rewind using a local pgdata as source # Stop the master and be ready to perform the rewind @@ -225,12 +231,12 @@ sub run_pg_rewind '>>', $log_path, '2>&1'); ok ($result, 'pg_rewind local'); } - elsif ($test_mode == "remote") + elsif ($test_mode eq "remote") { # Do rewind using a remote connection as source my $result = run(['./pg_rewind', - "--source-server=\"port=$port_standby dbname=postgres\"", + "--source-server", "port=$port_standby dbname=postgres", "--target-pgdata=$test_master_datadir"], '>>', $log_path, '2>&1'); ok ($result, 'pg_rewind remote'); diff --git a/src/bin/pg_rewind/t/001_basic.pl b/src/bin/pg_rewind/t/001_basic.pl index 7198a3ae83c..ae26d0129ea 100644 --- a/src/bin/pg_rewind/t/001_basic.pl +++ b/src/bin/pg_rewind/t/001_basic.pl @@ -1,80 +1,87 @@ use strict; use warnings; use TestLib; -use Test::More tests => 4; +use Test::More tests => 8; use RewindTest; -my $testmode = shift; +sub run_test +{ + my $test_mode = shift; -RewindTest::init_rewind_test('basic', $testmode); -RewindTest::setup_cluster(); + RewindTest::init_rewind_test('basic', $test_mode); + RewindTest::setup_cluster(); -# Create a test table and insert a row in master. -master_psql("CREATE TABLE tbl1 (d text)"); -master_psql("INSERT INTO tbl1 VALUES ('in master')"); + # Create a test table and insert a row in master. + master_psql("CREATE TABLE tbl1 (d text)"); + master_psql("INSERT INTO tbl1 VALUES ('in master')"); -# This test table will be used to test truncation, i.e. the table -# is extended in the old master after promotion -master_psql("CREATE TABLE trunc_tbl (d text)"); -master_psql("INSERT INTO trunc_tbl VALUES ('in master')"); + # This test table will be used to test truncation, i.e. the table + # is extended in the old master after promotion + master_psql("CREATE TABLE trunc_tbl (d text)"); + master_psql("INSERT INTO trunc_tbl VALUES ('in master')"); -# This test table will be used to test the "copy-tail" case, i.e. the -# table is truncated in the old master after promotion -master_psql("CREATE TABLE tail_tbl (id integer, d text)"); -master_psql("INSERT INTO tail_tbl VALUES (0, 'in master')"); + # This test table will be used to test the "copy-tail" case, i.e. the + # table is truncated in the old master after promotion + master_psql("CREATE TABLE tail_tbl (id integer, d text)"); + master_psql("INSERT INTO tail_tbl VALUES (0, 'in master')"); + master_psql("CHECKPOINT"); -master_psql("CHECKPOINT"); + RewindTest::create_standby(); -RewindTest::create_standby(); + # Insert additional data on master that will be replicated to standby + master_psql("INSERT INTO tbl1 values ('in master, before promotion')"); + master_psql("INSERT INTO trunc_tbl values ('in master, before promotion')"); + master_psql("INSERT INTO tail_tbl SELECT g, 'in master, before promotion: ' || g FROM generate_series(1, 10000) g"); -# Insert additional data on master that will be replicated to standby -master_psql("INSERT INTO tbl1 values ('in master, before promotion')"); -master_psql("INSERT INTO trunc_tbl values ('in master, before promotion')"); -master_psql("INSERT INTO tail_tbl SELECT g, 'in master, before promotion: ' || g FROM generate_series(1, 10000) g"); + master_psql('CHECKPOINT'); -master_psql('CHECKPOINT'); + RewindTest::promote_standby(); -RewindTest::promote_standby(); + # 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')"); -# 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')"); -# 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')"); + # Insert enough rows to trunc_tbl to extend the file. pg_rewind should + # truncate it back to the old size. + master_psql("INSERT INTO trunc_tbl SELECT 'in master, after promotion: ' || g FROM generate_series(1, 10000) g"); -# Insert enough rows to trunc_tbl to extend the file. pg_rewind should -# truncate it back to the old size. -master_psql("INSERT INTO trunc_tbl SELECT 'in master, after promotion: ' || g FROM generate_series(1, 10000) g"); + # Truncate tail_tbl. pg_rewind should copy back the truncated part + # (We cannot use an actual TRUNCATE command here, as that creates a + # whole new relfilenode) + master_psql("DELETE FROM tail_tbl WHERE id > 10"); + master_psql("VACUUM tail_tbl"); -# Truncate tail_tbl. pg_rewind should copy back the truncated part -# (We cannot use an actual TRUNCATE command here, as that creates a -# whole new relfilenode) -master_psql("DELETE FROM tail_tbl WHERE id > 10"); -master_psql("VACUUM tail_tbl"); + RewindTest::run_pg_rewind($test_mode); -RewindTest::run_pg_rewind(); - -check_query('SELECT * FROM tbl1', - qq(in master + check_query('SELECT * FROM tbl1', + qq(in master in master, before promotion in standby, after promotion ), - 'table content'); + 'table content'); -check_query('SELECT * FROM trunc_tbl', - qq(in master + check_query('SELECT * FROM trunc_tbl', + qq(in master in master, before promotion ), - 'truncation'); + 'truncation'); -check_query('SELECT count(*) FROM tail_tbl', - qq(10001 + check_query('SELECT count(*) FROM tail_tbl', + qq(10001 ), - 'tail-copy'); + 'tail-copy'); + +} + +# Run the test in both modes +run_test('local'); +run_test('remote'); exit(0); diff --git a/src/bin/pg_rewind/t/002_databases.pl b/src/bin/pg_rewind/t/002_databases.pl index 709c81e2650..1cf9a3a65d3 100644 --- a/src/bin/pg_rewind/t/002_databases.pl +++ b/src/bin/pg_rewind/t/002_databases.pl @@ -1,41 +1,49 @@ use strict; use warnings; use TestLib; -use Test::More tests => 2; +use Test::More tests => 4; use RewindTest; -my $testmode = shift; +sub run_test +{ + my $test_mode = shift; -RewindTest::init_rewind_test('databases', $testmode); -RewindTest::setup_cluster(); + RewindTest::init_rewind_test('databases', $test_mode); + RewindTest::setup_cluster(); -# Create a database in master. -master_psql('CREATE DATABASE inmaster'); + # Create a database in master. + master_psql('CREATE DATABASE inmaster'); -RewindTest::create_standby(); + RewindTest::create_standby(); -# Create another database, the creation is replicated to the standby -master_psql('CREATE DATABASE beforepromotion'); + # Create another database, the creation is replicated to the standby + master_psql('CREATE DATABASE beforepromotion'); -RewindTest::promote_standby(); + RewindTest::promote_standby(); -# Create databases in the old master and the new promoted standby. -master_psql('CREATE DATABASE master_afterpromotion'); -standby_psql('CREATE DATABASE standby_afterpromotion'); -# The clusters are now diverged. + # Create databases in the old master and the new promoted standby. + master_psql('CREATE DATABASE master_afterpromotion'); + standby_psql('CREATE DATABASE standby_afterpromotion'); + # The clusters are now diverged. -RewindTest::run_pg_rewind(); + RewindTest::run_pg_rewind($test_mode); -# Check that the correct databases are present after pg_rewind. -check_query('SELECT datname FROM pg_database', - qq(template1 + # Check that the correct databases are present after pg_rewind. + check_query('SELECT datname FROM pg_database', + qq(template1 template0 postgres inmaster beforepromotion standby_afterpromotion ), - 'database names'); + 'database names'); + +} + +# Run the test in both modes. +run_test('local'); +run_test('remote'); exit(0); diff --git a/src/bin/pg_rewind/t/003_extrafiles.pl b/src/bin/pg_rewind/t/003_extrafiles.pl index dd76fb83b54..218b865940c 100644 --- a/src/bin/pg_rewind/t/003_extrafiles.pl +++ b/src/bin/pg_rewind/t/003_extrafiles.pl @@ -3,59 +3,69 @@ use strict; use warnings; use TestLib; -use Test::More tests => 2; +use Test::More tests => 4; use File::Find; use RewindTest; -my $testmode = shift; -RewindTest::init_rewind_test('extrafiles', $testmode); -RewindTest::setup_cluster(); +sub run_test +{ + my $test_mode = shift; -# Create a subdir and files that will be present in both -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"; + RewindTest::init_rewind_test('extrafiles', $test_mode); + RewindTest::setup_cluster(); -RewindTest::create_standby(); + my $test_master_datadir = $RewindTest::test_master_datadir; -# Create different subdirs and files in master and standby + # Create a subdir and files that will be present in both + 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"; -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"; + RewindTest::create_standby(); -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"; + # Create different subdirs and files in master and standby -RewindTest::promote_standby(); -RewindTest::run_pg_rewind(); + 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"; -# List files in the data directory after rewind. -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"); + 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"; + + RewindTest::promote_standby(); + RewindTest::run_pg_rewind($test_mode); + + # List files in the data directory after rewind. + 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"); +} + +# Run the test in both modes. +run_test('local'); +run_test('remote'); exit(0);