From 3b5c60dc87f4440aa81d50d0c6363aea7a970347 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sun, 29 Oct 2023 16:48:16 +0100 Subject: [PATCH v3 2/2] pg_resetwal: Add more tests and test coverage Discussion: https://www.postgresql.org/message-id/flat/0f3ab4a1-ae80-56e8-3426-6b4a02507687@eisentraut.org --- src/bin/pg_resetwal/t/001_basic.pl | 120 +++++++++++++++++++++++++ src/bin/pg_resetwal/t/002_corrupted.pl | 4 + 2 files changed, 124 insertions(+) diff --git a/src/bin/pg_resetwal/t/001_basic.pl b/src/bin/pg_resetwal/t/001_basic.pl index 7e5efbf56b5..6c02c4ae74a 100644 --- a/src/bin/pg_resetwal/t/001_basic.pl +++ b/src/bin/pg_resetwal/t/001_basic.pl @@ -14,6 +14,7 @@ my $node = PostgreSQL::Test::Cluster->new('main'); $node->init; +$node->append_conf('postgresql.conf', 'track_commit_timestamp = on'); command_like([ 'pg_resetwal', '-n', $node->data_dir ], qr/checkpoint/, 'pg_resetwal -n produces output'); @@ -29,4 +30,123 @@ 'check PGDATA permissions'); } +command_ok([ 'pg_resetwal', '-D', $node->data_dir ], 'pg_resetwal runs'); +$node->start; +is($node->safe_psql("postgres", "SELECT 1;"), 1, 'server running and working after reset'); + +command_fails_like([ 'pg_resetwal', $node->data_dir ], qr/lock file .* exists/, 'fails if server running'); + +$node->stop('immediate'); +command_fails_like([ 'pg_resetwal', $node->data_dir ], qr/database server was not shut down cleanly/, 'does not run after immediate shutdown'); +command_ok([ 'pg_resetwal', '-f', $node->data_dir ], 'runs after immediate shutdown with force'); +$node->start; +is($node->safe_psql("postgres", "SELECT 1;"), 1, 'server running and working after forced reset'); + +$node->stop; + +# check various command-line handling + +# Note: This test intends to check that a nonexistent data directory +# gives a reasonable error message. Because of the way the code is +# currently structured, you get an error about readings permissions, +# which is perhaps suboptimal, so feel free to update this test if +# this gets improved. +command_fails_like([ 'pg_resetwal', 'foo' ], qr/error: could not read permissions of directory/, 'fails with nonexistent data directory'); + +command_fails_like([ 'pg_resetwal', 'foo', 'bar'], qr/too many command-line arguments/, 'fails with too many command-line arguments'); + +$ENV{PGDATA} = $node->data_dir; # not used +command_fails_like([ 'pg_resetwal' ], qr/no data directory specified/, 'fails with too few command-line arguments'); + +# error cases +# -c +command_fails_like([ 'pg_resetwal', '-c', 'foo', $node->data_dir], qr/error: invalid argument for option -c/, 'fails with incorrect -c option'); +command_fails_like([ 'pg_resetwal', '-c', '10,bar', $node->data_dir], qr/error: invalid argument for option -c/, 'fails with incorrect -c option part 2'); +command_fails_like([ 'pg_resetwal', '-c', '1,10', $node->data_dir], qr/greater than/, 'fails with -c value 1 part 1'); +command_fails_like([ 'pg_resetwal', '-c', '10,1', $node->data_dir], qr/greater than/, 'fails with -c value 1 part 2'); +# -e +command_fails_like([ 'pg_resetwal', '-e', 'foo', $node->data_dir], qr/error: invalid argument for option -e/, 'fails with incorrect -e option'); +command_fails_like([ 'pg_resetwal', '-e', '-1', $node->data_dir], qr/must not be -1/, 'fails with -e value -1'); +# -l +command_fails_like([ 'pg_resetwal', '-l', 'foo', $node->data_dir], qr/error: invalid argument for option -l/, 'fails with incorrect -l option'); +# -m +command_fails_like([ 'pg_resetwal', '-m', 'foo', $node->data_dir], qr/error: invalid argument for option -m/, 'fails with incorrect -m option'); +command_fails_like([ 'pg_resetwal', '-m', '10,bar', $node->data_dir], qr/error: invalid argument for option -m/, 'fails with incorrect -m option part 2'); +command_fails_like([ 'pg_resetwal', '-m', '0,10', $node->data_dir], qr/must not be 0/, 'fails with -m value 0 part 1'); +command_fails_like([ 'pg_resetwal', '-m', '10,0', $node->data_dir], qr/must not be 0/, 'fails with -m value 0 part 2'); +# -o +command_fails_like([ 'pg_resetwal', '-o', 'foo', $node->data_dir], qr/error: invalid argument for option -o/, 'fails with incorrect -o option'); +command_fails_like([ 'pg_resetwal', '-o', '0', $node->data_dir], qr/must not be 0/, 'fails with -o value 0'); +# -O +command_fails_like([ 'pg_resetwal', '-O', 'foo', $node->data_dir], qr/error: invalid argument for option -O/, 'fails with incorrect -O option'); +command_fails_like([ 'pg_resetwal', '-O', '-1', $node->data_dir], qr/must not be -1/, 'fails with -O value -1'); +# --wal-segsize +command_fails_like([ 'pg_resetwal', '--wal-segsize', 'foo', $node->data_dir], qr/error: invalid value/, 'fails with incorrect --wal-segsize option'); +command_fails_like([ 'pg_resetwal', '--wal-segsize', '13', $node->data_dir], qr/must be a power/, 'fails with invalid --wal-segsize value'); +# -u +command_fails_like([ 'pg_resetwal', '-u', 'foo', $node->data_dir], qr/error: invalid argument for option -u/, 'fails with incorrect -u option'); +command_fails_like([ 'pg_resetwal', '-u', '1', $node->data_dir], qr/must be greater than/, 'fails with -u value too small'); +# -x +command_fails_like([ 'pg_resetwal', '-x', 'foo', $node->data_dir], qr/error: invalid argument for option -x/, 'fails with incorrect -x option'); +command_fails_like([ 'pg_resetwal', '-x', '1', $node->data_dir], qr/must be greater than/, 'fails with -x value too small'); + +# run with control override options + +my $out = (run_command([ 'pg_resetwal', '-n', $node->data_dir ]))[0]; +$out =~ /^Database block size: *(\d+)$/m or die; +my $blcksz = $1; + +my @cmd = ('pg_resetwal', '-D', $node->data_dir); + +# some not-so-critical hardcoded values +push @cmd, '-e', 1; +push @cmd, '-l', '00000001000000320000004B'; +push @cmd, '-o', 100_000; +push @cmd, '--wal-segsize', 1; + +# these use the guidance from the documentation + +sub get_slru_files +{ + opendir(my $dh, $node->data_dir . '/' . $_[0]) or die $!; + my @files = sort grep { /[0-9A-F]+/ } readdir $dh; + closedir $dh; + return @files; +} + +my (@files, $mult); + +@files = get_slru_files('pg_commit_ts'); +# XXX: Should there be a multiplier, similar to the other options? +# -c argument is "old,new" +push @cmd, + '-c', sprintf("%d,%d", + hex($files[0]) == 0 ? 3 : hex($files[0]), hex($files[-1])); + +@files = get_slru_files('pg_multixact/offsets'); +$mult = 32 * $blcksz / 4; +# -m argument is "new,old" +push @cmd, + '-m', sprintf("%d,%d", + (hex($files[-1]) + 1) * $mult, + hex($files[0]) == 0 ? 1 : hex($files[0] * $mult)); + +@files = get_slru_files('pg_multixact/members'); +$mult = 32 * int($blcksz/20) * 4; +push @cmd, + '-O', (hex($files[-1]) + 1) * $mult; + +@files = get_slru_files('pg_xact'); +$mult = 32 * $blcksz * 4; +push @cmd, + '-u', (hex($files[0]) == 0 ? 3 : hex($files[0]) * $mult), + '-x', ((hex($files[-1]) + 1) * $mult); + +command_ok([@cmd, '-n'], 'runs with control override options, dry run'); +command_ok(\@cmd, 'runs with control override options'); +command_like([ 'pg_resetwal', '-n', $node->data_dir ], qr/^Latest checkpoint's NextOID: *100000$/m, 'spot check that control changes were applied'); + +$node->start; +ok(1, 'server started after reset'); + done_testing(); diff --git a/src/bin/pg_resetwal/t/002_corrupted.pl b/src/bin/pg_resetwal/t/002_corrupted.pl index b3a37728a42..ee888504730 100644 --- a/src/bin/pg_resetwal/t/002_corrupted.pl +++ b/src/bin/pg_resetwal/t/002_corrupted.pl @@ -55,4 +55,8 @@ ], 'processes zero WAL segment size'); +# now try to run it +command_fails_like([ 'pg_resetwal', $node->data_dir ], qr/not proceeding because control file values were guessed/, 'does not run when control file values were guessed'); +command_ok([ 'pg_resetwal', '-f', $node->data_dir ], 'runs with force when control file values were guessed'); + done_testing(); -- 2.42.0