parent
852c70198b
commit
ac795c9f8a
6 changed files with 299 additions and 48 deletions
@ -0,0 +1,175 @@ |
||||
<?php |
||||
|
||||
namespace TypePhp\Tests\Build; |
||||
|
||||
use PHPUnit\Framework\TestCase; |
||||
use TypePhp\CompilerTest; |
||||
use TypePhp\Exception\TestError; |
||||
use TypePhp\Platform\Linux; |
||||
use TypePhp\Platform\Macos; |
||||
use TypePhp\Platform\PlatformBase; |
||||
use TypePhp\Platform\Windows; |
||||
|
||||
final class NativeBuildConfigurationTest extends TestCase |
||||
{ |
||||
private array $temporaryDirectories = []; |
||||
|
||||
protected function tearDown(): void |
||||
{ |
||||
parent::tearDown(); |
||||
foreach ($this->temporaryDirectories as $dir) { |
||||
$this->removeDirectory($dir); |
||||
} |
||||
$this->temporaryDirectories = []; |
||||
} |
||||
|
||||
/** |
||||
* 三个平台都必须能解析到对应名称的 phpx 库: |
||||
* Windows -> phpx.lib,Linux -> libphpx.so,macOS -> libphpx.dylib。 |
||||
*/ |
||||
public function testFindPhpxLibraryResolvesAllPlatforms(): void |
||||
{ |
||||
$cases = [ |
||||
'Linux' => [new Linux(), '/lib/libphpx.so'], |
||||
'macOS' => [new Macos(), '/lib/libphpx.dylib'], |
||||
'Windows' => [new Windows(), '\\lib\\phpx.lib'], |
||||
]; |
||||
|
||||
foreach ($cases as $label => [$platform, $relativeLib]) { |
||||
$phpxDir = $this->temporaryDirectory('phpx-' . strtolower($label)); |
||||
// getPhpxDir() 会通过 realpath 规范化(macOS 上 /var -> /private/var), |
||||
// 这里按同样的规范化路径创建库文件,保证断言一致。 |
||||
$phpxDir = realpath($phpxDir) ?: $phpxDir; |
||||
if ($platform instanceof Windows) { |
||||
mkdir($phpxDir . '\\lib', 0777, true); |
||||
$libPath = $phpxDir . '\\lib\\phpx.lib'; |
||||
touch($libPath); |
||||
} else { |
||||
$libPath = $phpxDir . $relativeLib; |
||||
mkdir(dirname($libPath), 0777, true); |
||||
touch($libPath); |
||||
} |
||||
|
||||
$restore = $this->withPhpxHome($phpxDir); |
||||
try { |
||||
$compiler = $this->newCompiler($platform); |
||||
$this->assertSame( |
||||
$libPath, |
||||
$compiler->findPhpxLibraryForTest(), |
||||
"{$label} 平台 phpx 库解析失败" |
||||
); |
||||
} finally { |
||||
$restore(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public function testValidatePhpxLibraryFailsFastWhenMissing(): void |
||||
{ |
||||
$phpxDir = $this->temporaryDirectory('phpx-missing'); |
||||
mkdir($phpxDir . '/lib', 0777, true); |
||||
|
||||
$restore = $this->withPhpxHome($phpxDir); |
||||
try { |
||||
$compiler = $this->newCompiler(new Macos()); |
||||
$this->expectException(TestError::class); |
||||
$this->expectExceptionMessage('phpx library not found'); |
||||
$compiler->validatePhpxLibraryForTest(); |
||||
} finally { |
||||
$restore(); |
||||
} |
||||
} |
||||
|
||||
public function testPhpxDirPrefersPhpxHomeOverVendor(): void |
||||
{ |
||||
$root = $this->temporaryDirectory('phpx-priority-root'); |
||||
mkdir($root . '/vendor/swoole/phpx', 0777, true); |
||||
$phpxHome = $this->temporaryDirectory('phpx-home'); |
||||
$phpxHome = realpath($phpxHome) ?: $phpxHome; |
||||
|
||||
$compiler = new class($root) extends CompilerTest { |
||||
public function __construct(string $rootPath) |
||||
{ |
||||
parent::__construct($rootPath); |
||||
$this->forTest = true; |
||||
} |
||||
|
||||
public function getPhpxDirForTest(): string |
||||
{ |
||||
return $this->getPhpxDir(); |
||||
} |
||||
}; |
||||
|
||||
$restore = $this->withPhpxHome($phpxHome); |
||||
try { |
||||
$this->assertSame($phpxHome, $compiler->getPhpxDirForTest()); |
||||
} finally { |
||||
$restore(); |
||||
} |
||||
} |
||||
|
||||
private function newCompiler(PlatformBase $platform): object |
||||
{ |
||||
$root = $this->temporaryDirectory('phpx-compiler-root'); |
||||
$compiler = new class($root) extends CompilerTest { |
||||
public function __construct(string $rootPath) |
||||
{ |
||||
parent::__construct($rootPath); |
||||
$this->forTest = true; |
||||
} |
||||
|
||||
public function withPlatform(PlatformBase $platform): self |
||||
{ |
||||
$this->platform = $platform; |
||||
return $this; |
||||
} |
||||
|
||||
public function findPhpxLibraryForTest(): ?string |
||||
{ |
||||
return $this->findPhpxLibrary(); |
||||
} |
||||
|
||||
public function validatePhpxLibraryForTest(): void |
||||
{ |
||||
$this->validatePhpxLibrary(); |
||||
} |
||||
}; |
||||
|
||||
return $compiler->withPlatform($platform); |
||||
} |
||||
|
||||
private function withPhpxHome(string $dir): callable |
||||
{ |
||||
$previous = getenv('PHPX_HOME'); |
||||
putenv('PHPX_HOME=' . $dir); |
||||
return static function () use ($previous): void { |
||||
if ($previous === false) { |
||||
putenv('PHPX_HOME'); |
||||
} else { |
||||
putenv('PHPX_HOME=' . $previous); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
private function temporaryDirectory(string $prefix): string |
||||
{ |
||||
$dir = sys_get_temp_dir() . '/' . $prefix . '_' . uniqid(); |
||||
mkdir($dir, 0777, true); |
||||
$this->temporaryDirectories[] = $dir; |
||||
return $dir; |
||||
} |
||||
|
||||
private function removeDirectory(string $dir): void |
||||
{ |
||||
if (!is_dir($dir)) { |
||||
return; |
||||
} |
||||
|
||||
$files = array_diff(scandir($dir), ['.', '..']); |
||||
foreach ($files as $file) { |
||||
$path = $dir . DIRECTORY_SEPARATOR . $file; |
||||
is_dir($path) ? $this->removeDirectory($path) : unlink($path); |
||||
} |
||||
rmdir($dir); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue