composer: Proxy bin file regression in 2.2.0

Seems to be a regression in 2.2.0 (since RC-1 sorry for not testing earlier 😞 ) which can be summarised as a reintroduction of this bug: https://github.com/composer/composer/issues/10246 which I think was caused by this PR: https://github.com/composer/composer/pull/10137

Reproduction repo: https://github.com/jenkoian/composer-issue-10387

My composer.json:

{
    "name": "jenkoian/composer-issue-10387",
    "description": "Reproducer for composer issue #10387",
    "license": "MIT",
    "require": {
        "php": "^7.3"
    },
    "require-dev": {
        "phpunit/phpunit": "^9"
    }
}

Output of composer diagnose:

Checking composer.json: OK
Checking platform settings: OK
Checking git settings: OK
Checking http connectivity to packagist: OK
Checking https connectivity to packagist: OK
Checking github.com oauth access: OK
Checking disk free space: OK
Checking pubkeys:
Tags Public Key Fingerprint: 57815BA2 7E54DC31 7ECC7CC5 573090D0  87719BA6 8F3BB723 4E5D42D0 84A14642
Dev Public Key Fingerprint: 4AC45767 E5EC2265 2F0C1167 CBBB8A2B  0C708369 153E328C AD90147D AFE50952
OK
Checking composer version: OK
Composer version: 2.2.0
PHP version: 7.4.27
PHP binary path: /opt/homebrew/Cellar/php@7.4/7.4.27/bin/php
OpenSSL version: OpenSSL 1.1.1m  14 Dec 2021
cURL version: 7.80.0 libz 1.2.11 ssl (SecureTransport) OpenSSL/1.1.1m
zip: extension present, unzip present, 7-Zip not available

When I run this command:

vendor/bin/phpunit

I get the following output:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.4.27
Configuration: /Users/ianjenkins/Code/composer-issue/phpunit.xml.dist

E                                                                   1 / 1 (100%)

Time: 00:00.043, Memory: 6.00 MB

There was 1 error:

1) ExampleTest::test_example
PHPUnit\Framework\Exception: PHP Fatal error:  strict_types declaration must be the very first statement in the script in /Users/ianjenkins/Code/composer-issue/vendor/phpunit/phpunit/phpunit on line 2
PHP Stack trace:
PHP   1. {main}() Standard input code:0

Fatal error: strict_types declaration must be the very first statement in the script in /Users/ianjenkins/Code/composer-issue/vendor/phpunit/phpunit/phpunit on line 2

Call Stack:
    0.0004     548552   1. {main}() Standard input code:0

/Users/ianjenkins/Code/composer-issue/vendor/phpunit/phpunit/phpunit:91

And I expected this to happen:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.039, Memory: 6.00 MB

OK (1 test, 1 assertion)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 39 (28 by maintainers)

Commits related to this issue

Most upvoted comments

2.2.3 is out now - let’s hope we can finally put this issue behind for good 😄

OK I think the workaround should work, feel free to give it a shot with composer self-update --snapshot. A proper fix in PHPUnit to handle our new proxies would be better in the long term, but that’ll take a bit longer to sort out.

It seems the global state collection/restore process of PHPUnit includes all included files again which includes phpunit itself then because we now include it instead of running it directly.

I got a “fix” here by adding $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'] = [realpath(__DIR__ . '/..'.'/phpunit/phpunit/phpunit')]; to the vendor/bin/phpunit proxy. And I opened https://github.com/sebastianbergmann/phpunit/pull/4846 which should fix it at the source…

Will keep digging a bit to see if I find a better way to solve this.

We do have a similar issue on PrestaShop CI

We have narrowed down the problem. PR https://github.com/composer/composer/pull/10137 is believed to be the root cause as mentioned by @jenkoian. When running PrestaShop phpunit suite test, we used vendor/bin/phpunit which was a symlink when using Composer 2.1 . vendor/bin/phpunit is now a proxy file, when using Composer 2.2, that use include to include the phpunit binary.

It seems a combination of phpunit declaring the use of strict type and the use of include inside the proxy file generates the error

PHP Fatal error:  strict_types declaration must be the very first statement in the script in /home/runner/work/PrestaShop/PrestaShop/vendor/phpunit/phpunit/phpunit on line 2

In the short term, we work around the issue by running our test suite using the real phpunit binary vendor/phpunit/phpunit/phpunit instead of the proxy vendor/bin/phpunit

2.2.2 is now out with this fix 👍🏻

Oh I see now what is going on… we disabled snapshot builds for PHP < 7.2.5 in preparation of Composer 2.3 snapshots requiring 7.2.5, so it keeps using 2.2.2 for you on those old-PHP builds.

image

So this should be resolved with 2.2.3 👍🏻

OK I dug up some more info:

  • The fix in Composer 2.2.2 works for PHPUnit 6.5.0 and above, as they have support for __PHPUNIT_ISOLATION_BLACKLIST (and __PHPUNIT_ISOLATION_EXCLUDE_LIST in newer versions).
  • For versions below that, perhaps executing this somewhere in the test bootstrap would workaround the issue PHPUnit_Util_Blacklist::$blacklistedClassNames['PHPUnit_Framework_TestCase'] = 3;
  • I see an alternative hack to fix it in Composer, as the file excludes files with phpvfs:// (see https://github.com/sebastianbergmann/phpunit/blob/5.7.27/src/Util/GlobalState.php#L53-L78) I think I can work something up that’ll work, but it’s going to get a little ugly in BinaryInstaller 😦

@Seldaek I have 2 different results when disabling stream_wrapper_register or not:

$ php -d date.timezone=UTC ./vendor/bin/phpunit -c tests/Integration/phpunit.xml
PHPUnit 8.5.16 by Sebastian Bergmann and contributors.

E

Time: 241 ms, Memory: 26.00 MB

There was 1 error:

1) Tests\Integration\Adapter\Cart\CartPresenterTest::testProductAttributesAreProperlyConverted with data set #0 ('Taille : S- Couleur : Noir', array('S', 'Noir'))
PHPUnit\Framework\Exception: PHP Fatal error:  strict_types declaration must be the very first statement in the script in /Users/atomiix/Sites/prestashop-dev/vendor/phpunit/phpunit/phpunit on line 2
Fatal error: strict_types declaration must be the very first statement in the script in /Users/atomiix/Sites/prestashop-dev/vendor/phpunit/phpunit/phpunit on line 2

/Users/atomiix/Sites/prestashop-dev/vendor/phpunit/phpunit/phpunit:60

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.

Remaining deprecation notices (2)
$ php -ddisable_functions=stream_wrapper_register -d date.timezone=UTC ./vendor/bin/phpunit -c tests/Integration/phpunit.xml
PHP Fatal error:  strict_types declaration must be the very first statement in the script in /Users/atomiix/Sites/prestashop-dev/vendor/phpunit/phpunit/phpunit on line 2

Fatal error: strict_types declaration must be the very first statement in the script in /Users/atomiix/Sites/prestashop-dev/vendor/phpunit/phpunit/phpunit on line 2

Just wanted chime in and add that indeed f12a5b82140bff33062f09ac2b1d3d907ebc0911 / #10137 is the root cause, confirmed with the commands posted 2 posts above via git bisect. But that’s no big news I guess… 😃 UPDATE: wait I just figured out now that this test was a bit stupid and the outcome was expected. sorry