mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
88a633da17
Many options that were set per test can instead be inferred from the types, i.e. container, c, expect, and individual. Also finish renaming Perl unit tests with the -perl suffix.
263 lines
14 KiB
Perl
263 lines
14 KiB
Perl
####################################################################################################################################
|
|
# Unit tests for BackupInfo
|
|
####################################################################################################################################
|
|
package pgBackRestTest::Module::Backup::BackupInfoUnitPerlTest;
|
|
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::Info;
|
|
use pgBackRest::Backup::Info;
|
|
use pgBackRest::Common::Cipher;
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Lock;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Config::Config;
|
|
use pgBackRest::DbVersion;
|
|
use pgBackRest::InfoCommon;
|
|
use pgBackRest::Manifest;
|
|
use pgBackRest::Protocol::Storage::Helper;
|
|
use pgBackRest::Storage::Base;
|
|
|
|
use pgBackRestTest::Env::HostEnvTest;
|
|
use pgBackRestTest::Common::ExecuteTest;
|
|
use pgBackRestTest::Common::RunTest;
|
|
|
|
####################################################################################################################################
|
|
# initModule
|
|
####################################################################################################################################
|
|
sub initModule
|
|
{
|
|
my $self = shift;
|
|
|
|
$self->{strRepoPath} = $self->testPath() . '/repo';
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# initTest
|
|
####################################################################################################################################
|
|
sub initTest
|
|
{
|
|
my $self = shift;
|
|
|
|
# Load options
|
|
$self->configTestClear();
|
|
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
$self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo');
|
|
$self->configTestLoad(CFGCMD_ARCHIVE_PUSH);
|
|
|
|
# Create backup info path
|
|
storageRepo()->pathCreate(STORAGE_REPO_BACKUP, {bCreateParent => true});
|
|
|
|
# Create archive info path
|
|
storageRepo()->pathCreate(STORAGE_REPO_ARCHIVE, {bCreateParent => true});
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# run
|
|
####################################################################################################################################
|
|
sub run
|
|
{
|
|
my $self = shift;
|
|
|
|
my $i93ControlVersion = 937;
|
|
my $i93CatalogVersion = 201306121;
|
|
my $i94ControlVersion = 942;
|
|
my $i94CatalogVersion = 201409291;
|
|
|
|
################################################################################################################################
|
|
if ($self->begin("BackupInfo::check() && BackupInfo::confirmDb()"))
|
|
{
|
|
my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,
|
|
{bIgnoreMissing => true});
|
|
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true);
|
|
|
|
# All DB section matches
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(sub {$oBackupInfo->check(
|
|
PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93), false)}, 1, 'db section matches');
|
|
|
|
# DB section version mismatch
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(sub {$oBackupInfo->check(PG_VERSION_94, $i93ControlVersion, $i93CatalogVersion,
|
|
$self->dbSysId(PG_VERSION_93))}, ERROR_BACKUP_MISMATCH,
|
|
"database version = " . &PG_VERSION_94 . ", system-id " . $self->dbSysId(PG_VERSION_93) .
|
|
" does not match backup version = " . &PG_VERSION_93 . ", " . "system-id = " . $self->dbSysId(PG_VERSION_93) .
|
|
"\nHINT: is this the correct stanza?");
|
|
|
|
# DB section system-id mismatch
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(
|
|
sub {$oBackupInfo->check(PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_94))},
|
|
ERROR_BACKUP_MISMATCH,
|
|
"database version = " . &PG_VERSION_93 . ", system-id " . $self->dbSysId(PG_VERSION_94) .
|
|
" does not match backup version = " . &PG_VERSION_93 . ", " . "system-id = " . $self->dbSysId(PG_VERSION_93) .
|
|
"\nHINT: is this the correct stanza?");
|
|
|
|
# DB section control version mismatch
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(sub {$oBackupInfo->check(PG_VERSION_93, 123, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93))},
|
|
ERROR_BACKUP_MISMATCH, "database control-version = 123, catalog-version $i93CatalogVersion " .
|
|
"does not match backup control-version = $i93ControlVersion, catalog-version = $i93CatalogVersion" .
|
|
"\nHINT: this may be a symptom of database or repository corruption!");
|
|
|
|
# DB section catalog version mismatch
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(sub {$oBackupInfo->check(PG_VERSION_93, $i93ControlVersion, 123456789, $self->dbSysId(PG_VERSION_93))},
|
|
ERROR_BACKUP_MISMATCH, "database control-version = $i93ControlVersion, catalog-version 123456789 " .
|
|
"does not match backup control-version = $i93ControlVersion, catalog-version = $i93CatalogVersion" .
|
|
"\nHINT: this may be a symptom of database or repository corruption!");
|
|
|
|
my $strBackupLabel = "20170403-175647F";
|
|
|
|
$oBackupInfo->set(INFO_BACKUP_SECTION_BACKUP_CURRENT, $strBackupLabel, INFO_BACKUP_KEY_HISTORY_ID,
|
|
$oBackupInfo->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_HISTORY_ID));
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_93, $self->dbSysId(PG_VERSION_93))}, true,
|
|
'backup db matches');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_94, $self->dbSysId(PG_VERSION_93))}, false,
|
|
'backup db wrong version');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(sub {$oBackupInfo->confirmDb($strBackupLabel, PG_VERSION_93, $self->dbSysId(PG_VERSION_94))}, false,
|
|
'backup db wrong system-id');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin("BackupInfo::backupArchiveDbHistoryId()"))
|
|
{
|
|
my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,
|
|
{bIgnoreMissing => true});
|
|
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true);
|
|
|
|
my $oArchiveInfo = new pgBackRest::Archive::Info(storageRepo()->pathGet(STORAGE_REPO_ARCHIVE), false,
|
|
{bLoad => false, bIgnoreMissing => true});
|
|
$oArchiveInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), true);
|
|
|
|
# Map archiveId to Backup history id
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
my $strArchiveId = $oArchiveInfo->archiveId({strDbVersion => PG_VERSION_93, ullDbSysId => $self->dbSysId(PG_VERSION_93)});
|
|
$self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId,
|
|
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, 1, 'backupArchiveDbHistoryId found');
|
|
|
|
# Unable to map archiveId to Backup history id
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$strArchiveId = &PG_VERSION_94 . "-2";
|
|
$self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId,
|
|
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, "[undef]", 'backupArchiveDbHistoryId not found');
|
|
|
|
# Same version but different ullsystemid so continue looking until find match
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
# Update db section and db history sections
|
|
my $iHistoryId = $oBackupInfo->dbHistoryIdGet(true)+1;
|
|
$oBackupInfo->dbSectionSet(
|
|
PG_VERSION_94, $i94ControlVersion, $i94CatalogVersion, $self->dbSysId(PG_VERSION_93), $iHistoryId);
|
|
$oArchiveInfo->dbSectionSet(PG_VERSION_94, $self->dbSysId(PG_VERSION_93), $iHistoryId);
|
|
|
|
$oBackupInfo->save();
|
|
$oArchiveInfo->save();
|
|
|
|
$strArchiveId = &PG_VERSION_94 . "-" . $iHistoryId;
|
|
$self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId,
|
|
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, $iHistoryId, 'same db version but different system-id');
|
|
|
|
# Different version but same ullsystemid
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$iHistoryId = $oBackupInfo->dbHistoryIdGet(false)+1;
|
|
$oBackupInfo->dbSectionSet(
|
|
PG_VERSION_94, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_94), $iHistoryId);
|
|
$oArchiveInfo->dbSectionSet(PG_VERSION_94, $self->dbSysId(PG_VERSION_94), $iHistoryId);
|
|
|
|
$oBackupInfo->save();
|
|
$oArchiveInfo->save();
|
|
|
|
$strArchiveId = &PG_VERSION_93 . "-" . $iHistoryId;
|
|
$self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId,
|
|
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, "[undef]", 'same db system-id but different version');
|
|
|
|
# First and last version and ullsystemid same in backup.info but only 1st in archive info - return last
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$iHistoryId = $oBackupInfo->dbHistoryIdGet(true)+1;
|
|
$oBackupInfo->dbSectionSet(
|
|
PG_VERSION_93, $i93ControlVersion, $i93CatalogVersion, $self->dbSysId(PG_VERSION_93), $iHistoryId);
|
|
|
|
$oBackupInfo->save();
|
|
|
|
$strArchiveId = &PG_VERSION_93 . "-1";
|
|
$self->testResult(sub {$oBackupInfo->backupArchiveDbHistoryId($strArchiveId,
|
|
storageRepo()->pathGet(STORAGE_REPO_ARCHIVE))}, $iHistoryId, 'duplicate 1st and last version/sysid - last chosen');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin("encryption"))
|
|
{
|
|
# Create a backupInfo file
|
|
my $oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,
|
|
{bIgnoreMissing => true});
|
|
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true);
|
|
|
|
my $strFile = $oBackupInfo->{strFileName};
|
|
|
|
# Prepend encryption Magic signature to simulate encryption
|
|
executeTest('echo "' . CIPHER_MAGIC . '$(cat ' . $strFile . ')" > ' . $strFile);
|
|
|
|
$self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP))}, ERROR_CIPHER,
|
|
"unable to parse '$strFile'" .
|
|
"\nHINT: Is or was the repo encrypted?");
|
|
|
|
# Create encrypted files, change the passphrase and attempt to load - ensure flush error returned as parse error
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
# Remove the backup info files
|
|
executeTest('sudo rm ' . $oBackupInfo->{strFileName} . '*');
|
|
|
|
# Clear the storage repo settings and change the passphrase
|
|
storageRepoCacheClear($self->stanza());
|
|
|
|
my $strCipherPass = 'x';
|
|
$self->configTestClear();
|
|
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
|
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, $strCipherPass);
|
|
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
$self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo');
|
|
$self->configTestLoad(CFGCMD_ARCHIVE_PUSH);
|
|
|
|
# Confirm exception when not passing a sub passphrase
|
|
$self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,
|
|
{bIgnoreMissing => true})}, ERROR_ASSERT,
|
|
'a user passphrase and sub passphrase are both required when encrypting');
|
|
|
|
my $strCipherPassSub = cipherPassGen();
|
|
|
|
# Create encrypted files
|
|
$oBackupInfo = new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP), false, false,
|
|
{bIgnoreMissing => true, strCipherPassSub => $strCipherPassSub});
|
|
$oBackupInfo->create(PG_VERSION_93, $self->dbSysId(PG_VERSION_93), $i93ControlVersion, $i93CatalogVersion, true);
|
|
|
|
# Clear the storage repo settings and change the passphrase
|
|
storageRepoCacheClear($self->stanza());
|
|
$self->optionTestSet(CFGOPT_REPO_CIPHER_TYPE, CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
|
$self->optionTestSet(CFGOPT_REPO_CIPHER_PASS, BOGUS);
|
|
$self->optionTestSet(CFGOPT_STANZA, $self->stanza());
|
|
$self->optionTestSet(CFGOPT_REPO_PATH, $self->testPath() . '/repo');
|
|
$self->configTestLoad(CFGCMD_ARCHIVE_PUSH);
|
|
|
|
$self->testException(sub {new pgBackRest::Backup::Info(storageRepo()->pathGet(STORAGE_REPO_BACKUP))}, ERROR_CIPHER,
|
|
"unable to parse '" . $oBackupInfo->{strFileName} . "'" .
|
|
"\nHINT: Is or was the repo encrypted?");
|
|
}
|
|
}
|
|
|
|
1;
|