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.
144 lines
5.3 KiB
144 lines
5.3 KiB
<?php
|
|
/**
|
|
* This file is part of TypePHP(AOT).
|
|
*
|
|
* @link https://www.swoole.com/aot/
|
|
* @contact service@swoole.com
|
|
*/
|
|
|
|
namespace TypePhp\Tests\Build;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use TypePhp\Build\EmbeddedOpcodeGenerator;
|
|
|
|
/**
|
|
* @internal
|
|
* @coversNothing
|
|
*/
|
|
final class EmbeddedOpcodeGeneratorTest extends TestCase
|
|
{
|
|
private string $directory;
|
|
private string $buildDirectory;
|
|
private string $vendorFile;
|
|
private string $anonymousFile;
|
|
private string $ordinaryFile;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->directory = sys_get_temp_dir() . '/typephp-opcode-generator-' . bin2hex(random_bytes(6));
|
|
$this->buildDirectory = $this->directory . '/build';
|
|
$vendor = $this->directory . '/vendor';
|
|
mkdir($vendor . '/package', 0777, true);
|
|
file_put_contents($vendor . '/autoload.php', '<?php');
|
|
$this->vendorFile = $vendor . '/package/library.php';
|
|
$this->anonymousFile = $this->directory . '/anonymous.php';
|
|
$this->ordinaryFile = $this->directory . '/ordinary.php';
|
|
file_put_contents($this->vendorFile, '<?php return 1;');
|
|
file_put_contents($this->anonymousFile, '<?php return new class {};');
|
|
file_put_contents($this->ordinaryFile, '<?php return 2;');
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS),
|
|
\RecursiveIteratorIterator::CHILD_FIRST,
|
|
);
|
|
foreach ($iterator as $entry) {
|
|
$entry->isDir() ? rmdir($entry->getPathname()) : unlink($entry->getPathname());
|
|
}
|
|
rmdir($this->directory);
|
|
}
|
|
|
|
public function testPrepareReusesOnlyVendorAndAnonymousCaches(): void
|
|
{
|
|
$files = [$this->vendorFile, $this->anonymousFile, $this->ordinaryFile];
|
|
$generator = $this->generator();
|
|
$first = $generator->prepare($files, [$this->anonymousFile => '@typephp:anon:test']);
|
|
|
|
self::assertSame($files, $first->pendingFiles());
|
|
self::assertTrue($first->isVendorFile($this->vendorFile));
|
|
self::assertTrue($first->isAnonymousFile($this->anonymousFile));
|
|
self::assertNotSame(
|
|
$first->cacheDirectory($this->vendorFile),
|
|
$first->cacheDirectory($this->anonymousFile),
|
|
);
|
|
|
|
$vendorBlob = $this->writeBlob($first->cacheDirectory($this->vendorFile), $this->vendorFile, 'vendor');
|
|
$anonymousBlob = $this->writeBlob(
|
|
$first->cacheDirectory($this->anonymousFile),
|
|
$this->anonymousFile,
|
|
'anonymous',
|
|
);
|
|
$ordinaryBlob = $this->writeBlob(
|
|
$first->cacheDirectory($this->ordinaryFile),
|
|
$this->ordinaryFile,
|
|
'ordinary',
|
|
);
|
|
|
|
$second = $generator->prepare($files, [$this->anonymousFile => '@typephp:anon:test']);
|
|
|
|
self::assertSame([
|
|
$this->vendorFile => $vendorBlob,
|
|
$this->anonymousFile => $anonymousBlob,
|
|
], $second->cachedBlobs());
|
|
self::assertSame([$this->ordinaryFile], $second->pendingFiles());
|
|
self::assertSame(1, $second->vendorHits());
|
|
self::assertSame(1, $second->anonymousHits());
|
|
self::assertFileDoesNotExist($ordinaryBlob);
|
|
self::assertFileExists($this->buildDirectory . '/cache/opcache/compile-embedded-opcodes.php');
|
|
}
|
|
|
|
public function testForceClearsPersistentOpcodeCaches(): void
|
|
{
|
|
$files = [$this->vendorFile, $this->anonymousFile];
|
|
$anonymousKeys = [$this->anonymousFile => '@typephp:anon:test'];
|
|
$first = $this->generator()->prepare($files, $anonymousKeys);
|
|
$this->writeBlob($first->cacheDirectory($this->vendorFile), $this->vendorFile, 'vendor');
|
|
$this->writeBlob($first->cacheDirectory($this->anonymousFile), $this->anonymousFile, 'anonymous');
|
|
|
|
$forced = $this->generator(true)->prepare($files, $anonymousKeys);
|
|
|
|
self::assertSame([], $forced->cachedBlobs());
|
|
self::assertSame($files, $forced->pendingFiles());
|
|
}
|
|
|
|
public function testVendorSkipMarkerAvoidsRepeatedCompilation(): void
|
|
{
|
|
$generator = $this->generator();
|
|
$first = $generator->prepare([$this->vendorFile], []);
|
|
$cacheDirectory = $first->cacheDirectory($this->vendorFile);
|
|
mkdir($cacheDirectory, 0777, true);
|
|
file_put_contents(
|
|
$cacheDirectory . '/skipped-' . hash('sha256', $this->vendorFile) . '.txt',
|
|
$this->vendorFile,
|
|
);
|
|
|
|
$second = $generator->prepare([$this->vendorFile], []);
|
|
|
|
self::assertSame([], $second->pendingFiles());
|
|
self::assertSame(1, $second->skippedVendorCount());
|
|
self::assertSame(0, $second->vendorHits());
|
|
}
|
|
|
|
private function generator(bool $force = false): EmbeddedOpcodeGenerator
|
|
{
|
|
return new EmbeddedOpcodeGenerator(
|
|
$this->buildDirectory,
|
|
'app',
|
|
PHP_BINARY,
|
|
[],
|
|
PHP_VERSION,
|
|
'build-signature',
|
|
$force,
|
|
);
|
|
}
|
|
|
|
private function writeBlob(string $cacheDirectory, string $source, string $contents): string
|
|
{
|
|
$blob = $cacheDirectory . '/system' . $source . '.bin';
|
|
mkdir(dirname($blob), 0777, true);
|
|
file_put_contents($blob, $contents);
|
|
return $blob;
|
|
}
|
|
}
|
|
|