This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
<?php
namespace Gaufrette\Functional\Adapter;
use AsyncAws\SimpleS3\SimpleS3Client;
use Gaufrette\Adapter\AsyncAwsS3;
use Gaufrette\Adapter\AwsS3;
use Gaufrette\Filesystem;
class AsyncAwsS3Test extends FunctionalTestCase
{
/** @var string */
private $bucket;
/** @var SimpleS3Client */
private $client;
protected function setUp(): void
{
if (!class_exists(SimpleS3Client::class)) {
$this->markTestSkipped('You need to install async-aws/simple-s3 to run this test.');
}
$key = getenv('AWS_KEY');
$secret = getenv('AWS_SECRET');
if (empty($key) || empty($secret)) {
$this->markTestSkipped('Either AWS_KEY and/or AWS_SECRET env variables are not defined.');
}
$this->bucket = uniqid(getenv('AWS_BUCKET'));
$this->client = new SimpleS3Client([
'region' => 'eu-west-1',
'accessKeyId' => $key,
'accessKeySecret' => $secret,
]);
$this->createFilesystem(['create' => true]);
}
protected function tearDown(): void
{
if ($this->client === null) {
return;
}
try {
$files = $this->filesystem->listKeys();
foreach ($files as $file) {
$this->filesystem->delete($file);
}
$this->client->deleteBucket(['Bucket' => $this->bucket]);
} catch (\Throwable $e) {
}
}
private function createFilesystem(array $adapterOptions = [])
{
$this->filesystem = new Filesystem(new AsyncAwsS3($this->client, $this->bucket, $adapterOptions));
}
/**
* @test
*/
public function shouldThrowExceptionIfBucketMissingAndNotCreating(): void
{
$this->expectException(\RuntimeException::class);
$this->createFilesystem();
$this->filesystem->read('foo');
}
/**
* @test
*/
public function shouldWriteObjects(): void
{
$this->assertEquals(7, $this->filesystem->write('foo', 'testing'));
}
/**
* @test
*/
public function shouldCheckForObjectExistence(): void
{
$this->filesystem->write('foo', '');
$this->assertTrue($this->filesystem->has('foo'));
}
/**
* @test
*/
public function shouldCheckForObjectExistenceWithDirectory(): void
{
$this->createFilesystem(['directory' => 'bar', 'create' => true]);
$this->filesystem->write('foo', '');
$this->assertTrue($this->filesystem->has('foo'));
}
/**
* @test
*/
public function shouldListKeysWithoutDirectory(): void
{
$this->assertEquals([], $this->filesystem->listKeys());
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->listKeys());
}
/**
* @test
*/
public function shouldListKeysWithDirectory(): void
{
$this->createFilesystem(['create' => true, 'directory' => 'root/']);
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->listKeys());
$this->assertTrue($this->filesystem->has('test.txt'));
}
/**
* @test
*/
public function shouldGetKeysWithoutDirectory(): void
{
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->keys());
}
/**
* @test
*/
public function shouldGetKeysWithDirectory(): void
{
$this->createFilesystem(['create' => true, 'directory' => 'root/']);
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->keys());
}
/**
* @test
*/
public function shouldUploadWithGivenContentType(): void
{
/** @var AwsS3 $adapter */
$adapter = $this->filesystem->getAdapter();
$adapter->setMetadata('foo', ['ContentType' => 'text/html']);
$this->filesystem->write('foo', '<html></html>');
$this->assertEquals('text/html', $this->filesystem->mimeType('foo'));
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Aws\S3\S3Client;
use Gaufrette\Adapter\AwsS3;
use Gaufrette\Filesystem;
class AwsS3Test extends FunctionalTestCase
{
/** @var int */
private static $SDK_VERSION;
/** @var string */
private $bucket;
/** @var S3Client */
private $client;
protected function setUp(): void
{
$key = getenv('AWS_KEY');
$secret = getenv('AWS_SECRET');
if (empty($key) || empty($secret)) {
$this->markTestSkipped('Either AWS_KEY and/or AWS_SECRET env variables are not defined.');
}
if (self::$SDK_VERSION === null) {
self::$SDK_VERSION = method_exists(S3Client::class, 'getArguments') ? 3 : 2;
}
$this->bucket = uniqid(getenv('AWS_BUCKET'));
if (self::$SDK_VERSION === 3) {
// New way of instantiating S3Client for aws-sdk-php v3
$this->client = new S3Client([
'region' => 'eu-west-1',
'version' => 'latest',
'credentials' => [
'key' => $key,
'secret' => $secret,
],
]);
} else {
$this->client = S3Client::factory([
'region' => 'eu-west-1',
'version' => '2006-03-01',
'key' => $key,
'secret' => $secret,
]);
}
$this->createFilesystem(['create' => true]);
}
protected function tearDown(): void
{
if ($this->client === null || !$this->client->doesBucketExist($this->bucket)) {
return;
}
$result = $this->client->listObjects(['Bucket' => $this->bucket]);
if (!$result->hasKey('Contents')) {
$this->client->deleteBucket(['Bucket' => $this->bucket]);
return;
}
foreach ($result->get('Contents') as $staleObject) {
$this->client->deleteObject(['Bucket' => $this->bucket, 'Key' => $staleObject['Key']]);
}
$this->client->deleteBucket(['Bucket' => $this->bucket]);
}
private function createFilesystem(array $adapterOptions = [])
{
$this->filesystem = new Filesystem(new AwsS3($this->client, $this->bucket, $adapterOptions));
}
/**
* @test
*/
public function shouldThrowExceptionIfBucketMissingAndNotCreating(): void
{
$this->expectException(\RuntimeException::class);
$this->createFilesystem();
$this->filesystem->read('foo');
}
/**
* @test
*/
public function shouldWriteObjects(): void
{
$this->assertEquals(7, $this->filesystem->write('foo', 'testing'));
}
/**
* @test
*/
public function shouldCheckForObjectExistence(): void
{
$this->filesystem->write('foo', '');
$this->assertTrue($this->filesystem->has('foo'));
}
/**
* @test
*/
public function shouldCheckForObjectExistenceWithDirectory(): void
{
$this->createFilesystem(['directory' => 'bar', 'create' => true]);
$this->filesystem->write('foo', '');
$this->assertTrue($this->filesystem->has('foo'));
}
/**
* @test
*/
public function shouldListKeysWithoutDirectory(): void
{
$this->assertEquals([], $this->filesystem->listKeys());
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->listKeys());
}
/**
* @test
*/
public function shouldListKeysWithDirectory(): void
{
$this->createFilesystem(['create' => true, 'directory' => 'root/']);
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->listKeys());
$this->assertTrue($this->filesystem->has('test.txt'));
}
/**
* @test
*/
public function shouldGetKeysWithoutDirectory(): void
{
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->keys());
}
/**
* @test
*/
public function shouldGetKeysWithDirectory(): void
{
$this->createFilesystem(['create' => true, 'directory' => 'root/']);
$this->filesystem->write('test.txt', 'some content');
$this->assertEquals(['test.txt'], $this->filesystem->keys());
}
/**
* @test
*/
public function shouldUploadWithGivenContentType(): void
{
/** @var AwsS3 $adapter */
$adapter = $this->filesystem->getAdapter();
$adapter->setMetadata('foo', ['ContentType' => 'text/html']);
$this->filesystem->write('foo', '<html></html>');
$this->assertEquals('text/html', $this->filesystem->mimeType('foo'));
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\AzureBlobStorage;
use Gaufrette\Adapter\AzureBlobStorage\BlobProxyFactory;
use Gaufrette\Filesystem;
/**
* Class AzureBlobStorageTest
* @group AzureBlobStorage
*/
class AzureBlobStorageTest extends FunctionalTestCase
{
/** @var string Name of the Azure container used */
private $container;
/** @var AzureBlobStorage */
private $adapter;
protected function setUp(): void
{
$account = getenv('AZURE_ACCOUNT');
$key = getenv('AZURE_KEY');
$containerName = getenv('AZURE_CONTAINER');
if (empty($account) || empty($key) || empty($containerName)) {
$this->markTestSkipped('Either AZURE_ACCOUNT, AZURE_KEY and/or AZURE_CONTAINER env variables are not defined.');
}
$connection = sprintf('DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=core.windows.net', $account, $key);
$this->container = uniqid($containerName);
$this->adapter = new AzureBlobStorage(new BlobProxyFactory($connection), $this->container, true);
$this->filesystem = new Filesystem($this->adapter);
}
/**
* @test
* @group functional
*/
public function shouldGetContentType(): void
{
$path = '/somefile';
$content = 'Some content';
$this->filesystem->write($path, $content);
$this->assertEquals('text/plain', $this->filesystem->mimeType($path));
}
protected function tearDown(): void
{
if ($this->adapter === null) {
return;
}
$this->adapter->deleteContainer($this->container);
}
}

View File

@@ -0,0 +1,270 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\AzureBlobStorage;
use Gaufrette\Adapter\AzureBlobStorage\BlobProxyFactory;
use Gaufrette\Filesystem;
/**
* Class AzureMultiContainerBlobStorageTest
* @group AzureBlobStorage
* @group AzureMultiContainerBlobStorage
*/
class AzureMultiContainerBlobStorageTest extends FunctionalTestCase
{
private $adapter;
private $containers = [];
protected function setUp(): void
{
$this->markTestSkipped(__CLASS__ . ' is flaky.');
$account = getenv('AZURE_ACCOUNT');
$key = getenv('AZURE_KEY');
if (empty($account) || empty($key)) {
$this->markTestSkipped('Either AZURE_ACCOUNT and/or AZURE_KEY env variables are not defined.');
}
$connection = sprintf('BlobEndpoint=https://%1$s.blob.core.windows.net/;AccountName=%1$s;AccountKey=%2$s', $account, $key);
$this->adapter = new AzureBlobStorage(new BlobProxyFactory($connection));
$this->filesystem = new Filesystem($this->adapter);
}
/**
* @test
* @group functional
*/
public function shouldWriteAndRead(): void
{
$path1 = $this->createUniqueContainerName('container') . '/foo';
$path2 = $this->createUniqueContainerName('test') . '/subdir/foo';
$this->assertEquals(12, $this->filesystem->write($path1, 'Some content'));
$this->assertEquals(13, $this->filesystem->write($path2, 'Some content1', true));
$this->assertEquals('Some content', $this->filesystem->read($path1));
$this->assertEquals('Some content1', $this->filesystem->read($path2));
}
/**
* @test
* @group functional
*/
public function shouldUpdateFileContent(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$this->filesystem->write($path, 'Some content');
$this->filesystem->write($path, 'Some content updated', true);
$this->assertEquals('Some content updated', $this->filesystem->read($path));
}
/**
* @test
* @group functional
*/
public function shouldCheckIfFileExists(): void
{
$path1 = $this->createUniqueContainerName('container') . '/foo';
$path2 = $this->createUniqueContainerName('test') . '/somefile';
$this->assertFalse($this->filesystem->has($path1));
$this->filesystem->write($path1, 'Some content');
$this->assertTrue($this->filesystem->has($path1));
// @TODO: why is it done two times?
$this->assertFalse($this->filesystem->has($path2));
$this->assertFalse($this->filesystem->has($path2));
}
/**
* @test
* @group functional
*/
public function shouldGetMtime(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$this->filesystem->write($path, 'Some content');
$this->assertGreaterThan(0, $this->filesystem->mtime($path));
}
/**
* @test
* @group functional
*/
public function shouldGetSize(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$contentSize = $this->filesystem->write($path, 'Some content');
$this->assertEquals($contentSize, $this->filesystem->size($path));
}
/**
* @test
* @group functional
*/
public function shouldGetMd5Hash(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$content = 'Some content';
$this->filesystem->write($path, $content);
$this->assertEquals(\md5($content), $this->filesystem->checksum($path));
}
/**
* @test
* @group functional
*/
public function shouldGetContentType(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$content = 'Some content';
$this->filesystem->write($path, $content);
$this->assertEquals('text/plain', $this->filesystem->mimeType($path));
}
/**
* @test
* @group functional
* @expectedException \RuntimeException
* @expectedMessage Could not get mtime for the "foo" key
*/
public function shouldFailWhenTryMtimeForKeyWhichDoesNotExist(): void
{
$this->assertFalse($this->filesystem->mtime('container5/foo'));
}
/**
* @test
* @group functional
*/
public function shouldRenameFile(): void
{
$somedir = $this->createUniqueContainerName('somedir');
$path1 = $this->createUniqueContainerName('container') . '/foo';
$path2 = $this->createUniqueContainerName('container-new') . '/boo';
$path3 = $somedir . '/sub/boo';
$this->filesystem->write($path1, 'Some content');
$this->filesystem->rename($path1, $path2);
$this->assertFalse($this->filesystem->has($path1));
$this->assertEquals('Some content', $this->filesystem->read($path2));
$this->filesystem->write($path1, 'Some content');
$this->filesystem->rename($path1, $path3);
$this->assertFalse($this->filesystem->has($somedir . '/sub/foo'));
$this->assertEquals('Some content', $this->filesystem->read($path3));
}
/**
* @test
* @group functional
*/
public function shouldDeleteFile(): void
{
$path = $this->createUniqueContainerName('container') . '/foo';
$this->filesystem->write($path, 'Some content');
$this->assertTrue($this->filesystem->has($path));
$this->filesystem->delete($path);
$this->assertFalse($this->filesystem->has($path));
}
/**
* @test
* @group functional
*/
public function shouldFetchKeys(): void
{
$path1 = $this->createUniqueContainerName('container-1') . '/foo';
$path2 = $this->createUniqueContainerName('container-2') . '/bar';
$path3 = $this->createUniqueContainerName('container-3') . '/baz';
$this->filesystem->write($path1, 'Some content');
$this->filesystem->write($path2, 'Some content');
$this->filesystem->write($path3, 'Some content');
$actualKeys = $this->filesystem->keys();
foreach ([$path1, $path2, $path3] as $key) {
$this->assertContains($key, $actualKeys);
}
}
/**
* @test
* @group functional
*/
public function shouldWorkWithHiddenFiles(): void
{
$path = $this->createUniqueContainerName('container') . '/.foo';
$this->filesystem->write($path, 'hidden');
$this->assertTrue($this->filesystem->has($path));
$this->assertContains($path, $this->filesystem->keys());
$this->filesystem->delete($path);
$this->assertFalse($this->filesystem->has($path));
}
/**
* @test
* @group functional
*/
public function shouldKeepFileObjectInRegister(): void
{
$path = $this->createUniqueContainerName('container') . '/somefile';
$FileObjectA = $this->filesystem->createFile($path);
$FileObjectB = $this->filesystem->createFile($path);
$this->assertSame($FileObjectB, $FileObjectA);
}
/**
* @test
* @group functional
*/
public function shouldWriteToSameFile(): void
{
$path = $this->createUniqueContainerName('container') . '/somefile';
$FileObjectA = $this->filesystem->createFile($path);
$FileObjectA->setContent('ABC');
$FileObjectB = $this->filesystem->createFile($path);
$FileObjectB->setContent('DEF');
$this->assertEquals('DEF', $FileObjectA->getContent());
}
private function createUniqueContainerName($prefix)
{
$this->containers[] = $container = uniqid($prefix);
return $container;
}
protected function tearDown(): void
{
foreach ($this->containers as $container) {
$this->adapter->deleteContainer($container);
}
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Doctrine\DBAL\DriverManager;
use Gaufrette\Adapter\DoctrineDbal;
use Gaufrette\Filesystem;
class DoctrineDbalTest extends FunctionalTestCase
{
/** @var \Doctrine\DBAL\Connection */
private $connection;
public static function setUpBeforeClass(): void
{
if (!class_exists(DriverManager::class)) {
self::markTestSkipped('Package doctrine/dbal is not installed');
}
parent::setUpBeforeClass();
}
protected function setUp(): void
{
$this->connection = DriverManager::getConnection([
'driver' => 'pdo_sqlite',
'memory' => true,
]);
$schema = $this->connection->getSchemaManager()->createSchema();
$table = $schema->createTable('gaufrette');
$column = $table->addColumn('key', 'string');
if (method_exists($column, 'setPlatformOption')) {
// dbal 3.4+
$column->setPlatformOption('unique', true);
} else {
// BC layer dbal 2.x
$column->setUnique(true);
}
$table->addColumn('content', 'blob');
$table->addColumn('mtime', 'integer');
$table->addColumn('checksum', 'string', ['length' => 32]);
// Generates the SQL from the defined schema and execute each line
array_map([$this->connection, 'exec'], $schema->toSql($this->connection->getDatabasePlatform()));
$this->filesystem = new Filesystem(new DoctrineDbal($this->connection, 'gaufrette'));
}
protected function tearDown(): void
{
$schemaManager = $this->connection->getSchemaManager();
if (in_array('gaufrette', $schemaManager->listTableNames())) {
$schemaManager->dropTable('gaufrette');
}
}
/**
* @test
*/
public function shouldListKeys(): void
{
$this->filesystem->write('foo/foobar/bar.txt', 'data');
$this->filesystem->write('foo/bar/buzz.txt', 'data');
$this->filesystem->write('foobarbuz.txt', 'data');
$this->filesystem->write('foo', 'data');
$allKeys = $this->filesystem->listKeys(' ');
//empty pattern results in ->keys call
$this->assertEquals(
$this->filesystem->keys(),
$allKeys['keys']
);
//these values are canonicalized to avoid wrong order or keys issue
$keys = $this->filesystem->listKeys('foo');
$this->assertEqualsCanonicalizing(
$this->filesystem->keys(),
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo/foob');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo/');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt', 'foo/bar/buzz.txt'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt', 'foo/bar/buzz.txt', 'foobarbuz.txt', 'foo'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('fooz');
$this->assertEqualsCanonicalizing(
[],
$keys['keys']
);
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\Ftp;
use Gaufrette\Filesystem;
class FtpTest extends FunctionalTestCase
{
protected function setUp(): void
{
$host = getenv('FTP_HOST');
$port = getenv('FTP_PORT');
$user = getenv('FTP_USER');
$password = getenv('FTP_PASSWORD');
$baseDir = getenv('FTP_BASE_DIR');
if ($user === false || $password === false || $host === false || $baseDir === false) {
$this->markTestSkipped('Either FTP_HOST, FTP_USER, FTP_PASSWORD and/or FTP_BASE_DIR env variables are not defined.');
}
$adapter = new Ftp($baseDir, $host, ['port' => $port, 'username' => $user, 'password' => $password, 'passive' => true, 'create' => true]);
$this->filesystem = new Filesystem($adapter);
}
protected function tearDown(): void
{
if (null === $this->filesystem) {
return;
}
$adapter = $this->filesystem->getAdapter();
foreach ($adapter->keys() as $key) {
if (!$adapter->isDirectory($key)) {
$adapter->delete($key);
}
}
$keys = $adapter->keys();
rsort($keys);
foreach ($keys as $key) {
$adapter->delete($key);
}
$adapter->close();
}
}

View File

@@ -0,0 +1,218 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Exception\FileNotFound;
use Gaufrette\Filesystem;
use PHPUnit\Framework\TestCase;
abstract class FunctionalTestCase extends TestCase
{
/**
* @var Filesystem
*/
protected $filesystem;
public function getAdapterName()
{
if (!preg_match('/\\\\(\w+)Test$/', get_class($this), $matches)) {
throw new \RuntimeException(sprintf(
'Unable to guess filesystem name from class "%s", ' .
'please override the ->getAdapterName() method.',
get_class($this)
));
}
return $matches[1];
}
protected function setUp(): void
{
$basename = $this->getAdapterName();
$filename = sprintf(
'%s/adapters/%s.php',
dirname(__DIR__),
$basename
);
if (!file_exists($filename)) {
$this->markTestSkipped(
<<<EOF
To run the {$basename} filesystem tests, you must:
1. Copy the file "{$filename}.dist" as "{$filename}"
2. Modify the copied file to fit your environment
EOF
);
}
$adapter = include $filename;
$this->filesystem = new Filesystem($adapter);
}
protected function tearDown(): void
{
if (null === $this->filesystem) {
return;
}
$this->filesystem = null;
}
/**
* @test
* @group functional
*/
public function shouldWriteAndRead(): void
{
$this->assertEquals(12, $this->filesystem->write('foo', 'Some content'));
$this->assertEquals(13, $this->filesystem->write('test/subdir/foo', 'Some content1', true));
$this->assertEquals('Some content', $this->filesystem->read('foo'));
$this->assertEquals('Some content1', $this->filesystem->read('test/subdir/foo'));
}
/**
* @test
* @group functional
*/
public function shouldUpdateFileContent(): void
{
$this->filesystem->write('foo', 'Some content');
$this->filesystem->write('foo', 'Some content updated', true);
$this->assertEquals('Some content updated', $this->filesystem->read('foo'));
}
/**
* @test
* @group functional
*/
public function shouldCheckIfFileExists(): void
{
$this->assertFalse($this->filesystem->has('foo'));
$this->filesystem->write('foo', 'Some content');
$this->assertTrue($this->filesystem->has('foo'));
$this->assertFalse($this->filesystem->has('test/somefile'));
$this->assertFalse($this->filesystem->has('test/somefile'));
}
/**
* @test
* @group functional
*/
public function shouldGetMtime(): void
{
$this->filesystem->write('foo', 'Some content');
$this->assertGreaterThan(0, $this->filesystem->mtime('foo'));
}
/**
* @test
* @group functional
*/
public function shouldFailWhenTryMtimeForKeyWhichDoesNotExist(): void
{
$this->expectException(FileNotFound::class);
$this->expectExceptionMessage('The file "foo" was not found.');
$this->filesystem->mtime('foo');
}
/**
* @test
* @group functional
*/
public function shouldRenameFile(): void
{
$this->filesystem->write('foo', 'Some content');
$this->filesystem->rename('foo', 'boo');
$this->assertFalse($this->filesystem->has('foo'));
$this->assertEquals('Some content', $this->filesystem->read('boo'));
$this->filesystem->delete('boo');
$this->filesystem->write('foo', 'Some content');
$this->filesystem->rename('foo', 'somedir/sub/boo');
$this->assertFalse($this->filesystem->has('somedir/sub/foo'));
$this->assertEquals('Some content', $this->filesystem->read('somedir/sub/boo'));
}
/**
* @test
* @group functional
*/
public function shouldDeleteFile(): void
{
$this->filesystem->write('foo', 'Some content');
$this->assertTrue($this->filesystem->has('foo'));
$this->filesystem->delete('foo');
$this->assertFalse($this->filesystem->has('foo'));
}
/**
* @test
* @group functional
*/
public function shouldFetchKeys(): void
{
$this->assertEquals([], $this->filesystem->keys());
$this->filesystem->write('foo', 'Some content');
$this->filesystem->write('bar', 'Some content');
$this->filesystem->write('baz', 'Some content');
$actualKeys = $this->filesystem->keys();
$this->assertCount(3, $actualKeys);
foreach (['foo', 'bar', 'baz'] as $key) {
$this->assertContains($key, $actualKeys);
}
}
/**
* @test
* @group functional
*/
public function shouldWorkWithHiddenFiles(): void
{
$this->filesystem->write('.foo', 'hidden');
$this->assertTrue($this->filesystem->has('.foo'));
$this->assertContains('.foo', $this->filesystem->keys());
$this->filesystem->delete('.foo');
$this->assertFalse($this->filesystem->has('.foo'));
}
/**
* @test
* @group functional
*/
public function shouldKeepFileObjectInRegister(): void
{
$FileObjectA = $this->filesystem->createFile('somefile');
$FileObjectB = $this->filesystem->createFile('somefile');
$this->assertSame($FileObjectA, $FileObjectB);
}
/**
* @test
* @group functional
*/
public function shouldWriteToSameFile(): void
{
$FileObjectA = $this->filesystem->createFile('somefile');
$FileObjectA->setContent('ABC');
$FileObjectB = $this->filesystem->createFile('somefile');
$FileObjectB->setContent('DEF');
$this->assertEquals('DEF', $FileObjectA->getContent());
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\GoogleCloudStorage;
/**
* Functional tests for the GoogleCloudStorage adapter.
*
* Copy the ../adapters/GoogleCloudStorage.php.dist to GoogleCloudStorage.php and
* adapt to your needs.
*
* @author Patrik Karisch <patrik@karisch.guru>
*/
class GoogleCloudStorageTest extends FunctionalTestCase
{
/**
* @test
* @group functional
*/
public function shouldThrowExceptionIfBucketMissing()
{
$this->expectException(\RuntimeException::class);
/** @var \Gaufrette\Adapter\GoogleCloudStorage $adapter */
$adapter = $this->filesystem->getAdapter();
$adapter->setOptions([GoogleCloudStorage::OPTION_CREATE_BUCKET_IF_NOT_EXISTS => false]);
$adapter->setBucket('Gaufrette-' . mt_rand());
$adapter->read('foo');
}
/**
* @test
* @group functional
*/
public function shouldWriteAndReadWithDirectory()
{
/** @var \Gaufrette\Adapter\GoogleCloudStorage $adapter */
$adapter = $this->filesystem->getAdapter();
$oldOptions = $adapter->getOptions();
$adapter->setOptions(['directory' => 'Gaufrette']);
$this->assertEquals(12, $this->filesystem->write('foo', 'Some content'));
$this->assertEquals(13, $this->filesystem->write('test/subdir/foo', 'Some content1', true));
$this->assertEquals('Some content', $this->filesystem->read('foo'));
$this->assertEquals('Some content1', $this->filesystem->read('test/subdir/foo'));
$this->filesystem->delete('foo');
$this->filesystem->delete('test/subdir/foo');
$adapter->setOptions($oldOptions);
}
/**
* @test
* @group functional
*/
public function shouldSetMetadataCorrectly()
{
/** @var \Gaufrette\Adapter\GoogleCloudStorage $adapter */
$adapter = $this->filesystem->getAdapter();
$adapter->setMetadata('metadata.txt', [
'CacheControl' => 'public, maxage=7200',
'ContentDisposition' => 'attachment; filename="test.txt"',
'ContentEncoding' => 'identity',
'ContentLanguage' => 'en',
'Colour' => 'Yellow',
]);
$this->assertEquals(12, $this->filesystem->write('metadata.txt', 'Some content', true));
$reflectionObject = new \ReflectionObject($adapter);
$reflectionMethod = $reflectionObject->getMethod('getObjectData');
$reflectionMethod->setAccessible(true);
$metadata = $reflectionMethod->invoke($adapter, ['metadata.txt']);
$this->assertEquals('public, maxage=7200', $metadata->cacheControl);
$this->assertEquals('attachment; filename="test.txt"', $metadata->contentDisposition);
$this->assertEquals('identity', $metadata->contentEncoding);
$this->assertEquals('en', $metadata->contentLanguage);
$this->assertEquals([
'Colour' => 'Yellow',
], $metadata->metadata);
$this->filesystem->delete('metadata.txt');
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\GridFS;
use Gaufrette\Filesystem;
use MongoDB\Client;
class GridFSTest extends FunctionalTestCase
{
protected function setUp(): void
{
$uri = getenv('MONGO_URI');
$dbname = getenv('MONGO_DBNAME');
if ($uri === false || $dbname === false) {
$this->markTestSkipped('Either MONGO_URI or MONGO_DBNAME env variables are not defined.');
}
$client = new Client($uri);
$db = $client->selectDatabase($dbname);
$bucket = $db->selectGridFSBucket();
$bucket->drop();
$this->filesystem = new Filesystem(new GridFS($bucket));
}
/**
* @test
*/
public function shouldListKeys(): void
{
$this->filesystem->write('foo/foobar/bar.txt', 'data');
$this->filesystem->write('foo/bar/buzz.txt', 'data');
$this->filesystem->write('foobarbuz.txt', 'data');
$this->filesystem->write('foo', 'data');
$allKeys = $this->filesystem->listKeys(' ');
//empty pattern results in ->keys call
$this->assertEquals(
$this->filesystem->keys(),
$allKeys['keys']
);
//these values are canonicalized to avoid wrong order or keys issue
$keys = $this->filesystem->listKeys('foo');
$this->assertEqualsCanonicalizing(
$this->filesystem->keys(),
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo/foob');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo/');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt', 'foo/bar/buzz.txt'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('foo');
$this->assertEqualsCanonicalizing(
['foo/foobar/bar.txt', 'foo/bar/buzz.txt', 'foobarbuz.txt', 'foo'],
$keys['keys']
);
$keys = $this->filesystem->listKeys('fooz');
$this->assertEqualsCanonicalizing(
[],
$keys['keys']
);
}
/**
* @test
* Tests metadata written to GridFS can be retrieved after writing
*/
public function shouldRetrieveMetadataAfterWrite(): void
{
//Create local copy of fileadapter
$fileadpt = clone $this->filesystem->getAdapter();
$this->filesystem->getAdapter()->setMetadata('metadatatest', ['testing' => true]);
$this->filesystem->write('metadatatest', 'test');
$this->assertEquals($this->filesystem->getAdapter()->getMetadata('metadatatest'), $fileadpt->getMetadata('metadatatest'));
}
/**
* @test
* Test to see if filesize works
*/
public function shouldGetSize(): void
{
$this->filesystem->write('sizetest.txt', 'data');
$this->assertEquals(4, $this->filesystem->size('sizetest.txt'));
}
/**
* @test
* Should retrieve empty metadata w/o errors
*/
public function shouldRetrieveEmptyMetadata(): void
{
$this->filesystem->write('no-metadata.txt', 'content');
$this->assertEquals([], $this->filesystem->getAdapter()->getMetadata('no-metadata.txt'));
}
/**
* @test
* @group functional
*/
public function shouldGetMtime(): void
{
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$this->markTestSkipped('Not working on Windows.');
} else {
parent::shouldGetMtime();
}
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Filesystem;
use Gaufrette\Adapter\Local;
class LocalTest extends FunctionalTestCase
{
private $directory;
protected function setUp(): void
{
$this->directory = sprintf('%s/filesystem', str_replace('\\', '/', __DIR__));
if (!file_exists($this->directory)) {
mkdir($this->directory);
}
$this->filesystem = new Filesystem(new Local($this->directory));
}
protected function tearDown(): void
{
$adapter = $this->filesystem->getAdapter();
foreach ($this->filesystem->keys() as $key) {
$adapter->delete($key);
}
$this->filesystem = null;
rmdir($this->directory);
}
/**
* @test
* @group functional
*/
public function shouldWorkWithSyslink(): void
{
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$this->markTestSkipped('Symlinks are not supported on Windows.');
}
$dirname = sprintf(
'%s/adapters/aaa',
dirname(__DIR__)
);
$linkname = sprintf(
'%s/adapters/../../../../link',
dirname(__DIR__)
);
@mkdir($dirname);
@unlink($linkname);
symlink($dirname, $linkname);
$fs = new Filesystem(new Local($linkname));
$fs->write('test.txt', 'abc 123');
$this->assertSame('abc 123', $fs->read('test.txt'));
$fs->delete('test.txt');
@unlink($linkname);
@rmdir($dirname);
}
/**
* @test
* @covers Gaufrette\Adapter\Local
* @group functional
*/
public function shouldListingOnlyGivenDirectory(): void
{
$this->filesystem->write('aaa.txt', 'some content');
$this->filesystem->write('localDir/test.txt', 'some content');
$dirs = $this->filesystem->listKeys('localDir/test');
$this->assertEmpty($dirs['dirs']);
$this->assertCount(1, $dirs['keys']);
$this->assertEquals('localDir/test.txt', $dirs['keys'][0]);
$dirs = $this->filesystem->listKeys();
$this->assertCount(1, $dirs['dirs']);
$this->assertEquals('localDir', $dirs['dirs'][0]);
$this->assertCount(2, $dirs['keys']);
$this->assertEquals('aaa.txt', $dirs['keys'][0]);
$this->assertEquals('localDir/test.txt', $dirs['keys'][1]);
}
/**
* @test
* @covers Gaufrette\Adapter\Local
* @group functional
*/
public function shouldListingAllKeys(): void
{
$this->filesystem->write('aaa.txt', 'some content');
$this->filesystem->write('localDir/dir1/dir2/dir3/test.txt', 'some content');
$keys = $this->filesystem->keys();
$dirs = $this->filesystem->listKeys();
$this->assertCount(6, $keys);
$this->assertCount(4, $dirs['dirs']);
$this->assertEquals('localDir/dir1/dir2/dir3/test.txt', $dirs['keys'][1]);
}
/**
* @test
* @group functional
*/
public function shouldBeAbleToClearCache(): void
{
$this->filesystem->get('test.txt', true);
$this->filesystem->write('test.txt', '123', true);
$this->filesystem->get('test2.txt', true);
$this->filesystem->write('test2.txt', '123', true);
$fsReflection = new \ReflectionClass($this->filesystem);
$fsIsFileInRegister = $fsReflection->getMethod('isFileInRegister');
$fsIsFileInRegister->setAccessible(true);
$this->assertTrue($fsIsFileInRegister->invoke($this->filesystem, 'test.txt'));
$this->filesystem->removeFromRegister('test.txt');
$this->assertFalse($fsIsFileInRegister->invoke($this->filesystem, 'test.txt'));
$this->filesystem->clearFileRegister();
$fsRegister = $fsReflection->getProperty('fileRegister');
$fsRegister->setAccessible(true);
$this->assertCount(0, $fsRegister->getValue($this->filesystem));
}
/**
* @test
* @group functional
*/
public function shouldDeleteDirectory(): void
{
$path = $this->directory . DIRECTORY_SEPARATOR . 'delete-me.d';
mkdir($path);
$this->assertTrue(is_dir($path));
$this->assertTrue($this->filesystem->getAdapter()->delete('delete-me.d'));
$this->assertFalse(is_dir($path));
}
/**
* @test
* @group functional
*/
public function shouldNotDeleteTheAdapterRootDirectory(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Impossible to delete the root directory of this Local adapter');
$this->filesystem->getAdapter()->delete('/');
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\PhpseclibSftp;
use Gaufrette\Filesystem;
use phpseclib\Net\SFTP;
class PhpseclibSftpTest extends FunctionalTestCase
{
/** @var SFTP */
private $sftp;
/** @var string */
private $baseDir;
protected function setUp(): void
{
$host = getenv('SFTP_HOST');
$port = getenv('SFTP_PORT') ?: 22;
$user = getenv('SFTP_USER');
$password = getenv('SFTP_PASSWORD');
$baseDir = getenv('SFTP_BASE_DIR');
if ($host === false || $user === false || $password === false || $baseDir === false) {
$this->markTestSkipped('Either SFTP_HOST, SFTP_USER, SFTP_PASSWORD and/or SFTP_BASE_DIR env variables are not defined.');
}
$this->baseDir = rtrim($baseDir, '/') . '/' . uniqid();
$this->sftp = new SFTP($host, $port);
$this->sftp->login($user, $password);
$this->filesystem = new Filesystem(new PhpseclibSftp($this->sftp, $this->baseDir, true));
}
protected function tearDown(): void
{
if (!isset($this->sftp)) {
return;
}
$this->sftp->rmdir($this->baseDir);
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Filesystem;
use Gaufrette\Adapter\SafeLocal;
class SafeLocalTest extends FunctionalTestCase
{
protected function setUp(): void
{
if (!file_exists($this->getDirectory())) {
mkdir($this->getDirectory());
}
$this->filesystem = new Filesystem(new SafeLocal($this->getDirectory()));
}
protected function tearDown(): void
{
foreach ($this->filesystem->keys() as $key) {
$this->filesystem->delete($key);
}
$this->filesystem = null;
rmdir($this->getDirectory());
}
private function getDirectory(): string
{
return sprintf('%s/filesystem', __DIR__);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Gaufrette\Functional\Adapter;
use Gaufrette\Adapter\Zip;
use Gaufrette\Filesystem;
class ZipTest extends FunctionalTestCase
{
protected function setUp(): void
{
if (!extension_loaded('zip')) {
$this->markTestSkipped('The zip extension is not available.');
} elseif (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$this->markTestSkipped('Zip adapter is not supported on Windows.');
}
$this->filesystem = new Filesystem(new Zip(__DIR__ . '/test.zip'));
}
protected function tearDown(): void
{
parent::tearDown();
@unlink(__DIR__ . '/test.zip');
}
/**
* @test
* @group functional
*/
public function shouldNotAcceptInvalidZipArchive(): void
{
$this->expectException(\RuntimeException::class);
new Zip(__FILE__);
}
}

View File

@@ -0,0 +1,226 @@
<?php
namespace Gaufrette\Functional\FileStream;
use Gaufrette\StreamWrapper;
use PHPUnit\Framework\TestCase;
abstract class FunctionalTestCase extends TestCase
{
protected $filesystem;
/**
* @test
*/
public function shouldCheckIsFile()
{
$this->filesystem->write('test.txt', 'some content');
$this->assertTrue(is_file('gaufrette://filestream/test.txt'));
$this->filesystem->delete('test.txt');
$this->assertFalse(is_file('gaufrette://filestream/test.txt'));
}
/**
* @test
*/
public function shouldCheckFileExists()
{
$this->filesystem->write('test.txt', 'some content');
$this->assertFileExists('gaufrette://filestream/test.txt');
$this->filesystem->delete('test.txt');
$this->assertFileNotExists('gaufrette://filestream/test.txt');
}
/**
* @test
*/
public function shouldWriteAndReadFile()
{
file_put_contents('gaufrette://filestream/test.txt', 'test content');
$this->assertEquals('test content', file_get_contents('gaufrette://filestream/test.txt'));
$this->filesystem->delete('test.txt');
}
/**
* @test
*/
public function shouldNotReadWhenOpenInWriteMode()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('The stream does not allow read.');
$this->filesystem->write('test.txt', 'test content');
$fileHandler = fopen('gaufrette://filestream/test.txt', 'w');
fread($fileHandler, 10);
fclose($fileHandler);
$this->filesystem->delete('test.txt');
}
/**
* @test
*/
public function shouldNotWriteWhenOpenInReadMode()
{
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('The stream does not allow write.');
$this->filesystem->write('test.txt', 'test content');
$fileHandler = fopen('gaufrette://filestream/test.txt', 'r');
fwrite($fileHandler, 'test content2');
fclose($fileHandler);
$this->filesystem->delete('test.txt');
}
/**
* @test
*/
public function shouldWriteFromSettedPosition()
{
$fileHandler = fopen('gaufrette://filestream/test.txt', 'w');
fseek($fileHandler, 1, SEEK_SET);
fwrite($fileHandler, 'est');
fseek($fileHandler, 0, SEEK_SET);
fwrite($fileHandler, 't');
fclose($fileHandler);
$this->assertEquals('test', $this->filesystem->read('test.txt'));
$fileHandler = fopen('gaufrette://filestream/test.txt', 'w');
fseek($fileHandler, 0, SEEK_SET);
fwrite($fileHandler, 't');
fseek($fileHandler, 1, SEEK_SET);
fwrite($fileHandler, 'est');
fseek($fileHandler, 0, SEEK_SET);
fwrite($fileHandler, 'f');
fclose($fileHandler);
$this->assertEquals('fest', $this->filesystem->read('test.txt'));
}
/**
* @test
*/
public function shouldWriteEmptyContent()
{
$bytes = file_put_contents('gaufrette://filestream/test.txt', '');
$this->assertEquals('', file_get_contents('gaufrette://filestream/test.txt'));
$this->filesystem->delete('test.txt');
$this->assertSame(0, $bytes);
}
/**
* @test
*/
public function shouldSetAndGetPosition()
{
file_put_contents('gaufrette://filestream/test.txt', 'test content');
$fileHandler = fopen('gaufrette://filestream/test.txt', 'r+');
fseek($fileHandler, 1, SEEK_SET);
$this->assertEquals(1, ftell($fileHandler));
fseek($fileHandler, 1, SEEK_CUR);
$this->assertEquals(2, ftell($fileHandler));
fclose($fileHandler);
$fileHandler = fopen('gaufrette://filestream/test.txt', 'r+');
fseek($fileHandler, 1, SEEK_CUR);
$this->assertEquals(1, ftell($fileHandler));
fclose($fileHandler);
$fileHandler = fopen('gaufrette://filestream/test.txt', 'r+');
fseek($fileHandler, -2, SEEK_END);
$this->assertEquals(10, ftell($fileHandler));
fclose($fileHandler);
}
/**
* @test
*/
public function shouldNotSeekWhenWhenceParameterIsInvalid()
{
file_put_contents('gaufrette://filestream/test.txt', 'test content');
$fileHandler = fopen('gaufrette://filestream/test.txt', 'r+');
$this->assertEquals(-1, fseek($fileHandler, 1, 666));
}
/**
* @test
*/
public function shouldHandlesSubDir()
{
file_put_contents('gaufrette://filestream/subdir/test.txt', 'test content');
$this->assertTrue(is_file('gaufrette://filestream/subdir/test.txt'));
$this->filesystem->delete('subdir/test.txt');
$this->assertFalse(is_file('gaufrette://filestream/subdir/test.txt'));
}
/**
* @test
*/
public function shouldUnlinkFile()
{
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$this->markTestSkipped('Flaky test on windows.');
}
$this->filesystem->write('test.txt', 'some content');
unlink('gaufrette://filestream/test.txt');
$this->assertFalse($this->filesystem->has('test.txt'));
}
/**
* @test
*/
public function shouldCopyFile()
{
file_put_contents('gaufrette://filestream/copy1.txt', 'test content');
$this->assertTrue(is_file('gaufrette://filestream/copy1.txt'));
$this->assertFalse(is_file('gaufrette://filestream/copy2.txt'));
copy('gaufrette://filestream/copy1.txt', 'gaufrette://filestream/copy2.txt');
$this->assertTrue(is_file('gaufrette://filestream/copy1.txt'));
$this->assertTrue(is_file('gaufrette://filestream/copy2.txt'));
}
/**
* @test
* @dataProvider modesProvider
*/
public function shouldCreateNewFile($mode)
{
$fileHandler = fopen('gaufrette://filestream/test.txt', $mode);
$this->assertFileExists('gaufrette://filestream/test.txt');
}
public static function modesProvider()
{
return [
['w'],
['a+'],
['w+'],
['ab+'],
['wb'],
['wb+'],
];
}
protected function registerLocalFilesystemInStream()
{
$filesystemMap = StreamWrapper::getFilesystemMap();
$filesystemMap->set('filestream', $this->filesystem);
StreamWrapper::register();
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace Gaufrette\Functional\FileStream;
use Gaufrette\Filesystem;
use Gaufrette\Adapter\InMemory as InMemoryAdapter;
class InMemoryBufferTest extends FunctionalTestCase
{
protected function setUp(): void
{
$this->filesystem = new Filesystem(new InMemoryAdapter([]));
$this->registerLocalFilesystemInStream();
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Gaufrette\Functional\FileStream;
use Gaufrette\Filesystem;
use Gaufrette\Adapter\Local as LocalAdapter;
class LocalTest extends FunctionalTestCase
{
protected $directory;
protected function setUp(): void
{
$this->directory = __DIR__ . DIRECTORY_SEPARATOR . 'filesystem';
@mkdir($this->directory . DIRECTORY_SEPARATOR . 'subdir', 0777, true);
umask(0002);
$this->filesystem = new Filesystem(new LocalAdapter($this->directory, true, 0770));
$this->registerLocalFilesystemInStream();
}
/**
* @test
*/
public function shouldChmodDirectory(): void
{
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
$this->markTestSkipped('Chmod and umask are not available on Windows.');
}
$r = fopen('gaufrette://filestream/foo/bar', 'a+');
fclose($r);
$perms = fileperms($this->directory . '/foo/');
$this->assertEquals('0770', substr(sprintf('%o', $perms), -4));
}
protected function tearDown(): void
{
$adapter = $this->filesystem->getAdapter();
foreach ($this->filesystem->keys() as $key) {
$adapter->delete($key);
}
$this->filesystem = null;
rmdir($this->directory);
}
/**
* @test
*/
public function shouldSupportsDirectory(): void
{
$this->assertFileExists('gaufrette://filestream/subdir');
$this->assertDirectoryExists('gaufrette://filestream/subdir');
}
}

View File

@@ -0,0 +1,28 @@
<?php
use Gaufrette\Adapter\GoogleCloudStorage;
$keyFileLocation = '/home/me/path/to/service-auth-key.json';
$bucketName = 'gaufrette-bucket-test-' . uniqid();
$projectId = 'your-project-id-000';
$bucketLocation = 'EUROPE-WEST9';
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $keyFileLocation);
$client = new \Google\Client();
$client->setApplicationName('Gaufrette');
$client->addScope(Google\Service\Storage::DEVSTORAGE_FULL_CONTROL);
$client->useApplicationDefaultCredentials();
$service = new \Google\Service\Storage($client);
return new GoogleCloudStorage(
$service,
$bucketName,
[
GoogleCloudStorage::OPTION_CREATE_BUCKET_IF_NOT_EXISTS => true,
GoogleCloudStorage::OPTION_PROJECT_ID => $projectId,
GoogleCloudStorage::OPTION_LOCATION => $bucketLocation,
],
true
);