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

PHP deprecations triggered within a Closure cause internal PHPUnit assert() to fail #5864

Closed
DominicLuidold opened this issue Jun 14, 2024 · 5 comments
Labels
feature/test-runner CLI test runner type/bug Something is broken

Comments

@DominicLuidold
Copy link

DominicLuidold commented Jun 14, 2024

Q A
PHPUnit version 11.2.1
PHP version 8.3.8
Installation Method Composer
composer info | sort output
myclabs/deep-copy                  1.12.0 Create deep copies (clones) of your objects
nikic/php-parser                   5.0.2  A PHP parser written in PHP
phar-io/manifest                   2.0.4  Component for reading phar.io manifest information from a PHP Archive (PHAR)
phar-io/version                    3.2.1  Library for handling version information and constraints
phpunit/php-code-coverage          11.0.3 Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-file-iterator          5.0.0  FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-invoker                5.0.0  Invoke callables with a timeout
phpunit/php-text-template          4.0.0  Simple template engine.
phpunit/php-timer                  7.0.0  Utility class for timing
phpunit/phpunit                    11.2.1 The PHP Unit Testing framework.
sebastian/cli-parser               3.0.1  Library for parsing CLI options
sebastian/code-unit                3.0.0  Collection of value objects that represent the PHP code units
sebastian/code-unit-reverse-lookup 4.0.0  Looks up which function or method a line of code belongs to
sebastian/comparator               6.0.0  Provides the functionality to compare PHP values for equality
sebastian/complexity               4.0.0  Library for calculating the complexity of PHP code units
sebastian/diff                     6.0.1  Diff implementation
sebastian/environment              7.1.0  Provides functionality to handle HHVM/PHP environments
sebastian/exporter                 6.0.1  Provides the functionality to export PHP variables for visualization
sebastian/global-state             7.0.1  Snapshotting of global state
sebastian/lines-of-code            3.0.0  Library for counting the lines of code in PHP source code
sebastian/object-enumerator        6.0.0  Traverses array structures and object graphs to enumerate all referenced objects
sebastian/object-reflector         4.0.0  Allows reflection of object attributes, including inherited and non-public ones
sebastian/recursion-context        6.0.0  Provides functionality to recursively process PHP variables
sebastian/type                     5.0.0  Collection of value objects that represent the types of the PHP type system
sebastian/version                  5.0.0  Library that helps with managing the version number of Git-hosted PHP projects
theseer/tokenizer                  1.2.3  A small library for converting tokenized PHP source code into XML and potentially other formats

Summary

The PHPUnit\Runner\ErrorHandler#trigger() method fails the assert(isset($trace[1]['file'])); call if a PHP deprecation is triggered inside a Closure.

Current behavior

The following code, if covered by a PHPUnit test, causes an internal PHPUnit assert to fail, when:

  • assuming that declare(strict_types=1); is not set
  • we pass [456, '123', null] as argument to the sort method
  • the default phpunit.xml generated by vendor/bin/phpunit -generate-configuration is used
/**
 * @param array<string|int|null> $values
 *
 * @return array<string|int|null>
 */
public static function sort(array $values): array
{
    usort($values, function ($a, $b) {
        return strtolower($a) <=> strtolower($b);
    });

    return $values;
}
/vendor/bin/phpunit output
PHPUnit 11.2.1 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.8
Configuration: /repositories/phpunit-deprecation-trigger-closure-reproducer/phpunit.xml

.F                                                                  2 / 2 (100%)

Time: 00:00.003, Memory: 8.00 MB

There was 1 failure:

1) App\Tests\FooTest::testIntValuesWithNull
assert(isset($trace[1]['file']))

/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php:28
/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php:27
/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php:17
/repositories/phpunit-deprecation-trigger-closure-reproducer/tests/FooTest.php:40

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.
var_dump($trace); output
array(16) {
  [0]=>
  array(3) {
    ["file"]=>
    string(72) "/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php"
    ["line"]=>
    int(28)
    ["function"]=>
    string(10) "strtolower"
  }
  [1]=>
  array(3) {
    ["function"]=>
    string(13) "App\{closure}"
    ["class"]=>
    string(7) "App\Foo"
    ["type"]=>
    string(2) "::"
  }
  [2]=>
  array(3) {
    ["file"]=>
    string(72) "/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php"
    ["line"]=>
    int(27)
    ["function"]=>
    string(5) "usort"
  }
  [3]=>
  array(5) {
    ["file"]=>
    string(72) "/repositories/phpunit-deprecation-trigger-closure-reproducer/src/Foo.php"
    ["line"]=>
    int(17)
    ["function"]=>
    string(4) "sort"
    ["class"]=>
    string(7) "App\Foo"
    ["type"]=>
    string(2) "::"
  }
  [4]=>
  array(5) {
    ["file"]=>
    string(78) "/repositories/phpunit-deprecation-trigger-closure-reproducer/tests/FooTest.php"
    ["line"]=>
    int(40)
    ["function"]=>
    string(11) "__construct"
    ["class"]=>
    string(7) "App\Foo"
    ["type"]=>
    string(2) "->"
  }
  [5]=>
  array(5) {
    ["file"]=>
    string(110) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestCase.php"
    ["line"]=>
    int(1201)
    ["function"]=>
    string(21) "testIntValuesWithNull"
    ["class"]=>
    string(17) "App\Tests\FooTest"
    ["type"]=>
    string(2) "->"
  }
  [6]=>
  array(5) {
    ["file"]=>
    string(110) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestCase.php"
    ["line"]=>
    int(498)
    ["function"]=>
    string(7) "runTest"
    ["class"]=>
    string(26) "PHPUnit\Framework\TestCase"
    ["type"]=>
    string(2) "->"
  }
  [7]=>
  array(5) {
    ["file"]=>
    string(123) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php"
    ["line"]=>
    int(84)
    ["function"]=>
    string(7) "runBare"
    ["class"]=>
    string(26) "PHPUnit\Framework\TestCase"
    ["type"]=>
    string(2) "->"
  }
  [8]=>
  array(5) {
    ["file"]=>
    string(110) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestCase.php"
    ["line"]=>
    int(349)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(28) "PHPUnit\Framework\TestRunner"
    ["type"]=>
    string(2) "->"
  }
  [9]=>
  array(5) {
    ["file"]=>
    string(111) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
    ["line"]=>
    int(369)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(26) "PHPUnit\Framework\TestCase"
    ["type"]=>
    string(2) "->"
  }
  [10]=>
  array(5) {
    ["file"]=>
    string(111) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
    ["line"]=>
    int(369)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(27) "PHPUnit\Framework\TestSuite"
    ["type"]=>
    string(2) "->"
  }
  [11]=>
  array(5) {
    ["file"]=>
    string(111) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
    ["line"]=>
    int(369)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(27) "PHPUnit\Framework\TestSuite"
    ["type"]=>
    string(2) "->"
  }
  [12]=>
  array(5) {
    ["file"]=>
    string(109) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/TextUI/TestRunner.php"
    ["line"]=>
    int(62)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(27) "PHPUnit\Framework\TestSuite"
    ["type"]=>
    string(2) "->"
  }
  [13]=>
  array(5) {
    ["file"]=>
    string(110) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/src/TextUI/Application.php"
    ["line"]=>
    int(201)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(25) "PHPUnit\TextUI\TestRunner"
    ["type"]=>
    string(2) "->"
  }
  [14]=>
  array(5) {
    ["file"]=>
    string(91) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/phpunit"
    ["line"]=>
    int(104)
    ["function"]=>
    string(3) "run"
    ["class"]=>
    string(26) "PHPUnit\TextUI\Application"
    ["type"]=>
    string(2) "->"
  }
  [15]=>
  array(4) {
    ["file"]=>
    string(79) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/bin/phpunit"
    ["line"]=>
    int(122)
    ["args"]=>
    array(1) {
      [0]=>
      string(91) "/repositories/phpunit-deprecation-trigger-closure-reproducer/vendor/phpunit/phpunit/phpunit"
    }
    ["function"]=>
    string(7) "include"
  }
}

How to reproduce

Please see https://github.com/DominicLuidold/phpunit-deprecation-trigger-closure-reproducer for a minimal, self-contained, reproducing test case.

Expected behavior

The PHPUnit\Runner\ErrorHandler#trigger() method correctly handles PHP deprecations triggered within a Closure and reports them.

@DominicLuidold DominicLuidold added the type/bug Something is broken label Jun 14, 2024
@DominicLuidold
Copy link
Author

DominicLuidold commented Jun 14, 2024

It looks like I managed to overlook #5822 which already reported and attempted to fix this issue.

@sebastianbergmann
Copy link
Owner

I have now merged #5822 into 11.2 and main. Can you please test whether your problem persists with the current state of 11.2? Thanks!

@sebastianbergmann sebastianbergmann added status/waiting-for-feedback Waiting for feedback from original reporter feature/test-runner CLI test runner labels Jun 15, 2024
@DominicLuidold
Copy link
Author

@sebastianbergmann I can confirm that #5822 has fixed the issue 😄

@sebastianbergmann
Copy link
Owner

Thank you!

@sebastianbergmann sebastianbergmann removed the status/waiting-for-feedback Waiting for feedback from original reporter label Jun 15, 2024
@DarkSide666
Copy link
Contributor

Thanks guys for finishing this. I somehow overlooked git notification about closing #5822 PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/test-runner CLI test runner type/bug Something is broken
Projects
None yet
Development

No branches or pull requests

3 participants