From aeaa4ba4629d1b48bbf13fd7512a9f1171631d70 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Tue, 18 Jan 2022 12:38:10 -0500 Subject: [PATCH v1] Split 010_pg_basebackup.pl. --- .../t/010_pg_basebackup_basic.pl | 15 + ...ckup.pl => 011_pg_basebackup_integrity.pl} | 287 +--------------- .../t/012_pg_basebackup_options.pl | 318 ++++++++++++++++++ 3 files changed, 334 insertions(+), 286 deletions(-) create mode 100644 src/bin/pg_basebackup/t/010_pg_basebackup_basic.pl rename src/bin/pg_basebackup/t/{010_pg_basebackup.pl => 011_pg_basebackup_integrity.pl} (58%) create mode 100644 src/bin/pg_basebackup/t/012_pg_basebackup_options.pl diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup_basic.pl b/src/bin/pg_basebackup/t/010_pg_basebackup_basic.pl new file mode 100644 index 0000000000..48863dc213 --- /dev/null +++ b/src/bin/pg_basebackup/t/010_pg_basebackup_basic.pl @@ -0,0 +1,15 @@ + +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More tests => 9; + +program_help_ok('pg_basebackup'); +program_version_ok('pg_basebackup'); +program_options_handling_ok('pg_basebackup'); + +command_fails(['pg_basebackup'], + 'pg_basebackup needs target directory specified'); diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/011_pg_basebackup_integrity.pl similarity index 58% rename from src/bin/pg_basebackup/t/010_pg_basebackup.pl rename to src/bin/pg_basebackup/t/011_pg_basebackup_integrity.pl index f0243f28d4..68332931ac 100644 --- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl +++ b/src/bin/pg_basebackup/t/011_pg_basebackup_integrity.pl @@ -10,11 +10,7 @@ use File::Path qw(rmtree); use Fcntl qw(:seek); use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; -use Test::More tests => 115; - -program_help_ok('pg_basebackup'); -program_version_ok('pg_basebackup'); -program_options_handling_ok('pg_basebackup'); +use Test::More tests => 61; my $tempdir = PostgreSQL::Test::Utils::tempdir; @@ -35,9 +31,6 @@ $node->init(extra => ['--data-checksums']); $node->start; my $pgdata = $node->data_dir; -$node->command_fails(['pg_basebackup'], - 'pg_basebackup needs target directory specified'); - # Some Windows ANSI code pages may reject this filename, in which case we # quietly proceed without this bit of test coverage. if (open my $badchars, '>>', "$tempdir/pgdata/FOO\xe0\xe0\xe0BAR") @@ -400,281 +393,3 @@ foreach my $filename (@tempRelationFiles) ok( -d "$tempdir/backup1/pg_replslot", 'pg_replslot symlink copied as directory'); rmtree("$tempdir/backup1"); - -mkdir "$tempdir/tbl=spc2"; -$realTsDir = "$real_sys_tempdir/tbl=spc2"; -$node->safe_psql('postgres', "DROP TABLE test1;"); -$node->safe_psql('postgres', "DROP TABLE tblspc1_unlogged;"); -$node->safe_psql('postgres', "DROP TABLESPACE tblspc1;"); -$node->safe_psql('postgres', - "CREATE TABLESPACE tblspc2 LOCATION '$realTsDir';"); -$realTsDir =~ s/=/\\=/; -$node->command_ok( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backup3", '-Fp', - "-T$realTsDir=$real_tempdir/tbackup/tbl\\=spc2", - ], - 'mapping tablespace with = sign in path'); -ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated'); -$node->safe_psql('postgres', "DROP TABLESPACE tblspc2;"); -rmtree("$tempdir/backup3"); - -mkdir "$tempdir/$superlongname"; -$realTsDir = "$real_sys_tempdir/$superlongname"; -$node->safe_psql('postgres', - "CREATE TABLESPACE tblspc3 LOCATION '$realTsDir';"); -$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/tarbackup_l3", '-Ft' ], - 'pg_basebackup tar with long symlink target'); -$node->safe_psql('postgres', "DROP TABLESPACE tblspc3;"); -rmtree("$tempdir/tarbackup_l3"); - -$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/backupR", '-R' ], - 'pg_basebackup -R runs'); -ok(-f "$tempdir/backupR/postgresql.auto.conf", 'postgresql.auto.conf exists'); -ok(-f "$tempdir/backupR/standby.signal", 'standby.signal was created'); -my $recovery_conf = slurp_file "$tempdir/backupR/postgresql.auto.conf"; -rmtree("$tempdir/backupR"); - -my $port = $node->port; -like( - $recovery_conf, - qr/^primary_conninfo = '.*port=$port.*'\n/m, - 'postgresql.auto.conf sets primary_conninfo'); - -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxd" ], - 'pg_basebackup runs in default xlog mode'); -ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxd/pg_wal")), - 'WAL files copied'); -rmtree("$tempdir/backupxd"); - -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxf", '-X', 'fetch' ], - 'pg_basebackup -X fetch runs'); -ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxf/pg_wal")), - 'WAL files copied'); -rmtree("$tempdir/backupxf"); -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs", '-X', 'stream' ], - 'pg_basebackup -X stream runs'); -ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxs/pg_wal")), - 'WAL files copied'); -rmtree("$tempdir/backupxs"); -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxst", '-X', 'stream', '-Ft' ], - 'pg_basebackup -X stream runs in tar mode'); -ok(-f "$tempdir/backupxst/pg_wal.tar", "tar file was created"); -rmtree("$tempdir/backupxst"); -$node->command_ok( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backupnoslot", '-X', - 'stream', '--no-slot' - ], - 'pg_basebackup -X stream runs with --no-slot'); -rmtree("$tempdir/backupnoslot"); - -$node->command_fails( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_sl_fail", '-X', - 'stream', '-S', - 'slot0' - ], - 'pg_basebackup fails with nonexistent replication slot'); - -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C' ], - 'pg_basebackup -C fails without slot name'); - -$node->command_fails( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backupxs_slot", '-C', - '-S', 'slot0', - '--no-slot' - ], - 'pg_basebackup fails with -C -S --no-slot'); - -$node->command_ok( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C', '-S', 'slot0' ], - 'pg_basebackup -C runs'); -rmtree("$tempdir/backupxs_slot"); - -is( $node->safe_psql( - 'postgres', - q{SELECT slot_name FROM pg_replication_slots WHERE slot_name = 'slot0'} - ), - 'slot0', - 'replication slot was created'); -isnt( - $node->safe_psql( - 'postgres', - q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot0'} - ), - '', - 'restart LSN of new slot is not null'); - -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot1", '-C', '-S', 'slot0' ], - 'pg_basebackup fails with -C -S and a previously existing slot'); - -$node->safe_psql('postgres', - q{SELECT * FROM pg_create_physical_replication_slot('slot1')}); -my $lsn = $node->safe_psql('postgres', - q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'} -); -is($lsn, '', 'restart LSN of new slot is null'); -$node->command_fails( - [ @pg_basebackup_defs, '-D', "$tempdir/fail", '-S', 'slot1', '-X', 'none' ], - 'pg_basebackup with replication slot fails without WAL streaming'); -$node->command_ok( - [ - @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl", '-X', - 'stream', '-S', 'slot1' - ], - 'pg_basebackup -X stream with replication slot runs'); -$lsn = $node->safe_psql('postgres', - q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'} -); -like($lsn, qr!^0/[0-9A-Z]{7,8}$!, 'restart LSN of slot has advanced'); -rmtree("$tempdir/backupxs_sl"); - -$node->command_ok( - [ - @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl_R", '-X', - 'stream', '-S', 'slot1', '-R', - ], - 'pg_basebackup with replication slot and -R runs'); -like( - slurp_file("$tempdir/backupxs_sl_R/postgresql.auto.conf"), - qr/^primary_slot_name = 'slot1'\n/m, - 'recovery conf file sets primary_slot_name'); - -my $checksum = $node->safe_psql('postgres', 'SHOW data_checksums;'); -is($checksum, 'on', 'checksums are enabled'); -rmtree("$tempdir/backupxs_sl_R"); - -# create tables to corrupt and get their relfilenodes -my $file_corrupt1 = $node->safe_psql('postgres', - q{CREATE TABLE corrupt1 AS SELECT a FROM generate_series(1,10000) AS a; ALTER TABLE corrupt1 SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt1')} -); -my $file_corrupt2 = $node->safe_psql('postgres', - q{CREATE TABLE corrupt2 AS SELECT b FROM generate_series(1,2) AS b; ALTER TABLE corrupt2 SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt2')} -); - -# set page header and block sizes -my $pageheader_size = 24; -my $block_size = $node->safe_psql('postgres', 'SHOW block_size;'); - -# induce corruption -system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; -open $file, '+<', "$pgdata/$file_corrupt1"; -seek($file, $pageheader_size, SEEK_SET); -syswrite($file, "\0\0\0\0\0\0\0\0\0"); -close $file; -system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; - -$node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt" ], - 1, - [qr{^$}], - [qr/^WARNING.*checksum verification failed/s], - 'pg_basebackup reports checksum mismatch'); -rmtree("$tempdir/backup_corrupt"); - -# induce further corruption in 5 more blocks -system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; -open $file, '+<', "$pgdata/$file_corrupt1"; -for my $i (1 .. 5) -{ - my $offset = $pageheader_size + $i * $block_size; - seek($file, $offset, SEEK_SET); - syswrite($file, "\0\0\0\0\0\0\0\0\0"); -} -close $file; -system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; - -$node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt2" ], - 1, - [qr{^$}], - [qr/^WARNING.*further.*failures.*will.not.be.reported/s], - 'pg_basebackup does not report more than 5 checksum mismatches'); -rmtree("$tempdir/backup_corrupt2"); - -# induce corruption in a second file -system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; -open $file, '+<', "$pgdata/$file_corrupt2"; -seek($file, $pageheader_size, SEEK_SET); -syswrite($file, "\0\0\0\0\0\0\0\0\0"); -close $file; -system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; - -$node->command_checks_all( - [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt3" ], - 1, - [qr{^$}], - [qr/^WARNING.*7 total checksum verification failures/s], - 'pg_basebackup correctly report the total number of checksum mismatches'); -rmtree("$tempdir/backup_corrupt3"); - -# do not verify checksums, should return ok -$node->command_ok( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_corrupt4", '--no-verify-checksums', - ], - 'pg_basebackup with -k does not report checksum mismatch'); -rmtree("$tempdir/backup_corrupt4"); - -$node->safe_psql('postgres', "DROP TABLE corrupt1;"); -$node->safe_psql('postgres', "DROP TABLE corrupt2;"); - -note "Testing pg_basebackup with compression methods"; - -# Check ZLIB compression if available. -SKIP: -{ - skip "postgres was not built with ZLIB support", 5 - if (!check_pg_config("#define HAVE_LIBZ 1")); - - $node->command_ok( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_gzip", '--compress', - '1', '--format', - 't' - ], - 'pg_basebackup with --compress'); - $node->command_ok( - [ - @pg_basebackup_defs, '-D', - "$tempdir/backup_gzip2", '--gzip', - '--format', 't' - ], - 'pg_basebackup with --gzip'); - - # Verify that the stored files are generated with their expected - # names. - my @zlib_files = glob "$tempdir/backup_gzip/*.tar.gz"; - is(scalar(@zlib_files), 2, - "two files created with --compress (base.tar.gz and pg_wal.tar.gz)"); - my @zlib_files2 = glob "$tempdir/backup_gzip2/*.tar.gz"; - is(scalar(@zlib_files2), 2, - "two files created with --gzip (base.tar.gz and pg_wal.tar.gz)"); - - # Check the integrity of the files generated. - my $gzip = $ENV{GZIP_PROGRAM}; - skip "program gzip is not found in your system", 1 - if ( !defined $gzip - || $gzip eq '' - || system_log($gzip, '--version') != 0); - - my $gzip_is_valid = - system_log($gzip, '--test', @zlib_files, @zlib_files2); - is($gzip_is_valid, 0, "gzip verified the integrity of compressed data"); - rmtree("$tempdir/backup_gzip"); - rmtree("$tempdir/backup_gzip2"); -} diff --git a/src/bin/pg_basebackup/t/012_pg_basebackup_options.pl b/src/bin/pg_basebackup/t/012_pg_basebackup_options.pl new file mode 100644 index 0000000000..35c13f9e97 --- /dev/null +++ b/src/bin/pg_basebackup/t/012_pg_basebackup_options.pl @@ -0,0 +1,318 @@ + +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +use strict; +use warnings; +use Cwd; +use Config; +use File::Basename qw(basename dirname); +use File::Path qw(rmtree); +use Fcntl qw(:seek); +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More tests => 45; + +my $tempdir = PostgreSQL::Test::Utils::tempdir; +my $real_tempdir = PostgreSQL::Test::Utils::perl2host($tempdir); + +my $node = PostgreSQL::Test::Cluster->new('main'); + +# For nearly all pg_basebackup invocations some options should be specified, +# to keep test times reasonable. Using @pg_basebackup_defs as the first +# element of the array passed to to IPC::Run interpolate the array (as it is +# not a reference to an array)... +my @pg_basebackup_defs = ('pg_basebackup', '--no-sync', '-cfast'); + + +# Set umask so test directories and files are created with default permissions +umask(0077); + +# Initialize node +$node->init(allows_streaming => 1, extra => ['--data-checksums']); +$node->start; +my $pgdata = $node->data_dir; + +# Create a temporary directory in the system location and symlink it +# to our physical temp location. That way we can use shorter names +# for the tablespace directories, which hopefully won't run afoul of +# the 99 character length limit. +my $sys_tempdir = PostgreSQL::Test::Utils::tempdir_short; +my $real_sys_tempdir = PostgreSQL::Test::Utils::perl2host($sys_tempdir) . "/tempdir"; +my $shorter_tempdir = $sys_tempdir . "/tempdir"; +dir_symlink "$tempdir", $shorter_tempdir; + +mkdir "$tempdir/tbl=spc2"; +my $realTsDir = "$real_sys_tempdir/tbl=spc2"; +$node->safe_psql('postgres', + "CREATE TABLESPACE tblspc2 LOCATION '$realTsDir';"); +$realTsDir =~ s/=/\\=/; +$node->command_ok( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backup3", '-Fp', + "-T$realTsDir=$real_tempdir/tbackup/tbl\\=spc2", + ], + 'mapping tablespace with = sign in path'); +ok(-d "$tempdir/tbackup/tbl=spc2", 'tablespace with = sign was relocated'); +$node->safe_psql('postgres', "DROP TABLESPACE tblspc2;"); +rmtree("$tempdir/backup3"); + +my $superlongname = "superlongname_" . ("x" x 100); +mkdir "$tempdir/$superlongname"; +$realTsDir = "$real_sys_tempdir/$superlongname"; +$node->safe_psql('postgres', + "CREATE TABLESPACE tblspc3 LOCATION '$realTsDir';"); +$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/tarbackup_l3", '-Ft' ], + 'pg_basebackup tar with long symlink target'); +$node->safe_psql('postgres', "DROP TABLESPACE tblspc3;"); +rmtree("$tempdir/tarbackup_l3"); + +$node->command_ok([ @pg_basebackup_defs, '-D', "$tempdir/backupR", '-R' ], + 'pg_basebackup -R runs'); +ok(-f "$tempdir/backupR/postgresql.auto.conf", 'postgresql.auto.conf exists'); +ok(-f "$tempdir/backupR/standby.signal", 'standby.signal was created'); +my $recovery_conf = slurp_file "$tempdir/backupR/postgresql.auto.conf"; +rmtree("$tempdir/backupR"); + +my $port = $node->port; +like( + $recovery_conf, + qr/^primary_conninfo = '.*port=$port.*'\n/m, + 'postgresql.auto.conf sets primary_conninfo'); + +$node->command_ok( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxd" ], + 'pg_basebackup runs in default xlog mode'); +ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxd/pg_wal")), + 'WAL files copied'); +rmtree("$tempdir/backupxd"); + +$node->command_ok( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxf", '-X', 'fetch' ], + 'pg_basebackup -X fetch runs'); +ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxf/pg_wal")), + 'WAL files copied'); +rmtree("$tempdir/backupxf"); +$node->command_ok( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxs", '-X', 'stream' ], + 'pg_basebackup -X stream runs'); +ok(grep(/^[0-9A-F]{24}$/, slurp_dir("$tempdir/backupxs/pg_wal")), + 'WAL files copied'); +rmtree("$tempdir/backupxs"); +$node->command_ok( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxst", '-X', 'stream', '-Ft' ], + 'pg_basebackup -X stream runs in tar mode'); +ok(-f "$tempdir/backupxst/pg_wal.tar", "tar file was created"); +rmtree("$tempdir/backupxst"); +$node->command_ok( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backupnoslot", '-X', + 'stream', '--no-slot' + ], + 'pg_basebackup -X stream runs with --no-slot'); +rmtree("$tempdir/backupnoslot"); + +$node->command_fails( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backupxs_sl_fail", '-X', + 'stream', '-S', + 'slot0' + ], + 'pg_basebackup fails with nonexistent replication slot'); + +$node->command_fails( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C' ], + 'pg_basebackup -C fails without slot name'); + +$node->command_fails( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backupxs_slot", '-C', + '-S', 'slot0', + '--no-slot' + ], + 'pg_basebackup fails with -C -S --no-slot'); + +$node->command_ok( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot", '-C', '-S', 'slot0' ], + 'pg_basebackup -C runs'); +rmtree("$tempdir/backupxs_slot"); + +is( $node->safe_psql( + 'postgres', + q{SELECT slot_name FROM pg_replication_slots WHERE slot_name = 'slot0'} + ), + 'slot0', + 'replication slot was created'); +isnt( + $node->safe_psql( + 'postgres', + q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot0'} + ), + '', + 'restart LSN of new slot is not null'); + +$node->command_fails( + [ @pg_basebackup_defs, '-D', "$tempdir/backupxs_slot1", '-C', '-S', 'slot0' ], + 'pg_basebackup fails with -C -S and a previously existing slot'); + +$node->safe_psql('postgres', + q{SELECT * FROM pg_create_physical_replication_slot('slot1')}); +my $lsn = $node->safe_psql('postgres', + q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'} +); +is($lsn, '', 'restart LSN of new slot is null'); +$node->command_fails( + [ @pg_basebackup_defs, '-D', "$tempdir/fail", '-S', 'slot1', '-X', 'none' ], + 'pg_basebackup with replication slot fails without WAL streaming'); +$node->command_ok( + [ + @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl", '-X', + 'stream', '-S', 'slot1' + ], + 'pg_basebackup -X stream with replication slot runs'); +$lsn = $node->safe_psql('postgres', + q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'} +); +like($lsn, qr!^0/[0-9A-Z]{7,8}$!, 'restart LSN of slot has advanced'); +rmtree("$tempdir/backupxs_sl"); + +$node->command_ok( + [ + @pg_basebackup_defs, '-D', "$tempdir/backupxs_sl_R", '-X', + 'stream', '-S', 'slot1', '-R', + ], + 'pg_basebackup with replication slot and -R runs'); +like( + slurp_file("$tempdir/backupxs_sl_R/postgresql.auto.conf"), + qr/^primary_slot_name = 'slot1'\n/m, + 'recovery conf file sets primary_slot_name'); + +my $checksum = $node->safe_psql('postgres', 'SHOW data_checksums;'); +is($checksum, 'on', 'checksums are enabled'); +rmtree("$tempdir/backupxs_sl_R"); + +# create tables to corrupt and get their relfilenodes +my $file_corrupt1 = $node->safe_psql('postgres', + q{CREATE TABLE corrupt1 AS SELECT a FROM generate_series(1,10000) AS a; ALTER TABLE corrupt1 SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt1')} +); +my $file_corrupt2 = $node->safe_psql('postgres', + q{CREATE TABLE corrupt2 AS SELECT b FROM generate_series(1,2) AS b; ALTER TABLE corrupt2 SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt2')} +); + +# set page header and block sizes +my $pageheader_size = 24; +my $block_size = $node->safe_psql('postgres', 'SHOW block_size;'); + +# induce corruption +system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; +open my $file, '+<', "$pgdata/$file_corrupt1"; +seek($file, $pageheader_size, SEEK_SET); +syswrite($file, "\0\0\0\0\0\0\0\0\0"); +close $file; +system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; + +$node->command_checks_all( + [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt" ], + 1, + [qr{^$}], + [qr/^WARNING.*checksum verification failed/s], + 'pg_basebackup reports checksum mismatch'); +rmtree("$tempdir/backup_corrupt"); + +# induce further corruption in 5 more blocks +system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; +open $file, '+<', "$pgdata/$file_corrupt1"; +for my $i (1 .. 5) +{ + my $offset = $pageheader_size + $i * $block_size; + seek($file, $offset, SEEK_SET); + syswrite($file, "\0\0\0\0\0\0\0\0\0"); +} +close $file; +system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; + +$node->command_checks_all( + [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt2" ], + 1, + [qr{^$}], + [qr/^WARNING.*further.*failures.*will.not.be.reported/s], + 'pg_basebackup does not report more than 5 checksum mismatches'); +rmtree("$tempdir/backup_corrupt2"); + +# induce corruption in a second file +system_or_bail 'pg_ctl', '-D', $pgdata, 'stop'; +open $file, '+<', "$pgdata/$file_corrupt2"; +seek($file, $pageheader_size, SEEK_SET); +syswrite($file, "\0\0\0\0\0\0\0\0\0"); +close $file; +system_or_bail 'pg_ctl', '-D', $pgdata, 'start'; + +$node->command_checks_all( + [ @pg_basebackup_defs, '-D', "$tempdir/backup_corrupt3" ], + 1, + [qr{^$}], + [qr/^WARNING.*7 total checksum verification failures/s], + 'pg_basebackup correctly report the total number of checksum mismatches'); +rmtree("$tempdir/backup_corrupt3"); + +# do not verify checksums, should return ok +$node->command_ok( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backup_corrupt4", '--no-verify-checksums', + ], + 'pg_basebackup with -k does not report checksum mismatch'); +rmtree("$tempdir/backup_corrupt4"); + +$node->safe_psql('postgres', "DROP TABLE corrupt1;"); +$node->safe_psql('postgres', "DROP TABLE corrupt2;"); + +note "Testing pg_basebackup with compression methods"; + +# Check ZLIB compression if available. +SKIP: +{ + skip "postgres was not built with ZLIB support", 5 + if (!check_pg_config("#define HAVE_LIBZ 1")); + + $node->command_ok( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backup_gzip", '--compress', + '1', '--format', + 't' + ], + 'pg_basebackup with --compress'); + $node->command_ok( + [ + @pg_basebackup_defs, '-D', + "$tempdir/backup_gzip2", '--gzip', + '--format', 't' + ], + 'pg_basebackup with --gzip'); + + # Verify that the stored files are generated with their expected + # names. + my @zlib_files = glob "$tempdir/backup_gzip/*.tar.gz"; + is(scalar(@zlib_files), 2, + "two files created with --compress (base.tar.gz and pg_wal.tar.gz)"); + my @zlib_files2 = glob "$tempdir/backup_gzip2/*.tar.gz"; + is(scalar(@zlib_files2), 2, + "two files created with --gzip (base.tar.gz and pg_wal.tar.gz)"); + + # Check the integrity of the files generated. + my $gzip = $ENV{GZIP_PROGRAM}; + skip "program gzip is not found in your system", 1 + if ( !defined $gzip + || $gzip eq '' + || system_log($gzip, '--version') != 0); + + my $gzip_is_valid = + system_log($gzip, '--test', @zlib_files, @zlib_files2); + is($gzip_is_valid, 0, "gzip verified the integrity of compressed data"); + rmtree("$tempdir/backup_gzip"); + rmtree("$tempdir/backup_gzip2"); +} -- 2.24.3 (Apple Git-128)