941 lines
34 KiB
Perl
941 lines
34 KiB
Perl
#-------------------------------------------------------------------
|
|
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
|
#-------------------------------------------------------------------
|
|
# Please read the legal notices (docs/legal.txt) and the license
|
|
# (docs/license.txt) that came with this distribution before using
|
|
# this software.
|
|
#-------------------------------------------------------------------
|
|
# http://www.plainblack.com info@plainblack.com
|
|
#-------------------------------------------------------------------
|
|
|
|
use FindBin;
|
|
use strict;
|
|
use lib "$FindBin::Bin/lib";
|
|
|
|
use WebGUI::Test;
|
|
use WebGUI::Test::Event;
|
|
use WebGUI::Session;
|
|
use WebGUI::Storage;
|
|
|
|
use File::Spec;
|
|
use File::Temp qw/tempdir/;
|
|
use Image::Magick;
|
|
use Test::More;
|
|
use Test::Deep;
|
|
use Test::MockObject;
|
|
use Cwd;
|
|
use Path::Class::Dir;
|
|
|
|
my $session = WebGUI::Test->session;
|
|
|
|
my $cwd = Cwd::cwd();
|
|
|
|
my ($extensionTests, $fileIconTests, $block_extension_tests) = setupDataDrivenTests($session);
|
|
|
|
plan tests => 164
|
|
+ scalar @{ $extensionTests }
|
|
+ scalar @{ $fileIconTests }
|
|
+ scalar @{ $block_extension_tests }
|
|
;
|
|
|
|
my $uploadDir = $session->config->get('uploadsPath');
|
|
ok ($uploadDir, "uploadDir defined in config");
|
|
|
|
my $uploadUrl = $session->config->get('uploadsURL');
|
|
ok ($uploadUrl, "uploadDir defined in config");
|
|
|
|
####################################################
|
|
#
|
|
# get, getId
|
|
#
|
|
####################################################
|
|
|
|
ok ((-e $uploadDir and -d $uploadDir), "uploadDir exists and is a directory");
|
|
|
|
my $storage1 = WebGUI::Storage->get($session);
|
|
|
|
is( $storage1, undef, "get requires id to be passed");
|
|
|
|
$storage1 = WebGUI::Storage->get($session, 'foobar');
|
|
WebGUI::Test->addToCleanup($storage1);
|
|
|
|
isa_ok( $storage1, "WebGUI::Storage", "storage will accept non GUID arguments");
|
|
is ( $storage1->getId, 'foobar', 'getId returns the requested GUID');
|
|
|
|
is( $storage1->getErrorCount, 0, "No errors during path creation");
|
|
|
|
is( $storage1->getLastError, undef, "No errors during path creation");
|
|
|
|
####################################################
|
|
#
|
|
# getPathFrag, getDirectoryId, get
|
|
#
|
|
####################################################
|
|
|
|
is( $storage1->getPathFrag, '7e/8a/7e8a1b6ab', 'pathFrag returns correct value');
|
|
is( $storage1->getDirectoryId, '7e8a1b6ab', 'getDirectoryId returns the last path element');
|
|
|
|
##Build an old-style GUID storage location
|
|
my $uploadsBase = Path::Class::Dir->new($uploadDir);
|
|
my $newGuid = $session->id->generate();
|
|
my @guidPathParts = (substr($newGuid, 0, 2), substr($newGuid, 2, 2), $newGuid);
|
|
my $guidDir = $uploadsBase->subdir(@guidPathParts);
|
|
$guidDir->mkpath();
|
|
ok(-e $guidDir->stringify, 'created GUID storage location for backwards compatibility testing');
|
|
|
|
my $guidStorage = WebGUI::Storage->get($session, $newGuid);
|
|
WebGUI::Test->addToCleanup($guidStorage);
|
|
isa_ok($guidStorage, 'WebGUI::Storage');
|
|
is($guidStorage->getId, $newGuid, 'GUID storage has correct id');
|
|
is($guidStorage->getDirectoryId, $newGuid, '... getDirectoryId');
|
|
|
|
####################################################
|
|
#
|
|
# getPath, getUrl
|
|
#
|
|
####################################################
|
|
|
|
WebGUI::Test->originalConfig('cdn');
|
|
$session->config->delete('cdn');
|
|
# Note: the CDN configuration will be reverted after CDN tests below
|
|
|
|
my $storageDir1 = join '/', $uploadDir, '7e', '8a', '7e8a1b6ab';
|
|
is ($storage1->getPath, $storageDir1, 'getPath: path calculated correctly for directory');
|
|
my $storageFile1 = join '/', $storageDir1, 'baz';
|
|
is ($storage1->getPath('baz'), $storageFile1, 'getPath: path calculated correctly for file');
|
|
|
|
my $storageUrl1 = join '/', $uploadUrl, '7e', '8a', '7e8a1b6ab';
|
|
is ($storage1->getUrl, $storageUrl1, 'getUrl: url calculated correctly for directory');
|
|
my $storageUrl2 = join '/', $storageUrl1, 'bar';
|
|
is ($storage1->getUrl('bar'), $storageUrl2, 'getUrl: url calculated correctly for file');
|
|
|
|
ok( (-e $storageDir1 and -d $storageDir1), "Storage location created and is a directory");
|
|
|
|
$storage1->delete;
|
|
|
|
ok( !(-e $storageDir1), "Storage location deleted");
|
|
|
|
undef $storage1;
|
|
|
|
$storage1 = WebGUI::Storage->get($session, 'notAGUID');
|
|
my $storage2 = WebGUI::Storage->get($session, 'notAGoodId');
|
|
WebGUI::Test->addToCleanup($storage2);
|
|
|
|
ok(! $storage2->getErrorCount, 'No errors due to a shared common root');
|
|
|
|
ok( (-e $storage1->getPath and -d $storage1->getPath), "Storage location 1 created and is a directory");
|
|
ok( (-e $storage2->getPath and -d $storage2->getPath), "Storage location 2 created and is a directory");
|
|
|
|
$storage1->delete;
|
|
undef $storage1;
|
|
|
|
ok( (-e $storage2->getPath and -d $storage2->getPath), "Storage location 2 not touched");
|
|
|
|
$storage2->delete;
|
|
|
|
my $storageDir2 = join '/', $uploadDir, 'no';
|
|
|
|
ok (!(-e $storageDir2), "Storage2 cleaned up properly");
|
|
|
|
undef $storage2;
|
|
|
|
## NOTE: On case insensitive file systems more matches can occur on this test
|
|
## and if all of these exist, then the next test will fail.
|
|
|
|
my @dirOptions = qw/bad bAd Bad BAd Zod God Mod Tod Rod Bod Lod/;
|
|
|
|
my ($dir3, $dirOpt);
|
|
|
|
CHECKDIR: while ($dirOpt = pop @dirOptions) {
|
|
$dir3 = join '/', $uploadDir, substr $dirOpt,0,2;
|
|
last CHECKDIR if !-e $dir3;
|
|
}
|
|
my $storage3 = WebGUI::Storage->get($session, $dirOpt);
|
|
WebGUI::Test->addToCleanup($storage3);
|
|
|
|
is( $storage3->getErrorCount, 1, 'Error during creation of object due to short GUID');
|
|
|
|
SKIP: {
|
|
skip 'All directory names already exist', 1 unless $dirOpt;
|
|
ok(!(-e $dir3 and -d $dir3), 'No directories created for short guid');
|
|
}
|
|
|
|
undef $storage3;
|
|
|
|
####################################################
|
|
#
|
|
# storageExists
|
|
#
|
|
####################################################
|
|
|
|
my $existingStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($existingStorage);
|
|
ok(WebGUI::Storage->storageExists($session, $existingStorage->getId), "storageExists returns true when the storage exists");
|
|
ok(!WebGUI::Storage->storageExists($session, 'Never_WebGUI_GUID'), "... and false when it doesn't");
|
|
|
|
####################################################
|
|
#
|
|
# create, getHexId
|
|
#
|
|
####################################################
|
|
|
|
$storage1 = WebGUI::Storage->create($session);
|
|
|
|
isa_ok( $storage1, "WebGUI::Storage");
|
|
ok($session->id->valid($storage1->getId), 'create returns valid sessionIds');
|
|
ok($storage1->getHexId, 'getHexId returns something');
|
|
is($storage1->getHexId, $session->id->toHex($storage1->getId), '... returns the hexadecimal value of the GUID');
|
|
|
|
{
|
|
my $otherStorage = WebGUI::Storage->get($session, $storage1->getId);
|
|
is($otherStorage->getHexId, $storage1->getHexId, '... works with get');
|
|
}
|
|
|
|
is( $storage1->getErrorCount, 0, "No errors during object creation");
|
|
|
|
ok ((-e $storage1->getPath and -d $storage1->getPath), 'directory created correctly');
|
|
|
|
my $content = <<EOCON;
|
|
Hi, I'm a file.
|
|
I have two lines.
|
|
EOCON
|
|
|
|
sub fired_ok(&@) {
|
|
my ($block, @expected) = @_;
|
|
my @events = trap { $block->() } $session, 'storage::addFile';
|
|
my @got = map { $_->[3] } @events;
|
|
cmp_bag \@got, \@expected, 'events fired for ' . join ', ', @expected;
|
|
}
|
|
|
|
my $filename; fired_ok {
|
|
$filename = $storage1->addFileFromScalar('content', $content)
|
|
} 'content';
|
|
|
|
is ($filename, 'content', 'processed filename returned by addFileFromScalar');
|
|
|
|
my $filePath = $storage1->getPath($filename);
|
|
|
|
ok ((-e $filePath and -T $filePath), 'file was created as a text file');
|
|
|
|
is (-s $filePath, length $content, 'file is the right size');
|
|
|
|
is ($storage1->getFileSize($filename), length $content, 'getFileSize returns correct size');
|
|
|
|
open my $fcon, "< ".$filePath or
|
|
die "Unable to open $filePath for reading: $!\n";
|
|
my $fileContents;
|
|
{
|
|
local $/;
|
|
$fileContents = <$fcon>;
|
|
}
|
|
close $fcon;
|
|
|
|
is ($fileContents, $content, 'file contents match');
|
|
|
|
is ($storage1->getFileContentsAsScalar($filename), $content, 'getFileContentsAsScalar matches');
|
|
|
|
isnt($/, undef, 'getFileContentsAsScalar did not change $/');
|
|
|
|
foreach my $extTest (@{ $extensionTests }) {
|
|
is( $storage1->getFileExtension($extTest->{filename}), $extTest->{extension}, $extTest->{comment} );
|
|
}
|
|
|
|
####################################################
|
|
#
|
|
# getFiles
|
|
#
|
|
####################################################
|
|
|
|
my $fileStore = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($fileStore);
|
|
cmp_bag($fileStore->getFiles(1), ['.'], 'Starting with an empty storage object, no files in here except for . ');
|
|
fired_ok { $fileStore->addFileFromScalar('.dotfile', 'dot file') } '.dotfile';
|
|
cmp_bag($fileStore->getFiles(), [ ], 'getFiles() by default does not return dot files');
|
|
cmp_bag($fileStore->getFiles(1), ['.', '.dotfile'], 'getFiles(1) returns all files, including dot files');
|
|
fired_ok { $fileStore->addFileFromScalar('dot.file', 'dot.file') } 'dot.file';
|
|
cmp_bag($fileStore->getFiles(), ['dot.file'], 'getFiles() returns normal files');
|
|
cmp_bag($fileStore->getFiles(1), ['.', '.dotfile', 'dot.file'], 'getFiles(1) returns all files, including dot files');
|
|
|
|
####################################################
|
|
#
|
|
# getPathClassDir
|
|
#
|
|
####################################################
|
|
|
|
my $obj = $storage1->getPathClassDir;
|
|
isa_ok($obj, 'Path::Class::Dir');
|
|
is($obj->stringify, $storage1->getPath, '... Path::Class::Dir object has correct path');
|
|
|
|
####################################################
|
|
#
|
|
# addFileFromHashref
|
|
#
|
|
####################################################
|
|
|
|
my $storageHash = {'blah'=>"blah",'foo'=>"foo"};
|
|
fired_ok {
|
|
$storage1->addFileFromHashref("testfile-hash.file", $storageHash);
|
|
} 'testfile-hash.file';
|
|
ok (-e $storage1->getPath("testfile-hash.file"), 'addFileFromHashRef creates file');
|
|
|
|
####################################################
|
|
#
|
|
# getFileContentsAsHashref
|
|
#
|
|
####################################################
|
|
|
|
my $thawedHash = $storage1->getFileContentsAsHashref('testfile-hash.file');
|
|
cmp_deeply($storageHash, $thawedHash, 'getFileContentsAsHashref: thawed hash correctly');
|
|
|
|
####################################################
|
|
#
|
|
# copyFile
|
|
#
|
|
####################################################
|
|
|
|
$storage1->copyFile("testfile-hash.file", "testfile-hash-copied.file");
|
|
ok (-e $storage1->getPath("testfile-hash-copied.file"),'copyFile created file with new name');
|
|
ok (-e $storage1->getPath("testfile-hash.file"), "copyFile original file still exists");
|
|
|
|
####################################################
|
|
#
|
|
# renameFile
|
|
#
|
|
####################################################
|
|
|
|
$storage1->renameFile("testfile-hash.file", "testfile-hash-renamed.file");
|
|
ok (-e $storage1->getPath("testfile-hash-renamed.file"),'renameFile created file with new name');
|
|
ok (!(-e $storage1->getPath("testfile-hash.file")), "rename file original file is gone");
|
|
|
|
####################################################
|
|
#
|
|
# addFileFromFilesystem
|
|
#
|
|
####################################################
|
|
|
|
fired_ok {
|
|
$storage1->addFileFromFilesystem(
|
|
WebGUI::Test->getTestCollateralPath('littleTextFile'),
|
|
);
|
|
} 'littleTextFile';
|
|
|
|
ok(
|
|
grep(/littleTextFile/, @{ $storage1->getFiles }),
|
|
'addFileFromFilesystem: file added from test collateral area'
|
|
);
|
|
|
|
####################################################
|
|
#
|
|
# copy
|
|
#
|
|
####################################################
|
|
|
|
my $copiedStorage = $storage1->copy();
|
|
WebGUI::Test->addToCleanup($copiedStorage);
|
|
cmp_bag($copiedStorage->getFiles(), $storage1->getFiles(), 'copy: both storage objects have the same files');
|
|
|
|
my $secondCopy = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($secondCopy);
|
|
$storage1->copy($secondCopy);
|
|
cmp_bag($secondCopy->getFiles(), $storage1->getFiles(), 'copy: passing explicit variable');
|
|
|
|
my $s3copy = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($s3copy);
|
|
my @filesToCopy = qw/littleTextFile testfile-hash-renamed.file/;
|
|
$storage1->copy($s3copy, [@filesToCopy]);
|
|
cmp_bag($s3copy->getFiles(), [ @filesToCopy ], 'copy: passing explicit variable and files to copy');
|
|
{
|
|
my $deepStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($deepStorage);
|
|
my $deepDir = $deepStorage->getPathClassDir();
|
|
my $deepDeepDir = $deepDir->subdir('deep');
|
|
my $errorStr;
|
|
my @foo = $deepDeepDir->mkpath({ error => \$errorStr } );
|
|
fired_ok {
|
|
$deepStorage->addFileFromScalar('deep/file', 'deep file')
|
|
} 'deep/file';
|
|
cmp_bag(
|
|
$deepStorage->getFiles('all'),
|
|
[ '.', 'deep', 'deep/file' ],
|
|
'... storage setup for deep clear test'
|
|
);
|
|
my $deepCopy = $deepStorage->copy();
|
|
WebGUI::Test->addToCleanup($deepCopy);
|
|
cmp_bag(
|
|
$deepCopy->getFiles('all'),
|
|
[ '.', 'deep', 'deep/file' ],
|
|
'... all files copied, deeply'
|
|
);
|
|
}
|
|
|
|
|
|
####################################################
|
|
#
|
|
# deleteFile
|
|
#
|
|
####################################################
|
|
|
|
is(scalar @{ $storage1->getFiles }, 4, 'storage1 has 4 files');
|
|
is($storage1->deleteFile("testfile-hash-renamed.file"), 1, 'deleteFile: deleted 1 file');
|
|
is($storage1->deleteFile("testfile-hash-copied.file"), 1, 'deleteFile: deleted 1 file');
|
|
is($storage1->deleteFile("littleTextFile"), 1, 'deleteFile: deleted another file');
|
|
cmp_bag($storage1->getFiles, [$filename], 'deleteFile: storage1 has only 1 file');
|
|
|
|
##Test for out of object file deletion
|
|
my $hackedStore = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($hackedStore);
|
|
$hackedStore->addFileFromScalar('fileToHack', 'Can this file be deleted from another object?');
|
|
ok(-e $hackedStore->getPath('fileToHack'), 'set up a file for deleteFile to try and delete illegally');
|
|
my $hackedPath = '../../../'.$hackedStore->getPathFrag().'/fileToHack';
|
|
is($storage1->deleteFile($hackedPath), undef, 'deleteFile into another storage returns undef');
|
|
ok(-e $hackedStore->getPath('fileToHack'), 'deleteFile did not delete the file in another storage object');
|
|
|
|
####################################################
|
|
#
|
|
# createTemp, getHexId
|
|
#
|
|
####################################################
|
|
|
|
my $tempStor = WebGUI::Storage->createTemp($session);
|
|
WebGUI::Test->addToCleanup($tempStor);
|
|
|
|
isa_ok( $tempStor, "WebGUI::Storage", "createTemp creates WebGUI::Storage object");
|
|
is (substr($tempStor->getPathFrag, 0, 5), 'temp/', '... puts stuff in the temp directory');
|
|
ok (-e $tempStor->getPath(), '... directory was created');
|
|
ok($tempStor->getHexId, '... getHexId returns something');
|
|
is($tempStor->getHexId, $session->id->toHex($tempStor->getId), '... returns the hexadecimal value of the GUID');
|
|
|
|
####################################################
|
|
#
|
|
# block_extensions
|
|
#
|
|
####################################################
|
|
|
|
##Run a set of extensions through and watch how the files get changed.
|
|
foreach my $extTest (@{ $block_extension_tests }) {
|
|
is( $storage1->block_extensions($extTest->{filename}), $extTest->{blockname}, $extTest->{comment} );
|
|
}
|
|
|
|
####################################################
|
|
#
|
|
# tar
|
|
#
|
|
####################################################
|
|
|
|
my $tarStorage = $copiedStorage->tar('tar.tar');
|
|
WebGUI::Test->addToCleanup($tarStorage);
|
|
isa_ok( $tarStorage, "WebGUI::Storage", "tar: returns a WebGUI::Storage object");
|
|
is (substr($tarStorage->getPathFrag, 0, 5), 'temp/', 'tar: puts stuff in the temp directory');
|
|
cmp_bag($tarStorage->getFiles(), [ 'tar.tar' ], 'tar: storage contains only the tar file');
|
|
isnt($tarStorage->getPath, $copiedStorage->getPath, 'tar did not reuse the same path as the source storage object');
|
|
|
|
####################################################
|
|
#
|
|
# untar
|
|
#
|
|
####################################################
|
|
|
|
my $untarStorage = $tarStorage->untar('tar.tar');
|
|
WebGUI::Test->addToCleanup($untarStorage);
|
|
isa_ok( $untarStorage, "WebGUI::Storage", "untar: returns a WebGUI::Storage object");
|
|
is (substr($untarStorage->getPathFrag, 0, 5), 'temp/', 'untar: puts stuff in the temp directory');
|
|
cmp_bag($untarStorage->getFiles, $copiedStorage->getFiles, 'tar and untar loop preserve all files');
|
|
isnt($untarStorage->getPath, $tarStorage->getPath, 'untar did not reuse the same path as the tar storage object');
|
|
|
|
$tarStorage->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath('extensions.tar'));
|
|
my $extensionStorage = $tarStorage->untar('extensions.tar');
|
|
WebGUI::Test->addToCleanup($extensionStorage);
|
|
cmp_bag(
|
|
$extensionStorage->getFiles,
|
|
[ qw{ extension_pm.txt extension_perl.txt extension_html.txt extensions extensions/extension_html.txt }],
|
|
'untar fixes file extensions'
|
|
);
|
|
|
|
####################################################
|
|
#
|
|
# clear
|
|
#
|
|
####################################################
|
|
|
|
ok(scalar @{ $copiedStorage->getFiles } > 0, 'copiedStorage has some files');
|
|
$copiedStorage->clear;
|
|
cmp_bag(
|
|
$copiedStorage->getFiles('all'),
|
|
[ '.' ],
|
|
'clear removed all files from copiedStorage'
|
|
);
|
|
cmp_bag(
|
|
$copiedStorage->getFiles('all'),
|
|
[ '.' ],
|
|
'... removed _all_ files from copiedStorage, except for . and ..'
|
|
);
|
|
|
|
$copiedStorage->setPrivileges(3,3,3);
|
|
cmp_bag(
|
|
$copiedStorage->getFiles('all'),
|
|
[ '.', '.wgaccess' ],
|
|
'... removed _all_ files from copiedStorage, except for . and ..'
|
|
);
|
|
$copiedStorage->clear;
|
|
cmp_bag(
|
|
$copiedStorage->getFiles('all'),
|
|
[ '.' ],
|
|
'... removed .wgaccess file'
|
|
);
|
|
|
|
{
|
|
my $deepStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($deepStorage);
|
|
my $deepDir = $deepStorage->getPathClassDir();
|
|
my $deepDeepDir = $deepDir->subdir('deep');
|
|
my $errorStr;
|
|
$deepDeepDir->mkpath({ error => \$errorStr } );
|
|
$deepStorage->addFileFromScalar('deep/file', 'deep file');
|
|
cmp_bag(
|
|
$deepStorage->getFiles('all'),
|
|
[ '.', 'deep', 'deep/file' ],
|
|
'... storage setup for deep clear test'
|
|
);
|
|
$deepStorage->clear();
|
|
cmp_bag(
|
|
$deepStorage->getFiles('all'),
|
|
[ '.', ],
|
|
'... clear removes directories'
|
|
);
|
|
}
|
|
|
|
####################################################
|
|
#
|
|
# addFileFromFormPost
|
|
#
|
|
####################################################
|
|
|
|
$session->http->setStatus(413);
|
|
is($fileStore->addFileFromFormPost(), '', 'addFileFromFormPost returns empty string when HTTP status is 413');
|
|
|
|
$session->http->setStatus(200);
|
|
$session->request->upload('files', []);
|
|
my $formStore = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($formStore);
|
|
is($formStore->addFileFromFormPost('files'), undef, 'addFileFromFormPost returns empty string when asking for a form variable with no files attached');
|
|
|
|
$session->request->uploadFiles(
|
|
'oneFile',
|
|
[ WebGUI::Test->getTestCollateralPath('littleTextFile') ],
|
|
);
|
|
fired_ok {
|
|
is($formStore->addFileFromFormPost('oneFile'), 'littleTextFile', '... returns the name of the uploaded file')
|
|
} 'littleTextFile';
|
|
cmp_bag($formStore->getFiles, [ qw/littleTextFile/ ], '... adds the file to the storage location');
|
|
|
|
$session->request->uploadFiles(
|
|
'thumbFile',
|
|
[ WebGUI::Test->getTestCollateralPath('thumb-thumb.gif') ],
|
|
);
|
|
is($formStore->addFileFromFormPost('thumbFile'), 'thumb.gif', '... strips thumb- prefix from files');
|
|
cmp_bag($formStore->getFiles, [ qw/littleTextFile thumb.gif/ ], '... adds the file to the storage location');
|
|
|
|
####################################################
|
|
#
|
|
# getFileIconUrl
|
|
#
|
|
####################################################
|
|
|
|
foreach my $iconTest (@{ $fileIconTests }) {
|
|
is( $storage1->getFileIconUrl($iconTest->{filename}), $iconTest->{iconUrl}, $iconTest->{comment} );
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
# writeAccess
|
|
my $shallowStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($shallowStorage);
|
|
$shallowStorage->writeAccess( users => ["3"], groups => ["2"], assets => ["1"] );
|
|
my $shallowDir = $shallowStorage->getPathClassDir();
|
|
ok(-e $shallowDir->file('.wgaccess')->stringify, 'writeAccess: .wgaccess file created in shallow storage');
|
|
my $privs;
|
|
$privs = $shallowStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"assets":["1"],"groups":["2"],"users":["3"]}', '... correct group contents');
|
|
$shallowStorage->deleteFile('.wgaccess');
|
|
|
|
my $deepStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($deepStorage);
|
|
my $deepDir = $deepStorage->getPathClassDir();
|
|
my $deepDeepDir = $deepDir->subdir('deep');
|
|
my $errorStr;
|
|
$deepDeepDir->mkpath({ error => \$errorStr } );
|
|
ok(-e $deepDeepDir->stringify, 'created storage directory with a subdirectory for testing');
|
|
|
|
$deepStorage->writeAccess( users => ["3"], groups => ["2"], assets => ["1"] );
|
|
ok(-e $deepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage');
|
|
ok(-e $deepDeepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage subdir');
|
|
|
|
$privs = $deepStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"assets":["1"],"groups":["2"],"users":["3"]}', '... correct group contents, deep storage');
|
|
$privs = $deepStorage->getFileContentsAsScalar('deep/.wgaccess');
|
|
is ($privs, '{"assets":["1"],"groups":["2"],"users":["3"]}', '... correct group contents, deep storage subdir');
|
|
|
|
#----------------------------------------------------------------------------
|
|
# trash
|
|
my $shallowStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($shallowStorage);
|
|
$shallowStorage->trash;
|
|
my $shallowDir = $shallowStorage->getPathClassDir();
|
|
ok(-e $shallowDir->file('.wgaccess')->stringify, 'trash: .wgaccess file created in shallow storage');
|
|
my $privs;
|
|
$privs = $shallowStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"state":"trash"}', '... correct state');
|
|
$shallowStorage->deleteFile('.wgaccess');
|
|
|
|
my $deepStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($deepStorage);
|
|
my $deepDir = $deepStorage->getPathClassDir();
|
|
my $deepDeepDir = $deepDir->subdir('deep');
|
|
my $errorStr;
|
|
$deepDeepDir->mkpath({ error => \$errorStr } );
|
|
ok(-e $deepDeepDir->stringify, 'created storage directory with a subdirectory for testing');
|
|
|
|
$deepStorage->trash;
|
|
ok(-e $deepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage');
|
|
ok(-e $deepDeepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage subdir');
|
|
|
|
$privs = $deepStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"state":"trash"}', '... correct state contents, deep storage');
|
|
$privs = $deepStorage->getFileContentsAsScalar('deep/.wgaccess');
|
|
is ($privs, '{"state":"trash"}', '... correct state contents, deep storage subdir');
|
|
|
|
####################################################
|
|
#
|
|
# setPrivileges
|
|
#
|
|
####################################################
|
|
|
|
my $shallowStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($shallowStorage);
|
|
$shallowStorage->setPrivileges(3,3,3);
|
|
my $shallowDir = $shallowStorage->getPathClassDir();
|
|
ok(-e $shallowDir->file('.wgaccess')->stringify, 'setPrivilege: .wgaccess file created in shallow storage');
|
|
my $privs;
|
|
$privs = $shallowStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"assets":[],"groups":["3","3"],"users":["3"]}', '... correct group contents');
|
|
$shallowStorage->deleteFile('.wgaccess');
|
|
|
|
my $deepStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($deepStorage);
|
|
my $deepDir = $deepStorage->getPathClassDir();
|
|
my $deepDeepDir = $deepDir->subdir('deep');
|
|
my $errorStr;
|
|
$deepDeepDir->mkpath({ error => \$errorStr } );
|
|
ok(-e $deepDeepDir->stringify, 'created storage directory with a subdirectory for testing');
|
|
|
|
$deepStorage->setPrivileges(3,3,3);
|
|
ok(-e $deepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage');
|
|
ok(-e $deepDeepDir->file('.wgaccess')->stringify, '.wgaccess file created in deep storage subdir');
|
|
|
|
$privs = $deepStorage->getFileContentsAsScalar('.wgaccess');
|
|
is ($privs, '{"assets":[],"groups":["3","3"],"users":["3"]}', '... correct group contents, deep storage');
|
|
$privs = $deepStorage->getFileContentsAsScalar('deep/.wgaccess');
|
|
is ($privs, '{"assets":[],"groups":["3","3"],"users":["3"]}', '... correct group contents, deep storage subdir');
|
|
|
|
{
|
|
my $storage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($storage);
|
|
my $asset = WebGUI::Asset->getRoot($session);
|
|
$storage->setPrivileges( $asset );
|
|
my $accessFile = $storage->getPathClassDir->file('.wgaccess');
|
|
ok(-e $accessFile, 'setPrivilege: .wgaccess file created for asset permissions');
|
|
my $privs = $accessFile->slurp;
|
|
is ($privs, '{"assets":["' . $asset->getId . '"],"groups":[],"users":[]}', '... correct asset contents');
|
|
}
|
|
|
|
####################################################
|
|
#
|
|
# rotate
|
|
#
|
|
####################################################
|
|
|
|
# Create new storage for test of 'rotate' method
|
|
my $rotateTestStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($rotateTestStorage);
|
|
|
|
# Add test image from file system
|
|
my $file = "rotation_test.png";
|
|
$rotateTestStorage->addFileFromFilesystem( WebGUI::Test->getTestCollateralPath($file) );
|
|
|
|
# Rotate image by 90° CW
|
|
$rotateTestStorage->rotate( $file, 90 );
|
|
|
|
# Test based on dimensions
|
|
cmp_deeply( [ $rotateTestStorage->getSizeInPixels($file) ], [ 3, 2 ], "rotate: check if image was rotated by 90° CW (based on dimensions)" );
|
|
# Test based on single pixel
|
|
my $image = new Image::Magick;
|
|
$image->Read( $rotateTestStorage->getPath( $file ) );
|
|
is( $image->GetPixel( x=>3, y=>1 ), 1, "rotate: check if image was rotated by 90° CW (based on pixels)");
|
|
|
|
# Rotate image by 90° CCW
|
|
$rotateTestStorage->rotate( $file, -90 );
|
|
|
|
# Test based on dimensions
|
|
cmp_deeply( [ $rotateTestStorage->getSizeInPixels($file) ], [ 2, 3 ], "rotate: check if image was rotated by 90° CCW (based on dimensions)" );
|
|
# Test based on single pixel
|
|
my $image = new Image::Magick;
|
|
$image->Read( $rotateTestStorage->getPath( $file ) );
|
|
is( $image->GetPixel( x=>1, y=>1 ), 1, "rotate: check if image was rotated by 90° CCW (based on pixels)");
|
|
|
|
####################################################
|
|
#
|
|
# CDN (Content Delivery Network)
|
|
#
|
|
####################################################
|
|
|
|
my $cdnTestPath = tempdir();
|
|
my $cdnQueueTestPath = tempdir();
|
|
|
|
my $cdnCfg = {
|
|
"enabled" => 1,
|
|
"url" => "file://$cdnTestPath",
|
|
"queuePath" => $cdnQueueTestPath,
|
|
"syncProgram" => "cp -r -- '%s' $cdnTestPath/",
|
|
"deleteProgram" => "rm -r -- '$cdnTestPath/%s' > /dev/null 2>&1"
|
|
};
|
|
my $dest = substr($cdnCfg->{'url'}, 7);
|
|
$session->config->set('cdn', $cdnCfg);
|
|
my $cdnUrl = $cdnCfg->{'url'};
|
|
my $cdnUlen = length $cdnUrl;
|
|
my $cdnStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($cdnStorage);
|
|
# Functional URL before sync done
|
|
my $hexId = $session->id->toHex($cdnStorage->getId);
|
|
my $initUrl = join '/', $uploadUrl, $cdnStorage->getPathFrag;
|
|
is ($cdnStorage->getUrl, $initUrl, 'CDN: getUrl: URL before sync');
|
|
$filename = $cdnStorage->addFileFromScalar('cdnfile1', $content);
|
|
is ($filename, 'cdnfile1', 'CDN: filename returned by addFileFromScalar');
|
|
my $qFile = $cdnCfg->{'queuePath'} . '/' . $session->id->toHex($cdnStorage->getId);
|
|
my $dotCdn = $cdnStorage->getPath . '/.cdn';
|
|
ok (-e $qFile, 'CDN: queue file created when file added to storage');
|
|
|
|
### getCdnFileIterator
|
|
my $found = 0;
|
|
my $sobj = undef;
|
|
my $flist;
|
|
my $cdnPath = substr($cdnUrl, 7) . '/' . $hexId;
|
|
my $cdnFn = $cdnPath . '/' . $filename;
|
|
my $locIter = WebGUI::Storage->getCdnFileIterator($session);
|
|
my $already; # test the object type only once
|
|
if (is(ref($locIter), 'CODE', 'CDN: getCdnFileIterator to return sub ref')) {
|
|
while (my $sobj = $locIter->()) {
|
|
unless ($already) {
|
|
ok($sobj->isa('WebGUI::Storage'), 'CDN: iterator produces Storage objects');
|
|
$already = 1;
|
|
}
|
|
if ($sobj->getId eq $cdnStorage->getId) { # the one we want to test with
|
|
++$found;
|
|
$flist = $sobj->getFiles;
|
|
if (is(scalar @$flist, 1, 'CDN: there is one file in the storage')) {
|
|
my $file1 = $flist->[0];
|
|
is ($file1, $filename, 'CDN: correct filename in the storage');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
is ($found, 1, 'CDN: getCdnFileIterator found storage');
|
|
### syncToCdn
|
|
$cdnStorage->syncToCdn;
|
|
ok( (-e $cdnPath and -d $cdnPath), 'CDN: target directory created');
|
|
ok( (-e $cdnFn and -T $cdnFn), 'CDN: target text file created');
|
|
is (-s $cdnFn, length $content, 'CDN: file is the right size');
|
|
ok (!(-e $qFile), 'CDN: queue file removed after sync');
|
|
ok (-e $dotCdn, 'CDN: dot-cdn flag file present after sync');
|
|
### getUrl with CDN
|
|
my $locUrl = $cdnUrl . '/' . $session->id->toHex($cdnStorage->getId);
|
|
is ($cdnStorage->getUrl, $locUrl, 'CDN: getUrl: URL for directory');
|
|
my $fileUrl = $locUrl . '/' . 'cdn-file';
|
|
is ($cdnStorage->getUrl('cdn-file'), $fileUrl, 'CDN: getUrl: URL for file');
|
|
# SSL
|
|
my %mockEnv = %ENV;
|
|
my $env = Test::MockObject::Extends->new($session->env);
|
|
$env->mock('get', sub { return $mockEnv{$_[1]} } );
|
|
$mockEnv{HTTPS} = 'on';
|
|
$cdnCfg->{'sslAlt'} = 1;
|
|
$session->config->set('cdn', $cdnCfg);
|
|
is ($cdnStorage->getUrl, $initUrl, 'CDN: getUrl: URL with sslAlt flag');
|
|
$cdnCfg->{'sslUrl'} = 'https://ssl.example.com';
|
|
$session->config->set('cdn', $cdnCfg);
|
|
my $sslUrl = $cdnCfg->{'sslUrl'} . '/' . $session->id->toHex($cdnStorage->getId);
|
|
is ($cdnStorage->getUrl, $sslUrl, 'CDN: getUrl: sslUrl');
|
|
$mockEnv{HTTPS} = undef;
|
|
is ($cdnStorage->getUrl, $locUrl, 'CDN: getUrl: cleartext request to not use sslUrl');
|
|
# Copy
|
|
my $cdnCopy = $cdnStorage->copy;
|
|
WebGUI::Test->addToCleanup($cdnCopy);
|
|
my $qcp = $cdnCfg->{'queuePath'} . '/' . $session->id->toHex($cdnCopy->getId);
|
|
ok (-e $qcp, 'CDN: queue file created when storage location copied');
|
|
my $dotcp = $cdnCopy->getPath . '/.cdn';
|
|
ok (!(-e $dotcp), 'CDN: dot-cdn flag file absent after copy');
|
|
# On clear, need to see the entry in cdnQueue
|
|
$qFile = $cdnCfg->{'queuePath'} . '/' . $session->id->toHex($cdnStorage->getId);
|
|
$cdnStorage->clear;
|
|
ok (-e $qFile, 'CDN: queue file created when storage cleared');
|
|
ok (-s $qFile >= 7 && -s $qFile <= 9, 'CDN: queue file has right size for deleted (clear)');
|
|
ok (!(-e $dotCdn), 'CDN: dot-cdn flag file absent after clear');
|
|
### deleteFromCdn
|
|
$cdnStorage->deleteFromCdn;
|
|
ok(! (-e $cdnPath), 'CDN: target directory removed');
|
|
ok(! (-e $qFile), 'CDN: queue file removed');
|
|
# Idea: add a file back before testing delete
|
|
# Note: expect it is necessary to be able to delete after clear.
|
|
# On delete, need to see the entry in cdnQueue
|
|
$cdnStorage->delete;
|
|
ok (-e $qFile, 'CDN: queue file created when storage deleted');
|
|
ok (-s $qFile >= 7 && -s $qFile <= 9, 'CDN: queue file has right size for deleted');
|
|
$cdnStorage->deleteFromCdn;
|
|
ok(! (-e $qFile), 'CDN: queue file removed');
|
|
|
|
# partial cleanup here; complete cleanup in END block
|
|
undef $cdnStorage;
|
|
$session->config->delete('cdn');
|
|
|
|
|
|
####################################################
|
|
#
|
|
# Test what happens when the directory for a
|
|
# storage object does not exist.
|
|
#
|
|
####################################################
|
|
|
|
my $zombieStorage = WebGUI::Storage->create($session);
|
|
WebGUI::Test->addToCleanup($zombieStorage);
|
|
my $zombieDir = $zombieStorage->getPathClassDir;
|
|
$zombieDir->remove;
|
|
|
|
is( $zombieStorage->getPathClassDir, undef, 'bad storage: getPathClassDir returns undef');
|
|
cmp_deeply( $zombieStorage->getFiles, [], '... getFiles returns an empty array ref');
|
|
cmp_deeply( $zombieStorage->setPrivileges, undef, '... setPrivileges returns undef');
|
|
cmp_deeply( $zombieStorage->clear, undef, '... setPrivileges returns undef');
|
|
|
|
####################################################
|
|
#
|
|
# Make sure after all this that our CWD is still the same
|
|
#
|
|
####################################################
|
|
|
|
is($cwd, Cwd::cwd(), 'CWD must remain the same after addFileFromFilesystem, tar, untar, etc...');
|
|
|
|
####################################################
|
|
#
|
|
# Setup data driven tests here, to keep the top part of the
|
|
# test clean.
|
|
#
|
|
####################################################
|
|
|
|
sub setupDataDrivenTests {
|
|
my $session = shift;
|
|
my $extensionTests = [
|
|
{
|
|
filename => 'filename',
|
|
extension => undef,
|
|
comment => 'no extension',
|
|
},
|
|
{
|
|
filename => 'filename.',
|
|
extension => '',
|
|
comment => 'dot, but no extension',
|
|
},
|
|
{
|
|
filename => 'filename.txt',
|
|
extension => 'txt',
|
|
comment => 'simple extension',
|
|
},
|
|
{
|
|
filename => 'filename.TXT',
|
|
extension => 'txt',
|
|
comment => 'extensions are all lowercase',
|
|
},
|
|
{
|
|
filename => 'filename.FOO.BAR',
|
|
extension => 'bar',
|
|
comment => 'multiple extensions return last extension',
|
|
},
|
|
];
|
|
|
|
my $block_extension_tests = [
|
|
{
|
|
filename => 'filename',
|
|
blockname => 'filename',
|
|
comment => 'no extension',
|
|
},
|
|
{
|
|
filename => 'filename.pl',
|
|
blockname => 'filename_pl.txt',
|
|
comment => 'pl file',
|
|
},
|
|
{
|
|
filename => 'filename.perl',
|
|
blockname => 'filename_perl.txt',
|
|
comment => 'perl file',
|
|
},
|
|
{
|
|
filename => 'filename.cgi',
|
|
blockname => 'filename_cgi.txt',
|
|
comment => 'cgi file',
|
|
},
|
|
{
|
|
filename => 'filename.php',
|
|
blockname => 'filename_php.txt',
|
|
comment => 'php file',
|
|
},
|
|
{
|
|
filename => 'filename.asp',
|
|
blockname => 'filename_asp.txt',
|
|
comment => 'asp file',
|
|
},
|
|
{
|
|
filename => 'filename.pm',
|
|
blockname => 'filename_pm.txt',
|
|
comment => 'perl module file',
|
|
},
|
|
{
|
|
filename => 'filename.htm',
|
|
blockname => 'filename_htm.txt',
|
|
comment => 'htm file',
|
|
},
|
|
{
|
|
filename => 'filename.html',
|
|
blockname => 'filename_html.txt',
|
|
comment => 'html file',
|
|
},
|
|
{
|
|
filename => 'filename.pm.txt',
|
|
blockname => 'filename.pm.txt',
|
|
comment => 'internal .pm not touched',
|
|
},
|
|
{
|
|
filename => 'filename.txt.pm',
|
|
blockname => 'filename.txt_pm.txt',
|
|
comment => 'double extension handled',
|
|
},
|
|
];
|
|
my $fileIconTests = [
|
|
{
|
|
filename => 'filename',
|
|
iconUrl => $session->url->extras("fileIcons/unknown.gif"),
|
|
comment => 'no extension uses unknown icon',
|
|
},
|
|
{
|
|
filename => 'filename.txt',
|
|
iconUrl => $session->url->extras("fileIcons/txt.gif"),
|
|
comment => 'valid extension, lower case works',
|
|
},
|
|
{
|
|
filename => 'filename.TXT',
|
|
iconUrl => $session->url->extras("fileIcons/txt.gif"),
|
|
comment => 'valid extension, upper case works',
|
|
},
|
|
{
|
|
filename => 'filename.00TXT00',
|
|
iconUrl => $session->url->extras("fileIcons/unknown.gif"),
|
|
comment => 'unknown extension',
|
|
},
|
|
];
|
|
|
|
return ($extensionTests, $fileIconTests, $block_extension_tests);
|
|
}
|