v10-0004-Regression-tests-for-pg_validatebackup.patch
application/octet-stream
Filename: v10-0004-Regression-tests-for-pg_validatebackup.patch
Type: application/octet-stream
Part: 0
Message:
Re: backup manifests
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v10-0004
Subject: Regression tests for pg_validatebackup.
| File | + | − |
|---|---|---|
| src/bin/pg_validatebackup/.gitignore | 1 | 0 |
| src/bin/pg_validatebackup/Makefile | 6 | 0 |
| src/bin/pg_validatebackup/t/001_basic.pl | 27 | 0 |
| src/bin/pg_validatebackup/t/002_algorithm.pl | 55 | 0 |
| src/bin/pg_validatebackup/t/003_corruption.pl | 178 | 0 |
From 0fcfaa3691f681a5470399f97ab674873567bf48 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Tue, 10 Mar 2020 13:44:46 -0400
Subject: [PATCH v10 4/4] Regression tests for pg_validatebackup.
Patch by me, based in part on ideas from Mark Dilger and
Rajkumar Raghuwanshi.
---
src/bin/pg_validatebackup/.gitignore | 1 +
src/bin/pg_validatebackup/Makefile | 6 +
src/bin/pg_validatebackup/t/001_basic.pl | 27 +++
src/bin/pg_validatebackup/t/002_algorithm.pl | 55 ++++++
src/bin/pg_validatebackup/t/003_corruption.pl | 178 ++++++++++++++++++
5 files changed, 267 insertions(+)
create mode 100644 src/bin/pg_validatebackup/t/001_basic.pl
create mode 100644 src/bin/pg_validatebackup/t/002_algorithm.pl
create mode 100644 src/bin/pg_validatebackup/t/003_corruption.pl
diff --git a/src/bin/pg_validatebackup/.gitignore b/src/bin/pg_validatebackup/.gitignore
index 3ae1c1f03a..21e0a92429 100644
--- a/src/bin/pg_validatebackup/.gitignore
+++ b/src/bin/pg_validatebackup/.gitignore
@@ -1 +1,2 @@
/pg_validatebackup
+/tmp_check/
diff --git a/src/bin/pg_validatebackup/Makefile b/src/bin/pg_validatebackup/Makefile
index dde7eb3c02..04ef7d3051 100644
--- a/src/bin/pg_validatebackup/Makefile
+++ b/src/bin/pg_validatebackup/Makefile
@@ -31,3 +31,9 @@ uninstall:
clean distclean maintainer-clean:
rm -f pg_validatebackup$(X) $(OBJS)
+
+check:
+ $(prove_check)
+
+installcheck:
+ $(prove_installcheck)
diff --git a/src/bin/pg_validatebackup/t/001_basic.pl b/src/bin/pg_validatebackup/t/001_basic.pl
new file mode 100644
index 0000000000..49153f89ac
--- /dev/null
+++ b/src/bin/pg_validatebackup/t/001_basic.pl
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+use TestLib;
+use Test::More tests => 14;
+
+my $tempdir = TestLib::tempdir;
+
+program_help_ok('pg_validatebackup');
+program_version_ok('pg_validatebackup');
+program_options_handling_ok('pg_validatebackup');
+
+command_fails_like(['pg_validatebackup'],
+ qr/no backup directory specified/,
+ 'pg_validatebackup needs target directory specified');
+command_fails_like(['pg_validatebackup', $tempdir],
+ qr/could not open file.*\/backup_manifest\"/,
+ 'pg_validatebackup requires a manifest');
+
+# create fake manifest file
+open(my $fh, '>', "$tempdir/backup_manifest") || die "open: $!";
+close($fh);
+
+# but then try to use an alternate, nonexisting manifest
+command_fails_like(['pg_validatebackup', '-m', "$tempdir/not_the_manifest",
+ $tempdir],
+ qr/could not open file.*\/not_the_manifest\"/,
+ 'pg_validatebackup respects -m flag');
diff --git a/src/bin/pg_validatebackup/t/002_algorithm.pl b/src/bin/pg_validatebackup/t/002_algorithm.pl
new file mode 100644
index 0000000000..9bb89d3855
--- /dev/null
+++ b/src/bin/pg_validatebackup/t/002_algorithm.pl
@@ -0,0 +1,55 @@
+use strict;
+use warnings;
+use Cwd;
+use Config;
+use File::Path qw(rmtree);
+use PostgresNode;
+use TestLib;
+use Test::More tests => 19;
+
+my $master = get_new_node('master');
+$master->init(allows_streaming => 1);
+$master->start;
+
+for my $algorithm (qw(bogus none crc32c sha224 sha256 sha384 sha512))
+{
+ my $backup_path = $master->backup_dir . '/' . $algorithm;
+ my @backup = ('pg_basebackup', '-D', $backup_path, '-m', $algorithm,
+ '--no-sync');
+ my @validate = ('pg_validatebackup', '-e', $backup_path);
+
+ # A backup with a bogus algorithm should fail.
+ if ($algorithm eq 'bogus')
+ {
+ $master->command_fails(\@backup,
+ "backup fails with algorithm \"$algorithm\"");
+ next;
+ }
+
+ # A backup with a valid algorithm should work.
+ $master->command_ok(\@backup, "backup ok with algorithm \"$algorithm\"");
+
+ # We expect each real checksum algorithm to be mentioned on every line of
+ # the backup manifest file except the first and last; for simplicity, we
+ # just check that it shows up lots of times. When the checksum algorithm
+ # is none, we just check that the manifest exists.
+ if ($algorithm eq 'none')
+ {
+ ok(-f "$backup_path/backup_manifest", "backup manifest exists");
+ }
+ else
+ {
+ my $manifest = slurp_file("$backup_path/backup_manifest");
+ my $count_of_algorithm_in_manifest =
+ (() = $manifest =~ /$algorithm/mig);
+ cmp_ok($count_of_algorithm_in_manifest, '>', 100,
+ "$algorithm is mentioned many times in the manifest");
+ }
+
+ # Make sure that it validates OK.
+ $master->command_ok(\@validate,
+ "validate backup with algorithm \"$algorithm\"");
+
+ # Remove backup immediately to save disk space.
+ rmtree($backup_path);
+}
diff --git a/src/bin/pg_validatebackup/t/003_corruption.pl b/src/bin/pg_validatebackup/t/003_corruption.pl
new file mode 100644
index 0000000000..07ed7b6657
--- /dev/null
+++ b/src/bin/pg_validatebackup/t/003_corruption.pl
@@ -0,0 +1,178 @@
+use strict;
+use warnings;
+use Cwd;
+use Config;
+use File::Path qw(rmtree);
+use PostgresNode;
+use TestLib;
+use Test::More tests => 32;
+
+my $master = get_new_node('master');
+$master->init(allows_streaming => 1);
+$master->start;
+
+# Include a user-defined tablespace in the hopes of detecting problems in that
+# area.
+my $source_ts_path = TestLib::tempdir;
+$master->safe_psql('postgres', <<EOM);
+CREATE TABLE x1 (a int);
+INSERT INTO x1 VALUES (111);
+CREATE TABLESPACE ts1 LOCATION '$source_ts_path';
+CREATE TABLE x2 (a int) TABLESPACE ts1;
+INSERT INTO x1 VALUES (222);
+EOM
+
+my @scenario = (
+ {
+ 'name' => 'extra_file',
+ 'mutilate' => \&mutilate_extra_file,
+ 'fails_like' =>
+ qr/extra_file.*present on disk but not in the manifest/
+ },
+ {
+ 'name' => 'extra_tablespace_file',
+ 'mutilate' => \&mutilate_extra_tablespace_file,
+ 'fails_like' =>
+ qr/extra_ts_file.*present on disk but not in the manifest/
+ },
+ {
+ 'name' => 'missing_file',
+ 'mutilate' => \&mutilate_missing_file,
+ 'fails_like' =>
+ qr/pg_xact\/0000.*present in the manifest but not on disk/
+ },
+ {
+ 'name' => 'missing_tablespace',
+ 'mutilate' => \&mutilate_missing_tablespace,
+ 'fails_like' =>
+ qr/pg_tblspc.*present in the manifest but not on disk/
+ },
+ {
+ 'name' => 'append_to_file',
+ 'mutilate' => \&mutilate_append_to_file,
+ 'fails_like' =>
+ qr/has size \d+ on disk but size \d+ in the manifest/
+ },
+ {
+ 'name' => 'truncate_file',
+ 'mutilate' => \&mutilate_truncate_file,
+ 'fails_like' =>
+ qr/has size 0 on disk but size \d+ in the manifest/
+ },
+ {
+ 'name' => 'replace_file',
+ 'mutilate' => \&mutilate_replace_file,
+ 'fails_like' => qr/checksum mismatch for file/
+ },
+ {
+ 'name' => 'bad_manifest',
+ 'mutilate' => \&mutilate_bad_manifest,
+ 'fails_like' => qr/manifest checksum mismatch/
+ }
+);
+
+for my $scenario (@scenario)
+{
+ my $name = $scenario->{'name'};
+
+ # Take a backup and check that it validates OK.
+ my $backup_path = $master->backup_dir . '/' . $name;
+ my $backup_ts_path = TestLib::tempdir;
+ $master->command_ok(['pg_basebackup', '-D', $backup_path, '--no-sync',
+ '-T', "${source_ts_path}=${backup_ts_path}"],
+ "base backup ok");
+ command_ok(['pg_validatebackup', $backup_path ],
+ "intact backup validated");
+
+ # Mutilate the backup in some way.
+ $scenario->{'mutilate'}->($backup_path);
+
+ # Now check that the backup no longer validates.
+ command_fails_like(['pg_validatebackup', $backup_path ],
+ $scenario->{'fails_like'},
+ "corrupt backup fails validation: $name");
+}
+
+sub create_extra_file
+{
+ my ($backup_path, $relative_path) = @_;
+ my $pathname = "$backup_path/$relative_path";
+ open(my $fh, '>', $pathname) || die "open $pathname: $!";
+ print $fh "This is an extra file.\n";
+ close($fh);
+}
+
+# Add a file into the root directory of the backup.
+sub mutilate_extra_file
+{
+ my ($backup_path) = @_;
+ create_extra_file($backup_path, "extra_file");
+}
+
+# Add a file inside the user-defined tablespace.
+sub mutilate_extra_tablespace_file
+{
+ my ($backup_path) = @_;
+ my ($tsoid) = grep { $_ ne '.' && $_ ne '..' }
+ slurp_dir("$backup_path/pg_tblspc");
+ my ($catvdir) = grep { $_ ne '.' && $_ ne '..' }
+ slurp_dir("$backup_path/pg_tblspc/$tsoid");
+ my ($tsdboid) = grep { $_ ne '.' && $_ ne '..' }
+ slurp_dir("$backup_path/pg_tblspc/$tsoid/$catvdir");
+ create_extra_file($backup_path,
+ "pg_tblspc/$tsoid/$catvdir/$tsdboid/extra_ts_file");
+}
+
+# Remove a file.
+sub mutilate_missing_file
+{
+ my ($backup_path) = @_;
+ my $pathname = "$backup_path/pg_xact/0000";
+ unlink($pathname) || die "$pathname: $!";
+}
+
+# Remove the symlink to the user-defined tablespace.
+sub mutilate_missing_tablespace
+{
+ my ($backup_path) = @_;
+ my ($tsoid) = grep { $_ ne '.' && $_ ne '..' }
+ slurp_dir("$backup_path/pg_tblspc");
+ my $pathname = "$backup_path/pg_tblspc/$tsoid";
+ unlink($pathname) || die "$pathname: $!";
+}
+
+# Append an additional bytes to a file.
+sub mutilate_append_to_file
+{
+ my ($backup_path) = @_;
+ append_to_file "$backup_path/global/pg_control", 'x';
+}
+
+# Truncate a file to zero length.
+sub mutilate_truncate_file
+{
+ my ($backup_path) = @_;
+ my $pathname = "$backup_path/global/pg_control";
+ open(my $fh, '>', $pathname) || die "open $pathname: $!";
+ close($fh);
+}
+
+# Replace a file's contents without changing the length of the file. This is
+# not a particularly efficient way to do this, so we pick a file that's
+# expected to be short.
+sub mutilate_replace_file
+{
+ my ($backup_path) = @_;
+ my $pathname = "$backup_path/PG_VERSION";
+ my $contents = slurp_file($pathname);
+ open(my $fh, '>', $pathname) || die "open $pathname: $!";
+ print $fh 'q' x length($contents);
+ close($fh);
+}
+
+# Corrupt the backup manifest.
+sub mutilate_bad_manifest
+{
+ my ($backup_path) = @_;
+ append_to_file "$backup_path/backup_manifest", "\n";
+}
--
2.17.2 (Apple Git-113)