Skip to content

Commit

Permalink
Better fix for #4740
Browse files Browse the repository at this point in the history
Instead of replacing static loading with autoloading we now combine the best of both worlds. The PHAR now loads all sourcecode files bundled in it on startup (again), but assisted by an autoloader so that PHP's compiler can find code units that have not been loaded yet for perming method compatibility checks, for instance.
  • Loading branch information
sebastianbergmann committed Jul 26, 2021
1 parent d396026 commit becab3f
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ jobs:
java-version: 1.8

- name: Build unscoped PHAR for testing
run: ant unscoped-phar-snapshot generate-autoloader-for-test-fixture
run: ant unscoped-phar-snapshot

- name: Run regular tests with unscoped PHAR
run: ./build/artifacts/phpunit-snapshot.phar
Expand Down
4 changes: 2 additions & 2 deletions ChangeLog-8.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ All notable changes of the PHPUnit 8.5 release series are documented in this fil

## [8.5.19] - 2021-MM-DD

### Changed
### Fixed

* [#4740](https://github.com/sebastianbergmann/phpunit/issues/4740): The PHPUnit PHAR no longer imports all code units on startup
* [#4740](https://github.com/sebastianbergmann/phpunit/issues/4740): `phpunit.phar` does not work with PHP 8.1

## [8.5.18] - 2021-07-19

Expand Down
10 changes: 0 additions & 10 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@
<property name="prepare.done" value="true"/>
</target>

<target name="generate-autoloader-for-test-fixture" description="Generate autoloader for test fixture">
<exec executable="${basedir}/tools/phpab" taskname="phpab" failonerror="true">
<arg value="--output" />
<arg path="${basedir}/tests/autoload.php" />
<arg path="${basedir}/tests/_files" />
<arg path="${basedir}/tests/end-to-end/execution-order/_files" />
<arg path="${basedir}/tests/unit" />
</exec>
</target>

<target name="validate-composer-json" depends="clean" unless="validate-composer-json.done" description="Validate composer.json">
<exec executable="${basedir}/tools/composer" failonerror="true" taskname="composer">
<arg value="validate"/>
Expand Down
12 changes: 7 additions & 5 deletions build/templates/binary-phar-autoload.php.in
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,27 @@ unset($options);
define('__PHPUNIT_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', __FILE__));
define('__PHPUNIT_PHAR_ROOT__', 'phar://___PHAR___');

Phar::mapPhar('___PHAR___');

spl_autoload_register(
function ($class) {
static $classes = null;

if ($classes === null) {
$classes = [
___CLASSLIST___
];
$classes = [___CLASSLIST___];
}

if (isset($classes[$class])) {
require 'phar://___PHAR___' . $classes[$class];
require_once 'phar://___PHAR___' . $classes[$class];
}
},
___EXCEPTION___,
___PREPEND___
);

Phar::mapPhar('___PHAR___');
foreach ([___CLASSLIST___] as $file) {
require_once 'phar://___PHAR___' . $file;
}

if ($execute) {
if (isset($printManifest)) {
Expand Down
12 changes: 7 additions & 5 deletions build/templates/library-phar-autoload.php.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@
define('__PHPUNIT_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', __FILE__));
define('__PHPUNIT_PHAR_ROOT__', 'phar://___PHAR___');

Phar::mapPhar('___PHAR___');

spl_autoload_register(
function ($class) {
static $classes = null;

if ($classes === null) {
$classes = [
___CLASSLIST___
];
$classes = [___CLASSLIST___];
}

if (isset($classes[$class])) {
require 'phar://___PHAR___' . $classes[$class];
require_once 'phar://___PHAR___' . $classes[$class];
}
},
___EXCEPTION___,
___PREPEND___
);

Phar::mapPhar('___PHAR___');
foreach ([___CLASSLIST___] as $file) {
require_once 'phar://___PHAR___' . $file;
}

__HALT_COMPILER();
22 changes: 0 additions & 22 deletions src/TextUI/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
use function array_keys;
use function assert;
use function class_exists;
use function defined;
use function dirname;
use function explode;
use function extension_loaded;
use function fgets;
Expand All @@ -37,7 +35,6 @@
use function sprintf;
use function str_replace;
use function stream_resolve_include_path;
use function strpos;
use function strrpos;
use function substr;
use function trim;
Expand All @@ -48,7 +45,6 @@
use PharIo\Version\Version as PharIoVersion;
use PHPUnit\Framework\Exception;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Runner\StandardTestSuiteLoader;
Expand Down Expand Up @@ -1131,24 +1127,6 @@ protected function handleBootstrap(string $filename): void
} catch (Exception $e) {
$this->exitWithErrorMessage($e->getMessage());
}

if (!defined('__PHPUNIT_PHAR__') || !defined('__PHPUNIT_PHAR_ROOT__')) {
return;
}

$testCaseSource = (new ReflectionClass(TestCase::class))->getFileName();

if (strpos($testCaseSource, 'phar://' . __PHPUNIT_PHAR__) !== 0) {
$this->exitWithErrorMessage(
sprintf(
'Mixed installation detected, exiting.' . PHP_EOL . PHP_EOL .
'PHPUnit was invoked from %s.' . PHP_EOL .
'PHPUnit\'s code was loaded from %s.',
__PHPUNIT_PHAR__,
dirname($testCaseSource, 2)
)
);
}
}

protected function handleVersionCheck(): void
Expand Down
19 changes: 0 additions & 19 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,6 @@
*/
const TEST_FILES_PATH = __DIR__ . DIRECTORY_SEPARATOR . '_files' . DIRECTORY_SEPARATOR;

if (defined('__PHPUNIT_PHAR__')) {
if (!file_exists(__DIR__ . '/autoload.php')) {
print __DIR__ . '/autoload.php does not exist' . PHP_EOL;

exit(1);
}

require_once __DIR__ . '/autoload.php';

$jsonFile = realpath(__DIR__ . '/../composer.json');
$base = dirname($jsonFile);

foreach (json_decode(file_get_contents($jsonFile), true)['autoload-dev']['files'] as $file) {
require_once $base . DIRECTORY_SEPARATOR . $file;
}

return;
}

if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__) . '/vendor/autoload.php');
}
Expand Down

0 comments on commit becab3f

Please sign in to comment.