diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a6f2dc9..d81e94a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,7 +6,6 @@ cacheDirectory=".phpunit.cache" executionOrder="depends,defects" requireCoverageMetadata="true" - beStrictAboutCoverageMetadata="true" beStrictAboutOutputDuringTests="true" failOnRisky="true" failOnWarning="true"> diff --git a/src/DependencyResolver/Package.php b/src/DependencyResolver/Package.php index 7fabaeb..d6c1151 100644 --- a/src/DependencyResolver/Package.php +++ b/src/DependencyResolver/Package.php @@ -16,7 +16,7 @@ final class Package public const TYPE_PHP_MODULE = 'php-ext'; public const TYPE_ZEND_EXTENSION = 'php-ext-zend'; - private function __construct( + public function __construct( public readonly string $name, public readonly string $version, public readonly string|null $downloadUrl, diff --git a/src/DependencyResolver/UnableToResolveRequirement.php b/src/DependencyResolver/UnableToResolveRequirement.php index 3ab76ad..1815eef 100644 --- a/src/DependencyResolver/UnableToResolveRequirement.php +++ b/src/DependencyResolver/UnableToResolveRequirement.php @@ -23,10 +23,10 @@ class UnableToResolveRequirement extends RuntimeException public static function toPhpOrZendExtension(PackageInterface $locatedComposerPackage, string $requiredPackageName, string|null $requiredVersion): self { return new self(sprintf( - 'Package %s was not of type php-ext or php-ext-zend (requested %s%s)', + 'Package %s was not of type php-ext or php-ext-zend (requested %s%s).', $locatedComposerPackage->getName(), $requiredPackageName, - $requiredVersion !== null ? sprintf(' for version %s.', $requiredVersion) : '.', + $requiredVersion !== null ? sprintf(' for version %s', $requiredVersion) : '', )); } } diff --git a/test/assets/test-zip.zip b/test/assets/test-zip.zip new file mode 100644 index 0000000..451d018 Binary files /dev/null and b/test/assets/test-zip.zip differ diff --git a/test/unit/DependencyResolver/UnableToResolveRequirementTest.php b/test/unit/DependencyResolver/UnableToResolveRequirementTest.php new file mode 100644 index 0000000..e79b3ae --- /dev/null +++ b/test/unit/DependencyResolver/UnableToResolveRequirementTest.php @@ -0,0 +1,48 @@ +createMock(PackageInterface::class); + $package->method('getName')->willReturn('baz/bat'); + + $exception = UnableToResolveRequirement::toPhpOrZendExtension($package, 'foo/bar', '^1.2'); + + self::assertSame('Package baz/bat was not of type php-ext or php-ext-zend (requested foo/bar for version ^1.2).', $exception->getMessage()); + } + + public function testToPhpOrZendExtensionWithoutVersion(): void + { + $package = $this->createMock(PackageInterface::class); + $package->method('getName')->willReturn('baz/bat'); + + $exception = UnableToResolveRequirement::toPhpOrZendExtension($package, 'foo/bar', null); + + self::assertSame('Package baz/bat was not of type php-ext or php-ext-zend (requested foo/bar).', $exception->getMessage()); + } + + public function testFromRequirementWithVersion(): void + { + $exception = UnableToResolveRequirement::fromRequirement('foo/bar', '^1.2'); + + self::assertSame('Unable to find an installable package foo/bar for version ^1.2.', $exception->getMessage()); + } + + public function testFromRequirementWithoutVersion(): void + { + $exception = UnableToResolveRequirement::fromRequirement('foo/bar', null); + + self::assertSame('Unable to find an installable package foo/bar.', $exception->getMessage()); + } +} diff --git a/test/unit/Downloading/AddAuthenticationHeaderTest.php b/test/unit/Downloading/AddAuthenticationHeaderTest.php new file mode 100644 index 0000000..f24b0ee --- /dev/null +++ b/test/unit/Downloading/AddAuthenticationHeaderTest.php @@ -0,0 +1,56 @@ +createMock(AuthHelper::class); + $authHelper->expects(self::once()) + ->method('addAuthenticationHeader') + ->with([], 'github.com', $downloadUrl) + ->willReturn(['Authorization: whatever ABC123']); + + $requestWithAuthHeader = (new AddAuthenticationHeader())->withAuthHeaderFromComposer( + $request, + new Package('foo/bar', '1.2.3', $downloadUrl), + $authHelper, + ); + + self::assertSame('whatever ABC123', $requestWithAuthHeader->getHeaderLine('Authorization')); + } + + public function testExceptionIsThrownWhenPackageDoesNotHaveDownloadUrl(): void + { + $downloadUrl = 'http://test-uri/' . uniqid('path', true); + + $request = new Request('GET', $downloadUrl); + + $authHelper = $this->createMock(AuthHelper::class); + + $addAuthenticationHeader = new AddAuthenticationHeader(); + $package = new Package('foo/bar', '1.2.3', null); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The package foo/bar does not have a download URL'); + $addAuthenticationHeader->withAuthHeaderFromComposer($request, $package, $authHelper); + } +} diff --git a/test/unit/Downloading/DownloadZipTest.php b/test/unit/Downloading/DownloadZipTest.php new file mode 100644 index 0000000..a7e0473 --- /dev/null +++ b/test/unit/Downloading/DownloadZipTest.php @@ -0,0 +1,54 @@ + 'application/octet-stream', + 'Content-length' => (string) (strlen($fakeZipContent)), + ], + $fakeZipContent, + ), + ]); + + $guzzleMockClient = new Client(['handler' => HandlerStack::create($mockHandler)]); + + $localPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('pie_test_', true); + mkdir($localPath, 0777, true); + $downloadedZipFile = (new DownloadZip($guzzleMockClient)) + ->downloadZipAndReturnLocalPath( + new Request('GET', 'http://test-uri/'), + $localPath, + ); + + self::assertSame($fakeZipContent, file_get_contents($downloadedZipFile)); + } +} diff --git a/test/unit/Downloading/DownloadedPackageTest.php b/test/unit/Downloading/DownloadedPackageTest.php new file mode 100644 index 0000000..2d029c8 --- /dev/null +++ b/test/unit/Downloading/DownloadedPackageTest.php @@ -0,0 +1,28 @@ +extractedSourcePath); + self::assertSame($package, $downloadedPackage->package); + } +} diff --git a/test/unit/Downloading/ExtractZipTest.php b/test/unit/Downloading/ExtractZipTest.php new file mode 100644 index 0000000..f6d7149 --- /dev/null +++ b/test/unit/Downloading/ExtractZipTest.php @@ -0,0 +1,48 @@ +to(__DIR__ . '/../../assets/test-zip.zip', $localPath); + + // The test-zip.zip should contain a deterministic file content for this: + self::assertSame('Hello there! Test UUID b925c59b-3e6f-4e45-8029-19431df18de4', file_get_contents($extractedPath . DIRECTORY_SEPARATOR . 'test-file.txt')); + } + + public function testFailureToExtractZipWithInvalidZip(): void + { + $localPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('pie_test_DO_NOT_EXIST_', true); + + $extr = new ExtractZip(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage(sprintf('Could not open ZIP [%d]: %s', ZipArchive::ER_NOZIP, __FILE__)); + $extr->to(__FILE__, $localPath); + } +} diff --git a/test/unit/TargetPhp/PhpBinaryPathTest.php b/test/unit/TargetPhp/PhpBinaryPathTest.php index a18bdb5..212a195 100644 --- a/test/unit/TargetPhp/PhpBinaryPathTest.php +++ b/test/unit/TargetPhp/PhpBinaryPathTest.php @@ -7,8 +7,12 @@ namespace Php\PieUnitTest\TargetPhp; use Php\Pie\TargetPhp\PhpBinaryPath; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; +use Symfony\Component\Process\Process; +use function file_exists; +use function is_executable; use function sprintf; +use function trim; use const PHP_MAJOR_VERSION; use const PHP_MINOR_VERSION; @@ -24,4 +28,26 @@ final class PhpBinaryPathTest extends TestCase PhpBinaryPath::fromCurrentProcess()->version(), ); } + + public function testFromPhpConfigExecutable(): void + { + $process = (new Process(['which', 'php-config'])); + $exitCode = $process->run(); + $phpConfigExecutable = trim($process->getOutput()); + + if ($exitCode !== 0 || ! file_exists($phpConfigExecutable) || ! is_executable($phpConfigExecutable)) { + self::markTestSkipped('Needs php-config in path to run this test'); + } + + $phpBinary = PhpBinaryPath::fromPhpConfigExecutable($phpConfigExecutable); + + // NOTE: this makes an assumption that the `php-config` in path is the same as the version being executed + // In most cases, this will be the cases (e.g. in CI, running locally), but if you're trying to test this and + // the versions are not matching, that's probably why. + // @todo improve this assertion in future, if it becomes problematic + self::assertSame( + sprintf('%s.%s.%s', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION), + $phpBinary->version(), + ); + } } diff --git a/test/unit/TargetPhp/ResolveTargetPhpToPlatformRepositoryTest.php b/test/unit/TargetPhp/ResolveTargetPhpToPlatformRepositoryTest.php new file mode 100644 index 0000000..70b80a7 --- /dev/null +++ b/test/unit/TargetPhp/ResolveTargetPhpToPlatformRepositoryTest.php @@ -0,0 +1,41 @@ +getPackages(), + static function (BasePackage $package): bool { + return $package->getPrettyName() === 'php'; + }, + ); + + self::assertCount(1, $phpPackages); + assert(count($phpPackages) > 0); + + $phpPackage = $phpPackages[array_key_first($phpPackages)]; + + self::assertSame($php->version(), $phpPackage->getPrettyVersion()); + } +}