TypePHP 编译器 https://swoole.com/aot/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

241 lines
7.0 KiB

<?php
namespace TypePhp\Tests;
use PHPUnit\Framework\TestCase;
use TypePhp\Platform\PlatformFactory;
use TypePhp\Backend\CompilerFactory;
use TypePhp\Platform\Windows;
use TypePhp\Platform\Linux;
use TypePhp\Platform\Macos;
class FactoryTest extends TestCase
{
private string|false $originalPath;
private string $tmpDir;
protected function setUp(): void
{
parent::setUp();
$this->originalPath = getenv('PATH');
$this->tmpDir = sys_get_temp_dir() . '/compiler_factory_test_' . uniqid();
mkdir($this->tmpDir, 0777, true);
}
protected function tearDown(): void
{
parent::tearDown();
if ($this->originalPath === false) {
putenv('PATH');
} else {
putenv('PATH=' . $this->originalPath);
}
$this->removeDirectory($this->tmpDir);
}
private function removeDirectory(string $dir): void
{
if (!is_dir($dir)) {
return;
}
foreach (array_diff(scandir($dir), ['.', '..']) as $file) {
$path = $dir . DIRECTORY_SEPARATOR . $file;
is_dir($path) ? $this->removeDirectory($path) : unlink($path);
}
rmdir($dir);
}
private function createFakeExecutable(string $name): string
{
$path = $this->tmpDir . DIRECTORY_SEPARATOR . $name;
file_put_contents($path, "#!/bin/sh\nexit 0\n");
chmod($path, 0755);
return $path;
}
/**
* 测试 PlatformFactory 自动检测
*/
public function testPlatformFactoryAutoDetect(): void
{
$platform = PlatformFactory::create();
$this->assertNotNull($platform);
$this->assertTrue($platform->isCurrent());
}
/**
* 测试 PlatformFactory 平台判断
*/
public function testPlatformFactoryPlatformChecks(): void
{
// 至少有一个平台判断返回 true
$isAnyPlatform = PlatformFactory::isWindows() ||
PlatformFactory::isLinux() ||
PlatformFactory::isMacos();
$this->assertTrue($isAnyPlatform);
}
/**
* 测试 PlatformFactory 获取平台名称
*/
public function testPlatformFactoryGetName(): void
{
$name = PlatformFactory::getCurrentPlatformName();
$this->assertNotEmpty($name);
$this->assertIsString($name);
}
/**
* 测试 CompilerFactory 自动创建
*/
public function testCompilerFactoryAutoCreate(): void
{
$platform = PlatformFactory::create();
$compiler = CompilerFactory::create($platform);
$this->assertNotNull($compiler);
$this->assertEquals($platform, $compiler->getPlatform());
}
/**
* 测试 CompilerFactory 按名称创建 - MSVC
*/
public function testCompilerFactoryCreateMsvc(): void
{
$platform = new Windows();
$compiler = CompilerFactory::createByName('msvc', $platform);
$this->assertEquals('MSVC', $compiler->getName());
}
/**
* 测试 CompilerFactory 按名称创建 - GCC
*/
public function testCompilerFactoryCreateGcc(): void
{
$platform = new Linux();
$compiler = CompilerFactory::createByName('gcc', $platform);
$this->assertEquals('GCC', $compiler->getName());
}
/**
* 测试 CompilerFactory 按名称创建 - Clang
*/
public function testCompilerFactoryCreateClang(): void
{
$platform = new Linux();
$compiler = CompilerFactory::createByName('clang', $platform);
$this->assertEquals('Clang', $compiler->getName());
}
/**
* 测试 CompilerFactory 不支持的编译器
*/
public function testCompilerFactoryUnsupportedCompiler(): void
{
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Unsupported compiler');
$platform = new Linux();
CompilerFactory::createByName('unsupported', $platform);
}
/**
* 测试 CompilerFactory 自动检测
*/
public function testCompilerFactoryAutoDetect(): void
{
$result = CompilerFactory::autoDetect();
$this->assertArrayHasKey('platform', $result);
$this->assertArrayHasKey('compiler', $result);
$this->assertNotNull($result['platform']);
$this->assertNotNull($result['compiler']);
}
/**
* 测试 CompilerFactory 自动检测指定编译器
*/
public function testCompilerFactoryAutoDetectWithCompiler(): void
{
$result = CompilerFactory::autoDetect('gcc');
$this->assertNotNull($result['platform']);
$this->assertEquals('GCC', $result['compiler']->getName());
}
/**
* 测试平台与编译器匹配 - Windows + MSVC
*/
public function testPlatformCompilerMatchWindowsMsvc(): void
{
$platform = new Windows();
$compiler = CompilerFactory::create($platform);
$this->assertEquals('MSVC', $compiler->getName());
}
/**
* 测试平台与编译器匹配 - Linux + GCC
*/
public function testPlatformCompilerMatchLinuxGcc(): void
{
$platform = new Linux();
$compiler = CompilerFactory::create($platform);
$this->assertEquals('GCC', $compiler->getName());
}
/**
* 测试平台与编译器匹配 - macOS + Clang
*/
public function testPlatformCompilerMatchMacosClang(): void
{
$platform = new Macos();
$compiler = CompilerFactory::create($platform);
$this->assertEquals('Clang', $compiler->getName());
}
/**
* 测试编译器可以获取平台实例
*/
public function testCompilerGetPlatform(): void
{
$platform = new Windows();
$compiler = CompilerFactory::create($platform);
$retrievedPlatform = $compiler->getPlatform();
$this->assertSame($platform, $retrievedPlatform);
}
public function testCompilerCommandProgramParsesArgumentsAndQuotes(): void
{
$this->assertSame('clang++', CompilerFactory::getCommandProgram('clang++ -stdlib=libc++'));
$this->assertSame('/opt/llvm/bin/clang++', CompilerFactory::getCommandProgram('"/opt/llvm/bin/clang++" -O2'));
$this->assertSame('C:\\LLVM\\bin\\clang++.exe', CompilerFactory::getCommandProgram('"C:\\LLVM\\bin\\clang++.exe" -O2'));
$this->assertSame('', CompilerFactory::getCommandProgram(' '));
}
public function testCompilerCommandExecutableUsesPathAndIgnoresArguments(): void
{
$this->createFakeExecutable('fake-g++');
putenv('PATH=' . $this->tmpDir);
$this->assertTrue(CompilerFactory::isCommandExecutable('fake-g++ -std=c++20'));
$this->assertFalse(CompilerFactory::isCommandExecutable('missing-g++ -std=c++20'));
}
public function testCompilerCommandExecutableAcceptsQuotedAbsolutePath(): void
{
$compiler = $this->createFakeExecutable('quoted-clang++');
$this->assertTrue(CompilerFactory::isCommandExecutable('"' . $compiler . '" -O2'));
}
}