summaryrefslogtreecommitdiffstats
path: root/src/bin/pg_rewind/t/001_basic.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_rewind/t/001_basic.pl')
-rw-r--r--src/bin/pg_rewind/t/001_basic.pl194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/bin/pg_rewind/t/001_basic.pl b/src/bin/pg_rewind/t/001_basic.pl
new file mode 100644
index 0000000..db9201f
--- /dev/null
+++ b/src/bin/pg_rewind/t/001_basic.pl
@@ -0,0 +1,194 @@
+
+# Copyright (c) 2021-2022, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+use FindBin;
+use lib $FindBin::RealBin;
+
+use RewindTest;
+
+sub run_test
+{
+ my $test_mode = shift;
+
+ RewindTest::setup_cluster($test_mode);
+ RewindTest::start_primary();
+
+ # Create a test table and insert a row in primary.
+ primary_psql("CREATE TABLE tbl1 (d text)");
+ primary_psql("INSERT INTO tbl1 VALUES ('in primary')");
+
+ # This test table will be used to test truncation, i.e. the table
+ # is extended in the old primary after promotion
+ primary_psql("CREATE TABLE trunc_tbl (d text)");
+ primary_psql("INSERT INTO trunc_tbl VALUES ('in primary')");
+
+ # This test table will be used to test the "copy-tail" case, i.e. the
+ # table is truncated in the old primary after promotion
+ primary_psql("CREATE TABLE tail_tbl (id integer, d text)");
+ primary_psql("INSERT INTO tail_tbl VALUES (0, 'in primary')");
+
+ # This test table is dropped in the old primary after promotion.
+ primary_psql("CREATE TABLE drop_tbl (d text)");
+ primary_psql("INSERT INTO drop_tbl VALUES ('in primary')");
+
+ primary_psql("CHECKPOINT");
+
+ RewindTest::create_standby($test_mode);
+
+ # Insert additional data on primary that will be replicated to standby
+ primary_psql("INSERT INTO tbl1 values ('in primary, before promotion')");
+ primary_psql(
+ "INSERT INTO trunc_tbl values ('in primary, before promotion')");
+ primary_psql(
+ "INSERT INTO tail_tbl SELECT g, 'in primary, before promotion: ' || g FROM generate_series(1, 10000) g"
+ );
+
+ primary_psql('CHECKPOINT');
+
+ RewindTest::promote_standby();
+
+ # Insert a row in the old primary. This causes the primary and standby
+ # to have "diverged", it's no longer possible to just apply the
+ # standy's logs over primary directory - you need to rewind.
+ primary_psql("INSERT INTO tbl1 VALUES ('in primary, after promotion')");
+
+ # Also insert a new row in the standby, which won't be present in the
+ # old primary.
+ 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.
+ primary_psql(
+ "INSERT INTO trunc_tbl SELECT 'in primary, 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)
+ primary_psql("DELETE FROM tail_tbl WHERE id > 10");
+ primary_psql("VACUUM tail_tbl");
+
+ # Drop drop_tbl. pg_rewind should copy it back.
+ primary_psql(
+ "insert into drop_tbl values ('in primary, after promotion')");
+ primary_psql("DROP TABLE drop_tbl");
+
+ # Before running pg_rewind, do a couple of extra tests with several
+ # option combinations. As the code paths taken by those tests
+ # do not change for the "local" and "remote" modes, just run them
+ # in "local" mode for simplicity's sake.
+ if ($test_mode eq 'local')
+ {
+ my $primary_pgdata = $node_primary->data_dir;
+ my $standby_pgdata = $node_standby->data_dir;
+
+ # First check that pg_rewind fails if the target cluster is
+ # not stopped as it fails to start up for the forced recovery
+ # step.
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $primary_pgdata,
+ '--no-sync'
+ ],
+ 'pg_rewind with running target');
+
+ # Again with --no-ensure-shutdown, which should equally fail.
+ # This time pg_rewind complains without attempting to perform
+ # recovery once.
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $primary_pgdata,
+ '--no-sync', '--no-ensure-shutdown'
+ ],
+ 'pg_rewind --no-ensure-shutdown with running target');
+
+ # Stop the target, and attempt to run with a local source
+ # still running. This fails as pg_rewind requires to have
+ # a source cleanly stopped.
+ $node_primary->stop;
+ command_fails(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $primary_pgdata,
+ '--no-sync', '--no-ensure-shutdown'
+ ],
+ 'pg_rewind with unexpected running source');
+
+ # Stop the target cluster cleanly, and run again pg_rewind
+ # with --dry-run mode. If anything gets generated in the data
+ # folder, the follow-up run of pg_rewind will most likely fail,
+ # so keep this test as the last one of this subset.
+ $node_standby->stop;
+ command_ok(
+ [
+ 'pg_rewind', '--debug',
+ '--source-pgdata', $standby_pgdata,
+ '--target-pgdata', $primary_pgdata,
+ '--no-sync', '--dry-run'
+ ],
+ 'pg_rewind --dry-run');
+
+ # Both clusters need to be alive moving forward.
+ $node_standby->start;
+ $node_primary->start;
+ }
+
+ RewindTest::run_pg_rewind($test_mode);
+
+ check_query(
+ 'SELECT * FROM tbl1',
+ qq(in primary
+in primary, before promotion
+in standby, after promotion
+),
+ 'table content');
+
+ check_query(
+ 'SELECT * FROM trunc_tbl',
+ qq(in primary
+in primary, before promotion
+),
+ 'truncation');
+
+ check_query(
+ 'SELECT count(*) FROM tail_tbl',
+ qq(10001
+),
+ 'tail-copy');
+
+ check_query(
+ 'SELECT * FROM drop_tbl',
+ qq(in primary
+),
+ 'drop');
+
+ # Permissions on PGDATA should be default
+ SKIP:
+ {
+ skip "unix-style permissions not supported on Windows", 1
+ if ($windows_os);
+
+ ok(check_mode_recursive($node_primary->data_dir(), 0700, 0600),
+ 'check PGDATA permissions');
+ }
+
+ RewindTest::clean_rewind_test();
+ return;
+}
+
+# Run the test in both modes
+run_test('local');
+run_test('remote');
+run_test('archive');
+
+done_testing();