From 3933c2bbd5ee7757480c03793f4943d3190ee31f Mon Sep 17 00:00:00 2001 From: tienvx Date: Wed, 17 Apr 2024 10:38:45 +0700 Subject: [PATCH] refactor(2.0): Add ExtraDownloadsRepository --- .../Repository/ExtraDownloadsRepository.php | 144 +++++++++++ .../ExtraDownloadsRepositoryTest.php | 234 ++++++++++++++++++ 2 files changed, 378 insertions(+) create mode 100644 src/Composer/Repository/ExtraDownloadsRepository.php create mode 100644 tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php diff --git a/src/Composer/Repository/ExtraDownloadsRepository.php b/src/Composer/Repository/ExtraDownloadsRepository.php new file mode 100644 index 0000000..b642ced --- /dev/null +++ b/src/Composer/Repository/ExtraDownloadsRepository.php @@ -0,0 +1,144 @@ +initialize(); + } + + public function addPackage(PackageInterface $package): void + { + if ($package instanceof ExtraDownloadInterface) { + $this->extraDownloads[$package->getName()] = $package->getTrackingChecksum(); + } + } + + public function removePackage(PackageInterface $package): void + { + if ($package instanceof ExtraDownloadInterface) { + unset($this->extraDownloads[$package->getName()]); + } + } + + public function hasPackage(PackageInterface $package): bool + { + if (!$package instanceof ExtraDownloadInterface) { + return false; + } + $name = $package->getName(); + if (!isset($this->extraDownloads[$name])) { + return false; + } + + return $this->extraDownloads[$name] === $package->getTrackingChecksum(); + } + + protected function initialize(): void + { + $this->extraDownloads = []; + + if (!$this->file->exists()) { + return; + } + + try { + $packages = $this->file->read(); + + if (!\is_array($packages)) { + throw new \UnexpectedValueException('Could not parse package list from the repository'); + } + } catch (\Exception $e) { + throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.$e::class.'] '.$e->getMessage()); + } + + foreach ($packages as $name => $trackingChecksum) { + $this->extraDownloads[$name] = $trackingChecksum; + } + } + + public function reload(): void + { + $this->initialize(); + } + + public function isFresh(): bool + { + return !$this->file->exists(); + } + + public function write(bool $devMode, InstallationManager $installationManager): void + { + $this->file->write($this->extraDownloads); + } + + public function getCanonicalPackages(): array + { + return []; + } + + public function getDevPackageNames(): array + { + return []; + } + + public function setDevPackageNames(array $devPackageNames): void + { + } + + public function count(): int + { + return 0; + } + + public function getRepoName(): string + { + return 'installed extra downloads'; + } + + public function getDevMode(): ?bool + { + return null; + } + + public function findPackage(string $name, $constraint): ?PackageInterface + { + return null; + } + + public function findPackages(string $name, $constraint = null): array + { + return []; + } + + public function getPackages(): array + { + return []; + } + + public function getProviders(string $packageName): array + { + return []; + } + + public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = []): array + { + return []; + } + + public function search(string $query, int $mode = 0, ?string $type = null): array + { + return []; + } +} diff --git a/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php b/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php new file mode 100644 index 0000000..15dc994 --- /dev/null +++ b/tests/Unit/Composer/Repository/ExtraDownloadsRepositoryTest.php @@ -0,0 +1,234 @@ +fs = new FileSystem(); + $this->package = $this->createMock(PackageInterface::class); + $this->extraDownload = $this->createMock(ExtraDownloadInterface::class); + $this->repository = new ExtraDownloadsRepository(new JsonFile($this->fs->path($this->path))); + } + + protected function tearDown(): void + { + $this->fs = null; + } + + public function testAddPackage(): void + { + $this->repository->addPackage($this->package); + $this->assertExtraDownloads([]); + } + + public function testAddExtraDownload(): void + { + $this->extraDownload + ->expects($this->once()) + ->method('getName') + ->willReturn($this->name); + $this->extraDownload + ->expects($this->once()) + ->method('getTrackingChecksum') + ->willReturn($this->trackingChecksum); + $this->repository->addPackage($this->extraDownload); + $this->assertExtraDownloads([ + $this->name => $this->trackingChecksum, + ]); + } + + public function testRemovePackage(): void + { + $this->repository->removePackage($this->package); + $this->assertExtraDownloads([]); + } + + public function testRemoveExtraDownload(): void + { + $this->extraDownload + ->expects($this->exactly(2)) + ->method('getName') + ->willReturn($this->name); + $this->extraDownload + ->expects($this->once()) + ->method('getTrackingChecksum') + ->willReturn($this->trackingChecksum); + $this->repository->addPackage($this->extraDownload); + $this->assertExtraDownloads([ + $this->name => $this->trackingChecksum, + ]); + $this->repository->removePackage($this->extraDownload); + $this->assertExtraDownloads([]); + } + + public function testHasPackage(): void + { + $this->assertFalse($this->repository->hasPackage($this->package)); + } + + public function getHasExtraDownloadTests(): array + { + return [ + [false], + [true], + ]; + } + + /** + * @dataProvider getHasExtraDownloadTests + */ + public function testHasExtraDownload(bool $sameTrackingChecksum): void + { + $this->extraDownload + ->expects($this->exactly(3)) + ->method('getName') + ->willReturn($this->name); + $trackingChecksum = $sameTrackingChecksum ? $this->trackingChecksum : '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'; + $this->extraDownload + ->expects($this->exactly(2)) + ->method('getTrackingChecksum') + ->willReturnOnConsecutiveCalls($this->trackingChecksum, $trackingChecksum); + $this->assertFalse($this->repository->hasPackage($this->extraDownload)); + $this->repository->addPackage($this->extraDownload); + $this->assertSame($sameTrackingChecksum, $this->repository->hasPackage($this->extraDownload)); + } + + public function testReloadFromInvalidFile(): void + { + $this->fs->createDirectory(\dirname($this->path), true); + $this->fs->createFile($this->path, 'not json data'); + $this->expectException(InvalidRepositoryException::class); + $this->expectExceptionMessage('Invalid repository data in '.$this->fs->path($this->path).', packages could not be loaded: ['.ParsingException::class.'] "'.$this->fs->path($this->path).'" does not contain valid JSON'); + $this->repository->reload(); + } + + public function testReloadFromJsonString(): void + { + $this->fs->createDirectory(\dirname($this->path), true); + $this->fs->createFile($this->path, json_encode('some text')); + $this->expectException(InvalidRepositoryException::class); + $this->expectExceptionMessage('Invalid repository data in '.$this->fs->path($this->path).', packages could not be loaded: ['.\UnexpectedValueException::class.'] Could not parse package list from the repository'); + $this->repository->reload(); + } + + public function testReload(): void + { + $this->fs->createDirectory(\dirname($this->path), true); + $this->fs->createFile($this->path, json_encode([ + $this->name => $this->trackingChecksum, + ])); + $this->repository->reload(); + $this->assertExtraDownloads([ + $this->name => $this->trackingChecksum, + ]); + } + + public function testIsFresh(): void + { + $this->assertTrue($this->repository->isFresh()); + $this->fs->createDirectory(\dirname($this->path), true); + $this->fs->createFile($this->path, 'data'); + $this->assertFalse($this->repository->isFresh()); + } + + public function testWrite(): void + { + $this->extraDownload + ->expects($this->once()) + ->method('getName') + ->willReturn($this->name); + $this->extraDownload + ->expects($this->once()) + ->method('getTrackingChecksum') + ->willReturn($this->trackingChecksum); + $this->repository->addPackage($this->extraDownload); + $this->assertFileDoesNotExist($this->fs->path($this->path)); + $this->repository->write(true, $this->createMock(InstallationManager::class)); + $this->assertFileExists($this->fs->path($this->path)); + $this->assertJsonStringEqualsJsonString(json_encode([ + $this->name => $this->trackingChecksum, + ]), file_get_contents($this->fs->path($this->path))); + } + + private function assertExtraDownloads(array $extraDownloads): void + { + $reflection = new \ReflectionProperty($this->repository, 'extraDownloads'); + $this->assertSame($extraDownloads, $reflection->getValue($this->repository)); + } + + public function testGetCanonicalPackages(): void + { + $this->assertSame([], $this->repository->getCanonicalPackages()); + } + + public function testGetDevPackageNames(): void + { + $this->assertSame([], $this->repository->getDevPackageNames()); + } + + public function testCount(): void + { + $this->assertSame(0, $this->repository->count()); + } + + public function testGetRepoName(): void + { + $this->assertSame('installed extra downloads', $this->repository->getRepoName()); + } + + public function testGetDevMode(): void + { + $this->assertNull($this->repository->getDevMode()); + } + + public function testFindPackage(): void + { + $this->assertNull($this->repository->findPackage('any package name', 'any constraint')); + } + + public function testFindPackages(): void + { + $this->assertSame([], $this->repository->findPackages('any package name', 'any constraint')); + } + + public function testGetPackages(): void + { + $this->assertSame([], $this->repository->getPackages()); + } + + public function testGetProviders(): void + { + $this->assertSame([], $this->repository->getProviders('any package name')); + } + + public function testLoadPackages(): void + { + $this->assertSame([], $this->repository->loadPackages([], [], [], [])); + } + + public function testSearch(): void + { + $this->assertSame([], $this->repository->search('package query')); + } +}