Skip to content

Commit 153c4ab

Browse files
committed
Add tests for function/class declared in a file included repeatedly
1 parent 097c927 commit 153c4ab

8 files changed

+191
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
$className = AnonymousClassNameCache::get_class(fn () => new class() {
4+
public static function verify() {
5+
return 'ok';
6+
}
7+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
Repeated include must not increase memory - anonymous class
3+
--SKIPIF--
4+
<?php
5+
// TODO test should pass even without opcache, but fixes are needed
6+
// related bug tracker https://bugs.php.net/bug.php?id=76982
7+
if (!extension_loaded('Zend OPcache') || !opcache_get_status()['opcache_enabled']) {
8+
die('skip test currently requires opcache enabled');
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
// new anonymous class declared and included multiple times always has a new class name,
15+
// this test accounts for that and tests if an anonymous class declared in a closure
16+
// invoked once does not increase memory consumption
17+
18+
final class AnonymousClassNameCache
19+
{
20+
/** @var array<string, string> */
21+
private static $classNameByFxHash = [];
22+
23+
private function __construct()
24+
{
25+
}
26+
27+
public static function get_class(\Closure $createAnonymousClassFx): string
28+
{
29+
$fxRefl = new \ReflectionFunction($createAnonymousClassFx);
30+
$fxHash = $fxRefl->getFileName() . ':' . $fxRefl->getStartLine() . '-' . $fxRefl->getEndLine();
31+
32+
if (!isset(self::$classNameByFxHash[$fxHash])) {
33+
self::$classNameByFxHash[$fxHash] = get_class($createAnonymousClassFx());
34+
}
35+
36+
return self::$classNameByFxHash[$fxHash];
37+
}
38+
}
39+
40+
$classNamePrev = null;
41+
$m = -1;
42+
$mDiff = -1;
43+
$mPrev = 0;
44+
for ($i = 0; $i < (PHP_OS_FAMILY === 'Windows' ? 1_000 /* include is slow on Windows */ : 20_000); $i++) {
45+
require __DIR__ . '/anonymous_class.inc';
46+
if ($classNamePrev !== null && $className !== $classNamePrev) {
47+
echo 'Class name is different: ' . $className . ' vs ' . $classNamePrev . ' (' . $i . ' iteration)' . "\n";
48+
exit(1);
49+
}
50+
$classNamePrev = $className;
51+
assert($className::verify() === 'ok');
52+
$m = memory_get_usage();
53+
$mDiff = $m - $mPrev;
54+
if ($mPrev !== 0 && $mDiff !== 0) {
55+
echo 'Increased memory detected: ' . $mDiff . ' B (' . $i . ' iteration)' . "\n";
56+
exit(1);
57+
}
58+
$mPrev = $m;
59+
}
60+
echo 'done';
61+
62+
?>
63+
--EXPECT--
64+
done
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
$funcA = function () {
4+
return 'ok';
5+
};
6+
7+
$funcB = fn () => 'okB';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Repeated include must not increase memory - anonymous function
3+
--SKIPIF--
4+
<?php
5+
// TODO test should pass even without opcache, but fixes are needed
6+
// related bug tracker https://bugs.php.net/bug.php?id=76982
7+
if (!extension_loaded('Zend OPcache') || !opcache_get_status()['opcache_enabled']) {
8+
die('skip test currently requires opcache enabled');
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
$m = -1;
15+
$mDiff = -1;
16+
$mPrev = 0;
17+
for ($i = 0; $i < (PHP_OS_FAMILY === 'Windows' ? 1_000 /* include is slow on Windows */ : 20_000); $i++) {
18+
require __DIR__ . '/anonymous_function.inc';
19+
assert($funcA() === 'ok');
20+
assert($funcB() === 'okB');
21+
$m = memory_get_usage();
22+
$mDiff = $m - $mPrev;
23+
if ($mPrev !== 0 && $mDiff !== 0) {
24+
echo 'Increased memory detected: ' . $mDiff . ' B (' . $i . ' iteration)' . "\n";
25+
exit(1);
26+
}
27+
$mPrev = $m;
28+
}
29+
echo 'done';
30+
31+
?>
32+
--EXPECT--
33+
done
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
if (!class_exists(Test::class)) {
4+
class Test {
5+
public static function verify() {
6+
return 'ok';
7+
}
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Repeated include must not increase memory - class in if condition
3+
--SKIPIF--
4+
<?php
5+
// TODO test should pass even without opcache, but fixes are needed
6+
// related bug tracker https://bugs.php.net/bug.php?id=76982
7+
if (!extension_loaded('Zend OPcache') || !opcache_get_status()['opcache_enabled']) {
8+
die('skip test currently requires opcache enabled');
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
$m = -1;
15+
$mDiff = -1;
16+
$mPrev = 0;
17+
for ($i = 0; $i < (PHP_OS_FAMILY === 'Windows' ? 1_000 /* include is slow on Windows */ : 20_000); $i++) {
18+
require __DIR__ . '/class_in_if.inc';
19+
assert(Test::verify() === 'ok');
20+
$m = memory_get_usage();
21+
$mDiff = $m - $mPrev;
22+
if ($mPrev !== 0 && $mDiff !== 0) {
23+
echo 'Increased memory detected: ' . $mDiff . ' B (' . $i . ' iteration)' . "\n";
24+
exit(1);
25+
}
26+
$mPrev = $m;
27+
}
28+
echo 'done';
29+
30+
?>
31+
--EXPECT--
32+
done
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
if (!function_exists('test')) {
4+
function test() {
5+
return 'ok';
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Repeated include must not increase memory - function in if condition
3+
--SKIPIF--
4+
<?php
5+
// TODO test should pass even without opcache, but fixes are needed
6+
// related bug tracker https://bugs.php.net/bug.php?id=76982
7+
if (!extension_loaded('Zend OPcache') || !opcache_get_status()['opcache_enabled']) {
8+
die('skip test currently requires opcache enabled');
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
$m = -1;
15+
$mDiff = -1;
16+
$mPrev = 0;
17+
for ($i = 0; $i < (PHP_OS_FAMILY === 'Windows' ? 1_000 /* include is slow on Windows */ : 20_000); $i++) {
18+
require __DIR__ . '/function_in_if.inc';
19+
assert(test() === 'ok');
20+
$m = memory_get_usage();
21+
$mDiff = $m - $mPrev;
22+
if ($mPrev !== 0 && $mDiff !== 0) {
23+
echo 'Increased memory detected: ' . $mDiff . ' B (' . $i . ' iteration)' . "\n";
24+
exit(1);
25+
}
26+
$mPrev = $m;
27+
}
28+
echo 'done';
29+
30+
?>
31+
--EXPECT--
32+
done

0 commit comments

Comments
 (0)