mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-16 10:20:02 +02:00
22aa532be1
Prevent a regression of the issue fixed in f88012ce
by adding some tests.
352 lines
20 KiB
Perl
352 lines
20 KiB
Perl
####################################################################################################################################
|
|
# Tests for Storage::Local module
|
|
####################################################################################################################################
|
|
package pgBackRestTest::Module::Storage::StoragePerlTest;
|
|
use parent 'pgBackRestTest::Common::RunTest';
|
|
|
|
####################################################################################################################################
|
|
# Perl includes
|
|
####################################################################################################################################
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
use English '-no_match_vars';
|
|
|
|
use pgBackRest::Config::Config;
|
|
use pgBackRest::Common::Exception;
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::LibC qw(:crypto);
|
|
use pgBackRest::Storage::Base;
|
|
|
|
use pgBackRestTest::Common::ContainerTest;
|
|
use pgBackRestTest::Common::ExecuteTest;
|
|
use pgBackRestTest::Common::RunTest;
|
|
use pgBackRestTest::Env::Host::HostBackupTest;
|
|
|
|
####################################################################################################################################
|
|
# run
|
|
####################################################################################################################################
|
|
sub run
|
|
{
|
|
my $self = shift;
|
|
|
|
# Define test file
|
|
my $strFile = $self->testPath() . '/file.txt';
|
|
my $strFileCopy = $self->testPath() . '/file.txt.copy';
|
|
my $strFileHash = 'bbbcf2c59433f68f22376cd2439d6cd309378df6';
|
|
my $strFileContent = 'TESTDATA';
|
|
my $iFileSize = length($strFileContent);
|
|
|
|
# Create local storage
|
|
$self->{oStorageLocal} = new pgBackRest::Storage::Storage('<LOCAL>');
|
|
|
|
################################################################################################################################
|
|
if ($self->begin("pathGet()"))
|
|
{
|
|
$self->testResult(sub {$self->storageLocal()->pathGet('file')}, '/file', 'relative path');
|
|
$self->testResult(sub {$self->storageLocal()->pathGet('/file2')}, '/file2', 'absolute path');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('put()'))
|
|
{
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile))}, 0, 'put empty');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->put($strFile)}, 0, 'put empty (all defaults)');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile), $strFileContent)}, $iFileSize, 'put');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->put($self->storageLocal()->openWrite($strFile), \$strFileContent)}, $iFileSize,
|
|
'put reference');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('get()'))
|
|
{
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->get($self->storageLocal()->openRead($strFile, {bIgnoreMissing => true}))}, undef,
|
|
'get missing');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->storageLocal()->put($strFile);
|
|
$self->testResult(sub {${$self->storageLocal()->get($strFile)}}, undef, 'get empty');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->storageLocal()->put($strFile, $strFileContent);
|
|
$self->testResult(sub {${$self->storageLocal()->get($strFile)}}, $strFileContent, 'get');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {${$self->storageLocal()->get($self->storageLocal()->openRead($strFile))}}, $strFileContent, 'get from io');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('hashSize()'))
|
|
{
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->put($strFile, $strFileContent)}, 8, 'put');
|
|
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->hashSize($strFile)},
|
|
qw{(} . cryptoHashOne('sha1', $strFileContent) . ', ' . $iFileSize . qw{)}, ' check hash/size');
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->hashSize(BOGUS, {bIgnoreMissing => true})}, "([undef], [undef])",
|
|
' check missing hash/size');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('copy()'))
|
|
{
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(
|
|
sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, ERROR_FILE_MISSING,
|
|
"unable to open missing file '${strFile}' for read");
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->exists($strFileCopy)}, false, ' destination does not exist');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->copy(
|
|
$self->storageLocal()->openRead($strFile, {bIgnoreMissing => true}),
|
|
$self->storageLocal()->openWrite($strFileCopy))},
|
|
false, 'missing source io');
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->exists($strFileCopy)}, false, ' destination does not exist');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(
|
|
sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, ERROR_FILE_MISSING,
|
|
"unable to open missing file '${strFile}' for read");
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->storageLocal()->put($strFile, $strFileContent);
|
|
|
|
$self->testResult(sub {$self->storageLocal()->copy($strFile, $strFileCopy)}, true, 'copy filename->filename');
|
|
$self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->storageLocal()->remove($strFileCopy);
|
|
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->copy($self->storageLocal()->openRead($strFile), $strFileCopy)}, true, 'copy io->filename');
|
|
$self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy');
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->storageLocal()->remove($strFileCopy);
|
|
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->copy(
|
|
$self->storageLocal()->openRead($strFile), $self->storageLocal()->openWrite($strFileCopy))},
|
|
true, 'copy io->io');
|
|
$self->testResult(sub {${$self->storageLocal()->get($strFileCopy)}}, $strFileContent, ' check copy');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('exists()'))
|
|
{
|
|
$self->storageLocal()->put($self->testPath() . "/test.file");
|
|
|
|
$self->testResult(sub {$self->storageLocal()->exists($self->testPath() . "/test.file")}, true, 'existing file');
|
|
$self->testResult(sub {$self->storageLocal()->exists($self->testPath() . "/test.missing")}, false, 'missing file');
|
|
$self->testResult(sub {$self->storageLocal()->exists($self->testPath())}, false, 'path');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('info()'))
|
|
{
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->info($self->testPath())},
|
|
"{group => " . $self->group() . ", mode => 0770, type => d, user => " . $self->pgUser() . "}",
|
|
'stat dir successfully');
|
|
|
|
$self->testException(sub {$self->storageLocal()->info(BOGUS)}, ERROR_FILE_OPEN,
|
|
"unable to get info for missing path/file '/bogus'");
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin("manifest() and list()"))
|
|
{
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(
|
|
sub {$self->storageLocal()->manifest($self->testPath() . '/missing')},
|
|
ERROR_PATH_MISSING, "unable to list file info for missing path '" . $self->testPath() . "/missing'");
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
# Setup test data
|
|
executeTest('mkdir -m 750 ' . $self->testPath() . '/sub1');
|
|
executeTest('mkdir -m 750 ' . $self->testPath() . '/sub1/sub2');
|
|
executeTest('mkdir -m 750 ' . $self->testPath() . '/sub2');
|
|
|
|
executeTest("echo 'TESTDATA' > " . $self->testPath() . '/test.txt');
|
|
utime(1111111111, 1111111111, $self->testPath() . '/test.txt');
|
|
executeTest('chmod 1640 ' . $self->testPath() . '/test.txt');
|
|
|
|
executeTest("echo 'TESTDATA_' > ". $self->testPath() . '/sub1/test-sub1.txt');
|
|
utime(1111111112, 1111111112, $self->testPath() . '/sub1/test-sub1.txt');
|
|
executeTest('chmod 0640 ' . $self->testPath() . '/sub1/test-sub1.txt');
|
|
|
|
executeTest("echo 'TESTDATA_' > ". $self->testPath() . '/sub1/.test-sub1.txt');
|
|
utime(1111111112, 1111111112, $self->testPath() . '/sub1/.test-sub1.txt');
|
|
executeTest('chmod 0640 ' . $self->testPath() . '/sub1/.test-sub1.txt');
|
|
|
|
executeTest("echo 'TESTDATA__' > " . $self->testPath() . '/sub1/sub2/test-sub2.txt');
|
|
utime(1111111113, 1111111113, $self->testPath() . '/sub1/sub2/test-sub2.txt');
|
|
executeTest('chmod 0646 ' . $self->testPath() . '/sub1/sub2/test-sub2.txt');
|
|
|
|
executeTest('mkfifo -m 606 ' . $self->testPath() . '/sub1/apipe');
|
|
|
|
executeTest('ln ' . $self->testPath() . '/test.txt ' . $self->testPath() . '/sub1/test-hardlink.txt');
|
|
executeTest('ln ' . $self->testPath() . '/test.txt ' . $self->testPath() . '/sub1/sub2/test-hardlink.txt');
|
|
|
|
executeTest('ln -s .. ' . $self->testPath() . '/sub1/test');
|
|
executeTest('chmod 0700 ' . $self->testPath() . '/sub1/test');
|
|
executeTest('ln -s ../.. ' . $self->testPath() . '/sub1/sub2/test');
|
|
executeTest('chmod 0750 ' . $self->testPath() . '/sub1/sub2/test');
|
|
|
|
executeTest('chmod 0770 ' . $self->testPath());
|
|
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->manifest($self->testPath())},
|
|
'{. => {group => ' . $self->group() . ', mode => 0770, type => d, user => ' . $self->pgUser() . '}, ' .
|
|
'sub1 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' .
|
|
'sub1/.test-sub1.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111112, size => 10, type => f, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub1/apipe => {group => ' . $self->group() . ', mode => 0606, type => s, user => ' . $self->pgUser() . '}, ' .
|
|
'sub1/sub2 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' .
|
|
'sub1/sub2/test => {group => ' . $self->group() . ', link_destination => ../.., type => l, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub1/sub2/test-hardlink.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub1/sub2/test-sub2.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0646, modification_time => 1111111113, size => 11, type => f, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub1/test => {group => ' . $self->group() . ', link_destination => .., type => l, user => ' . $self->pgUser() . '}, ' .
|
|
'sub1/test-hardlink.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub1/test-sub1.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111112, size => 10, type => f, user => ' .
|
|
$self->pgUser() . '}, ' .
|
|
'sub2 => {group => ' . $self->group() . ', mode => 0750, type => d, user => ' . $self->pgUser() . '}, ' .
|
|
'test.txt => ' .
|
|
'{group => ' . $self->group() . ', mode => 0640, modification_time => 1111111111, size => 9, type => f, user => ' .
|
|
$self->pgUser() . '}}',
|
|
'complete manifest');
|
|
|
|
$self->testResult(sub {$self->storageLocal()->list($self->testPath())}, "(sub1, sub2, test.txt)", "list");
|
|
$self->testResult(sub {$self->storageLocal()->list($self->testPath(), {strExpression => "2\$"})}, "sub2", "list");
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->list($self->testPath(), {strSortOrder => 'reverse'})}, "(test.txt, sub2, sub1)",
|
|
"list reverse");
|
|
$self->testResult(sub {$self->storageLocal()->list($self->testPath() . "/sub2")}, "[undef]", "list empty");
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->list($self->testPath() . "/sub99", {bIgnoreMissing => true})}, "[undef]", "list missing");
|
|
$self->testException(
|
|
sub {$self->storageLocal()->list($self->testPath() . "/sub99")}, ERROR_PATH_MISSING,
|
|
"unable to list files for missing path '" . $self->testPath() . "/sub99'");
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('move()'))
|
|
{
|
|
my $strFileCopy = "${strFile}.copy";
|
|
my $strFileSub = $self->testPath() . '/sub/file.txt';
|
|
|
|
#---------------------------------------------------------------------------------------------------------------------------
|
|
$self->testException(
|
|
sub {$self->storageLocal()->move($strFile, $strFileCopy)}, ERROR_FILE_MOVE,
|
|
"unable to move '${strFile}' to '${strFile}.copy': No such file or directory");
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('owner()'))
|
|
{
|
|
my $strFile = $self->testPath() . "/test.txt";
|
|
|
|
$self->testException(
|
|
sub {$self->storageLocal()->owner($strFile, 'root')}, ERROR_FILE_MISSING,
|
|
"unable to stat '${strFile}': No such file or directory");
|
|
|
|
executeTest("touch ${strFile}");
|
|
|
|
$self->testException(
|
|
sub {$self->storageLocal()->owner($strFile, BOGUS)}, ERROR_FILE_OWNER,
|
|
"unable to set ownership for '${strFile}' because user 'bogus' does not exist");
|
|
$self->testException(
|
|
sub {$self->storageLocal()->owner($strFile, undef, BOGUS)}, ERROR_FILE_OWNER,
|
|
"unable to set ownership for '${strFile}' because group 'bogus' does not exist");
|
|
|
|
$self->testResult(sub {$self->storageLocal()->owner($strFile)}, undef, "no ownership changes");
|
|
$self->testResult(sub {$self->storageLocal()->owner($strFile, TEST_USER)}, undef, "same user");
|
|
$self->testResult(sub {$self->storageLocal()->owner($strFile, undef, TEST_GROUP)}, undef, "same group");
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->owner($strFile, TEST_USER, TEST_GROUP)}, undef,
|
|
"same user, group");
|
|
|
|
$self->testException(
|
|
sub {$self->storageLocal()->owner($strFile, 'root', undef)}, ERROR_FILE_OWNER,
|
|
"unable to set ownership for '${strFile}': Operation not permitted");
|
|
$self->testException(
|
|
sub {$self->storageLocal()->owner($strFile, undef, 'root')}, ERROR_FILE_OWNER,
|
|
"unable to set ownership for '${strFile}': Operation not permitted");
|
|
|
|
executeTest("sudo chown :root ${strFile}");
|
|
$self->testResult(
|
|
sub {$self->storageLocal()->owner($strFile, undef, TEST_GROUP)}, undef, "change group back from root");
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('pathCreate()'))
|
|
{
|
|
my $strTestPath = $self->testPath() . "/" . BOGUS;
|
|
|
|
$self->testResult(sub {$self->storageLocal()->pathCreate($strTestPath)}, "[undef]",
|
|
"test creation of path " . $strTestPath);
|
|
|
|
$self->testException(sub {$self->storageLocal()->pathCreate($strTestPath)}, ERROR_PATH_CREATE,
|
|
"unable to create path '". $strTestPath. "'");
|
|
|
|
$self->testResult(sub {$self->storageLocal()->pathCreate($strTestPath, {bIgnoreExists => true})}, "[undef]",
|
|
"ignore path exists");
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('pathExists()'))
|
|
{
|
|
$self->storageLocal()->put($self->testPath() . "/test.file");
|
|
|
|
$self->testResult(sub {$self->storageLocal()->pathExists($self->testPath() . "/test.file")}, false, 'existing file');
|
|
$self->testResult(sub {$self->storageLocal()->pathExists($self->testPath() . "/test.missing")}, false, 'missing file');
|
|
$self->testResult(sub {$self->storageLocal()->pathExists($self->testPath())}, true, 'path');
|
|
}
|
|
|
|
################################################################################################################################
|
|
if ($self->begin('pathSync()'))
|
|
{
|
|
$self->testResult(sub {$self->storageLocal()->pathSync($self->testPath())}, "[undef]", "test path sync");
|
|
}
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# Getters
|
|
####################################################################################################################################
|
|
# sub host {return '127.0.0.1'}
|
|
# sub pathLocal {return shift->{strPathLocal}};
|
|
# sub pathRemote {return shift->{strPathRemote}};
|
|
sub storageLocal {return shift->{oStorageLocal}};
|
|
# sub storageEncrypt {return shift->{oStorageEncrypt}};
|
|
# sub storageRemote {return shift->{oStorageRemote}};
|
|
|
|
1;
|