[s3_storage] Bump version of akeeba/s3 to version 2.3.1

- Address https://github.com/friendica/friendica/issues/12011#issuecomment-1854681792
This commit is contained in:
Hypolite Petovan 2023-12-18 21:28:16 -05:00
parent 9daa11eb10
commit 3e74af9775
61 changed files with 1472 additions and 708 deletions

View file

@ -0,0 +1,62 @@
# Testing notes
## Against Amazon S3 proper
This is the _canonical_ method for testing this library since Amazon S3 proper is the canonical provider of the S3 API (and not all of its quirks are fully documented, we might add).
Copy `config.dist.php` to `config.php` and enter the connection information to your Amazon S3 or compatible service.
## Against [LocalStack](https://localstack.cloud)
This method is very useful for development.
Install LocalStack [as per their documentation](https://docs.localstack.cloud/getting-started/installation/).
You will also need to install [`awslocal`](https://github.com/localstack/awscli-local) like so:
```php
pip install awscli
pip install awscli-local
```
Start LocalStack e.g. `localstack start -d`
Create a new bucket called `test` i.e. `awslocal s3 mk s3://test`
Copy `config.dist.php` to `config.php` and make the following changes:
```php
define('DEFAULT_ENDPOINT', 'localhost.localstack.cloud:4566');
define('DEFAULT_ACCESS_KEY', 'ANYRANDOMSTRINGWILLDO');
define('DEFAULT_SECRET_KEY', 'ThisIsAlwaysIgnoredByLocalStack');
define('DEFAULT_REGION', 'us-east-1');
define('DEFAULT_BUCKET', 'test');
define('DEFAULT_SIGNATURE', 'v4');
define('DEFAULT_PATH_ACCESS', true);
```
Note that single- and dualstack tests result in the same URLs for all S3-compatible services, including LocalStack. These tests are essentially duplicates in this use case.
## Against Wasabi
Wasabi nominally supports v4 signatures, but their implementation is actually _non-canonical_, as they only read the date from the optional `x-amz-date` header, without falling back to the standard HTTP `Date` header. We have added a workaround for this behaviour which necessitates testing with it.
Just like with Amazon S3 proper, copy `config.dist.php` to `config.php` and enter the connection information to your Wasabi storage. You will also need to set up the custom endpoint like so:
```php
define('DEFAULT_ENDPOINT', 's3.eu-central-2.wasabisys.com');
```
**IMPORTANT!** The above endpoint will be different, depending on which region you've created your bucket in. The example above assumes the `eu-central-2` region. If you use the wrong region the tests _will_ fail!
## Against Synology C2
Synology C2 is an S3-“compatible” storage service. It is not very “compatible” though, since they implemented Amazon's documentation of the v4 signatures instead of how the v4 signatures work in the real world (yeah, there's a very big difference). While Amazon S3 _in reality_ expects all dates to be formatted as per RFC1123, they document that they expect them to be formatted as per “ISO 8601” and they give their _completely wrong_ interpretation of what the “ISO 8601” format is. Synology did not catch that discrepancy, and they only expect the wrongly formatted dates which is totally NOT what S3 itself expects. Luckily, most third party implementations expect either format because they've caught the discrepancy between documentation and reality, therefore making it possible for us to come up with a viable workaround.
And that's why we need to test with C2 as well, folks.
Copy `config.dist.php` to `config.php` and enter the connection information to your Synology S3 service.
It is very important to note two things:
```php
define('DEFAULT_ENDPOINT', 'eu-002.s3.synologyc2.net');
define('DEFAULT_REGION', 'eu-002');
```
The endpoint URL is given in the Synology C2 Object Manager, next to each bucket. Note the part before `.s3.`. This is the **region** you need to use with v4 signatures. They do not document this anywhere.

View file

@ -3,13 +3,13 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
use RuntimeException;
abstract class AbstractTest
@ -58,24 +58,24 @@ abstract class AbstractTest
*/
protected static function createFile(int $size = AbstractTest::SIX_HUNDRED_KB, int $blockSize = self::BLOCK_SIZE, bool $reuseBlock = true)
{
$tempFilePath = tempnam(self::getTempFolder(), 'as3');
$tempFilePath = tempnam(static::getTempFolder(), 'as3');
if ($tempFilePath === false)
{
throw new RuntimeException("Cannot create a temporary file.");
}
$fp = @fopen($tempFilePath, 'wb', false);
$fp = @fopen($tempFilePath, 'w', false);
if ($fp === false)
{
throw new RuntimeException("Cannot write to the temporary file.");
}
$blockSize = self::BLOCK_SIZE;
$blockSize = static::BLOCK_SIZE;
$lastBlockSize = $size % $blockSize;
$wholeBlocks = (int) (($size - $lastBlockSize) / $blockSize);
$blockData = self::getRandomData();
$blockData = static::getRandomData();
for ($i = 0; $i < $wholeBlocks; $i++)
{
@ -83,7 +83,7 @@ abstract class AbstractTest
if (!$reuseBlock)
{
$blockData = self::getRandomData($blockSize);
$blockData = static::getRandomData($blockSize);
}
}
@ -155,7 +155,7 @@ abstract class AbstractTest
return false;
}
return hash_file(self::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(self::FILE_HASHING_ALGORITHM, $unknownFilePath);
return hash_file(static::FILE_HASHING_ALGORITHM, $referenceFilePath) === hash_file(static::FILE_HASHING_ALGORITHM, $unknownFilePath);
}
/**

View file

@ -3,15 +3,15 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
/**
* Upload, download and delete big files (over 1MB), without multipart uploads. Uses string or file sources.
@ -51,7 +51,7 @@ class BigFiles extends AbstractTest
/**
* Number of uploaded chunks.
*
* This is set by self::upload(). Zero for single part uploads, non-zero for multipart uploads.
* This is set by static::upload(). Zero for single part uploads, non-zero for multipart uploads.
*
* @var int
*/
@ -59,42 +59,42 @@ class BigFiles extends AbstractTest
public static function upload5MBString(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat');
return static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat');
}
public static function upload6MBString(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat');
return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat');
}
public static function upload10MBString(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat');
return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat');
}
public static function upload11MBString(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::ELEVEN_MB, 'bigtest_11mb.dat');
return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat');
}
public static function upload5MBFile(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::FIVE_MB, 'bigtest_5mb.dat', false);
return static::upload($s3, $options, static::FIVE_MB, 'bigtest_5mb.dat', false);
}
public static function upload6MBFile(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::SIX_MB, 'bigtest_6mb.dat', false);
return static::upload($s3, $options, static::SIX_MB, 'bigtest_6mb.dat', false);
}
public static function upload10MBFile(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::TEN_MB, 'bigtest_10mb.dat', false);
return static::upload($s3, $options, static::TEN_MB, 'bigtest_10mb.dat', false);
}
public static function upload11MBFile(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::ELEVEN_MB, 'bigtest_11mb.dat', false);
return static::upload($s3, $options, static::ELEVEN_MB, 'bigtest_11mb.dat', false);
}
protected static function upload(Connector $s3, array $options, int $size, string $uri, bool $useString = true): bool
@ -103,24 +103,24 @@ class BigFiles extends AbstractTest
$dotPos = strrpos($uri, '.');
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
self::$numberOfChunks = 0;
static::$numberOfChunks = 0;
if ($useString)
{
$sourceData = self::getRandomData($size);
$sourceData = static::getRandomData($size);
$input = Input::createFromData($sourceData);
}
else
{
// Create a file with random data
$sourceFile = self::createFile($size);
$sourceFile = static::createFile($size);
$input = Input::createFromFile($sourceFile);
}
// Upload the file. Throws exception if it fails.
$bucket = $options['bucket'];
if (!self::$multipart)
if (!static::$multipart)
{
$s3->putObject($input, $bucket, $uri);
}
@ -149,7 +149,7 @@ class BigFiles extends AbstractTest
$input->setEtags($eTags);
$input->setPartNumber($partNumber);
$etag = $s3->uploadMultipart($input, $bucket, $uri, [], self::$uploadChunkSize);
$etag = $s3->uploadMultipart($input, $bucket, $uri, [], static::$uploadChunkSize);
// If the result was null we have no more file parts to process.
if (is_null($etag))
@ -166,7 +166,7 @@ class BigFiles extends AbstractTest
$partNumber++;
}
self::$numberOfChunks = count($eTags);
static::$numberOfChunks = count($eTags);
// Finalize the multipart upload. Tells Amazon to construct the file from the uploaded parts.
$s3->finalizeMultipart($input, $bucket, $uri);
@ -176,7 +176,7 @@ class BigFiles extends AbstractTest
$result = true;
// Should I download the file and compare its contents?
if (self::$downloadAfter)
if (static::$downloadAfter)
{
if ($useString)
{
@ -184,16 +184,16 @@ class BigFiles extends AbstractTest
$downloadedData = $s3->getObject($bucket, $uri);
// Compare the file contents.
$result = self::areStringsEqual($sourceData, $downloadedData);
$result = static::areStringsEqual($sourceData, $downloadedData);
}
else
{
// Download the data. Throws exception if it fails.
$downloadedFile = tempnam(self::getTempFolder(), 'as3');
$downloadedFile = tempnam(static::getTempFolder(), 'as3');
$s3->getObject($bucket, $uri, $downloadedFile);
// Compare the file contents.
$result = self::areFilesEqual($sourceFile, $downloadedFile);
$result = static::areFilesEqual($sourceFile, $downloadedFile);
@unlink($downloadedFile);
}
@ -206,7 +206,7 @@ class BigFiles extends AbstractTest
}
// Should I delete the remotely stored file?
if (self::$deleteRemote)
if (static::$deleteRemote)
{
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
class BucketLocation extends AbstractTest
{
@ -18,7 +18,7 @@ class BucketLocation extends AbstractTest
{
$location = $s3->getBucketLocation($options['bucket']);
self::assert($location === $options['region'], "Bucket {$options['bucket']} reports being in region {$location} instead of expected {$options['region']}");
static::assert($location === $options['region'], "Bucket {$options['bucket']} reports being in region {$location} instead of expected {$options['region']}");
return true;
}

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
use RuntimeException;
class BucketsList extends AbstractTest
@ -19,16 +19,16 @@ class BucketsList extends AbstractTest
{
$buckets = $s3->listBuckets(true);
self::assert(is_array($buckets), "Detailed buckets list is not an array");
self::assert(isset($buckets['owner']), "Detailed buckets list does not list an owner");
self::assert(isset($buckets['owner']['id']), "Detailed buckets list does not list an owner's id");
self::assert(isset($buckets['owner']['name']), "Detailed buckets list does not list an owner's name");
self::assert(isset($buckets['buckets']), "Detailed buckets list does not list any buckets");
static::assert(is_array($buckets), "Detailed buckets list is not an array");
static::assert(isset($buckets['owner']), "Detailed buckets list does not list an owner");
static::assert(isset($buckets['owner']['id']), "Detailed buckets list does not list an owner's id");
static::assert(isset($buckets['owner']['name']), "Detailed buckets list does not list an owner's name");
static::assert(isset($buckets['buckets']), "Detailed buckets list does not list any buckets");
foreach ($buckets['buckets'] as $bucketInfo)
{
self::assert(isset($bucketInfo['name']), "Bucket information does not list a name");
self::assert(isset($bucketInfo['time']), "Bucket information does not list a created times");
static::assert(isset($bucketInfo['name']), "Bucket information does not list a name");
static::assert(isset($bucketInfo['time']), "Bucket information does not list a created times");
if ($bucketInfo['name'] === $options['bucket'])
{
@ -43,8 +43,8 @@ class BucketsList extends AbstractTest
{
$buckets = $s3->listBuckets(false);
self::assert(is_array($buckets), "Simple buckets list is not an array");
self::assert(in_array($options['bucket'], $buckets), "Simple buckets list does not include configured bucket {$options['bucket']}");
static::assert(is_array($buckets), "Simple buckets list is not an array");
static::assert(in_array($options['bucket'], $buckets), "Simple buckets list does not include configured bucket {$options['bucket']}");
return true;
}

View file

@ -0,0 +1,67 @@
<?php
/**
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\S3\Connector;
use Akeeba\S3\Exception\CannotDeleteFile;
use Akeeba\S3\Exception\CannotGetFile;
use Akeeba\S3\Input;
class HeadObject extends AbstractTest
{
public static function testExistingFile(Connector $s3, array $options): bool
{
$uri = 'head_test.dat';
// Randomize the name. Required for archive buckets where you cannot overwrite data.
$dotPos = strrpos($uri, '.');
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
// Create a file with random data
$sourceFile = static::createFile(AbstractTest::TEN_KB);
// Upload the file. Throws exception if it fails.
$bucket = $options['bucket'];
$input = Input::createFromFile($sourceFile);
$s3->putObject($input, $bucket, $uri);
$headers = $s3->headObject($bucket, $uri);
static::assert(isset($headers['size']), 'The returned headers do not contain the object size');
static::assert($headers['size'] == AbstractTest::TEN_KB, 'The returned size does not match');
// Remove the local files
@unlink($sourceFile);
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);
return true;
}
public static function testMissingFile(Connector $s3, array $options): bool
{
$bucket = $options['bucket'];
try
{
$headers = $s3->headObject($bucket, md5(microtime(false)) . '_does_not_exist');
}
catch (CannotGetFile $e)
{
return true;
}
return false;
}
}

View file

@ -3,16 +3,16 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Exception\CannotPutFile;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Connector;
use Akeeba\S3\Exception\CannotPutFile;
use Akeeba\S3\Input;
class ListFiles extends AbstractTest
{
@ -34,9 +34,9 @@ class ListFiles extends AbstractTest
public static function setup(Connector $s3, array $options): void
{
$data = self::getRandomData(self::TEN_KB);
$data = static::getRandomData(static::TEN_KB);
foreach (self::$paths as $uri)
foreach (static::$paths as $uri)
{
$input = Input::createFromData($data);
try
@ -52,7 +52,7 @@ class ListFiles extends AbstractTest
public static function teardown(Connector $s3, array $options): void
{
foreach (self::$paths as $uri)
foreach (static::$paths as $uri)
{
try
{
@ -69,29 +69,29 @@ class ListFiles extends AbstractTest
{
$listing = $s3->getBucket($options['bucket'], 'listtest_');
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 3, "I am expecting to see 3 files");
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 3, "I am expecting to see 3 files");
// Make sure I have the expected files
self::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing");
self::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing");
self::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing");
static::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing");
static::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing");
static::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing");
self::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing");
self::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing");
static::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing");
static::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing");
static::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing");
// I must not see the files not matching the prefix I gave
self::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing");
static::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing");
foreach ($listing as $fileName => $info)
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
return true;
@ -101,37 +101,37 @@ class ListFiles extends AbstractTest
{
$listing = $s3->getBucket($options['bucket'], 'listtest_', null, 1);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing)));
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing)));
$files = array_keys($listing);
$continued = $s3->getBucket($options['bucket'], 'listtest_', array_shift($files));
self::assert(is_array($continued), "The continued files listing must be an array");
self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
static::assert(is_array($continued), "The continued files listing must be an array");
static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
$listing = array_merge($listing, $continued);
// Make sure I have the expected files
self::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing");
self::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing");
self::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing");
static::assert(array_key_exists('listtest_one.dat', $listing), "File listtest_one.dat not in listing");
static::assert(array_key_exists('listtest_two.dat', $listing), "File listtest_two.dat not in listing");
static::assert(array_key_exists('listtest_three.dat', $listing), "File listtest_three.dat not in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing");
self::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing");
self::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing");
static::assert(!array_key_exists('listtest_four.dat', $listing), "File listtest_four.dat in listing");
static::assert(!array_key_exists('listtest_five.dat', $listing), "File listtest_five.dat in listing");
static::assert(!array_key_exists('listtest_six.dat', $listing), "File listtest_six.dat in listing");
// I must not see the files not matching the prefix I gave
self::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing");
static::assert(!array_key_exists('spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('ham.dat', $listing), "File ham.dat in listing");
foreach ($listing as $fileName => $info)
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
return true;
@ -141,30 +141,30 @@ class ListFiles extends AbstractTest
{
$listing = $s3->getBucket($options['bucket'], 'list_deeper/test_');
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 3, "I am expecting to see 3 files");
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 3, "I am expecting to see 3 files");
// Make sure I have the expected files
self::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
self::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
self::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
static::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
static::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
static::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
// I must not see the files with different prefix
self::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing");
self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing");
static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
foreach ($listing as $fileName => $info)
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
return true;
@ -174,41 +174,41 @@ class ListFiles extends AbstractTest
{
$listing = $s3->getBucket($options['bucket'], 'list_deeper/test_', null, 1);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing)));
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 1, sprintf("I am expecting to see 1 file, %s seen", count($listing)));
$files = array_keys($listing);
$continued = $s3->getBucket($options['bucket'], 'list_deeper/test_', array_shift($files));
self::assert(is_array($continued), "The continued files listing must be an array");
self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
static::assert(is_array($continued), "The continued files listing must be an array");
static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
$listing = array_merge($listing, $continued);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 3, "I am expecting to see 3 files");
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 3, "I am expecting to see 3 files");
// Make sure I have the expected files
self::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
self::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
self::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
static::assert(array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
static::assert(array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
static::assert(array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
// I must not see the files with different prefix
self::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing");
self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat in listing");
static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
foreach ($listing as $fileName => $info)
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
return true;
@ -224,42 +224,42 @@ class ListFiles extends AbstractTest
*/
$listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, 1);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 1, sprintf("I am expecting to see 1 files, %s seen", count($listing)));
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 1, sprintf("I am expecting to see 1 files, %s seen", count($listing)));
$files = array_keys($listing);
$continued = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', array_shift($files));
self::assert(is_array($continued), "The continued files listing must be an array");
self::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
static::assert(is_array($continued), "The continued files listing must be an array");
static::assert(count($continued) == 2, sprintf("I am expecting to see 2 files, %s seen", count($continued)));
$listing = array_merge($listing, $continued);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 3, "I am expecting to see 3 files");
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 3, "I am expecting to see 3 files");
// Make sure I have the expected files
self::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing");
self::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing");
self::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing");
// I must not see the files with different prefix
self::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat in listing");
self::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat in listing");
self::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat in listing");
self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat in listing");
static::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat in listing");
static::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat in listing");
static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File spam.dat in listing");
foreach ($listing as $fileName => $info)
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
return true;
@ -269,37 +269,37 @@ class ListFiles extends AbstractTest
{
$listing = $s3->getBucket($options['bucket'], 'list_deeper/listtest_', null, null, '/', true);
self::assert(is_array($listing), "The files listing must be an array");
self::assert(count($listing) == 4, sprintf("I am expecting to see 4 entries, %s entries seen.", count($listing)));
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) == 4, sprintf("I am expecting to see 4 entries, %s entries seen.", count($listing)));
// Make sure I have the expected files
self::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing");
self::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing");
self::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing");
self::assert(array_key_exists('list_deeper/listtest_deeper/', $listing), "Folder listtest_deeper not in listing");
static::assert(array_key_exists('list_deeper/listtest_four.dat', $listing), "File listtest_four.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_five.dat', $listing), "File listtest_five.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_six.dat', $listing), "File listtest_six.dat not in listing");
static::assert(array_key_exists('list_deeper/listtest_deeper/', $listing), "Folder listtest_deeper not in listing");
// I must not see the files in subdirectories
self::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File seven.dat in listing");
self::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File eight.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/seven.dat', $listing), "File seven.dat in listing");
static::assert(!array_key_exists('list_deeper/listtest_deeper/eight.dat', $listing), "File eight.dat in listing");
// I must not see the files with different prefix
self::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
self::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
self::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
self::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
static::assert(!array_key_exists('list_deeper/spam.dat', $listing), "File spam.dat in listing");
static::assert(!array_key_exists('list_deeper/test_one.dat', $listing), "File test_one.dat not in listing");
static::assert(!array_key_exists('list_deeper/test_two.dat', $listing), "File test_two.dat not in listing");
static::assert(!array_key_exists('list_deeper/test_three.dat', $listing), "File test_three.dat not in listing");
foreach ($listing as $fileName => $info)
{
if (substr($fileName, -1) !== '/')
{
self::assert(isset($info['name']), "File entries must have a name");
self::assert(isset($info['time']), "File entries must have a time");
self::assert(isset($info['size']), "File entries must have a size");
self::assert(isset($info['hash']), "File entries must have a hash");
static::assert(isset($info['name']), "File entries must have a name");
static::assert(isset($info['time']), "File entries must have a time");
static::assert(isset($info['size']), "File entries must have a size");
static::assert(isset($info['hash']), "File entries must have a hash");
}
else
{
self::assert(isset($info['prefix']), "Folder entries must return a prefix");
static::assert(isset($info['prefix']), "Folder entries must return a prefix");
}
}

View file

@ -0,0 +1,111 @@
<?php
/**
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
class ListThousandsOfFiles extends AbstractTest
{
private const PATH_PREFIX = 'massive/';
public static function setup(Connector $s3, array $options): void
{
if (defined('CREATE_2100_FILES') && CREATE_2100_FILES === false)
{
return;
}
$data = static::getRandomData(128);
echo "\nPopulating with 2100 files\n";
for ($i = 1; $i <= 2100; $i++)
{
if ($i % 10 === 0)
{
echo "Uploading from $i...\n";
}
$uri = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i);
$input = Input::createFromData($data);
$s3->putObject($input, $options['bucket'], $uri);
}
}
public static function testGetAll(Connector $s3, array $options): bool
{
$listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX);
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) === 2100, "I am expecting to see 2100 files");
for ($i = 1; $i <= 2100; $i++)
{
$key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i);
static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key));
}
return true;
}
public static function testGetHundred(Connector $s3, array $options): bool
{
$listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX, null, 100);
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) === 100, "I am expecting to see 100 files");
for ($i = 1; $i <= 100; $i++)
{
$key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i);
static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key));
}
return true;
}
public static function testGetElevenHundred(Connector $s3, array $options): bool
{
$listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX, null, 1100);
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) === 1100, "I am expecting to see 1100 files");
for ($i = 1; $i <= 1100; $i++)
{
$key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i);
static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key));
}
return true;
}
public static function testGetLastHundred(Connector $s3, array $options): bool
{
$listing = $s3->getBucket($options['bucket'], static::PATH_PREFIX . 'test_20', null);
static::assert(is_array($listing), "The files listing must be an array");
static::assert(count($listing) === 100, "I am expecting to see 100 files");
for ($i = 2000; $i <= 2099; $i++)
{
$key = sprintf('%stest_%04u.dat', static::PATH_PREFIX, $i);
static::assert(array_key_exists($key, $listing), sprintf('Results should list object %s', $key));
}
return true;
}
}

View file

@ -1,16 +1,22 @@
<?php
/**
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
class Multipart extends BigFiles
{
public static function setup(Connector $s3, array $options): void
{
self::$multipart = true;
static::$multipart = true;
parent::setup($s3, $options);
}
@ -20,7 +26,7 @@ class Multipart extends BigFiles
$result = parent::upload5MBString($s3, $options);
$expectedChunks = 1;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -30,7 +36,7 @@ class Multipart extends BigFiles
$result = parent::upload6MBString($s3, $options);
$expectedChunks = 2;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -40,7 +46,7 @@ class Multipart extends BigFiles
$result = parent::upload10MBString($s3, $options);
$expectedChunks = 2;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -50,7 +56,7 @@ class Multipart extends BigFiles
$result = parent::upload11MBString($s3, $options);
$expectedChunks = 3;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -60,7 +66,7 @@ class Multipart extends BigFiles
$result = parent::upload5MBFile($s3, $options);
$expectedChunks = 1;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -70,7 +76,7 @@ class Multipart extends BigFiles
$result = parent::upload6MBFile($s3, $options);
$expectedChunks = 2;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -80,7 +86,7 @@ class Multipart extends BigFiles
$result = parent::upload10MBFile($s3, $options);
$expectedChunks = 2;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}
@ -90,7 +96,7 @@ class Multipart extends BigFiles
$result = parent::upload11MBFile($s3, $options);
$expectedChunks = 3;
self::assert(self::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, self::$numberOfChunks));
static::assert(static::$numberOfChunks === $expectedChunks, sprintf("Expected %s chunks, upload complete in %s chunks", $expectedChunks, static::$numberOfChunks));
return $result;
}

View file

@ -3,33 +3,33 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Acl;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Acl;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
use RuntimeException;
class SignedURLs extends AbstractTest
{
public static function signedURLPublicObject(Connector $s3, array $options): bool
{
return self::signedURL($s3, $options, Acl::ACL_PUBLIC_READ);
return static::signedURL($s3, $options, Acl::ACL_PUBLIC_READ);
}
public static function signedURLPrivateObject(Connector $s3, array $options): bool
{
return self::signedURL($s3, $options, Acl::ACL_PRIVATE);
return static::signedURL($s3, $options, Acl::ACL_PRIVATE);
}
private static function signedURL(Connector $s3, array $options, string $aclPrivilege): bool
{
$tempData = self::getRandomData(AbstractTest::TEN_KB);
$tempData = static::getRandomData(AbstractTest::TEN_KB);
$input = Input::createFromData($tempData);
$uri = 'test.' . md5(microtime(false)) . '.dat';
@ -52,7 +52,7 @@ class SignedURLs extends AbstractTest
throw new RuntimeException("Failed to download from signed URL {$downloadURL}");
}
self::assert(self::areStringsEqual($tempData, $downloadedData), "Wrong data received from signed URL {$downloadURL}");
static::assert(static::areStringsEqual($tempData, $downloadedData), "Wrong data received from signed URL {$downloadURL}");
return true;
}

View file

@ -0,0 +1,43 @@
<?php
/**
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
/**
* Upload, download and delete small files (under 1MB) using a string source
*
* @package Akeeba\MiniTest\Test
*/
class SingleSmallFile extends AbstractTest
{
public static function upload(Connector $s3, array $options): bool
{
$uri = 'test.txt';
$sourceData = <<< TEXT
This is a small text file.
TEXT;
// Upload the data. Throws exception if it fails.
$bucket = $options['bucket'];
$input = Input::createFromData($sourceData);
$s3->putObject($input, $bucket, $uri);
$downloadedData = $s3->getObject($bucket, $uri);
$result = static::areStringsEqual($sourceData, $downloadedData);
$s3->deleteObject($bucket, $uri);
return $result ?? true;
}
}

View file

@ -3,15 +3,15 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
/**
* Upload, download and delete small files (under 1MB) using a file source
@ -36,32 +36,32 @@ class SmallFiles extends AbstractTest
public static function upload10KbRoot(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat');
return static::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.dat');
}
public static function upload10KbRootGreek(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::TEN_KB, οκιμή_10kb.dat');
return static::upload($s3, $options, AbstractTest::TEN_KB, οκιμή_10kb.dat');
}
public static function upload10KbFolderGreek(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μουοκιμή_10kb.dat');
return static::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μουοκιμή_10kb.dat');
}
public static function upload600KbRoot(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat');
return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.dat');
}
public static function upload10KbFolder(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat');
return static::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.dat');
}
public static function upload600KbFolder(Connector $s3, array $options): bool
{
return self::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.dat');
return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.dat');
}
protected static function upload(Connector $s3, array $options, int $size, string $uri): bool
@ -71,7 +71,7 @@ class SmallFiles extends AbstractTest
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
// Create a file with random data
$sourceFile = self::createFile($size);
$sourceFile = static::createFile($size);
// Upload the file. Throws exception if it fails.
$bucket = $options['bucket'];
@ -83,14 +83,14 @@ class SmallFiles extends AbstractTest
$result = true;
// Should I download the file and compare its contents?
if (self::$downloadAfter)
if (static::$downloadAfter)
{
// Donwload the data. Throws exception if it fails.
$downloadedFile = tempnam(self::getTempFolder(), 'as3');
$downloadedFile = tempnam(static::getTempFolder(), 'as3');
$s3->getObject($bucket, $uri, $downloadedFile);
// Compare the file contents.
$result = self::areFilesEqual($sourceFile, $downloadedFile);
$result = static::areFilesEqual($sourceFile, $downloadedFile);
}
// Remove the local files
@ -98,7 +98,7 @@ class SmallFiles extends AbstractTest
@unlink($downloadedFile);
// Should I delete the remotely stored file?
if (self::$deleteRemote)
if (static::$deleteRemote)
{
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
/**
* Upload and download small files (under 1MB) using a file source
@ -21,7 +21,7 @@ class SmallFilesNoDelete extends SmallFiles
{
public static function setup(Connector $s3, array $options): void
{
self::$deleteRemote = false;
static::$deleteRemote = false;
parent::setup($s3, $options);
}

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
/**
* Upload small files (under 1MB) using a file source
@ -21,8 +21,8 @@ class SmallFilesOnlyUpload extends SmallFiles
{
public static function setup(Connector $s3, array $options): void
{
self::$deleteRemote = false;
self::$downloadAfter = false;
static::$deleteRemote = false;
static::$downloadAfter = false;
parent::setup($s3, $options);
}

View file

@ -3,15 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
/**
* Upload, download and delete small files (under 1MB) using a string source
@ -27,7 +26,7 @@ class SmallInlineFiles extends SmallFiles
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
// Create some random data to upload
$sourceData = self::getRandomData($size);
$sourceData = static::getRandomData($size);
// Upload the data. Throws exception if it fails.
$bucket = $options['bucket'];
@ -39,15 +38,15 @@ class SmallInlineFiles extends SmallFiles
$result = true;
// Should I download the file and compare its contents with my random data?
if (self::$downloadAfter)
if (static::$downloadAfter)
{
$downloadedData = $s3->getObject($bucket, $uri);
$result = self::areStringsEqual($sourceData, $downloadedData);
$result = static::areStringsEqual($sourceData, $downloadedData);
}
// Should I delete the remotely stored file?
if (self::$deleteRemote)
if (static::$deleteRemote)
{
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
/**
* Upload and download small files (under 1MB) using a string source
@ -21,7 +21,7 @@ class SmallInlineFilesNoDelete extends SmallInlineFiles
{
public static function setup(Connector $s3, array $options): void
{
self:: $deleteRemote = false;
static:: $deleteRemote = false;
parent::setup($s3, $options);
}

View file

@ -3,14 +3,14 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\S3\Connector;
/**
* Upload small files (under 1MB) using a string source
@ -21,8 +21,8 @@ class SmallInlineFilesOnlyUpload extends SmallInlineFiles
{
public static function setup(Connector $s3, array $options): void
{
self::$deleteRemote = false;
self::$downloadAfter = false;
static::$deleteRemote = false;
static::$downloadAfter = false;
parent::setup($s3, $options);
}

View file

@ -0,0 +1,131 @@
<?php
/**
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
/**
* Upload, download and delete small XML files (under 1MB) using a string source
*
* @package Akeeba\MiniTest\Test
*/
class SmallInlineXMLFiles extends SmallFiles
{
public static function upload10KbRoot(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::TEN_KB, 'root_10kb.xml');
}
public static function upload10KbRootGreek(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::TEN_KB, οκιμή_10kb.xml');
}
public static function upload10KbFolderGreek(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::TEN_KB, 'ο_φάκελός_μουοκιμή_10kb.xml');
}
public static function upload600KbRoot(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'root_600kb.xml');
}
public static function upload10KbFolder(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::TEN_KB, 'my_folder/10kb.xml');
}
public static function upload600KbFolder(Connector $s3, array $options): bool
{
return static::upload($s3, $options, AbstractTest::SIX_HUNDRED_KB, 'my_folder/600kb.xml');
}
protected static function upload(Connector $s3, array $options, int $size, string $uri): bool
{
// Randomize the name. Required for archive buckets where you cannot overwrite data.
$dotPos = strrpos($uri, '.');
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
// Create some random data to upload
$sourceData = static::createXMLFile($size);
// Upload the data. Throws exception if it fails.
$bucket = $options['bucket'];
$input = Input::createFromData($sourceData);
$s3->putObject($input, $bucket, $uri);
// Tentatively accept that this method succeeded.
$result = true;
// Should I download the file and compare its contents with my random data?
if (static::$downloadAfter)
{
$downloadedData = $s3->getObject($bucket, $uri);
$result = static::areStringsEqual($sourceData, $downloadedData);
}
// Should I delete the remotely stored file?
if (static::$deleteRemote)
{
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);
}
return $result;
}
private static function createXMLFile(int $size): string
{
$out = <<< XML
<?xml version="1.0" encoding="utf-8" ?>
<root>
XML;
$chunks = floor(($size - 55) / 1024);
for ($i = 1; $i <= $chunks; $i++)
{
$randomBlock = static::genRandomData(1024 - 63);
$out .= <<< XML
<element>
<id>$i</id>
<data><![CDATA[$randomBlock]]></data>
</element>
XML;
}
$out .= <<< XML
</root>
XML;
return $out;
}
private static function genRandomData(int $length): string
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';
$maxLength = strlen($chars) - 1;
$salt = '';
for ($i = 0; $i < $length; $i++)
{
$salt .= substr($chars, random_int(0, $maxLength), 1);
}
return $salt;
}
}

View file

@ -3,17 +3,17 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
namespace Akeeba\MiniTest\Test;
use Akeeba\Engine\Postproc\Connector\S3v4\Acl;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\Engine\Postproc\Connector\S3v4\StorageClass;
use Akeeba\S3\Acl;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
use Akeeba\S3\StorageClass;
class StorageClasses extends AbstractTest
{
@ -23,12 +23,12 @@ class StorageClasses extends AbstractTest
public static function uploadRRS(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY);
return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::REDUCED_REDUNDANCY);
}
public static function uploadIntelligentTiering(Connector $s3, array $options): bool
{
return self::upload($s3, $options, self::TEN_KB, 'rrs_test_10kb.dat', StorageClass::INTELLIGENT_TIERING);
return static::upload($s3, $options, static::TEN_KB, 'rrs_test_10kb.dat', StorageClass::INTELLIGENT_TIERING);
}
protected static function upload(Connector $s3, array $options, int $size, string $uri, string $storageClass = null)
@ -38,7 +38,7 @@ class StorageClasses extends AbstractTest
$uri = substr($uri, 0, $dotPos) . '.' . md5(microtime(false)) . substr($uri, $dotPos);
// Create some random data to upload
$sourceData = self::getRandomData($size);
$sourceData = static::getRandomData($size);
// Upload the data. Throws exception if it fails.
$bucket = $options['bucket'];
@ -54,15 +54,15 @@ class StorageClasses extends AbstractTest
$result = true;
// Should I download the file and compare its contents with my random data?
if (self::$downloadAfter)
if (static::$downloadAfter)
{
$downloadedData = $s3->getObject($bucket, $uri);
$result = self::areStringsEqual($sourceData, $downloadedData);
$result = static::areStringsEqual($sourceData, $downloadedData);
}
// Should I delete the remotely stored file?
if (self::$deleteRemote)
if (static::$deleteRemote)
{
// Delete the remote file. Throws exception if it fails.
$s3->deleteObject($bucket, $uri);

View file

@ -3,10 +3,12 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
// Custom Endpoint. The example below is for using LocalStack, see https://localstack.cloud/
// define('DEFAULT_ENDPOINT', 'localhost.localstack.cloud:4566');
// Default Amazon S3 Access Key
define('DEFAULT_ACCESS_KEY', 'your s3 access key');
// Default Amazon S3 Secret Key
@ -23,6 +25,8 @@ define('DEFAULT_DUALSTACK', false);
define('DEFAULT_PATH_ACCESS', false);
// Should I use SSL by default?
define('DEFAULT_SSL', true);
// Create the 2100 test files in the bucket?
define('CREATE_2100_FILES', true);
/**
* Tests for standard key pairs allowing us to read, write and delete
@ -33,7 +37,9 @@ $standardTests = [
'BucketsList',
'BucketLocation',
'SmallFiles',
'HeadObject',
'SmallInlineFiles',
'SmallInlineXMLFiles',
'SignedURLs',
'StorageClasses',
'ListFiles',

View file

@ -3,13 +3,13 @@
* Akeeba Engine
*
* @package akeebaengine
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @copyright Copyright (c)2006-2023 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
use Akeeba\Engine\Postproc\Connector\S3v4\Configuration;
use Akeeba\Engine\Postproc\Connector\S3v4\Connector;
use Akeeba\Engine\Postproc\Connector\S3v4\Input;
use Akeeba\S3\Configuration;
use Akeeba\S3\Connector;
use Akeeba\S3\Input;
// Necessary for including the library
define('AKEEBAENGINE', 1);
@ -167,7 +167,7 @@ foreach ($testConfigurations as $description => $setup)
'dualstack' => DEFAULT_DUALSTACK,
'path_access' => DEFAULT_PATH_ACCESS,
'ssl' => DEFAULT_SSL,
'endpoint' => null,
'endpoint' => defined('DEFAULT_ENDPOINT') ? constant('DEFAULT_ENDPOINT') : null,
], $setup['configuration']);
// Extract the test classes/methods to run
@ -185,15 +185,21 @@ foreach ($testConfigurations as $description => $setup)
// Create the S3 configuration object
$s3Configuration = new Configuration($configOptions['access'], $configOptions['secret'], $configOptions['signature'], $configOptions['region']);
$s3Configuration->setUseDualstackUrl($configOptions['dualstack']);
$s3Configuration->setUseLegacyPathStyle($configOptions['path_access']);
$s3Configuration->setSSL($configOptions['ssl']);
$s3Configuration->setRegion($configOptions['region']);
$s3Configuration->setSignatureMethod($configOptions['signature']);
if (!is_null($configOptions['endpoint']))
{
$s3Configuration->setEndpoint($configOptions['endpoint']);
// We need to redo this because setting the endpoint may reset these options
$s3Configuration->setRegion($configOptions['region']);
$s3Configuration->setSignatureMethod($configOptions['signature']);
}
$s3Configuration->setUseDualstackUrl($configOptions['dualstack']);
$s3Configuration->setUseLegacyPathStyle($configOptions['path_access']);
$s3Configuration->setSSL($configOptions['ssl']);
// Create the connector object
$s3Connector = new Connector($s3Configuration);