From 271056d48108ea3609f04cc8d8c8201037940d60 Mon Sep 17 00:00:00 2001 From: tinect Date: Tue, 22 Oct 2024 21:52:16 +0200 Subject: [PATCH] feat: add testcase for writeBatch --- src/BunnyCDNAdapter.php | 4 +- src/BunnyCDNClient.php | 8 +-- tests/FlysystemAdapterTest.php | 96 +++++++++++++++++++++++++++++++++- tests/MockClient.php | 25 +++++++-- 4 files changed, 120 insertions(+), 13 deletions(-) diff --git a/src/BunnyCDNAdapter.php b/src/BunnyCDNAdapter.php index 7fe95a6..f31edb0 100644 --- a/src/BunnyCDNAdapter.php +++ b/src/BunnyCDNAdapter.php @@ -222,9 +222,9 @@ public function writeBatch(array $writeBatches, Config $config): void } }; - $pool = new Pool($this->client->client, $requests(), [ + $pool = new Pool($this->client->guzzleClient, $requests(), [ 'concurrency' => $concurrency, - 'rejected' => function (RequestException $reason, int $index) { + 'rejected' => function (RequestException|RuntimeException $reason, int $index) { throw UnableToWriteFile::atLocation($index, $reason->getMessage()); }, ]); diff --git a/src/BunnyCDNClient.php b/src/BunnyCDNClient.php index 72f147c..8354a89 100644 --- a/src/BunnyCDNClient.php +++ b/src/BunnyCDNClient.php @@ -11,14 +11,14 @@ class BunnyCDNClient { - public Guzzle $client; + public Guzzle $guzzleClient; public function __construct( public string $storage_zone_name, private string $api_key, private string $region = BunnyCDNRegion::FALKENSTEIN ) { - $this->client = new Guzzle(); + $this->guzzleClient = new Guzzle(); } private static function get_base_url($region): string @@ -54,7 +54,7 @@ public function createRequest(string $path, string $method = 'GET', array $heade */ private function request(Request $request, array $options = []): mixed { - $contents = $this->client->send($request, $options)->getBody()->getContents(); + $contents = $this->guzzleClient->send($request, $options)->getBody()->getContents(); return json_decode($contents, true) ?? $contents; } @@ -125,7 +125,7 @@ public function download(string $path): string public function stream(string $path) { try { - return $this->client->send($this->createRequest($path), ['stream' => true])->getBody()->detach(); + return $this->guzzleClient->send($this->createRequest($path), ['stream' => true])->getBody()->detach(); // @codeCoverageIgnoreStart } catch (GuzzleException $e) { throw match ($e->getCode()) { diff --git a/tests/FlysystemAdapterTest.php b/tests/FlysystemAdapterTest.php index 9b0f313..ceedcbf 100644 --- a/tests/FlysystemAdapterTest.php +++ b/tests/FlysystemAdapterTest.php @@ -3,6 +3,9 @@ namespace PlatformCommunity\Flysystem\BunnyCDN\Tests; use Faker\Factory; +use GuzzleHttp\Client as Guzzle; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; use League\Flysystem\AdapterTestUtilities\FilesystemAdapterTestCase; use League\Flysystem\Config; use League\Flysystem\Filesystem; @@ -13,11 +16,13 @@ use League\Flysystem\UnableToMoveFile; use League\Flysystem\UnableToProvideChecksum; use League\Flysystem\UnableToRetrieveMetadata; +use League\Flysystem\UnableToWriteFile; use League\Flysystem\Visibility; use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNAdapter; use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNClient; use PlatformCommunity\Flysystem\BunnyCDN\BunnyCDNRegion; use PlatformCommunity\Flysystem\BunnyCDN\Util; +use PlatformCommunity\Flysystem\BunnyCDN\WriteBatchFile; use Throwable; if (\is_file(__DIR__.'/ClientDI.php')) { @@ -54,7 +59,34 @@ private static function bunnyCDNClient(): BunnyCDNClient return new BunnyCDNClient($storage_zone, $api_key, $region ?? BunnyCDNRegion::DEFAULT); } - return new MockClient('test_storage_zone', '123'); + $mockedClient = new MockClient('test_storage_zone', '123'); + + $mockedClient->guzzleClient = new Guzzle([ + 'handler' => function (Request $request) use ($mockedClient) { + $path = $request->getUri()->getPath(); + $method = $request->getMethod(); + + if ($method === 'PUT' && $path === 'destination.txt') { + $mockedClient->filesystem->write('destination.txt', 'text'); + + return new Response(200); + } + + if ($method === 'PUT' && $path === 'destination2.txt') { + $mockedClient->filesystem->write('destination2.txt', 'text2'); + + return new Response(200); + } + + if ($method === 'PUT' && \in_array($path, ['failing.txt', 'failing2.txt'])) { + throw new \RuntimeException('Failed to write file'); + } + + throw new \RuntimeException('Unexpected request: '.$method.' '.$path); + }, + ]); + + return $mockedClient; } public static function createFilesystemAdapter(): FilesystemAdapter @@ -474,11 +506,71 @@ public function test_regression_issue_39() $this->runScenario(function () { $adapter = $this->adapter(); - $this->adapter()->write('test.json', json_encode(['test' => 123]), new Config([])); + $adapter->write('test.json', json_encode(['test' => 123]), new Config([])); $response = $adapter->read('/test.json'); $this->assertIsString($response); }); } + + public function test_write_batch(): void + { + $this->runScenario(function () { + $firstTmpFile = \tmpfile(); + fwrite($firstTmpFile, 'text'); + $firstTmpPath = stream_get_meta_data($firstTmpFile)['uri']; + + $secondTmpFile = \tmpfile(); + fwrite($secondTmpFile, 'text2'); + $secondTmpPath = stream_get_meta_data($secondTmpFile)['uri']; + + $adapter = $this->adapter(); + + $adapter->writeBatch( + [ + new WriteBatchFile($firstTmpPath, 'destination.txt'), + new WriteBatchFile($secondTmpPath, 'destination2.txt'), + ], + new Config() + ); + + \fclose($firstTmpFile); + \fclose($secondTmpFile); + + $this->assertSame('text', $adapter->read('destination.txt')); + $this->assertSame('text2', $adapter->read('destination2.txt')); + }); + } + + public function test_failing_write_batch(): void + { + if (self::$isLive) { + $this->markTestSkipped('This test is not applicable in live mode'); + } + + $this->runScenario(function () { + $firstTmpFile = \tmpfile(); + fwrite($firstTmpFile, 'text'); + $firstTmpPath = stream_get_meta_data($firstTmpFile)['uri']; + + $secondTmpFile = \tmpfile(); + fwrite($secondTmpFile, 'text2'); + $secondTmpPath = stream_get_meta_data($firstTmpFile)['uri']; + + $adapter = $this->adapter(); + + $this->expectException(UnableToWriteFile::class); + $adapter->writeBatch( + [ + new WriteBatchFile($firstTmpPath, 'failing.txt'), + new WriteBatchFile($secondTmpPath, 'failing2.txt'), + ], + new Config() + ); + + \fclose($firstTmpFile); + \fclose($secondTmpFile); + }); + } } diff --git a/tests/MockClient.php b/tests/MockClient.php index bdd7216..d237a1e 100644 --- a/tests/MockClient.php +++ b/tests/MockClient.php @@ -3,6 +3,8 @@ namespace PlatformCommunity\Flysystem\BunnyCDN\Tests; use Faker\Factory; +use GuzzleHttp\Client as Guzzle; +use GuzzleHttp\Psr7\Request; use League\Flysystem\FileAttributes; use League\Flysystem\Filesystem; use League\Flysystem\FilesystemException; @@ -20,6 +22,8 @@ class MockClient extends BunnyCDNClient */ public Filesystem $filesystem; + public Guzzle $guzzleClient; + public function __construct(string $storage_zone_name, string $api_key, string $region = '') { parent::__construct($storage_zone_name, $api_key, $region); @@ -41,8 +45,10 @@ public function list(string $path): array 'Checksum' => hash('sha256', $this->filesystem->read($file->path())), ]); })->toArray(); - } catch (FilesystemException $exception) { + } catch (FilesystemException) { } + + return []; } /** @@ -81,8 +87,10 @@ public function upload(string $path, $contents): array 'HttpCode' => 201, 'Message' => 'File uploaded.', ]; - } catch (FilesystemException $exception) { + } catch (FilesystemException) { } + + return []; } /** @@ -98,8 +106,10 @@ public function make_directory(string $path): array 'HttpCode' => 201, 'Message' => 'Directory created.', ]; - } catch (FilesystemException $exception) { + } catch (FilesystemException) { } + + return []; } /** @@ -121,9 +131,9 @@ public function delete(string $path): array 'HttpCode' => 200, 'Message' => 'File deleted successfuly.', // ಠ_ಠ Spelling @bunny.net ]; - } catch (NotFoundException $e) { + } catch (NotFoundException) { throw new NotFoundException('404'); - } catch (\Exception $e) { + } catch (\Exception) { return [ 'HttpCode' => 404, 'Message' => 'File deleted successfuly.', // ಠ_ಠ Spelling @bunny.net @@ -131,6 +141,11 @@ public function delete(string $path): array } } + public function getUploadRequest(string $path, $contents): Request + { + return new Request('PUT', $path, [], $contents); + } + private static function example_file($path = '/directory/test.png', $storage_zone = 'storage_zone', $override = []): array { ['file' => $file, 'dir' => $dir] = Util::splitPathIntoDirectoryAndFile($path);