1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-14 10:13:05 +02:00
pgbackrest/test/lib/pgBackRestTest/Module/Stanza/StanzaAllPerlTest.pm
David Steele 3434240097 Remove incompletely implemented online option from the check command.
Offline operation runs counter to the purpose of this command, which is to check if archiving and backups are working correctly.

Reported by Jason O'Donnell.
2018-08-12 19:24:21 -04:00

824 lines
51 KiB
Perl

####################################################################################################################################
# Unit tests for Stanza module
####################################################################################################################################
package pgBackRestTest::Module::Stanza::StanzaAllPerlTest;
use parent 'pgBackRestTest::Env::HostEnvTest';
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess);
use English '-no_match_vars';
use File::Basename qw(dirname);
use Storable qw(dclone);
use pgBackRest::Archive::Common;
use pgBackRest::Archive::Info;
use pgBackRest::Backup::Common;
use pgBackRest::Backup::Info;
use pgBackRest::Common::Cipher;
use pgBackRest::Common::Exception;
use pgBackRest::Common::Ini;
use pgBackRest::Common::Lock;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::Config::Config;
use pgBackRest::DbVersion;
use pgBackRest::InfoCommon;
use pgBackRest::Manifest;
use pgBackRest::Protocol::Helper;
use pgBackRest::Stanza;
use pgBackRest::Protocol::Storage::Helper;
use pgBackRestTest::Env::HostEnvTest;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::FileTest;
use pgBackRestTest::Env::Host::HostBackupTest;
use pgBackRestTest::Common::RunTest;
####################################################################################################################################
# initModule
####################################################################################################################################
sub initModule
{
my $self = shift;
$self->{strDbPath} = $self->testPath() . '/db';
$self->{strRepoPath} = $self->testPath() . '/repo';
$self->{strArchivePath} = "$self->{strRepoPath}/archive/" . $self->stanza();
$self->{strBackupPath} = "$self->{strRepoPath}/backup/" . $self->stanza();
$self->{strSpoolPath} = "$self->{strArchivePath}/out";
}
####################################################################################################################################
# initTest
####################################################################################################################################
sub initTest
{
my $self = shift;
# Create archive info path
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
# Create backup info path
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
# Generate pg_control file
storageTest()->pathCreate($self->{strDbPath} . '/' . DB_PATH_GLOBAL, {bCreateParent => true});
$self->controlGenerate($self->{strDbPath}, PG_VERSION_94);
}
####################################################################################################################################
# run
####################################################################################################################################
sub run
{
my $self = shift;
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
$self->optionTestSet(CFGOPT_PG_PATH, $self->{strDbPath});
$self->optionTestSet(CFGOPT_REPO_PATH, $self->{strRepoPath});
$self->optionTestSet(CFGOPT_LOG_PATH, $self->testPath());
$self->optionTestSetBool(CFGOPT_ONLINE, false);
$self->optionTestSet(CFGOPT_DB_TIMEOUT, 5);
$self->optionTestSet(CFGOPT_PROTOCOL_TIMEOUT, 6);
my $iDbControl = 942;
my $iDbCatalog = 201409291;
################################################################################################################################
if ($self->begin("Stanza::new"))
{
#---------------------------------------------------------------------------------------------------------------------------
$self->optionTestSetBool(CFGOPT_ONLINE, true);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testException(sub {(new pgBackRest::Stanza())}, ERROR_DB_CONNECT,
"could not connect to server: No such file or directory\n");
$self->optionTestSetBool(CFGOPT_ONLINE, false);
}
################################################################################################################################
if ($self->begin("Stanza::process()"))
{
$self->optionTestSetBool(CFGOPT_ONLINE, false);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
my $oStanza = new pgBackRest::Stanza();
rmdir($self->{strArchivePath});
rmdir($self->{strBackupPath});
$self->testResult(sub {$oStanza->process()}, 0, 'parent paths recreated successfully');
}
################################################################################################################################
if ($self->begin("Stanza::stanzaCreate()"))
{
$self->configTestLoad(CFGCMD_STANZA_CREATE);
my $oStanza = new pgBackRest::Stanza();
my $strBackupInfoFile = storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
my $strBackupInfoFileCopy = storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
my $strArchiveInfoFile = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE);
# No force. Archive dir not empty. No archive.info file. Backup directory empty.
#---------------------------------------------------------------------------------------------------------------------------
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/9.4-1");
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"archive directory not empty" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# No force. Archive dir not empty. No archive.info file. Backup directory not empty. No backup.info file.
#---------------------------------------------------------------------------------------------------------------------------
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/12345");
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"backup directory and/or archive directory not empty" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# No force. Archive dir empty. No archive.info file. Backup directory not empty. No backup.info file.
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . "/9.4-1", {bRecurse => true});
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"backup directory not empty" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# No force. No archive.info file and no archive sub-directories or files. Backup.info exists and no backup sub-directories
# or files
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . "/12345", {bRecurse => true});
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_MISSING,
"archive information missing" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# No force. No backup.info file (backup.info.copy only) and no backup sub-directories or files. Archive.info exists and no
# archive sub-directories or files
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO);
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), true);
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
"no error on missing backup.info since backup.info.copy exists and DB section OK");
# No force. No backup.info file (backup.info.copy only) and no backup sub-directories or files. No archive.info file
# (archive.info.copy only) and no archive sub-directories or files
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE);
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), true);
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
"no error on missing archive.info since archive.info.copy exists and DB section OK");
# No force. No backup.info files and no backup sub-directories or files. Archive.info exists and no
# archive sub-directories or files
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT);
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), true);
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_MISSING,
"backup information missing" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# No force. archive.info DB mismatch. backup.info correct DB.
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
(new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true}))->create(PG_VERSION_93,
$self->dbSysId(PG_VERSION_93), true);
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_INVALID,
"backup info file or archive info file invalid\n" .
"HINT: use stanza-upgrade if the database has been upgraded or use --force");
# No force. archive.info DB mismatch. backup.info DB mismatch.
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_93,
$self->dbSysId(PG_VERSION_93), $iDbControl, $iDbCatalog, true);
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_FILE_INVALID,
"backup info file or archive info file invalid\n" .
"HINT: use stanza-upgrade if the database has been upgraded or use --force");
# No force. Create stanza.
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza without force');
# No force with .info and .info.copy files already existing
#--------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
"info files exist and check out ok - stanza create not needed");
# No force. Remove only backup.info.copy file - confirm stanza create does not throw an error since copy is still valid
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strBackupInfoFileCopy);
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
"info.copy file exists and check out ok - stanza create not needed");
# Force on. Valid archive.info exists. Invalid backup.info exists.
#---------------------------------------------------------------------------------------------------------------------------
$self->optionTestSetBool(CFGOPT_FORCE, true);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_93), $iDbControl, $iDbCatalog, true);
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and existing info files');
$self->testResult(sub {(new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))}, 2, ' backup.info reconstructed');
# Force on, Repo-Sync off. Archive dir empty. No archive.info file. Backup directory not empty. No backup.info file.
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strBackupInfoFile . "*");
forceStorageRemove(storageRepo(), $strArchiveInfoFile . "*");
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/12345");
$oStanza = new pgBackRest::Stanza();
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force');
$self->testResult(
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
PG_VERSION_94,
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
1, ' new info files correct');
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . "/12345"), {bRecurse => true});
# Force on. Attempt to change encryption on the repo
#---------------------------------------------------------------------------------------------------------------------------
# Create unencrypted archive file
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
"/0000000100000001/000000010000000100000001-1e34fa1c833090d94b9bb14f2a8d3153dca6ea27");
executeTest('cp ' . $self->dataPath() . "/filecopy.archive2.bin ${strArchivedFile}");
# Create unencrypted backup manifest file
my $strBackupLabel = timestampFileFormat(undef, 1482000000) . 'F';
my $strBackupPath = storageRepo->pathGet(STORAGE_REPO_BACKUP . "/${strBackupLabel}");
my $strBackupManifestFile = "$strBackupPath/" . FILE_MANIFEST;
my $oBackupManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)});
storageRepo()->pathCreate($strBackupPath);
$oBackupManifest->save();
# Get the unencrypted content for later encryption
my $tUnencryptedArchiveContent = ${storageRepo()->get($strArchivedFile)};
my $tUnencryptedBackupContent = ${storageRepo()->get($strBackupManifestFile)};
# Change the permissions on the archived file so reconstruction fails
executeTest('sudo chmod 220 ' . $strArchivedFile);
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_FILE_OPEN,
"unable to open '" . $strArchivedFile . "': Permission denied");
executeTest('sudo chmod 644 ' . $strArchivedFile);
# Clear the cached repo settings and change repo settings to encrypted
storageRepoCacheClear($self->stanza());
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"files exist - the encryption type or passphrase cannot be changed");
# Remove the backup sub directories and files so that the archive file is attempted to be read
forceStorageRemove(storageRepo(), $strBackupPath, {bRecurse => true});
$self->testException(sub {(new pgBackRest::Stanza())->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"files exist - the encryption type or passphrase cannot be changed");
# Remove the archive sub directories and files so that only the info files exist - stanza create is allowed with force
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strArchiveIdPath, {bRecurse => true});
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and new encrypted settings');
# Confirm encrypted
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
. ARCHIVE_INFO_FILE)}, true, ' new archive info encrypted');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
. FILE_BACKUP_INFO)}, true, ' new backup info encrypted');
# Store the unencrypted archived file as encrypted and check stanza-create
#---------------------------------------------------------------------------------------------------------------------------
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1");
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
storageRepo()->put($strArchivedFile, $tUnencryptedArchiveContent);
storageRepo()->pathCreate($strBackupPath); # Empty backup path - no backup in progress
# Confirm encrypted and create the stanza with force
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, 'new archive WAL encrypted');
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, ' successfully recreate stanza with force from encrypted WAL');
# Confirm the backup and archive info are encrypted and check the contents
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
. ARCHIVE_INFO_FILE)}, true, ' new archive info encrypted');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
. FILE_BACKUP_INFO)}, true, ' new backup info encrypted');
$self->testResult(
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
PG_VERSION_94,
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
1, ' new archive.info and backup.info files correct');
# Store the unencrypted backup.manifest file as encrypted and check stanza-create
#---------------------------------------------------------------------------------------------------------------------------
# Try to create a manifest without a passphrase in an encrypted storage
$self->testException(sub {new pgBackRest::Manifest($strBackupManifestFile,
{bLoad => false, strDbVersion => PG_VERSION_94, iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94)})},
ERROR_CIPHER, 'passphrase is required when storage is encrypted');
# Get the encryption passphrase and create the new manifest
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
$oBackupManifest = new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94),
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => cipherPassGen()});
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_LABEL, undef, $strBackupLabel);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_CHECK, undef, true);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ARCHIVE_COPY, undef, false);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_BACKUP_STANDBY, undef, false);
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_START, undef, 1);
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_ARCHIVE_STOP, undef, 1);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_CHECKSUM_PAGE, undef, true);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_COMPRESS, undef, true);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_HARDLINK, undef, false);
$oBackupManifest->boolSet(MANIFEST_SECTION_BACKUP_OPTION, MANIFEST_KEY_ONLINE, undef, true);
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_START, undef, time());
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TIMESTAMP_STOP, undef, time());
$oBackupManifest->set(MANIFEST_SECTION_BACKUP, MANIFEST_KEY_TYPE, undef, CFGOPTVAL_BACKUP_TYPE_FULL);
$oBackupManifest->set(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_VERSION, undef, PG_VERSION_94);
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CONTROL, undef, $iDbControl);
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_CATALOG, undef, $iDbCatalog);
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_SYSTEM_ID, undef, $self->dbSysId(PG_VERSION_94));
$oBackupManifest->numericSet(MANIFEST_SECTION_BACKUP_DB, MANIFEST_KEY_DB_ID, undef, 1);
$oBackupManifest->save();
# Confirm encrypted and create the stanza with force
$self->testResult(sub {storageRepo()->encrypted($strBackupManifestFile)}, true, 'new backup manifest encrypted');
$self->testResult(sub {$oStanza->stanzaCreate()}, 0,
' successfully recreate stanza with force from encrypted manifest and WAL');
# Confirm the backup and archive info are encrypted and check the contents
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
. ARCHIVE_INFO_FILE)}, true, ' recreated archive info encrypted');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
. FILE_BACKUP_INFO)}, true, ' recreated backup info encrypted');
$self->testResult(
sub {(new pgBackRest::Archive::Info($self->{strArchivePath}))->check(
PG_VERSION_94,
$self->dbSysId(PG_VERSION_94)) && (new pgBackRest::Backup::Info($self->{strBackupPath}))->check(PG_VERSION_94,
$iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94))},
1, ' recreated archive.info and backup.info files correct');
# Move the encrypted info files out of the repo so they are missing but backup exists. --force cannot be used
#---------------------------------------------------------------------------------------------------------------------------
executeTest('sudo mv ' . storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/' . ARCHIVE_INFO_FILE . '* ' .
$self->testPath() . '/');
executeTest('sudo mv ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/' . FILE_BACKUP_INFO . '* ' .
$self->testPath() . '/');
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"backup directory and/or archive directory not empty and repo is encrypted and info file(s) are missing," .
" --force cannot be used");
# Move the files back for the next test
executeTest('sudo mv ' . $self->testPath() . '/' . ARCHIVE_INFO_FILE . '* ' .
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/');
executeTest('sudo mv ' . $self->testPath() . '/' . FILE_BACKUP_INFO . '* ' .
storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/');
# Change repo encryption settings to unencrypted - stanza create is not allowed even with force
#---------------------------------------------------------------------------------------------------------------------------
# Clear the cached repo settings and change repo settings to unencrypted
storageRepoCacheClear($self->stanza());
$self->optionTestClear(CFGOPT_REPO_CIPHER_TYPE);
$self->optionTestClear(CFGOPT_REPO_CIPHER_PASS);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testException(sub {$oStanza->stanzaCreate()}, ERROR_PATH_NOT_EMPTY,
"files exist - the encryption type or passphrase cannot be changed");
# With only info files - stanza create is allowed with force
#---------------------------------------------------------------------------------------------------------------------------
forceStorageRemove(storageRepo(), $strArchiveIdPath, {bRecurse => true});
forceStorageRemove(storageRepo(), $strBackupPath, {bRecurse => true});
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created stanza with force and new unencrypted settings');
# Confirm unencrypted
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
. ARCHIVE_INFO_FILE)}, false, ' new archive info unencrypted');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
. FILE_BACKUP_INFO)}, false, ' new backup info unencrypted');
# Clear --force
$self->optionTestClear(CFGOPT_FORCE);
}
################################################################################################################################
if ($self->begin("Stanza::infoFileCreate"))
{
$self->configTestLoad(CFGCMD_STANZA_CREATE);
my $oStanza = new pgBackRest::Stanza();
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
# Archive dir not empty. Warning returned.
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->pathCreate($self->{strArchivePath} . "/9.3-0", {bIgnoreExists => true, bCreateParent => true});
$self->testResult(sub {$oStanza->infoFileCreate($oArchiveInfo)}, "(0, [undef])",
'successful with archive.info file warning',
{strLogExpect => "WARN: found empty directory " . $self->{strArchivePath} . "/9.3-0"});
}
################################################################################################################################
if ($self->begin("Stanza::infoObject()"))
{
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
my $oStanza = new pgBackRest::Stanza();
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_MISSING,
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
" does not exist and is required to perform a backup." .
"\nHINT: has a stanza-create been performed?");
# Force valid but not set.
#---------------------------------------------------------------------------------------------------------------------------
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$oStanza = new pgBackRest::Stanza();
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_MISSING,
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
" does not exist and is required to perform a backup." .
"\nHINT: has a stanza-create been performed?" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.");
# Force.
#---------------------------------------------------------------------------------------------------------------------------
$self->optionTestSetBool(CFGOPT_FORCE, true);
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testResult(sub {$oStanza->infoObject(STORAGE_REPO_ARCHIVE, $self->{strArchivePath})}, "[object]",
'archive force successful');
$self->testResult(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, "[object]",
'backup force successful');
# Cause an error to be thrown by changing the permissions of the archive directory so it cannot be read
#---------------------------------------------------------------------------------------------------------------------------
executeTest('sudo chmod 220 ' . $self->{strArchivePath});
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_ARCHIVE, $self->{strArchivePath})}, ERROR_FILE_OPEN,
"unable to open '" . $self->{strArchivePath} . "/archive.info': Permission denied");
executeTest('sudo chmod 640 ' . $self->{strArchivePath});
# Reset force option --------
$self->optionTestClear(CFGOPT_FORCE);
# Cause an error to be thrown by changing the permissions of the backup file so it cannot be read
#---------------------------------------------------------------------------------------------------------------------------
$self->configTestLoad(CFGCMD_STANZA_CREATE);
(new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true}))->create(PG_VERSION_94,
$self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO . INI_COPY_EXT));
executeTest('sudo chmod 220 ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO));
$self->testException(sub {$oStanza->infoObject(STORAGE_REPO_BACKUP, $self->{strBackupPath})}, ERROR_FILE_OPEN,
"unable to open '" . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) .
"': Permission denied");
executeTest('sudo chmod 640 ' . storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO));
}
################################################################################################################################
if ($self->begin("Stanza::stanzaUpgrade()"))
{
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
$oArchiveInfo->create('9.3', '6999999999999999999', true);
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true});
$oBackupInfo->create('9.3', '6999999999999999999', '937', '201306121', true);
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
my $oStanza = new pgBackRest::Stanza();
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, 'successfully upgraded');
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, 'upgrade not required');
# Attempt to change the encryption settings
#---------------------------------------------------------------------------------------------------------------------------
# Clear the cached repo settings and change repo settings to encrypted
storageRepoCacheClear($self->stanza());
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
$self->testException(sub {$oStanza->stanzaUpgrade()}, ERROR_CIPHER,
"unable to parse '" . $self->{strArchivePath} . "/archive.info'" .
"\nHINT: Is or was the repo encrypted?");
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO) . "*");
forceStorageRemove(storageRepo(), storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . qw{/} . ARCHIVE_INFO_FILE) . "*");
# Create encrypted info files with prior passphrase then attempt to change
#---------------------------------------------------------------------------------------------------------------------------
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true,
strCipherPassSub => cipherPassGen()});
$oArchiveInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), true);
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true,
strCipherPassSub => cipherPassGen()});
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), '937', '201306121', true);
# Attempt to upgrade with a different passphrase
storageRepoCacheClear($self->stanza());
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'y');
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
$self->testException(sub {$oStanza->stanzaUpgrade()}, ERROR_CIPHER,
"unable to parse '" . $self->{strArchivePath} . "/archive.info'" .
"\nHINT: Is or was the repo encrypted?");
storageRepoCacheClear($self->stanza());
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
# Create encrypted archived file
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1/0000000100000001");
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
"/0000000100000001/000000010000000100000001-" . $self->walGenerateContentChecksum(PG_VERSION_93));
storageRepo()->put(
$strArchivedFile, $self->walGenerateContent(PG_VERSION_93), {strCipherPass => $oArchiveInfo->cipherPassSub()});
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, 'created encrypted archive WAL');
# Upgrade
$self->testResult(sub {$oStanza->stanzaUpgrade()}, undef, ' successfully upgraded');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE) . '/'
. ARCHIVE_INFO_FILE)}, true, ' upgraded archive info encrypted');
$self->testResult(sub {storageRepo()->encrypted(storageRepo()->pathGet(STORAGE_REPO_BACKUP) . '/'
. FILE_BACKUP_INFO)}, true, ' upgraded backup info encrypted');
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
my $hHistoryArchive = $oArchiveInfo->dbHistoryList();
my $hHistoryBackup = $oBackupInfo->dbHistoryList();
$self->testResult(sub {($hHistoryArchive->{1}{&INFO_DB_VERSION} eq PG_VERSION_93) &&
($hHistoryArchive->{1}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_93)) &&
($hHistoryArchive->{2}{&INFO_DB_VERSION} eq PG_VERSION_94) &&
($hHistoryArchive->{2}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_94)) &&
($hHistoryBackup->{1}{&INFO_DB_VERSION} eq PG_VERSION_93) &&
($hHistoryBackup->{1}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_93)) &&
($hHistoryBackup->{2}{&INFO_DB_VERSION} eq PG_VERSION_94) &&
($hHistoryBackup->{2}{&INFO_SYSTEM_ID} eq $self->dbSysId(PG_VERSION_94)) &&
($oArchiveInfo->check(PG_VERSION_94, $self->dbSysId(PG_VERSION_94)) eq PG_VERSION_94 . "-2") &&
($oBackupInfo->check(PG_VERSION_94, $iDbControl, $iDbCatalog, $self->dbSysId(PG_VERSION_94)) == 2) }, true,
' encrypted archive and backup info files upgraded');
# Clear configuration
storageRepoCacheClear($self->stanza());
$self->optionTestClear(CFGOPT_REPO_CIPHER_TYPE);
$self->optionTestClear(CFGOPT_REPO_CIPHER_PASS);
}
################################################################################################################################
if ($self->begin("Stanza::upgradeCheck()"))
{
$self->configTestLoad(CFGCMD_STANZA_UPGRADE);
my $oStanza = new pgBackRest::Stanza();
# Create the archive file with current data
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath}, false, {bIgnoreMissing => true});
$oArchiveInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), true);
# Create the backup file with outdated data
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath}, false, false, {bIgnoreMissing => true});
$oBackupInfo->create(PG_VERSION_93, 6999999999999999999, '937', '201306121', true);
# Confirm upgrade is needed for backup
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, true,
'backup upgrade needed');
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, false,
'archive upgrade not needed');
# Change archive file to contain outdated data
$oArchiveInfo->create(PG_VERSION_93, 6999999999999999999, true);
# Confirm upgrade is needed for both
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, true,
'archive upgrade needed');
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, true,
'backup upgrade needed');
# Change the backup file to contain current data
$oBackupInfo->create(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), $iDbControl, $iDbCatalog, true);
# Confirm upgrade is needed for archive
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, false,
'backup upgrade not needed');
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, true,
'archive upgrade needed');
#---------------------------------------------------------------------------------------------------------------------------
# Perform an upgrade and then confirm upgrade is not necessary
$oStanza->process();
$oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
$oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
$self->testResult(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ARCHIVE_MISMATCH)}, false,
'archive upgrade not necessary');
$self->testResult(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_BACKUP_MISMATCH)}, false,
'backup upgrade not necessary');
#---------------------------------------------------------------------------------------------------------------------------
# Change the DB data
$oStanza->{oDb}{strDbVersion} = '9.3';
$oStanza->{oDb}{ullDbSysId} = 6999999999999999999;
# Pass an expected error that is different than the actual error and confirm an error is thrown
$self->testException(sub {$oStanza->upgradeCheck($oArchiveInfo, STORAGE_REPO_ARCHIVE, ERROR_ASSERT)},
ERROR_ARCHIVE_MISMATCH,
"WAL segment version 9.3 does not match archive version 9.4\n" .
'WAL segment system-id 6999999999999999999 does not match archive system-id ' . $self->dbSysId(PG_VERSION_94) . "\n" .
"HINT: are you archiving to the correct stanza?");
$self->testException(sub {$oStanza->upgradeCheck($oBackupInfo, STORAGE_REPO_BACKUP, ERROR_ASSERT)}, ERROR_BACKUP_MISMATCH,
"database version = 9.3, system-id 6999999999999999999 does not match backup version = 9.4, " .
'system-id = ' . $self->dbSysId(PG_VERSION_94) . "\nHINT: is this the correct stanza?");
}
################################################################################################################################
if ($self->begin("Stanza::errorForce()"))
{
$self->configTestLoad(CFGCMD_STANZA_CREATE);
my $oStanza = new pgBackRest::Stanza();
my $strMessage = "archive information missing" .
"\nHINT: use stanza-create --force to force the stanza data to be recreated.";
$self->testException(sub {$oStanza->errorForce($strMessage, ERROR_FILE_MISSING, undef, true,
$self->{strArchivePath}, $self->{strBackupPath})}, ERROR_FILE_MISSING, $strMessage);
my $strFile = $self->{strArchivePath} . qw{/} . 'file.txt';
my $strFileContent = 'TESTDATA';
executeTest("echo -n '${strFileContent}' | tee ${strFile}");
$self->testException(sub {$oStanza->errorForce($strMessage, ERROR_FILE_MISSING, $strFile, true,
$self->{strArchivePath}, $self->{strBackupPath})}, ERROR_FILE_MISSING, $strMessage);
}
################################################################################################################################
if ($self->begin("Stanza::stanzaDelete()"))
{
# Create the stanza
$self->configTestLoad(CFGCMD_STANZA_CREATE);
my $oStanza = new pgBackRest::Stanza();
$oStanza->stanzaCreate();
# Attempt to delete without running stop
#---------------------------------------------------------------------------------------------------------------------------
$self->optionTestClear(CFGOPT_ONLINE);
$self->configTestLoad(CFGCMD_STANZA_DELETE);
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_FILE_MISSING,
"stop file does not exist for stanza '" . $self->stanza() . "'" .
"\nHINT: has the pgbackrest stop command been run on this server?");
# Create a stop file and attempt to delete with postgres running
#---------------------------------------------------------------------------------------------------------------------------
lockStop();
# Simulate postgres still running
executeTest('touch ' . $self->{strDbPath} . qw(/) . DB_FILE_POSTMASTERPID);
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_POSTMASTER_RUNNING,
DB_FILE_POSTMASTERPID . " exists - looks like the postmaster is running. " .
"To delete stanza '" . $self->stanza() . "', shutdown the postmaster for stanza '" . $self->stanza() .
"' and try again, or use --force.");
# Force deletion
#---------------------------------------------------------------------------------------------------------------------------
$self->optionTestSetBool(CFGOPT_FORCE, true);
$self->configTestLoad(CFGCMD_STANZA_DELETE);
$self->testResult(sub {$oStanza->stanzaDelete()}, undef, 'successfully delete stanza with force');
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
storageRepo()->pathExists($self->{strBackupPath})},
false, ' neither archive nor backup repo paths for the stanza exist');
# Remove postmaster.pid and clear force
storageTest()->remove($self->{strDbPath} . qw(/) . DB_FILE_POSTMASTERPID);
$self->optionTestClear(CFGOPT_FORCE);
# Rerun stanza-delete without force and with missing stanza directories
#---------------------------------------------------------------------------------------------------------------------------
$self->testResult(sub {$oStanza->stanzaDelete()}, undef, 'successful - stanza already deleted');
# Recursive dir delete with archive directory and stanza directory but missing info files
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1", {bCreateParent => true});
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_94 . "-1/0000000100000001");
executeTest('touch ' . $self->{strArchivePath} . "/" . PG_VERSION_94 . "-1/0000000100000001/" . BOGUS);
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
my $strFullLabel = backupLabelFormat(CFGOPTVAL_BACKUP_TYPE_FULL, undef, 1482000000);
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/${strFullLabel}", {bCreateParent => true});
executeTest('touch ' . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
# Create an inaccessible file
executeTest("sudo chgrp 777 " . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
executeTest("sudo chown 777 " . $self->{strBackupPath} . "/${strFullLabel}/" . BOGUS);
lockStop();
$self->testResult(sub {$oStanza->stanzaDelete()}, undef,
'successful - recursive delete with missing info files and inaccessible file');
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
storageRepo()->pathExists($self->{strBackupPath})},
false, ' neither archive nor backup repo paths for the stanza exist');
# Make the archive directory inaccessible
#---------------------------------------------------------------------------------------------------------------------------
storageTest()->pathCreate($self->{strArchivePath}, {bIgnoreExists => true, bCreateParent => true});
executeTest("sudo chgrp 7777 " . $self->{strArchivePath});
executeTest("sudo chown 7777 " . $self->{strArchivePath});
lockStop();
$self->testException(sub {$oStanza->stanzaDelete()}, ERROR_FILE_OPEN,
"unable to remove file '" . $self->{strArchivePath} . "/" . ARCHIVE_INFO_FILE . "': Permission denied");
# Remove the repo
executeTest("sudo rm -rf " . $self->{strArchivePath});
# Clear the cached repo settings and change repo settings to encrypted
#---------------------------------------------------------------------------------------------------------------------------
storageRepoCacheClear($self->stanza());
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, 'x');
$self->configTestLoad(CFGCMD_STANZA_CREATE);
$self->testResult(sub {$oStanza->stanzaCreate()}, 0, 'successfully created encrypted stanza');
# Create encrypted archived file
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1/0000000100000001");
my $strArchiveIdPath = storageRepo()->pathGet(STORAGE_REPO_ARCHIVE . "/" . PG_VERSION_93 . "-1");
my $strArchivedFile = storageRepo()->pathGet($strArchiveIdPath .
"/0000000100000001/000000010000000100000001-" . $self->walGenerateContentChecksum(PG_VERSION_93));
my $oArchiveInfo = new pgBackRest::Archive::Info($self->{strArchivePath});
storageRepo()->put(
$strArchivedFile, $self->walGenerateContent(PG_VERSION_93), {strCipherPass => $oArchiveInfo->cipherPassSub()});
$self->testResult(sub {storageRepo()->encrypted($strArchivedFile)}, true, ' created encrypted archive WAL');
my $strBackupPath = storageRepo->pathGet(STORAGE_REPO_BACKUP . "/${strFullLabel}");
my $strBackupManifestFile = "$strBackupPath/" . FILE_MANIFEST;
my $iDbCatalogVersion = 201409291;
storageRepo()->pathCreate(STORAGE_REPO_BACKUP . "/${strFullLabel}", {bCreateParent => true});
my $oBackupInfo = new pgBackRest::Backup::Info($self->{strBackupPath});
$self->testResult(sub {(new pgBackRest::Manifest($strBackupManifestFile, {bLoad => false, strDbVersion => PG_VERSION_94,
iDbCatalogVersion => $self->dbCatalogVersion(PG_VERSION_94),
strCipherPass => $oBackupInfo->cipherPassSub(), strCipherPassSub => 'x'}))->save()},
"[undef]", ' manifest saved');
lockStop();
$self->testResult(sub {$oStanza->stanzaDelete()}, undef,
' successful - recursive delete on encrypted repo');
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
storageRepo()->pathExists($self->{strBackupPath})},
false, ' neither archive nor backup repo paths for the stanza exist');
# For test coverage: create new stanza with delete command, call process and remove only backup path
#---------------------------------------------------------------------------------------------------------------------------
lockStop();
$self->configTestLoad(CFGCMD_STANZA_DELETE);
$oStanza = new pgBackRest::Stanza();
storageTest()->pathCreate($self->{strBackupPath}, {bIgnoreExists => true, bCreateParent => true});
$self->testResult(sub {$oStanza->process()}, 0,
'successfully remove backup path');
$self->testResult(sub {storageRepo()->pathExists($self->{strArchivePath}) ||
storageRepo()->pathExists($self->{strBackupPath})},
false, ' neither archive nor backup repo paths for the stanza exist');
}
}
1;