Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple JIT test improvements #12406

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
35c0183
Add PHPSeclib, Psalm and PHPStan to nightly tests
danog Oct 12, 2023
2813621
Add JIT check
danog Oct 22, 2023
7d0f061
Add infection to testsuite, repeat JIT tests
danog Oct 22, 2023
d8997a5
Repeat windows JIT tests too
danog Oct 22, 2023
ce13272
Merge
danog Oct 22, 2023
7c02611
Merge remote-tracking branch 'origin/master' into test_repeat
danog Oct 23, 2023
5c12927
Fix
danog Nov 11, 2023
1d97fcf
Add phpseclib, Psalm, PHPStan nightly tests
danog Nov 15, 2023
a6dc102
Merge remote-tracking branch 'origin/PHP-8.2' into tests_psalm_phpsta…
danog Feb 1, 2024
1bb6a1b
Add infection to matrix
danog Feb 1, 2024
12b8a63
Bump config
danog Feb 1, 2024
8f64c9e
Cleanup
danog Feb 1, 2024
596d31a
Merge remote-tracking branch 'origin/master' into test_repeat
danog Feb 1, 2024
590323c
Parallelize nightly tests and add more community libraries
danog Feb 2, 2024
2727ab9
Bump
danog Feb 2, 2024
d3eca11
Bump
danog Feb 2, 2024
9626b10
Bump
danog Feb 2, 2024
826e8a3
Fix
danog Feb 2, 2024
3c9739d
Fix
danog Feb 2, 2024
c853e32
Fix
danog Feb 2, 2024
64ad873
Add --enable-rtld-deepbind configure flag
danog Nov 13, 2024
3bdc28b
Bump
danog Nov 13, 2024
066184f
Merge remote-tracking branch 'php/master' into tests_psalm_phpstan_ph…
danog Nov 13, 2024
030d1a4
Bump
danog Nov 13, 2024
40d5421
Bump
danog Nov 13, 2024
632cf7e
Merge branch 'tests_psalm_phpstan_phpseclib'
danog Nov 13, 2024
7ac12be
Merge branch 'test_repeat'
danog Nov 13, 2024
495749a
Bump
danog Nov 13, 2024
103fd82
bump
danog Nov 13, 2024
1f40a4c
Improve tests
danog Nov 15, 2024
5fe1dc1
Merge remote-tracking branch 'php/master'
danog Nov 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/test-linux/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ runs:
export SKIP_IO_CAPTURE_TESTS=1
export STACK_LIMIT_DEFAULTS_CHECK=1
sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
${{ inputs.jitType == 'disable' && '' || '--repeat 2' }} \
-d opcache.jit=${{ inputs.jitType }} \
-d opcache.protect_memory=1 \
-d opcache.jit_buffer_size=64M \
Expand Down
1 change: 1 addition & 0 deletions .github/actions/test-macos/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ runs:
export CI_NO_IPV6=1
export STACK_LIMIT_DEFAULTS_CHECK=1
sapi/cli/php run-tests.php -P -q ${{ inputs.runTestsParameters }} \
${{ inputs.jitType == 'disable' && '' || '--repeat 2' }} \
-d opcache.jit=${{ inputs.jitType }} \
-d opcache.protect_memory=1 \
-d opcache.jit_buffer_size=64M \
Expand Down
30 changes: 30 additions & 0 deletions .github/jit_check.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

register_shutdown_function(function () {
$status = opcache_get_status(false);
var_dump($status);

if ($status["memory_usage"]["free_memory"] < 10*1024*1024) {
fwrite(STDERR, "Not enough free opcache memory!".PHP_EOL);
}
if ($status["interned_strings_usage"]["free_memory"] < 1*1024*1024) {
fwrite(STDERR, "Not enough free interned strings memory!".PHP_EOL);
}
if ($status["jit"]["buffer_free"] < 10*1024*1024) {
fwrite(STDERR, "Not enough free JIT memory!".PHP_EOL);
}
if (!$status["jit"]["on"]) {
fwrite(STDERR, "JIT is not enabled!".PHP_EOL);
}

unset($status);
while (gc_collect_cycles());
});

$argc--;
array_shift($argv);

$_SERVER['argc']--;
array_shift($_SERVER['argv']);

require $argv[0];
266 changes: 266 additions & 0 deletions .github/nightly.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
<?php

putenv("ASAN_OPTIONS=exitcode=139");
putenv("SYMFONY_DEPRECATIONS_HELPER=max[total]=999");
putenv("PHPSECLIB_ALLOW_JIT=1");

function printMutex(string $result): void {
flock(STDOUT, LOCK_EX);
fwrite(STDOUT, $result.PHP_EOL);
flock(STDOUT, LOCK_UN);
}

function e(string $cmd, string $extra = ''): string {
exec("bash -c ".escapeshellarg("$cmd 2>&1"), $result, $code);
$result = implode("\n", $result);
if ($code) {
printMutex("An error occurred while executing $cmd (status $code, extra info $extra): $result");
die(1);
}
return $result;
}

$parallel = (int) ($argv[1] ?? 0);
$parallel = $parallel ?: ((int)`nproc`);
$parallel = $parallel ?: 8;

$repos = [];

$repos["phpunit"] = [
"https://github.com/sebastianbergmann/phpunit.git",
"main",
null,
["./phpunit"],
1
];

$repos["infection"] = [
"https://github.com/infection/infection",
"master",
null,
["vendor/bin/phpunit"],
1
];

$repos["wordpress"] = [
"https://github.com/WordPress/wordpress-develop.git",
"",
function (): void {
$f = file_get_contents('wp-tests-config-sample.php');
$f = str_replace('youremptytestdbnamehere', 'test', $f);
$f = str_replace('yourusernamehere', 'root', $f);
$f = str_replace('yourpasswordhere', 'root', $f);
file_put_contents('wp-tests-config.php', $f);
},
["vendor/bin/phpunit"],
1
];

foreach (['amp', 'cache', 'dns', 'file', 'http', 'parallel', 'parser', 'pipeline', 'process', 'serialization', 'socket', 'sync', 'websocket-client', 'websocket-server'] as $repo) {
$repos["amphp-$repo"] = ["https://github.com/amphp/$repo.git", "", null, ["vendor/bin/phpunit"], 1];
}

$repos["laravel"] = [
"https://github.com/laravel/framework.git",
"master",
function (): void {
$c = file_get_contents("tests/Filesystem/FilesystemTest.php");
$c = str_replace("public function testSharedGet()", "#[\\PHPUnit\\Framework\\Attributes\\Group('skip')]\n public function testSharedGet()", $c);
file_put_contents("tests/Filesystem/FilesystemTest.php", $c);
},
["vendor/bin/phpunit", "--exclude-group", "skip"],
1
];

foreach (['async', 'cache', 'child-process', 'datagram', 'dns', 'event-loop', 'promise', 'promise-stream', 'promise-timer', 'stream'] as $repo) {
$repos["reactphp-$repo"] = ["https://github.com/reactphp/$repo.git", "", null, ["vendor/bin/phpunit"], 1];
}

$repos["revolt"] = ["https://github.com/revoltphp/event-loop.git", "", null, ["vendor/bin/phpunit"], 2];

$repos["symfony"] = [
"https://github.com/symfony/symfony.git",
"",
function (): void {
e("php ./phpunit install");

// Test causes a heap-buffer-overflow but I cannot reproduce it locally...
$c = file_get_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php");
$c = str_replace("public function testSanitizeDeepNestedString()", "/** @group skip */\n public function testSanitizeDeepNestedString()", $c);
file_put_contents("src/Symfony/Component/HtmlSanitizer/Tests/HtmlSanitizerCustomTest.php", $c);
// Buggy FFI test in Symfony, see https://github.com/symfony/symfony/issues/47668
$c = file_get_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php");
$c = str_replace("*/\n public function testCastNonTrailingCharPointer()", "* @group skip\n */\n public function testCastNonTrailingCharPointer()", $c);
file_put_contents("src/Symfony/Component/VarDumper/Tests/Caster/FFICasterTest.php", $c);
},
function (): iterable {
$it = new RecursiveDirectoryIterator("src/Symfony");
/** @var SplFileInfo $file */
foreach(new RecursiveIteratorIterator($it) as $file) {
if ($file->getBasename() == 'phpunit.xml.dist') {
yield [
getcwd()."/phpunit",
dirname($file->getRealPath()),
"--exclude-group",
"tty,benchmark,intl-data,transient",
"--exclude-group",
"skip"
];
}
}
},
1
];

$finalStatus = 0;
$parentPids = [];

$waitOne = function () use (&$finalStatus, &$parentPids): void {
$res = pcntl_wait($status);
if ($res === -1) {
printMutex("An error occurred while waiting with waitpid!");
$finalStatus = $finalStatus ?: 1;
return;
}
if (!isset($parentPids[$res])) {
printMutex("Unknown PID $res returned!");
$finalStatus = $finalStatus ?: 1;
return;
}
$desc = $parentPids[$res];
unset($parentPids[$res]);
if (pcntl_wifexited($status)) {
$status = pcntl_wexitstatus($status);
printMutex("Child task $desc exited with status $status");
if ($status !== 0) {
$finalStatus = $status;
}
} elseif (pcntl_wifstopped($status)) {
$status = pcntl_wstopsig($status);
printMutex("Child task $desc stopped by signal $status");
$finalStatus = 1;
} elseif (pcntl_wifsignaled($status)) {
$status = pcntl_wtermsig($status);
printMutex("Child task $desc terminated by signal $status");
$finalStatus = 1;
}
};

$waitAll = function () use ($waitOne, &$parentPids): void {
while ($parentPids) {
$waitOne();
}
};

printMutex("Cloning repos...");

foreach ($repos as $dir => [$repo, $branch, $prepare, $command, $repeat]) {
$pid = pcntl_fork();
if ($pid) {
$parentPids[$pid] = "clone $dir";
continue;
}

chdir(sys_get_temp_dir());
if ($branch) {
$branch = "--branch $branch";
}
e("git clone $repo $branch --depth 1 $dir");

exit(0);
}

$waitAll();

printMutex("Done cloning repos!");

printMutex("Preparing repos (max $parallel processes)...");
foreach ($repos as $dir => [$repo, $branch, $prepare, $command, $repeat]) {
chdir(sys_get_temp_dir()."/$dir");
$rev = e("git rev-parse HEAD", $dir);

$pid = pcntl_fork();
if ($pid) {
$parentPids[$pid] = "prepare $dir ($rev)";
if (count($parentPids) >= $parallel) {
$waitOne();
}
continue;
}

e("composer i --ignore-platform-reqs", $dir);
if ($prepare) {
$prepare();
}

exit(0);
}
$waitAll();

printMutex("Done preparing repos!");

printMutex("Running tests (max $parallel processes)...");
foreach ($repos as $dir => [$repo, $branch, $prepare, $command, $repeat]) {
chdir(sys_get_temp_dir()."/$dir");
$rev = e("git rev-parse HEAD", $dir);

if ($command instanceof Closure) {
$commands = iterator_to_array($command());
} else {
$commands = [$command];
}

foreach ($commands as $idx => $cmd) {
$cmd = array_merge([
PHP_BINARY,
'--repeat',
$repeat,
'-f',
__DIR__.'/jit_check.php',
], $cmd);

$cmdStr = implode(" ", $cmd);

$pid = pcntl_fork();
if ($pid) {
$parentPids[$pid] = "test $dir ($rev): $cmdStr";
if (count($parentPids) >= $parallel) {
$waitOne();
}
continue;
}

$output = sys_get_temp_dir()."/out_{$dir}_$idx.txt";

$p = proc_open($cmd, [
["pipe", "r"],
["file", $output, "a"],
["file", $output, "a"]
], $pipes, sys_get_temp_dir()."/$dir");

if ($p === false) {
printMutex("Failure starting $cmdStr");
exit(1);
}

$final = 0;
$status = proc_close($p);
if ($status !== 0) {
if ($status > 128) {
$final = $status;
}
printMutex(
"$dir ($rev): $cmdStr terminated with status $status:".PHP_EOL
.file_get_contents($output).PHP_EOL
);
}

exit($final);
}
}

$waitAll();

printMutex("All done!");

die($finalStatus);
2 changes: 1 addition & 1 deletion .github/scripts/windows/test_task.bat
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ set OPENSSL_CONF=
rem set SSLEAY_CONF=

rem prepare for OPcache
if "%OPCACHE%" equ "1" set OPCACHE_OPTS=-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=64M -d opcache.jit=tracing
if "%OPCACHE%" equ "1" set OPCACHE_OPTS=-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.protect_memory=1 -d opcache.jit_buffer_size=64M -d opcache.jit_max_root_traces=100000 -d opcache.jit_max_side_traces=100000 -d opcache.jit_max_exit_counters=100000 -d opcache.jit=tracing --repeat 2

rem prepare for enchant
mkdir %~d0\usr\local\lib\enchant-2
Expand Down
Loading
Loading