mirror of
https://github.com/php/pie.git
synced 2026-03-23 23:12:17 +01:00
Added a bunch of unit tests for existing code
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
cacheDirectory=".phpunit.cache"
|
||||
executionOrder="depends,defects"
|
||||
requireCoverageMetadata="true"
|
||||
beStrictAboutCoverageMetadata="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) : '',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
BIN
test/assets/test-zip.zip
Normal file
BIN
test/assets/test-zip.zip
Normal file
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\DependencyResolver;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Php\Pie\DependencyResolver\UnableToResolveRequirement;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(UnableToResolveRequirement::class)]
|
||||
final class UnableToResolveRequirementTest extends TestCase
|
||||
{
|
||||
public function testToPhpOrZendExtensionWithVersion(): void
|
||||
{
|
||||
$package = $this->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());
|
||||
}
|
||||
}
|
||||
56
test/unit/Downloading/AddAuthenticationHeaderTest.php
Normal file
56
test/unit/Downloading/AddAuthenticationHeaderTest.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\Downloading;
|
||||
|
||||
use Composer\Util\AuthHelper;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use Php\Pie\DependencyResolver\Package;
|
||||
use Php\Pie\Downloading\AddAuthenticationHeader;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
use function uniqid;
|
||||
|
||||
#[CoversClass(AddAuthenticationHeader::class)]
|
||||
final class AddAuthenticationHeaderTest extends TestCase
|
||||
{
|
||||
public function testAuthorizationHeaderIsAdded(): void
|
||||
{
|
||||
$downloadUrl = 'http://test-uri/' . uniqid('path', true);
|
||||
|
||||
$request = new Request('GET', $downloadUrl);
|
||||
|
||||
$authHelper = $this->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);
|
||||
}
|
||||
}
|
||||
54
test/unit/Downloading/DownloadZipTest.php
Normal file
54
test/unit/Downloading/DownloadZipTest.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\Downloading;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Handler\MockHandler;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Php\Pie\Downloading\DownloadZip;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function file_get_contents;
|
||||
use function mkdir;
|
||||
use function strlen;
|
||||
use function sys_get_temp_dir;
|
||||
use function uniqid;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
#[CoversClass(DownloadZip::class)]
|
||||
final class DownloadZipTest extends TestCase
|
||||
{
|
||||
public function testDownloadZipAndReturnLocalPath(): void
|
||||
{
|
||||
$fakeZipContent = uniqid('fakeZipContent', true);
|
||||
|
||||
$mockHandler = new MockHandler([
|
||||
new Response(
|
||||
200,
|
||||
[
|
||||
'Content-type' => '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));
|
||||
}
|
||||
}
|
||||
28
test/unit/Downloading/DownloadedPackageTest.php
Normal file
28
test/unit/Downloading/DownloadedPackageTest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\Downloading;
|
||||
|
||||
use Php\Pie\DependencyResolver\Package;
|
||||
use Php\Pie\Downloading\DownloadedPackage;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function uniqid;
|
||||
|
||||
#[CoversClass(DownloadedPackage::class)]
|
||||
final class DownloadedPackageTest extends TestCase
|
||||
{
|
||||
public function testFromPackageAndExtractedPath(): void
|
||||
{
|
||||
$package = new Package('foo/bar', '1.2.3', null);
|
||||
|
||||
$extractedSourcePath = uniqid('/path/to/downloaded/package', true);
|
||||
|
||||
$downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath($package, $extractedSourcePath);
|
||||
|
||||
self::assertSame($extractedSourcePath, $downloadedPackage->extractedSourcePath);
|
||||
self::assertSame($package, $downloadedPackage->package);
|
||||
}
|
||||
}
|
||||
48
test/unit/Downloading/ExtractZipTest.php
Normal file
48
test/unit/Downloading/ExtractZipTest.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\Downloading;
|
||||
|
||||
use Php\Pie\Downloading\ExtractZip;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
use ZipArchive;
|
||||
|
||||
use function file_get_contents;
|
||||
use function mkdir;
|
||||
use function sprintf;
|
||||
use function sys_get_temp_dir;
|
||||
use function uniqid;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/** @covers \Php\Pie\Downloading\ExtractZip */
|
||||
#[CoversClass(ExtractZip::class)]
|
||||
final class ExtractZipTest extends TestCase
|
||||
{
|
||||
public function testZipFileCanBeExtracted(): void
|
||||
{
|
||||
$localPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('pie_test_', true);
|
||||
mkdir($localPath, 0777, true);
|
||||
|
||||
$extr = new ExtractZip();
|
||||
|
||||
$extractedPath = $extr->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);
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\TargetPhp;
|
||||
|
||||
use Composer\Package\BasePackage;
|
||||
use Php\Pie\TargetPhp\PhpBinaryPath;
|
||||
use Php\Pie\TargetPhp\ResolveTargetPhpToPlatformRepository;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function array_filter;
|
||||
use function array_key_first;
|
||||
use function assert;
|
||||
use function count;
|
||||
|
||||
#[CoversClass(ResolveTargetPhpToPlatformRepository::class)]
|
||||
final class ResolveTargetPhpToPlatformRepositoryTest extends TestCase
|
||||
{
|
||||
public function testPlatformRepositoryIsReturned(): void
|
||||
{
|
||||
$php = PhpBinaryPath::fromCurrentProcess();
|
||||
|
||||
$platformRepository = (new ResolveTargetPhpToPlatformRepository())($php);
|
||||
|
||||
$phpPackages = array_filter(
|
||||
$platformRepository->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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user