]> granicus.if.org Git - postgresql/commitdiff
Add TAP tests for pg_verify_checksums
authorMichael Paquier <michael@paquier.xyz>
Fri, 12 Oct 2018 00:12:31 +0000 (09:12 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 12 Oct 2018 00:12:31 +0000 (09:12 +0900)
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

src/bin/initdb/t/001_initdb.pl
src/bin/pg_verify_checksums/.gitignore
src/bin/pg_verify_checksums/Makefile
src/bin/pg_verify_checksums/t/001_basic.pl [new file with mode: 0644]
src/bin/pg_verify_checksums/t/002_actions.pl [new file with mode: 0644]

index 5dc629fd5ecbc5e2c622749bcd8197b65ac89072..759779adb24d5e64a0e3937ab8fd7b8b0abd1cbc 100644 (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');
 
index d1dcdaf0dd433c56d501e0470dbcaa7f2ccf4d52..0e5e569a54c5de1976a684b002647bdb80e95cdf 100644 (file)
@@ -1 +1,3 @@
 /pg_verify_checksums
+
+/tmp_check/
index d16261571f8da159fc5a5b085f0da3ab0f1f4c5e..cfe4ab1b8bb6921c075e00fe9ba6fe8e9bb6c8e7 100644 (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)
diff --git a/src/bin/pg_verify_checksums/t/001_basic.pl b/src/bin/pg_verify_checksums/t/001_basic.pl
new file mode 100644 (file)
index 0000000..1fa2e12
--- /dev/null
@@ -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');
diff --git a/src/bin/pg_verify_checksums/t/002_actions.pl b/src/bin/pg_verify_checksums/t/002_actions.pl
new file mode 100644 (file)
index 0000000..dc29da0
--- /dev/null
@@ -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');