first commit

This commit is contained in:
julien
2026-03-20 22:13:41 +01:00
commit 41f8b3afb4
323 changed files with 27222 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
namespace Tests\Media;
use Netig\Netslim\Media\Application\MediaApplicationService;
use Netig\Netslim\Media\Application\UseCase\DeleteMedia;
use Netig\Netslim\Media\Application\UseCase\StoreMedia;
use Netig\Netslim\Media\Contracts\MediaUsageReaderInterface;
use Netig\Netslim\Media\Domain\Entity\Media;
use Netig\Netslim\Media\Domain\Repository\MediaRepositoryInterface;
use Netig\Netslim\Media\Domain\Service\UploadedMediaInterface;
use Netig\Netslim\Media\Infrastructure\LocalMediaStorage;
use PDOException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
#[\PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations]
final class MediaServiceDuplicateAfterInsertRaceTest extends TestCase
{
/** @var MediaRepositoryInterface&MockObject */
private MediaRepositoryInterface $repository;
private MediaUsageReaderInterface $mediaUsageReader;
private string $uploadDir;
private MediaApplicationService $service;
protected function setUp(): void
{
$this->repository = $this->createMock(MediaRepositoryInterface::class);
$this->mediaUsageReader = $this->createMock(MediaUsageReaderInterface::class);
$this->uploadDir = sys_get_temp_dir() . '/slim_media_race_' . uniqid('', true);
@mkdir($this->uploadDir, 0755, true);
$storage = new LocalMediaStorage($this->uploadDir);
$this->service = new MediaApplicationService(
$this->repository,
$this->mediaUsageReader,
new StoreMedia($this->repository, $storage, '/media', 5 * 1024 * 1024),
new DeleteMedia($this->repository, $storage),
);
}
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('findByHashForUser')
->with($hash, 1)
->willReturnOnConsecutiveCalls(null, $duplicate);
$this->repository->expects($this->once())
->method('create')
->willThrowException(new PDOException('duplicate key'));
$file = $this->makeUploadedFileFromPath($tmpFile, filesize($tmpFile));
$media = $this->service->store($file, 1);
self::assertSame('/media/existing.gif', $media->getUrl());
self::assertSame(77, $media->getId());
self::assertCount(0, glob($this->uploadDir . '/*') ?: []);
@unlink($tmpFile);
}
private function makeUploadedFileFromPath(string $path, int $size): UploadedMediaInterface
{
$file = $this->createMock(UploadedMediaInterface::class);
$file->method('getSize')->willReturn($size);
$file->method('getTemporaryPath')->willReturn($path);
$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;
}
}