*/ public static function phpPathProvider(): array { // data providers cannot return empty, even if the test is skipped if (Platform::isWindows()) { return ['skip' => ['skip']]; } $possiblePhpConfigPaths = array_filter( [ '/usr/bin/php-config', '/usr/bin/php-config8.5', '/usr/bin/php-config8.4', '/usr/bin/php-config8.3', '/usr/bin/php-config8.2', '/usr/bin/php-config8.1', '/usr/bin/php-config8.0', '/usr/bin/php-config7.4', '/usr/bin/php-config7.3', '/usr/bin/php-config7.2', ], static fn (string $phpConfigPath) => file_exists($phpConfigPath) && is_executable($phpConfigPath), ); return array_combine( $possiblePhpConfigPaths, array_map(static fn (string $phpConfigPath) => [$phpConfigPath], $possiblePhpConfigPaths), ); } #[DataProvider('phpPathProvider')] public function testUnixInstallCanInstallExtensionBuiltFromSource(string $phpConfig): void { $installRoot = '/tmp/' . uniqid('pie-test-install-root-', true); $oldInstallRoot = getenv('INSTALL_ROOT'); putenv('INSTALL_ROOT=' . $installRoot); assert($phpConfig !== ''); if (Platform::isWindows()) { self::markTestSkipped('Unix build test cannot be run on Windows'); } $output = new BufferIO(); $targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromPhpConfigExecutable($phpConfig), null, null); $extensionPath = $targetPlatform->phpBinaryPath->extensionPath($installRoot); $composerPackage = $this->createMock(CompletePackageInterface::class); $composerPackage ->method('getExtra') ->willReturn([self::COMPOSER_PACKAGE_EXTRA_KEY => DownloadUrlMethod::ComposerDefaultDownload->value]); $downloadedPackage = DownloadedPackage::fromPackageAndExtractedPath( new Package( $composerPackage, ExtensionType::PhpModule, ExtensionName::normaliseFromString('pie_test_ext'), 'pie_test_ext', '0.1.0', null, ), self::TEST_EXTENSION_PATH, ); $built = (new UnixBuild())->__invoke( $downloadedPackage, $targetPlatform, ['--enable-pie_test_ext'], $output, ); $installedSharedObject = (new UnixInstall(new SetupIniFile(new PickBestSetupIniApproach([]))))->__invoke( $downloadedPackage, $targetPlatform, $built, $output, true, ); $outputString = $output->getOutput(); self::assertStringContainsString('Install complete: ' . $extensionPath . '/pie_test_ext.so', $outputString); self::assertStringContainsString('You must now add "extension=pie_test_ext" to your php.ini', $outputString); self::assertSame($extensionPath . '/pie_test_ext.so', $installedSharedObject->filePath); self::assertFileExists($installedSharedObject->filePath); $rmCommand = ['rm', $installedSharedObject->filePath]; if (! is_writable($installedSharedObject->filePath)) { array_unshift($rmCommand, 'sudo'); } (new Process($rmCommand))->mustRun(); (new Process(['make', 'clean'], $downloadedPackage->extractedSourcePath))->mustRun(); (new Process(['phpize', '--clean'], $downloadedPackage->extractedSourcePath))->mustRun(); (new Filesystem())->remove($installRoot); putenv('INSTALL_ROOT=' . $oldInstallRoot); } #[DataProvider('phpPathProvider')] public function testUnixInstallCanInstallPrePackagedBinary(string $phpConfig): void { $installRoot = '/tmp/' . uniqid('pie-test-install-root-', true); $oldInstallRoot = getenv('INSTALL_ROOT'); putenv('INSTALL_ROOT=' . $installRoot); assert($phpConfig !== ''); if (Platform::isWindows()) { self::markTestSkipped('Unix build test cannot be run on Windows'); } $output = new BufferIO(); $targetPlatform = TargetPlatform::fromPhpBinaryPath(PhpBinaryPath::fromPhpConfigExecutable($phpConfig), null, null); $extensionPath = $installRoot . $targetPlatform->phpBinaryPath->extensionPath(); mkdir($extensionPath, 0777, true); // First build it (otherwise the test assets would need to have a binary for every test platform...) $composerPackage = $this->createMock(CompletePackageInterface::class); $composerPackage ->method('getExtra') ->willReturn([self::COMPOSER_PACKAGE_EXTRA_KEY => DownloadUrlMethod::ComposerDefaultDownload->value]); $built = (new UnixBuild())->__invoke( DownloadedPackage::fromPackageAndExtractedPath( new Package( $composerPackage, ExtensionType::PhpModule, ExtensionName::normaliseFromString('pie_test_ext'), 'pie_test_ext', '0.1.0', null, ), self::TEST_EXTENSION_PATH, ), $targetPlatform, ['--enable-pie_test_ext'], $output, ); /** * Move the built .so into a new path; this simulates a pre-packaged binary, which would not have Makefile etc * so this ensures we're not accidentally relying on any build mechanism (`make install` or otherwise) */ mkdir(self::TEST_PREBUILT_PATH, 0777, true); $prebuiltBinaryFilePath = self::TEST_PREBUILT_PATH . DIRECTORY_SEPARATOR . 'pie_test_ext.so'; rename($built->filePath, $prebuiltBinaryFilePath); $prebuiltBinaryFile = BinaryFile::fromFileWithSha256Checksum($prebuiltBinaryFilePath); $composerPackage = $this->createMock(CompletePackageInterface::class); $composerPackage ->method('getExtra') ->willReturn([self::COMPOSER_PACKAGE_EXTRA_KEY => DownloadUrlMethod::PrePackagedBinary->value]); $installedSharedObject = (new UnixInstall(new SetupIniFile(new PickBestSetupIniApproach([]))))->__invoke( DownloadedPackage::fromPackageAndExtractedPath( new Package( $composerPackage, ExtensionType::PhpModule, ExtensionName::normaliseFromString('pie_test_ext'), 'pie_test_ext', '0.1.0', null, ), self::TEST_PREBUILT_PATH, ), $targetPlatform, $prebuiltBinaryFile, $output, true, ); $outputString = $output->getOutput(); self::assertStringContainsString('Install complete: ' . $extensionPath . '/pie_test_ext.so', $outputString); self::assertStringContainsString('You must now add "extension=pie_test_ext" to your php.ini', $outputString); self::assertSame($extensionPath . '/pie_test_ext.so', $installedSharedObject->filePath); self::assertFileExists($installedSharedObject->filePath); $rmCommand = ['rm', $installedSharedObject->filePath]; if (! is_writable($installedSharedObject->filePath)) { array_unshift($rmCommand, 'sudo'); } (new Process($rmCommand))->mustRun(); (new Filesystem())->remove($prebuiltBinaryFile->filePath); (new Filesystem())->remove($installRoot); putenv('INSTALL_ROOT=' . $oldInstallRoot); } }