From ec58093164025317f491a5d6cf85757be6f348e7 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 17 Mar 2026 10:56:42 +0000 Subject: [PATCH] 542: improve architecture parsing and more test cases --- phpstan-baseline.neon | 12 ----- src/Platform/TargetPhp/PhpBinaryPath.php | 23 +++++++- src/Platform/TargetPlatform.php | 30 ++--------- .../Platform/TargetPhp/PhpBinaryPathTest.php | 52 +++++++++++++++---- test/unit/Platform/TargetPlatformTest.php | 2 +- .../SelfManage/Update/ReleaseIsNewerTest.php | 2 +- 6 files changed, 71 insertions(+), 50 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 775159ab..24d60e92 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -312,18 +312,6 @@ parameters: count: 1 path: src/Platform/TargetPhp/PhpizePath.php - - - message: '#^Call to function array_key_exists\(\) with 2 and array\{non\-falsy\-string, string, non\-falsy\-string\} will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Platform/TargetPlatform.php - - - - message: '#^Strict comparison using \!\=\= between non\-falsy\-string and '''' will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: src/Platform/TargetPlatform.php - - message: '#^Dead catch \- Php\\Pie\\SelfManage\\Verify\\GithubCliNotAvailable is never thrown in the try block\.$#' identifier: catch.neverThrown diff --git a/src/Platform/TargetPhp/PhpBinaryPath.php b/src/Platform/TargetPhp/PhpBinaryPath.php index 63682c7b..d9ce3c93 100644 --- a/src/Platform/TargetPhp/PhpBinaryPath.php +++ b/src/Platform/TargetPhp/PhpBinaryPath.php @@ -327,6 +327,20 @@ public function majorMinorVersion(): string public function machineType(): Architecture { + /** + * On Windows, this will be x32 or x64; should not be used on other platforms + * + * Based on xdebug.org wizard, copyright Derick Rethans, used under MIT licence + * + * @link https://github.com/xdebug/xdebug.org/blob/aff649f2c3ca303ad471e6ed9dd29c0db16d3e22/src/XdebugVersion.php#L186-L190 + */ + if ( + $this->operatingSystem() === OperatingSystem::Windows + && preg_match('/Architecture([ =>\t]*)(x[0-9]*)/', $this->phpinfo(), $m) + ) { + return Architecture::parseArchitecture($m[2]); + } + $phpMachineType = self::cleanWarningAndDeprecationsFromOutput(Process::run([ $this->phpBinaryPath, '-r', @@ -334,7 +348,14 @@ public function machineType(): Architecture ])); Assert::stringNotEmpty($phpMachineType, 'Could not determine PHP machine type'); - return Architecture::parseArchitecture($phpMachineType); + $unameArchitecture = Architecture::parseArchitecture($phpMachineType); + + // If we're not on ARM, a more reliable way of determining 32-bit/64-bit is to use PHP_INT_SIZE + if ($unameArchitecture !== Architecture::arm64) { + return $this->phpIntSize() === 4 ? Architecture::x86 : Architecture::x86_64; + } + + return $unameArchitecture; } public function phpIntSize(): int diff --git a/src/Platform/TargetPlatform.php b/src/Platform/TargetPlatform.php index c6cf5f62..bd43ea1c 100644 --- a/src/Platform/TargetPlatform.php +++ b/src/Platform/TargetPlatform.php @@ -7,7 +7,6 @@ use Fidry\CpuCoreCounter\CpuCoreCounter; use Php\Pie\Platform\TargetPhp\PhpBinaryPath; -use function array_key_exists; use function explode; use function function_exists; use function posix_getuid; @@ -39,31 +38,10 @@ public static function isRunningAsRoot(): bool public static function fromPhpBinaryPath(PhpBinaryPath $phpBinaryPath, int|null $makeParallelJobs): self { - $os = $phpBinaryPath->operatingSystem(); - $osFamily = $phpBinaryPath->operatingSystemFamily(); - - $phpinfo = $phpBinaryPath->phpinfo(); - - $architecture = $phpBinaryPath->machineType(); - - // If we're not on ARM, a more reliable way of determining 32-bit/64-bit is to use PHP_INT_SIZE - if ($architecture !== Architecture::arm64) { - $architecture = $phpBinaryPath->phpIntSize() === 4 ? Architecture::x86 : Architecture::x86_64; - } - - /** - * Based on xdebug.org wizard, copyright Derick Rethans, used under MIT licence - * - * @link https://github.com/xdebug/xdebug.org/blob/aff649f2c3ca303ad471e6ed9dd29c0db16d3e22/src/XdebugVersion.php#L186-L190 - */ - if ( - preg_match('/Architecture([ =>\t]*)(x[0-9]*)/', $phpinfo, $m) - && array_key_exists(2, $m) - && $m[2] !== '' - ) { - $architecture = Architecture::parseArchitecture($m[2]); - } - + $os = $phpBinaryPath->operatingSystem(); + $osFamily = $phpBinaryPath->operatingSystemFamily(); + $phpinfo = $phpBinaryPath->phpinfo(); + $architecture = $phpBinaryPath->machineType(); $windowsCompiler = null; $threadSafety = ThreadSafetyMode::ThreadSafe; diff --git a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php index 3bf6b74e..8df5b6ec 100644 --- a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php +++ b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php @@ -29,22 +29,25 @@ use function array_map; use function array_unique; use function assert; +use function chmod; use function count; use function defined; use function dirname; use function file_exists; +use function file_put_contents; use function get_loaded_extensions; use function ini_get; use function is_dir; use function is_executable; use function mkdir; -use function php_uname; use function phpversion; use function sprintf; use function strtolower; use function sys_get_temp_dir; +use function tempnam; use function trim; use function uniqid; +use function unlink; use const DIRECTORY_SEPARATOR; use const PHP_INT_SIZE; @@ -240,15 +243,46 @@ public function testMajorMinorVersion(): void ); } - public function testMachineType(): void + /** @return list */ + public static function machineTypeProvider(): array { - $myUnameMachineType = php_uname('m'); - assert($myUnameMachineType !== ''); - self::assertSame( - Architecture::parseArchitecture($myUnameMachineType), - PhpBinaryPath::fromCurrentProcess() - ->machineType(), - ); + return [ + // x86 (32-bit) + [OperatingSystem::Windows, 'Architecture => x32', '', 4, Architecture::x86], + [OperatingSystem::NonWindows, 'Architecture => x86', 'x86', 4, Architecture::x86], + [OperatingSystem::NonWindows, '', 'x86', 4, Architecture::x86], + + // x86_64 (64-bit) + [OperatingSystem::Windows, 'Architecture => x64', 'AMD64', 8, Architecture::x86_64], + [OperatingSystem::Windows, 'Architecture => x64', '', 8, Architecture::x86_64], + [OperatingSystem::NonWindows, 'Architecture => x86_64', 'x86_64', 8, Architecture::x86_64], + [OperatingSystem::NonWindows, '', 'x86_64', 8, Architecture::x86_64], + + // arm64 + [OperatingSystem::NonWindows, 'Architecture => arm64', 'arm64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, '', 'arm64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, 'Architecture => aarch64', 'aarch64', 8, Architecture::arm64], + [OperatingSystem::NonWindows, '', 'aarch64', 8, Architecture::arm64], + ]; + } + + #[RequiresOperatingSystemFamily('Linux')] + #[DataProvider('machineTypeProvider')] + public function testMachineType(OperatingSystem $os, string $phpinfo, string $uname, int $phpIntSize, Architecture $expectedArchitecture): void + { + $tmpSh = tempnam(sys_get_temp_dir(), uniqid('pie_machine_type_test')); + file_put_contents($tmpSh, "#!/usr/bin/env bash\necho \"" . $uname . "\";\n"); + chmod($tmpSh, 0777); + + $phpBinary = $this->createPartialMock(PhpBinaryPath::class, ['operatingSystem', 'phpinfo', 'phpIntSize']); + (new ReflectionMethod($phpBinary, '__construct'))->invoke($phpBinary, $tmpSh, null); + + $phpBinary->method('operatingSystem')->willReturn($os); + $phpBinary->method('phpinfo')->willReturn($phpinfo); + $phpBinary->method('phpIntSize')->willReturn($phpIntSize); + + self::assertEquals($expectedArchitecture, $phpBinary->machineType()); + unlink($tmpSh); } public function testPhpIntSize(): void diff --git a/test/unit/Platform/TargetPlatformTest.php b/test/unit/Platform/TargetPlatformTest.php index 3753181a..bca8ceb7 100644 --- a/test/unit/Platform/TargetPlatformTest.php +++ b/test/unit/Platform/TargetPlatformTest.php @@ -28,7 +28,7 @@ public function testWindowsPlatformFromPhpInfo(): void ->willReturn(OperatingSystemFamily::Windows); $phpBinaryPath->expects(self::any()) ->method('machineType') - ->willReturn(Architecture::x86); + ->willReturn(Architecture::x86_64); $phpBinaryPath->expects(self::any()) ->method('phpinfo') ->willReturn(<<<'TEXT' diff --git a/test/unit/SelfManage/Update/ReleaseIsNewerTest.php b/test/unit/SelfManage/Update/ReleaseIsNewerTest.php index ca44fea8..a1e06f8e 100644 --- a/test/unit/SelfManage/Update/ReleaseIsNewerTest.php +++ b/test/unit/SelfManage/Update/ReleaseIsNewerTest.php @@ -15,7 +15,7 @@ final class ReleaseIsNewerTest extends TestCase { /** @return array */ - public function provider(): array + public static function provider(): array { return [ 'stable-oldstable-to-newstable' => [Channel::Stable, '1.0.0', '1.0.1', true],