Add TAP tests for pg_verify_checksums

All options available in the utility get coverage:
- Tests with disabled page checksums.
- Tests with enabled test checksums.
- Emulation of corruption and broken checksums with a full scan and
single relfilenode scan.

This patch has been contributed mainly by Michael Banck and Magnus
Hagander with things presented on various threads, and I have gathered
all the contents into a single patch.

Author: Michael Banck, Magnus Hagander, Michael Paquier
Reviewed-by: Peter Eisentraut
Discussion: https://postgr.es/m/20181005012645.GE1629@paquier.xyz
This commit is contained in:
Michael Paquier 2018-10-12 09:12:31 +09:00
parent cda6a8d01d
commit b34e84f160
5 changed files with 98 additions and 1 deletions

View File

@ -8,7 +8,7 @@ use Fcntl ':mode';
use File::stat qw{lstat};
use PostgresNode;
use TestLib;
use Test::More tests => 18;
use Test::More tests => 22;
my $tempdir = TestLib::tempdir;
my $xlogdir = "$tempdir/pgxlog";
@ -58,6 +58,18 @@ mkdir $datadir;
"check PGDATA permissions");
}
}
# Control file should tell that data checksums are disabled by default.
command_like(['pg_controldata', $datadir],
qr/Data page checksum version:.*0/,
'checksums are disabled in control file');
# pg_verify_checksums fails with checksums disabled by default. This is
# not part of the tests included in pg_verify_checksums to save from
# the creation of an extra instance.
command_fails(
[ 'pg_verify_checksums', '-D', $datadir],
"pg_verify_checksums fails with data checksum disabled");
command_ok([ 'initdb', '-S', $datadir ], 'sync only');
command_fails([ 'initdb', $datadir ], 'existing data directory');

View File

@ -1 +1,3 @@
/pg_verify_checksums
/tmp_check/

View File

@ -34,3 +34,9 @@ uninstall:
clean distclean maintainer-clean:
rm -f pg_verify_checksums$(X) $(OBJS)
rm -rf tmp_check
check:
$(prove_check)
installcheck:
$(prove_installcheck)

View File

@ -0,0 +1,8 @@
use strict;
use warnings;
use TestLib;
use Test::More tests => 8;
program_help_ok('pg_verify_checksums');
program_version_ok('pg_verify_checksums');
program_options_handling_ok('pg_verify_checksums');

View File

@ -0,0 +1,69 @@
# Do basic sanity checks supported by pg_verify_checksums using
# an initialized cluster.
use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 12;
# Initialize node with checksums enabled.
my $node = get_new_node('node_checksum');
$node->init(extra => ['--data-checksums']);
my $pgdata = $node->data_dir;
# Control file should know that checksums are enabled.
command_like(['pg_controldata', $pgdata],
qr/Data page checksum version:.*1/,
'checksums enabled in control file');
# Checksums pass on a newly-created cluster
command_ok(['pg_verify_checksums', '-D', $pgdata],
"succeeds with offline cluster");
# Checks cannot happen with an online cluster
$node->start;
command_fails(['pg_verify_checksums', '-D', $pgdata],
"fails with online cluster");
# Create table to corrupt and get its relfilenode
$node->safe_psql('postgres',
"SELECT a INTO corrupt1 FROM generate_series(1,10000) AS a;
ALTER TABLE corrupt1 SET (autovacuum_enabled=false);");
my $file_corrupted = $node->safe_psql('postgres',
"SELECT pg_relation_filepath('corrupt1')");
my $relfilenode_corrupted = $node->safe_psql('postgres',
"SELECT relfilenode FROM pg_class WHERE relname = 'corrupt1';");
# Set page header and block size
my $pageheader_size = 24;
my $block_size = $node->safe_psql('postgres', 'SHOW block_size;');
$node->stop;
# Checksums are correct for single relfilenode as the table is not
# corrupted yet.
command_ok(['pg_verify_checksums', '-D', $pgdata,
'-r', $relfilenode_corrupted],
"succeeds for single relfilenode with offline cluster");
# Time to create some corruption
open my $file, '+<', "$pgdata/$file_corrupted";
seek($file, $pageheader_size, 0);
syswrite($file, '\0\0\0\0\0\0\0\0\0');
close $file;
# Global checksum checks fail
$node->command_checks_all([ 'pg_verify_checksums', '-D', $pgdata],
1,
[qr/Bad checksums:.*1/],
[qr/checksum verification failed/],
'fails with corrupted data');
# Checksum checks on single relfilenode fail
$node->command_checks_all([ 'pg_verify_checksums', '-D', $pgdata, '-r',
$relfilenode_corrupted],
1,
[qr/Bad checksums:.*1/],
[qr/checksum verification failed/],
'fails for corrupted data on single relfilenode');