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.
141 lines
4.2 KiB
141 lines
4.2 KiB
<?php
|
|
|
|
namespace TypePhp\Tests;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use TypePhp\Backend\CompilerBackend;
|
|
use TypePhp\Build\NativeBuilder;
|
|
use TypePhp\CompilerTest;
|
|
|
|
class ParallelCompileTest extends TestCase
|
|
{
|
|
public function testWaitRetriesWhenInterrupted(): void
|
|
{
|
|
$compiler = new ScriptedWaitCompiler([
|
|
[-1, 0, PCNTL_EINTR],
|
|
[123, 0, 0],
|
|
]);
|
|
|
|
$this->assertSame([123, 0], $compiler->waitForTest());
|
|
$this->assertSame(2, $compiler->getWaitCallCount());
|
|
}
|
|
|
|
public function testWaitFailureOtherThanInterruptionThrows(): void
|
|
{
|
|
$compiler = new ScriptedWaitCompiler([
|
|
[-1, 0, PCNTL_ECHILD],
|
|
]);
|
|
|
|
$this->expectException(\RuntimeException::class);
|
|
$this->expectExceptionMessage('Failed to wait for compiler process');
|
|
$compiler->waitForTest();
|
|
}
|
|
|
|
public function testSignaledChildIsNotSuccessful(): void
|
|
{
|
|
$compiler = new ScriptedWaitCompiler([]);
|
|
|
|
$this->assertTrue($compiler->statusSucceeded(0));
|
|
$this->assertFalse($compiler->statusSucceeded(1 << 8));
|
|
$this->assertFalse($compiler->statusSucceeded(SIGTERM));
|
|
}
|
|
|
|
public function testForkFailureStillReapsRunningCompilerProcesses(): void
|
|
{
|
|
$compiler = new ScriptedWaitCompiler(
|
|
[[101, 0, 0]],
|
|
[101, -1]
|
|
);
|
|
|
|
try {
|
|
$compiler->compileInParallelForTest(['first.cc', 'second.cc', 'third.cc'], 2);
|
|
$this->fail('The fork failure should fail the parallel compilation');
|
|
} catch (\Exception $e) {
|
|
$this->assertStringContainsString('second.cc', $e->getMessage());
|
|
$this->assertStringContainsString('third.cc', $e->getMessage());
|
|
}
|
|
|
|
$this->assertSame(1, $compiler->getWaitCallCount());
|
|
}
|
|
|
|
public function testParallelDispatcherReportsEachCompletedTask(): void
|
|
{
|
|
$builder = new NativeBuilder($this->createMock(CompilerBackend::class));
|
|
$forkResults = [101, 102];
|
|
$waitResults = [[102, 0], [101, 1 << 8]];
|
|
$completed = [];
|
|
|
|
$result = $builder->dispatchParallel(
|
|
['first.cc', 'second.cc'],
|
|
2,
|
|
static fn(string $source): string => $source . '.o',
|
|
static function (): void {},
|
|
static function () use (&$forkResults): int {
|
|
return array_shift($forkResults);
|
|
},
|
|
static function () use (&$waitResults): array {
|
|
return array_shift($waitResults);
|
|
},
|
|
static fn(int $status): bool => $status === 0,
|
|
static function (string $source, string $object, int $status, bool $success, int $count) use (&$completed): void {
|
|
$completed[] = [$source, $object, $status, $success, $count];
|
|
},
|
|
);
|
|
|
|
$this->assertSame(['second.cc.o'], $result['objects']);
|
|
$this->assertSame(['first.cc'], $result['failures']);
|
|
$this->assertSame([
|
|
['second.cc', 'second.cc.o', 0, true, 1],
|
|
['first.cc', 'first.cc.o', 1 << 8, false, 2],
|
|
], $completed);
|
|
}
|
|
}
|
|
|
|
class ScriptedWaitCompiler extends CompilerTest
|
|
{
|
|
private int $waitCallCount = 0;
|
|
private int $lastWaitError = 0;
|
|
|
|
public function __construct(private array $waitResults, private array $forkResults = [])
|
|
{
|
|
parent::__construct(ROOT_PATH);
|
|
$this->noProgress = true;
|
|
}
|
|
|
|
protected function pcntlFork(): int
|
|
{
|
|
return array_shift($this->forkResults);
|
|
}
|
|
|
|
protected function pcntlWait(?int &$status): int
|
|
{
|
|
$this->waitCallCount++;
|
|
[$pid, $status, $this->lastWaitError] = array_shift($this->waitResults);
|
|
return $pid;
|
|
}
|
|
|
|
protected function pcntlLastError(): int
|
|
{
|
|
return $this->lastWaitError;
|
|
}
|
|
|
|
public function waitForTest(): array
|
|
{
|
|
return $this->waitForCompileChild();
|
|
}
|
|
|
|
public function statusSucceeded(int $status): bool
|
|
{
|
|
return $this->compileChildSucceeded($status);
|
|
}
|
|
|
|
public function getWaitCallCount(): int
|
|
{
|
|
return $this->waitCallCount;
|
|
}
|
|
|
|
public function compileInParallelForTest(array $sourceFiles, int $jobs): array
|
|
{
|
|
return $this->compileWithPcntl($sourceFiles, $jobs);
|
|
}
|
|
}
|
|
|