first commit
This commit is contained in:
90
tests/Media/MediaServiceDuplicateAfterInsertRaceTest.php
Normal file
90
tests/Media/MediaServiceDuplicateAfterInsertRaceTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Media;
|
||||
|
||||
use App\Media\Media;
|
||||
use App\Media\MediaRepositoryInterface;
|
||||
use App\Media\MediaService;
|
||||
use PDOException;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
final class MediaServiceDuplicateAfterInsertRaceTest extends TestCase
|
||||
{
|
||||
/** @var MediaRepositoryInterface&MockObject */
|
||||
private MediaRepositoryInterface $repository;
|
||||
|
||||
private string $uploadDir;
|
||||
|
||||
private MediaService $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->repository = $this->createMock(MediaRepositoryInterface::class);
|
||||
$this->uploadDir = sys_get_temp_dir() . '/slim_media_race_' . uniqid('', true);
|
||||
@mkdir($this->uploadDir, 0755, true);
|
||||
|
||||
$this->service = new MediaService($this->repository, $this->uploadDir, '/media', 5 * 1024 * 1024);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
foreach (glob($this->uploadDir . '/*') ?: [] as $file) {
|
||||
@unlink($file);
|
||||
}
|
||||
@rmdir($this->uploadDir);
|
||||
}
|
||||
|
||||
public function testReturnsDuplicateUrlWhenInsertRaceOccurs(): void
|
||||
{
|
||||
$tmpFile = $this->createMinimalGif();
|
||||
$hash = hash_file('sha256', $tmpFile);
|
||||
self::assertNotFalse($hash);
|
||||
|
||||
$duplicate = new Media(77, 'existing.gif', '/media/existing.gif', $hash, 1);
|
||||
|
||||
$this->repository->expects($this->exactly(2))
|
||||
->method('findByHash')
|
||||
->with($hash)
|
||||
->willReturnOnConsecutiveCalls(null, $duplicate);
|
||||
|
||||
$this->repository->expects($this->once())
|
||||
->method('create')
|
||||
->willThrowException(new PDOException('duplicate key'));
|
||||
|
||||
$file = $this->makeUploadedFileFromPath($tmpFile, filesize($tmpFile));
|
||||
$url = $this->service->store($file, 1);
|
||||
|
||||
self::assertSame('/media/existing.gif', $url);
|
||||
self::assertCount(0, glob($this->uploadDir . '/*') ?: []);
|
||||
|
||||
@unlink($tmpFile);
|
||||
}
|
||||
|
||||
private function makeUploadedFileFromPath(string $path, int $size): UploadedFileInterface
|
||||
{
|
||||
$stream = $this->createMock(StreamInterface::class);
|
||||
$stream->method('getMetadata')->with('uri')->willReturn($path);
|
||||
|
||||
$file = $this->createMock(UploadedFileInterface::class);
|
||||
$file->method('getSize')->willReturn($size);
|
||||
$file->method('getStream')->willReturn($stream);
|
||||
$file->method('moveTo')->willReturnCallback(static function (string $dest) use ($path): void {
|
||||
copy($path, $dest);
|
||||
});
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function createMinimalGif(): string
|
||||
{
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'slim_gif_');
|
||||
self::assertNotFalse($tmpFile);
|
||||
file_put_contents($tmpFile, base64_decode('R0lGODdhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='));
|
||||
|
||||
return $tmpFile;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user