Skip to content

Commit 10ad9d8

Browse files
committed
Add pg_rewind tests for encrypted WAL
These tests are a copy of upstream's pg_rewind tests with small changes in setup_cluster to set WAL encryption on. `standby_source` test is not copied as it fails because of changes needed in pg_basebackup.
1 parent f1a34d2 commit 10ad9d8

11 files changed

+1287
-0
lines changed

contrib/pg_tde/meson.build

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ tap_tests = [
118118
't/013_crash_recovery.pl',
119119
't/014_pg_waldump_basic.pl',
120120
't/015_pg_waldump_fullpage.pl',
121+
't/016_pg_rewind_basic.pl',
122+
't/017_pg_rewind_databases.pl',
123+
't/018_pg_rewind_extrafiles.pl',
124+
't/019_pg_rewind_pg_xlog_symlink.pl',
125+
't/020_pg_rewind_same_timeline.pl',
126+
't/021_pg_rewind_options.pl',
127+
't/022_pg_rewind_min_recovery_point.pl',
128+
't/023_pg_rewind_growing_files.pl',
129+
't/024_pg_rewind_keep_recycled_wals.pl',
121130
]
122131

123132
tests += {
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
2+
# Copyright (c) 2021-2024, PostgreSQL Global Development Group
3+
4+
use strict;
5+
use warnings FATAL => 'all';
6+
use PostgreSQL::Test::Utils;
7+
use Test::More;
8+
9+
use FindBin;
10+
use lib $FindBin::RealBin;
11+
12+
use RewindTest;
13+
14+
sub run_test
15+
{
16+
my $test_mode = shift;
17+
18+
RewindTest::setup_cluster($test_mode);
19+
RewindTest::start_primary();
20+
21+
# Create an in-place tablespace with some data on it.
22+
primary_psql("CREATE TABLESPACE space_test LOCATION ''");
23+
primary_psql("CREATE TABLE space_tbl (d text) TABLESPACE space_test");
24+
primary_psql(
25+
"INSERT INTO space_tbl VALUES ('in primary, before promotion')");
26+
27+
# Create a test table and insert a row in primary.
28+
primary_psql("CREATE TABLE tbl1 (d text)");
29+
primary_psql("INSERT INTO tbl1 VALUES ('in primary')");
30+
31+
# This test table will be used to test truncation, i.e. the table
32+
# is extended in the old primary after promotion
33+
primary_psql("CREATE TABLE trunc_tbl (d text)");
34+
primary_psql("INSERT INTO trunc_tbl VALUES ('in primary')");
35+
36+
# This test table will be used to test the "copy-tail" case, i.e. the
37+
# table is truncated in the old primary after promotion
38+
primary_psql("CREATE TABLE tail_tbl (id integer, d text)");
39+
primary_psql("INSERT INTO tail_tbl VALUES (0, 'in primary')");
40+
41+
# This test table is dropped in the old primary after promotion.
42+
primary_psql("CREATE TABLE drop_tbl (d text)");
43+
primary_psql("INSERT INTO drop_tbl VALUES ('in primary')");
44+
45+
primary_psql("CHECKPOINT");
46+
47+
RewindTest::create_standby($test_mode);
48+
49+
# Insert additional data on primary that will be replicated to standby
50+
primary_psql("INSERT INTO tbl1 values ('in primary, before promotion')");
51+
primary_psql(
52+
"INSERT INTO trunc_tbl values ('in primary, before promotion')");
53+
primary_psql(
54+
"INSERT INTO tail_tbl SELECT g, 'in primary, before promotion: ' || g FROM generate_series(1, 10000) g"
55+
);
56+
57+
primary_psql('CHECKPOINT');
58+
59+
RewindTest::promote_standby();
60+
61+
# Insert a row in the old primary. This causes the primary and standby
62+
# to have "diverged", it's no longer possible to just apply the
63+
# standby's logs over primary directory - you need to rewind.
64+
primary_psql("INSERT INTO tbl1 VALUES ('in primary, after promotion')");
65+
66+
# Also insert a new row in the standby, which won't be present in the
67+
# old primary.
68+
standby_psql("INSERT INTO tbl1 VALUES ('in standby, after promotion')");
69+
70+
# Insert enough rows to trunc_tbl to extend the file. pg_rewind should
71+
# truncate it back to the old size.
72+
primary_psql(
73+
"INSERT INTO trunc_tbl SELECT 'in primary, after promotion: ' || g FROM generate_series(1, 10000) g"
74+
);
75+
76+
# Truncate tail_tbl. pg_rewind should copy back the truncated part
77+
# (We cannot use an actual TRUNCATE command here, as that creates a
78+
# whole new relfilenode)
79+
primary_psql("DELETE FROM tail_tbl WHERE id > 10");
80+
primary_psql("VACUUM tail_tbl");
81+
82+
# Drop drop_tbl. pg_rewind should copy it back.
83+
primary_psql(
84+
"insert into drop_tbl values ('in primary, after promotion')");
85+
primary_psql("DROP TABLE drop_tbl");
86+
87+
# Insert some data in the in-place tablespace for the old primary and
88+
# the standby.
89+
primary_psql(
90+
"INSERT INTO space_tbl VALUES ('in primary, after promotion')");
91+
standby_psql(
92+
"INSERT INTO space_tbl VALUES ('in standby, after promotion')");
93+
94+
# Before running pg_rewind, do a couple of extra tests with several
95+
# option combinations. As the code paths taken by those tests
96+
# do not change for the "local" and "remote" modes, just run them
97+
# in "local" mode for simplicity's sake.
98+
if ($test_mode eq 'local')
99+
{
100+
my $primary_pgdata = $node_primary->data_dir;
101+
my $standby_pgdata = $node_standby->data_dir;
102+
103+
# First check that pg_rewind fails if the target cluster is
104+
# not stopped as it fails to start up for the forced recovery
105+
# step.
106+
command_fails(
107+
[
108+
'pg_rewind', '--debug',
109+
'--source-pgdata', $standby_pgdata,
110+
'--target-pgdata', $primary_pgdata,
111+
'--no-sync'
112+
],
113+
'pg_rewind with running target');
114+
115+
# Again with --no-ensure-shutdown, which should equally fail.
116+
# This time pg_rewind complains without attempting to perform
117+
# recovery once.
118+
command_fails(
119+
[
120+
'pg_rewind', '--debug',
121+
'--source-pgdata', $standby_pgdata,
122+
'--target-pgdata', $primary_pgdata,
123+
'--no-sync', '--no-ensure-shutdown'
124+
],
125+
'pg_rewind --no-ensure-shutdown with running target');
126+
127+
# Stop the target, and attempt to run with a local source
128+
# still running. This fails as pg_rewind requires to have
129+
# a source cleanly stopped.
130+
$node_primary->stop;
131+
command_fails(
132+
[
133+
'pg_rewind', '--debug',
134+
'--source-pgdata', $standby_pgdata,
135+
'--target-pgdata', $primary_pgdata,
136+
'--no-sync', '--no-ensure-shutdown'
137+
],
138+
'pg_rewind with unexpected running source');
139+
140+
# Stop the target cluster cleanly, and run again pg_rewind
141+
# with --dry-run mode. If anything gets generated in the data
142+
# folder, the follow-up run of pg_rewind will most likely fail,
143+
# so keep this test as the last one of this subset.
144+
$node_standby->stop;
145+
command_ok(
146+
[
147+
'pg_rewind', '--debug',
148+
'--source-pgdata', $standby_pgdata,
149+
'--target-pgdata', $primary_pgdata,
150+
'--no-sync', '--dry-run'
151+
],
152+
'pg_rewind --dry-run');
153+
154+
# Both clusters need to be alive moving forward.
155+
$node_standby->start;
156+
$node_primary->start;
157+
}
158+
159+
RewindTest::run_pg_rewind($test_mode);
160+
161+
check_query(
162+
'SELECT * FROM space_tbl ORDER BY d',
163+
qq(in primary, before promotion
164+
in standby, after promotion
165+
),
166+
'table content');
167+
168+
check_query(
169+
'SELECT * FROM tbl1',
170+
qq(in primary
171+
in primary, before promotion
172+
in standby, after promotion
173+
),
174+
'table content');
175+
176+
check_query(
177+
'SELECT * FROM trunc_tbl',
178+
qq(in primary
179+
in primary, before promotion
180+
),
181+
'truncation');
182+
183+
check_query(
184+
'SELECT count(*) FROM tail_tbl',
185+
qq(10001
186+
),
187+
'tail-copy');
188+
189+
check_query(
190+
'SELECT * FROM drop_tbl',
191+
qq(in primary
192+
),
193+
'drop');
194+
195+
# Permissions on PGDATA should be default
196+
SKIP:
197+
{
198+
skip "unix-style permissions not supported on Windows", 1
199+
if ($windows_os);
200+
201+
ok(check_mode_recursive($node_primary->data_dir(), 0700, 0600),
202+
'check PGDATA permissions');
203+
}
204+
205+
RewindTest::clean_rewind_test();
206+
return;
207+
}
208+
209+
# Run the test in both modes
210+
run_test('local');
211+
run_test('remote');
212+
run_test('archive');
213+
214+
done_testing();
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
# Copyright (c) 2021-2024, PostgreSQL Global Development Group
3+
4+
use strict;
5+
use warnings FATAL => 'all';
6+
use PostgreSQL::Test::Utils;
7+
use Test::More;
8+
9+
use FindBin;
10+
use lib $FindBin::RealBin;
11+
12+
use RewindTest;
13+
14+
sub run_test
15+
{
16+
my $test_mode = shift;
17+
18+
RewindTest::setup_cluster($test_mode, ['-g']);
19+
RewindTest::start_primary();
20+
21+
# Create a database in primary with a table.
22+
primary_psql('CREATE DATABASE inprimary');
23+
primary_psql('CREATE TABLE inprimary_tab (a int)', 'inprimary');
24+
25+
RewindTest::create_standby($test_mode);
26+
27+
# Create another database with another table, the creation is
28+
# replicated to the standby.
29+
primary_psql('CREATE DATABASE beforepromotion');
30+
primary_psql('CREATE TABLE beforepromotion_tab (a int)',
31+
'beforepromotion');
32+
33+
RewindTest::promote_standby();
34+
35+
# Create databases in the old primary and the new promoted standby.
36+
primary_psql('CREATE DATABASE primary_afterpromotion');
37+
primary_psql('CREATE TABLE primary_promotion_tab (a int)',
38+
'primary_afterpromotion');
39+
standby_psql('CREATE DATABASE standby_afterpromotion');
40+
standby_psql('CREATE TABLE standby_promotion_tab (a int)',
41+
'standby_afterpromotion');
42+
43+
# The clusters are now diverged.
44+
45+
RewindTest::run_pg_rewind($test_mode);
46+
47+
# Check that the correct databases are present after pg_rewind.
48+
check_query(
49+
'SELECT datname FROM pg_database ORDER BY 1',
50+
qq(beforepromotion
51+
inprimary
52+
postgres
53+
standby_afterpromotion
54+
template0
55+
template1
56+
),
57+
'database names');
58+
59+
# Permissions on PGDATA should have group permissions
60+
SKIP:
61+
{
62+
skip "unix-style permissions not supported on Windows", 1
63+
if ($windows_os || $Config::Config{osname} eq 'cygwin');
64+
65+
ok(check_mode_recursive($node_primary->data_dir(), 0750, 0640),
66+
'check PGDATA permissions');
67+
}
68+
69+
RewindTest::clean_rewind_test();
70+
return;
71+
}
72+
73+
# Run the test in both modes.
74+
run_test('local');
75+
run_test('remote');
76+
77+
done_testing();

0 commit comments

Comments
 (0)