File manager - Edit - /home/u608250662/domains/ptfecables.in/public_html/media/uploads/phpunit.tar
Back
php-text-template/ChangeLog.md 0000644 00000003735 15253321353 0012311 0 ustar 00 # ChangeLog All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [4.0.1] - 2024-07-03 ### Changed * This project now uses PHPStan instead of Psalm for static analysis ## [4.0.0] - 2024-02-02 ### Removed * The `SebastianBergmann\Template\Template::setFile()` method has been removed * This component is no longer supported on PHP 8.1 ## [3.0.1] - 2023-08-31 ### Changed * Warnings from `file_put_contents()` are now suppressed ## [3.0.0] - 2023-02-03 ### Removed * This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 ## [2.0.4] - 2020-10-26 ### Fixed * `SebastianBergmann\Template\Exception` now correctly extends `\Throwable` ## [2.0.3] - 2020-09-28 ### Changed * Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` ## [2.0.2] - 2020-06-26 ### Added * This component is now supported on PHP 8 ## [2.0.1] - 2020-06-15 ### Changed * Tests etc. are now ignored for archive exports ## [2.0.0] - 2020-02-07 ### Changed * The `Text_Template` class was renamed to `SebastianBergmann\Template\Template` ### Removed * Removed support for PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0, PHP 7.1, and PHP 7.2 [4.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/4.0.0...4.0.1 [4.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/3.0...4.0.0 [3.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.4...3.0.0 [2.0.4]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.3...2.0.4 [2.0.3]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.2...2.0.3 [2.0.2]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.1...2.0.2 [2.0.1]: https://github.com/sebastianbergmann/php-text-template/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/sebastianbergmann/php-text-template/compare/1.2.1...2.0.0 php-text-template/src/exceptions/Exception.php 0000644 00000000560 15253321353 0015550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-text-template. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Template; use Throwable; interface Exception extends Throwable { } php-text-template/src/exceptions/RuntimeException.php 0000644 00000000654 15253321353 0017120 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-text-template. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Template; use InvalidArgumentException; final class RuntimeException extends InvalidArgumentException implements Exception { } php-text-template/src/exceptions/InvalidArgumentException.php 0000644 00000000626 15253321353 0020565 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-text-template. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Template; final class InvalidArgumentException extends \InvalidArgumentException implements Exception { } php-text-template/src/Template.php 0000644 00000006145 15253321353 0013211 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-text-template. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Template; use function array_keys; use function array_merge; use function file_get_contents; use function file_put_contents; use function is_file; use function is_string; use function sprintf; use function str_replace; final class Template { /** * @var non-empty-string */ private readonly string $template; /** * @var non-empty-string */ private readonly string $openDelimiter; /** * @var non-empty-string */ private readonly string $closeDelimiter; /** * @var array<string,string> */ private array $values = []; /** * @param non-empty-string $templateFile * @param non-empty-string $openDelimiter * @param non-empty-string $closeDelimiter * * @throws InvalidArgumentException */ public function __construct(string $templateFile, string $openDelimiter = '{', string $closeDelimiter = '}') { $this->template = $this->loadTemplateFile($templateFile); $this->openDelimiter = $openDelimiter; $this->closeDelimiter = $closeDelimiter; } /** * @param array<string,string> $values */ public function setVar(array $values, bool $merge = true): void { if (!$merge || empty($this->values)) { $this->values = $values; return; } $this->values = array_merge($this->values, $values); } public function render(): string { $keys = []; foreach (array_keys($this->values) as $key) { $keys[] = $this->openDelimiter . $key . $this->closeDelimiter; } return str_replace($keys, $this->values, $this->template); } /** * @codeCoverageIgnore */ public function renderTo(string $target): void { if (!@file_put_contents($target, $this->render())) { throw new RuntimeException( sprintf( 'Writing rendered result to "%s" failed', $target, ), ); } } /** * @param non-empty-string $file * * @throws InvalidArgumentException * * @return non-empty-string */ private function loadTemplateFile(string $file): string { if (is_file($file)) { $template = file_get_contents($file); if (is_string($template) && !empty($template)) { return $template; } } $distFile = $file . '.dist'; if (is_file($distFile)) { $template = file_get_contents($distFile); if (is_string($template) && !empty($template)) { return $template; } } throw new InvalidArgumentException( sprintf( 'Failed to load template "%s"', $file, ), ); } } php-text-template/composer.json 0000644 00000002064 15253321353 0012654 0 ustar 00 { "name": "phpunit/php-text-template", "description": "Simple template engine.", "type": "library", "keywords": [ "template" ], "homepage": "https://github.com/sebastianbergmann/php-text-template/", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy" }, "config": { "platform": { "php": "8.2.0" }, "optimize-autoloader": true, "sort-packages": true }, "prefer-stable": true, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-main": "4.0-dev" } } } php-text-template/.psalm/config.xml 0000644 00000001020 15253321353 0013302 0 ustar 00 <?xml version="1.0"?> <psalm xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" resolveFromConfigFile="false" errorBaseline=".psalm/baseline.xml" findUnusedBaselineEntry="true" findUnusedCode="false" > <projectFiles> <directory name="src" /> <ignoreFiles> <directory name="vendor" /> </ignoreFiles> </projectFiles> </psalm> php-text-template/.psalm/baseline.xml 0000644 00000000114 15253321353 0013622 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <files psalm-version="dev-master@"/> php-text-template/LICENSE 0000644 00000002773 15253321353 0011146 0 ustar 00 BSD 3-Clause License Copyright (c) 2009-2024, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. php-text-template/SECURITY.md 0000644 00000003565 15253321353 0011732 0 ustar 00 # Security Policy If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `sebastian@phpunit.de`. Please include as much of the information listed below as you can to help us better understand and resolve the issue: * The type of issue * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. ## Web Context The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. php-text-template/README.md 0000644 00000001562 15253321353 0011413 0 ustar 00 [](https://packagist.org/packages/phpunit/php-text-template) [](https://github.com/sebastianbergmann/php-text-template/actions) [](https://codecov.io/gh/sebastianbergmann/php-text-template) # php-text-template ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): composer require phpunit/php-text-template If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: composer require --dev phpunit/php-text-template php-invoker/ChangeLog.md 0000644 00000003751 15253321353 0011167 0 ustar 00 # ChangeLog All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. ## [5.0.1] - 2024-07-03 ### Changed * This project now uses PHPStan instead of Psalm for static analysis ## [5.0.0] - 2024-02-02 ### Removed * This component is no longer supported on PHP 8.1 ## [4.0.0] - 2023-02-03 ### Removed * This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 ## [3.1.1] - 2020-09-28 ### Changed * Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` ## [3.1.0] - 2020-08-06 ### Changed * [#14](https://github.com/sebastianbergmann/php-invoker/pull/14): Clear alarm in `finally` block ## [3.0.2] - 2020-06-26 ### Added * This component is now supported on PHP 8 ## [3.0.1] - 2020-06-15 ### Changed * Tests etc. are now ignored for archive exports ## [3.0.0] - 2020-02-07 ### Added * Added `canInvokeWithTimeout()` method to check requirements for the functionality provided by this component to work ### Changed * Moved `"ext-pcntl": "*"` requirement from `require` to `suggest` so that this component can be installed even if `ext/pcntl` is not available * `invoke()` now raises an exception when the requirements for the functionality provided by this component to work are not met ### Removed * This component is no longer supported on PHP 7.1 and PHP 7.2 [5.0.1]: https://github.com/sebastianbergmann/php-invoker/compare/5.0.1...5.0.1 [5.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/4.0...5.0.0 [4.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.1...4.0.0 [3.1.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.1.0...3.1.1 [3.1.0]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.2...3.1.0 [3.0.2]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.1...3.0.2 [3.0.1]: https://github.com/sebastianbergmann/php-invoker/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/sebastianbergmann/php-invoker/compare/2.0.0...3.0.0 php-invoker/src/exceptions/Exception.php 0000644 00000000551 15253321353 0014430 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-invoker. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Invoker; use Throwable; interface Exception extends Throwable { } php-invoker/src/exceptions/ProcessControlExtensionNotLoadedException.php 0000644 00000002266 15253321353 0023024 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-invoker. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Invoker; use function extension_loaded; use function function_exists; use function implode; use RuntimeException; final class ProcessControlExtensionNotLoadedException extends RuntimeException implements Exception { public function __construct() { $message = []; if (!extension_loaded('pcntl')) { $message[] = 'The pcntl (process control) extension for PHP must be loaded.'; } if (!function_exists('pcntl_signal')) { $message[] = 'The pcntl_signal() function must not be disabled.'; } if (!function_exists('pcntl_async_signals')) { $message[] = 'The pcntl_async_signals() function must not be disabled.'; } if (!function_exists('pcntl_alarm')) { $message[] = 'The pcntl_alarm() function must not be disabled.'; } parent::__construct(implode(PHP_EOL, $message)); } } php-invoker/src/exceptions/TimeoutException.php 0000644 00000000625 15253321353 0016001 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-invoker. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Invoker; use RuntimeException; final class TimeoutException extends RuntimeException implements Exception { } php-invoker/src/Invoker.php 0000644 00000003350 15253321353 0011726 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-invoker. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Invoker; use const SIGALRM; use function call_user_func_array; use function extension_loaded; use function function_exists; use function pcntl_alarm; use function pcntl_async_signals; use function pcntl_signal; use function sprintf; use Throwable; final class Invoker { /** * @param array<mixed> $arguments * * @throws Throwable */ public function invoke(callable $callable, array $arguments, int $timeout): mixed { if (!$this->canInvokeWithTimeout()) { // @codeCoverageIgnoreStart throw new ProcessControlExtensionNotLoadedException; // @codeCoverageIgnoreEnd } pcntl_signal( SIGALRM, static function () use ($timeout): void { throw new TimeoutException( sprintf( 'Execution aborted after %d second%s', $timeout, $timeout === 1 ? '' : 's', ), ); }, ); pcntl_async_signals(true); pcntl_alarm($timeout); try { return call_user_func_array($callable, $arguments); } finally { pcntl_alarm(0); } } public function canInvokeWithTimeout(): bool { return extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_async_signals') && function_exists('pcntl_alarm'); } } php-invoker/composer.json 0000644 00000002312 15253321353 0011530 0 ustar 00 { "name": "phpunit/php-invoker", "description": "Invoke callables with a timeout", "type": "library", "keywords": [ "process" ], "homepage": "https://github.com/sebastianbergmann/php-invoker/", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "security": "https://github.com/sebastianbergmann/php-invoker/security/policy" }, "prefer-stable": true, "config": { "platform": { "php": "8.2.0" }, "optimize-autoloader": true, "sort-packages": true }, "require": { "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", "phpunit/phpunit": "^11.0" }, "autoload": { "classmap": [ "src/" ] }, "autoload-dev": { "classmap": [ "tests/_fixture/" ] }, "suggest": { "ext-pcntl": "*" }, "extra": { "branch-alias": { "dev-main": "5.0-dev" } } } php-invoker/LICENSE 0000644 00000002773 15253321353 0010026 0 ustar 00 BSD 3-Clause License Copyright (c) 2011-2024, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. php-invoker/SECURITY.md 0000644 00000003565 15253321353 0010612 0 ustar 00 # Security Policy If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `sebastian@phpunit.de`. Please include as much of the information listed below as you can to help us better understand and resolve the issue: * The type of issue * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. ## Web Context The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. php-invoker/README.md 0000644 00000001513 15253321353 0010267 0 ustar 00 # phpunit/php-invoker [](https://packagist.org/packages/phpunit/php-invoker) [](https://github.com/sebastianbergmann/php-invoker/actions) [](https://codecov.io/gh/sebastianbergmann/php-invoker) ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): ``` composer require phpunit/php-invoker ``` If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: ``` composer require --dev phpunit/php-invoker ``` php-file-iterator/ChangeLog.md 0000644 00000014266 15253321353 0012263 0 ustar 00 # Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [5.0.1] - 2024-07-03 ### Changed * This project now uses PHPStan instead of Psalm for static analysis ## [5.0.0] - 2024-02-02 ### Removed * This component is no longer supported on PHP 8.1 ## [4.1.0] - 2023-08-31 ### Added * [#81](https://github.com/sebastianbergmann/php-file-iterator/issues/81): Accept `array|string $paths` in `Facade::getFilesAsArray()` ## [4.0.2] - 2023-05-07 ### Fixed * [#80](https://github.com/sebastianbergmann/php-file-iterator/pull/80): Ignore unresolvable symbolic link ## [4.0.1] - 2023-02-10 ### Fixed * [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/61): Excluded directories are traversed unnecessarily ## [4.0.0] - 2023-02-03 ### Removed * The optional `$commonPath` parameter of `SebastianBergmann\FileIterator\Facade` as well as the functionality it controlled has been removed * The `SebastianBergmann\FileIterator\Factory` and `SebastianBergmann\FileIterator\Iterator` classes are now marked `@internal` * This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 ## [3.0.6] - 2021-12-02 ### Changed * [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths ## [3.0.5] - 2020-09-28 ### Changed * Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` ## [3.0.4] - 2020-07-11 ### Fixed * [#67](https://github.com/sebastianbergmann/php-file-iterator/issues/67): `TypeError` in `SebastianBergmann\FileIterator\Iterator::accept()` ## [3.0.3] - 2020-06-26 ### Added * This component is now supported on PHP 8 ## [3.0.2] - 2020-06-15 ### Changed * Tests etc. are now ignored for archive exports ## [3.0.1] - 2020-04-18 ### Fixed * [#64](https://github.com/sebastianbergmann/php-file-iterator/issues/64): Release tarball contains Composer PHAR ## [3.0.0] - 2020-02-07 ### Removed * This component is no longer supported on PHP 7.1 and PHP 7.2 ## [2.0.5] - 2021-12-02 ### Changed * [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths ### Fixed * [#74](https://github.com/sebastianbergmann/php-file-iterator/pull/74): Document return type of `SebastianBergmann\FileIterator\Iterator::accept()` so that Symfony's `DebugClassLoader` does not trigger a deprecation warning ## [2.0.4] - 2021-07-19 ### Changed * Added `ReturnTypeWillChange` attribute to `SebastianBergmann\FileIterator\Iterator::accept()` because the return type of `\FilterIterator::accept()` will change in PHP 8.1 ## [2.0.3] - 2020-11-30 ### Changed * Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` ## [2.0.2] - 2018-09-13 ### Fixed * [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory ## [2.0.1] - 2018-06-11 ### Fixed * [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory ## [2.0.0] - 2018-05-28 ### Fixed * [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path ### Changed * This component now uses namespaces ### Removed * This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 ## [1.4.5] - 2017-11-27 ### Fixed * [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30) ## [1.4.4] - 2017-11-27 ### Fixed * [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path ## [1.4.3] - 2017-11-25 ### Fixed * [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names ## [1.4.2] - 2016-11-26 No changes ## [1.4.1] - 2015-07-26 No changes ## 1.4.0 - 2015-04-02 ### Added * [#23](https://github.com/sebastianbergmann/php-file-iterator/pull/23): Added support for wildcards (glob) in exclude [5.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/5.0.0...5.0.1 [5.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.1...5.0.0 [4.1.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.2...4.1.0 [4.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.1...4.0.2 [4.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/4.0.0...4.0.1 [4.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.6...4.0.0 [3.0.6]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.5...3.0.6 [3.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.4...3.0.5 [3.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.3...3.0.4 [3.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.2...3.0.3 [3.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.1...3.0.2 [3.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/3.0.0...3.0.1 [3.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.5...3.0.0 [2.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.4...2.0.5 [2.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.3...2.0.4 [2.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...2.0.3 [2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2 [2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1 [2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.5...2.0.0 [1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5 [1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4 [1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3 [1.4.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.1...1.4.2 [1.4.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.0...1.4.1 php-file-iterator/src/ExcludeIterator.php 0000644 00000003501 15253321353 0014503 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-file-iterator. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\FileIterator; use function assert; use function str_starts_with; use RecursiveDirectoryIterator; use RecursiveFilterIterator; use SplFileInfo; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator */ final class ExcludeIterator extends RecursiveFilterIterator { /** * @var list<string> */ private array $exclude; /** * @param list<string> $exclude */ public function __construct(RecursiveDirectoryIterator $iterator, array $exclude) { parent::__construct($iterator); $this->exclude = $exclude; } public function accept(): bool { $current = $this->current(); assert($current instanceof SplFileInfo); $path = $current->getRealPath(); if ($path === false) { return false; } foreach ($this->exclude as $exclude) { if (str_starts_with($path, $exclude)) { return false; } } return true; } public function hasChildren(): bool { return $this->getInnerIterator()->hasChildren(); } public function getChildren(): self { return new self( $this->getInnerIterator()->getChildren(), $this->exclude, ); } public function getInnerIterator(): RecursiveDirectoryIterator { $innerIterator = parent::getInnerIterator(); assert($innerIterator instanceof RecursiveDirectoryIterator); return $innerIterator; } } php-file-iterator/src/Facade.php 0000644 00000002615 15253321353 0012550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-file-iterator. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\FileIterator; use function array_unique; use function assert; use function sort; use SplFileInfo; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class Facade { /** * @param list<non-empty-string>|non-empty-string $paths * @param list<non-empty-string>|string $suffixes * @param list<non-empty-string>|string $prefixes * @param list<non-empty-string> $exclude * * @return list<non-empty-string> */ public function getFilesAsArray(array|string $paths, array|string $suffixes = '', array|string $prefixes = '', array $exclude = []): array { $iterator = (new Factory)->getFileIterator($paths, $suffixes, $prefixes, $exclude); $files = []; foreach ($iterator as $file) { assert($file instanceof SplFileInfo); $file = $file->getRealPath(); if ($file) { $files[] = $file; } } $files = array_unique($files); sort($files); return $files; } } php-file-iterator/src/Iterator.php 0000644 00000005714 15253321353 0013201 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-file-iterator. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\FileIterator; use function assert; use function preg_match; use function realpath; use function str_ends_with; use function str_replace; use function str_starts_with; use FilterIterator; use SplFileInfo; /** * @template-extends FilterIterator<int, SplFileInfo, \Iterator> * * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator */ final class Iterator extends FilterIterator { public const PREFIX = 0; public const SUFFIX = 1; private false|string $basePath; /** * @var list<string> */ private array $suffixes; /** * @var list<string> */ private array $prefixes; /** * @param list<string> $suffixes * @param list<string> $prefixes */ public function __construct(string $basePath, \Iterator $iterator, array $suffixes = [], array $prefixes = []) { $this->basePath = realpath($basePath); $this->prefixes = $prefixes; $this->suffixes = $suffixes; parent::__construct($iterator); } public function accept(): bool { $current = $this->getInnerIterator()->current(); assert($current instanceof SplFileInfo); $filename = $current->getFilename(); $realPath = $current->getRealPath(); if ($realPath === false) { // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd } return $this->acceptPath($realPath) && $this->acceptPrefix($filename) && $this->acceptSuffix($filename); } private function acceptPath(string $path): bool { // Filter files in hidden directories by checking path that is relative to the base path. if (preg_match('=/\.[^/]*/=', str_replace((string) $this->basePath, '', $path))) { return false; } return true; } private function acceptPrefix(string $filename): bool { return $this->acceptSubString($filename, $this->prefixes, self::PREFIX); } private function acceptSuffix(string $filename): bool { return $this->acceptSubString($filename, $this->suffixes, self::SUFFIX); } /** * @param list<string> $subStrings */ private function acceptSubString(string $filename, array $subStrings, int $type): bool { if (empty($subStrings)) { return true; } foreach ($subStrings as $string) { if (($type === self::PREFIX && str_starts_with($filename, $string)) || ($type === self::SUFFIX && str_ends_with($filename, $string))) { return true; } } return false; } } php-file-iterator/src/Factory.php 0000644 00000006022 15253321353 0013010 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-file-iterator. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\FileIterator; use const GLOB_ONLYDIR; use function array_filter; use function array_map; use function array_merge; use function array_values; use function glob; use function is_dir; use function is_string; use function realpath; use AppendIterator; use FilesystemIterator; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-file-iterator */ final class Factory { /** * @param list<non-empty-string>|non-empty-string $paths * @param list<non-empty-string>|string $suffixes * @param list<non-empty-string>|string $prefixes * @param list<non-empty-string> $exclude */ public function getFileIterator(array|string $paths, array|string $suffixes = '', array|string $prefixes = '', array $exclude = []): AppendIterator { if (is_string($paths)) { $paths = [$paths]; } $paths = $this->resolveWildcards($paths); $exclude = $this->resolveWildcards($exclude); if (is_string($prefixes)) { if ($prefixes !== '') { $prefixes = [$prefixes]; } else { $prefixes = []; } } if (is_string($suffixes)) { if ($suffixes !== '') { $suffixes = [$suffixes]; } else { $suffixes = []; } } $iterator = new AppendIterator; foreach ($paths as $path) { if (is_dir($path)) { $iterator->append( new Iterator( $path, new RecursiveIteratorIterator( new ExcludeIterator( new RecursiveDirectoryIterator($path, FilesystemIterator::FOLLOW_SYMLINKS | FilesystemIterator::SKIP_DOTS), $exclude, ), ), $suffixes, $prefixes, ), ); } } return $iterator; } /** * @param list<non-empty-string> $paths * * @return list<non-empty-string> */ private function resolveWildcards(array $paths): array { $_paths = [[]]; foreach ($paths as $path) { if ($locals = glob($path, GLOB_ONLYDIR)) { $_paths[] = array_map('\realpath', $locals); } else { // @codeCoverageIgnoreStart $_paths[] = [realpath($path)]; // @codeCoverageIgnoreEnd } } return array_values(array_filter(array_merge(...$_paths))); } } php-file-iterator/composer.json 0000644 00000002200 15253321353 0012615 0 ustar 00 { "name": "phpunit/php-file-iterator", "description": "FilterIterator implementation that filters files based on a list of suffixes.", "type": "library", "keywords": [ "iterator", "filesystem" ], "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy" }, "config": { "platform": { "php": "8.2.0" }, "optimize-autoloader": true, "sort-packages": true }, "prefer-stable": true, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-main": "5.0-dev" } } } php-file-iterator/LICENSE 0000644 00000002773 15253321353 0011117 0 ustar 00 BSD 3-Clause License Copyright (c) 2009-2024, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. php-file-iterator/SECURITY.md 0000644 00000003565 15253321353 0011703 0 ustar 00 # Security Policy If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `sebastian@phpunit.de`. Please include as much of the information listed below as you can to help us better understand and resolve the issue: * The type of issue * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. ## Web Context The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. php-file-iterator/README.md 0000644 00000002024 15253321353 0011356 0 ustar 00 [](https://packagist.org/packages/phpunit/php-file-iterator) [](https://github.com/sebastianbergmann/php-file-iterator/actions) [](https://shepherd.dev/github/sebastianbergmann/php-file-iterator) [](https://codecov.io/gh/sebastianbergmann/php-file-iterator) # php-file-iterator ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): composer require phpunit/php-file-iterator If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: composer require --dev phpunit/php-file-iterator php-timer/ChangeLog.md 0000644 00000012313 15253321353 0010624 0 ustar 00 # ChangeLog All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [7.0.1] - 2024-07-03 ### Changed * This project now uses PHPStan instead of Psalm for static analysis ## [7.0.0] - 2024-02-02 ### Removed * This component is no longer supported on PHP 8.1 ## [6.0.0] - 2023-02-03 ### Removed * This component is no longer supported on PHP 7.3, PHP 7.4 and PHP 8.0 ## [5.0.3] - 2020-10-26 ### Fixed * `SebastianBergmann\Timer\Exception` now correctly extends `\Throwable` ## [5.0.2] - 2020-09-28 ### Changed * Changed PHP version constraint in `composer.json` from `^7.3 || ^8.0` to `>=7.3` ## [5.0.1] - 2020-06-26 ### Added * This component is now supported on PHP 8 ## [5.0.0] - 2020-06-07 ### Changed * Parameter type for `SebastianBergmann\Timer\Duration::fromMicroseconds()` was changed from `int` to `float` * Parameter type for `SebastianBergmann\Timer\Duration::fromNanoseconds()` was changed from `int` to `float` * Return type for `SebastianBergmann\Timer\Duration::asNanoseconds()` was changed from `int` to `float` ### Fixed * [#31](https://github.com/sebastianbergmann/php-timer/issues/31): Type Error on 32-bit systems (where `hrtime()` returns `float` instead of `int`) ## [4.0.0] - 2020-06-01 ### Added * Introduced `Duration` value object for encapsulating a duration with nanosecond granularity * Introduced `ResourceUsageFormatter` object for formatting resource usage with option to explicitly pass a duration (instead of looking at the unreliable `$_SERVER['REQUEST_TIME_FLOAT']` variable) ### Changed * The methods of `Timer` are no longer static * `Timer::stop()` now returns a `Duration` value object ### Removed * Functionality that is now implemented in `Duration` and `ResourceUsageFormatter` has been removed from `Timer` ## [3.1.4] - 2020-04-20 ### Changed * `Timer::timeSinceStartOfRequest()` no longer tries `$_SERVER['REQUEST_TIME']` when `$_SERVER['REQUEST_TIME_FLOAT']` is not available (`$_SERVER['REQUEST_TIME_FLOAT']` was added in PHP 5.4 and this library requires PHP 7.3) * Improved exception messages when `$_SERVER['REQUEST_TIME_FLOAT']` is not set or is not of type `float` ### Changed ## [3.1.3] - 2020-04-20 ### Changed * `Timer::timeSinceStartOfRequest()` now raises an exception if `$_SERVER['REQUEST_TIME_FLOAT']` does not contain a `float` (or `$_SERVER['REQUEST_TIME']` does not contain an `int`) ## [3.1.2] - 2020-04-17 ### Changed * Improved the fix for [#30](https://github.com/sebastianbergmann/php-timer/issues/30) and restored usage of `hrtime()` ## [3.1.1] - 2020-04-17 ### Fixed * [#30](https://github.com/sebastianbergmann/php-timer/issues/30): Resolution of time returned by `Timer::stop()` is different than before (this reverts using `hrtime()` instead of `microtime()`) ## [3.1.0] - 2020-04-17 ### Added * `Timer::secondsToShortTimeString()` as alternative to `Timer::secondsToTimeString()` ### Changed * `Timer::start()` and `Timer::stop()` now use `hrtime()` (high resolution monotonic timer) instead of `microtime()` * `Timer::timeSinceStartOfRequest()` now uses `Timer::secondsToShortTimeString()` for time formatting * Improved formatting of `Timer::secondsToTimeString()` result ## [3.0.0] - 2020-02-07 ### Removed * This component is no longer supported on PHP 7.1 and PHP 7.2 ## [2.1.2] - 2019-06-07 ### Fixed * [#21](https://github.com/sebastianbergmann/php-timer/pull/21): Formatting of memory consumption does not work on 32bit systems ## [2.1.1] - 2019-02-20 ### Changed * Improved formatting of memory consumption for `resourceUsage()` ## [2.1.0] - 2019-02-20 ### Changed * Improved formatting of memory consumption for `resourceUsage()` ## [2.0.0] - 2018-02-01 ### Changed * This component now uses namespaces ### Removed * This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0 [7.0.1]: https://github.com/sebastianbergmann/php-timer/compare/7.0.0...7.0.1 [7.0.0]: https://github.com/sebastianbergmann/php-timer/compare/6.0...7.0.0 [6.0.0]: https://github.com/sebastianbergmann/php-timer/compare/5.0.3...6.0.0 [5.0.3]: https://github.com/sebastianbergmann/php-timer/compare/5.0.2...5.0.3 [5.0.2]: https://github.com/sebastianbergmann/php-timer/compare/5.0.1...5.0.2 [5.0.1]: https://github.com/sebastianbergmann/php-timer/compare/5.0.0...5.0.1 [5.0.0]: https://github.com/sebastianbergmann/php-timer/compare/4.0.0...5.0.0 [4.0.0]: https://github.com/sebastianbergmann/php-timer/compare/3.1.4...4.0.0 [3.1.4]: https://github.com/sebastianbergmann/php-timer/compare/3.1.3...3.1.4 [3.1.3]: https://github.com/sebastianbergmann/php-timer/compare/3.1.2...3.1.3 [3.1.2]: https://github.com/sebastianbergmann/php-timer/compare/3.1.1...3.1.2 [3.1.1]: https://github.com/sebastianbergmann/php-timer/compare/3.1.0...3.1.1 [3.1.0]: https://github.com/sebastianbergmann/php-timer/compare/3.0.0...3.1.0 [3.0.0]: https://github.com/sebastianbergmann/php-timer/compare/2.1.2...3.0.0 [2.1.2]: https://github.com/sebastianbergmann/php-timer/compare/2.1.1...2.1.2 [2.1.1]: https://github.com/sebastianbergmann/php-timer/compare/2.1.0...2.1.1 [2.1.0]: https://github.com/sebastianbergmann/php-timer/compare/2.0.0...2.1.0 [2.0.0]: https://github.com/sebastianbergmann/php-timer/compare/1.0.9...2.0.0 php-timer/src/Duration.php 0000644 00000004751 15253321353 0011547 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use function floor; use function sprintf; /** * @immutable */ final readonly class Duration { private float $nanoseconds; private int $hours; private int $minutes; private int $seconds; private int $milliseconds; public static function fromMicroseconds(float $microseconds): self { return new self($microseconds * 1000); } public static function fromNanoseconds(float $nanoseconds): self { return new self($nanoseconds); } private function __construct(float $nanoseconds) { $this->nanoseconds = $nanoseconds; $timeInMilliseconds = $nanoseconds / 1000000; $hours = floor($timeInMilliseconds / 60 / 60 / 1000); $hoursInMilliseconds = $hours * 60 * 60 * 1000; $minutes = floor($timeInMilliseconds / 60 / 1000) % 60; $minutesInMilliseconds = $minutes * 60 * 1000; $seconds = floor(($timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds) / 1000); $secondsInMilliseconds = $seconds * 1000; $milliseconds = $timeInMilliseconds - $hoursInMilliseconds - $minutesInMilliseconds - $secondsInMilliseconds; $this->hours = (int) $hours; $this->minutes = $minutes; $this->seconds = (int) $seconds; $this->milliseconds = (int) $milliseconds; } public function asNanoseconds(): float { return $this->nanoseconds; } public function asMicroseconds(): float { return $this->nanoseconds / 1000; } public function asMilliseconds(): float { return $this->nanoseconds / 1000000; } public function asSeconds(): float { return $this->nanoseconds / 1000000000; } public function asString(): string { $result = ''; if ($this->hours > 0) { $result = sprintf('%02d', $this->hours) . ':'; } $result .= sprintf('%02d', $this->minutes) . ':'; $result .= sprintf('%02d', $this->seconds); if ($this->milliseconds > 0) { $result .= '.' . sprintf('%03d', $this->milliseconds); } return $result; } } php-timer/src/Timer.php 0000644 00000001635 15253321353 0011040 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use function array_pop; use function hrtime; final class Timer { /** * @var list<float> */ private array $startTimes = []; public function start(): void { $this->startTimes[] = (float) hrtime(true); } /** * @throws NoActiveTimerException */ public function stop(): Duration { if (empty($this->startTimes)) { throw new NoActiveTimerException( 'Timer::start() has to be called before Timer::stop()', ); } return Duration::fromNanoseconds((float) hrtime(true) - array_pop($this->startTimes)); } } php-timer/src/exceptions/Exception.php 0000644 00000000545 15253321353 0014076 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use Throwable; interface Exception extends Throwable { } php-timer/src/exceptions/NoActiveTimerException.php 0000644 00000000623 15253321353 0016525 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use LogicException; final class NoActiveTimerException extends LogicException implements Exception { } php-timer/src/exceptions/TimeSinceStartOfRequestNotAvailableException.php 0000644 00000000655 15253321353 0023037 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use RuntimeException; final class TimeSinceStartOfRequestNotAvailableException extends RuntimeException implements Exception { } php-timer/src/ResourceUsageFormatter.php 0000644 00000004104 15253321353 0014412 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-timer. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Timer; use function is_float; use function memory_get_peak_usage; use function microtime; use function sprintf; final class ResourceUsageFormatter { /** * @var array<string,int> */ private const SIZES = [ 'GB' => 1073741824, 'MB' => 1048576, 'KB' => 1024, ]; public function resourceUsage(Duration $duration): string { return sprintf( 'Time: %s, Memory: %s', $duration->asString(), $this->bytesToString(memory_get_peak_usage(true)), ); } /** * @throws TimeSinceStartOfRequestNotAvailableException */ public function resourceUsageSinceStartOfRequest(): string { if (!isset($_SERVER['REQUEST_TIME_FLOAT'])) { throw new TimeSinceStartOfRequestNotAvailableException( 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not available', ); } if (!is_float($_SERVER['REQUEST_TIME_FLOAT'])) { throw new TimeSinceStartOfRequestNotAvailableException( 'Cannot determine time at which the request started because $_SERVER[\'REQUEST_TIME_FLOAT\'] is not of type float', ); } return $this->resourceUsage( Duration::fromMicroseconds( (1000000 * (microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'])), ), ); } private function bytesToString(int $bytes): string { foreach (self::SIZES as $unit => $value) { if ($bytes >= $value) { return sprintf('%.2f %s', $bytes / $value, $unit); } } // @codeCoverageIgnoreStart return $bytes . ' byte' . ($bytes !== 1 ? 's' : ''); // @codeCoverageIgnoreEnd } } php-timer/composer.json 0000644 00000002023 15253321353 0011172 0 ustar 00 { "name": "phpunit/php-timer", "description": "Utility class for timing", "type": "library", "keywords": [ "timer" ], "homepage": "https://github.com/sebastianbergmann/php-timer/", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "security": "https://github.com/sebastianbergmann/php-timer/security/policy" }, "prefer-stable": true, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "config": { "platform": { "php": "8.2.0" }, "optimize-autoloader": true, "sort-packages": true }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-main": "7.0-dev" } } } php-timer/LICENSE 0000644 00000002773 15253321353 0007471 0 ustar 00 BSD 3-Clause License Copyright (c) 2010-2024, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. php-timer/SECURITY.md 0000644 00000003565 15253321353 0010255 0 ustar 00 # Security Policy If you believe you have found a security vulnerability in the library that is developed in this repository, please report it to us through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `sebastian@phpunit.de`. Please include as much of the information listed below as you can to help us better understand and resolve the issue: * The type of issue * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. ## Web Context The library that is developed in this repository was either extracted from [PHPUnit](https://github.com/sebastianbergmann/phpunit) or developed specifically as a dependency for PHPUnit. The library is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using the library in an HTTP or web context or with untrusted input data is performed. The library might also contain functionality that intentionally exposes internal application data for debugging purposes. If the library is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. php-timer/README.md 0000644 00000004510 15253321353 0007732 0 ustar 00 # phpunit/php-timer [](https://packagist.org/packages/phpunit/php-timer) [](https://github.com/sebastianbergmann/php-timer/actions) [](https://codecov.io/gh/sebastianbergmann/php-timer) Utility class for timing things, factored out of PHPUnit into a stand-alone component. ## Installation You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/): ``` composer require phpunit/php-timer ``` If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency: ``` composer require --dev phpunit/php-timer ``` ## Usage ### Basic Timing ```php require __DIR__ . '/vendor/autoload.php'; use SebastianBergmann\Timer\Timer; $timer = new Timer; $timer->start(); foreach (\range(0, 100000) as $i) { // ... } $duration = $timer->stop(); var_dump(get_class($duration)); var_dump($duration->asString()); var_dump($duration->asSeconds()); var_dump($duration->asMilliseconds()); var_dump($duration->asMicroseconds()); var_dump($duration->asNanoseconds()); ``` The code above yields the output below: ``` string(32) "SebastianBergmann\Timer\Duration" string(9) "00:00.002" float(0.002851062) float(2.851062) float(2851.062) int(2851062) ``` ### Resource Consumption #### Explicit duration ```php require __DIR__ . '/vendor/autoload.php'; use SebastianBergmann\Timer\ResourceUsageFormatter; use SebastianBergmann\Timer\Timer; $timer = new Timer; $timer->start(); foreach (\range(0, 100000) as $i) { // ... } print (new ResourceUsageFormatter)->resourceUsage($timer->stop()); ``` The code above yields the output below: ``` Time: 00:00.002, Memory: 6.00 MB ``` #### Duration since PHP Startup (using unreliable `$_SERVER['REQUEST_TIME_FLOAT']`) ```php require __DIR__ . '/vendor/autoload.php'; use SebastianBergmann\Timer\ResourceUsageFormatter; foreach (\range(0, 100000) as $i) { // ... } print (new ResourceUsageFormatter)->resourceUsageSinceStartOfRequest(); ``` The code above yields the output below: ``` Time: 00:00.002, Memory: 6.00 MB ``` phpunit/src/Framework/TestBuilder.php 0000644 00000025255 15253321353 0013731 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function array_merge; use function assert; use PHPUnit\Metadata\Api\DataProvider; use PHPUnit\Metadata\Api\Groups; use PHPUnit\Metadata\BackupGlobals; use PHPUnit\Metadata\BackupStaticProperties; use PHPUnit\Metadata\ExcludeGlobalVariableFromBackup; use PHPUnit\Metadata\ExcludeStaticPropertyFromBackup; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Metadata\PreserveGlobalState; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use ReflectionClass; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestBuilder { /** * @param ReflectionClass<TestCase> $theClass * @param non-empty-string $methodName * @param list<non-empty-string> $groups * * @throws InvalidDataProviderException */ public function build(ReflectionClass $theClass, string $methodName, array $groups = []): Test { $className = $theClass->getName(); $data = (new DataProvider)->providedData( $className, $methodName, ); if ($data !== null) { return $this->buildDataProviderTestSuite( $methodName, $className, $data, $this->shouldTestMethodBeRunInSeparateProcess($className, $methodName), $this->shouldGlobalStateBePreserved($className, $methodName), $this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className), $this->backupSettings($className, $methodName), $groups, ); } $test = new $className($methodName); $this->configureTestCase( $test, $this->shouldTestMethodBeRunInSeparateProcess($className, $methodName), $this->shouldGlobalStateBePreserved($className, $methodName), $this->shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess($className), $this->backupSettings($className, $methodName), ); return $test; } /** * @param non-empty-string $methodName * @param class-string<TestCase> $className * @param array<list<mixed>> $data * @param array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} $backupSettings * @param list<non-empty-string> $groups */ private function buildDataProviderTestSuite(string $methodName, string $className, array $data, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings, array $groups): DataProviderTestSuite { $dataProviderTestSuite = DataProviderTestSuite::empty( $className . '::' . $methodName, ); $groups = array_merge( $groups, (new Groups)->groups($className, $methodName), ); foreach ($data as $_dataName => $_data) { $_test = new $className($methodName); $_test->setData($_dataName, $_data); $this->configureTestCase( $_test, $runTestInSeparateProcess, $preserveGlobalState, $runClassInSeparateProcess, $backupSettings, ); $dataProviderTestSuite->addTest($_test, $groups); } return $dataProviderTestSuite; } /** * @param array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} $backupSettings */ private function configureTestCase(TestCase $test, bool $runTestInSeparateProcess, ?bool $preserveGlobalState, bool $runClassInSeparateProcess, array $backupSettings): void { if ($runTestInSeparateProcess) { $test->setRunTestInSeparateProcess(true); } if ($runClassInSeparateProcess) { $test->setRunClassInSeparateProcess(true); } if ($preserveGlobalState !== null) { $test->setPreserveGlobalState($preserveGlobalState); } if ($backupSettings['backupGlobals'] !== null) { $test->setBackupGlobals($backupSettings['backupGlobals']); } else { $test->setBackupGlobals(ConfigurationRegistry::get()->backupGlobals()); } $test->setBackupGlobalsExcludeList($backupSettings['backupGlobalsExcludeList']); if ($backupSettings['backupStaticProperties'] !== null) { $test->setBackupStaticProperties($backupSettings['backupStaticProperties']); } else { $test->setBackupStaticProperties(ConfigurationRegistry::get()->backupStaticProperties()); } $test->setBackupStaticPropertiesExcludeList($backupSettings['backupStaticPropertiesExcludeList']); } /** * @param class-string<TestCase> $className * @param non-empty-string $methodName * * @return array{backupGlobals: ?bool, backupGlobalsExcludeList: list<string>, backupStaticProperties: ?bool, backupStaticPropertiesExcludeList: array<string,list<string>>} */ private function backupSettings(string $className, string $methodName): array { $metadataForClass = MetadataRegistry::parser()->forClass($className); $metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName); $metadataForClassAndMethod = MetadataRegistry::parser()->forClassAndMethod($className, $methodName); $backupGlobals = null; $backupGlobalsExcludeList = []; if ($metadataForMethod->isBackupGlobals()->isNotEmpty()) { $metadata = $metadataForMethod->isBackupGlobals()->asArray()[0]; assert($metadata instanceof BackupGlobals); if ($metadata->enabled()) { $backupGlobals = true; } } elseif ($metadataForClass->isBackupGlobals()->isNotEmpty()) { $metadata = $metadataForClass->isBackupGlobals()->asArray()[0]; assert($metadata instanceof BackupGlobals); if ($metadata->enabled()) { $backupGlobals = true; } } foreach ($metadataForClassAndMethod->isExcludeGlobalVariableFromBackup() as $metadata) { assert($metadata instanceof ExcludeGlobalVariableFromBackup); $backupGlobalsExcludeList[] = $metadata->globalVariableName(); } $backupStaticProperties = null; $backupStaticPropertiesExcludeList = []; if ($metadataForMethod->isBackupStaticProperties()->isNotEmpty()) { $metadata = $metadataForMethod->isBackupStaticProperties()->asArray()[0]; assert($metadata instanceof BackupStaticProperties); if ($metadata->enabled()) { $backupStaticProperties = true; } } elseif ($metadataForClass->isBackupStaticProperties()->isNotEmpty()) { $metadata = $metadataForClass->isBackupStaticProperties()->asArray()[0]; assert($metadata instanceof BackupStaticProperties); if ($metadata->enabled()) { $backupStaticProperties = true; } } foreach ($metadataForClassAndMethod->isExcludeStaticPropertyFromBackup() as $metadata) { assert($metadata instanceof ExcludeStaticPropertyFromBackup); if (!isset($backupStaticPropertiesExcludeList[$metadata->className()])) { $backupStaticPropertiesExcludeList[$metadata->className()] = []; } $backupStaticPropertiesExcludeList[$metadata->className()][] = $metadata->propertyName(); } return [ 'backupGlobals' => $backupGlobals, 'backupGlobalsExcludeList' => $backupGlobalsExcludeList, 'backupStaticProperties' => $backupStaticProperties, 'backupStaticPropertiesExcludeList' => $backupStaticPropertiesExcludeList, ]; } /** * @param class-string<TestCase> $className * @param non-empty-string $methodName */ private function shouldGlobalStateBePreserved(string $className, string $methodName): ?bool { $metadataForMethod = MetadataRegistry::parser()->forMethod($className, $methodName); if ($metadataForMethod->isPreserveGlobalState()->isNotEmpty()) { $metadata = $metadataForMethod->isPreserveGlobalState()->asArray()[0]; assert($metadata instanceof PreserveGlobalState); return $metadata->enabled(); } $metadataForClass = MetadataRegistry::parser()->forClass($className); if ($metadataForClass->isPreserveGlobalState()->isNotEmpty()) { $metadata = $metadataForClass->isPreserveGlobalState()->asArray()[0]; assert($metadata instanceof PreserveGlobalState); return $metadata->enabled(); } return null; } /** * @param class-string<TestCase> $className * @param non-empty-string $methodName */ private function shouldTestMethodBeRunInSeparateProcess(string $className, string $methodName): bool { if (MetadataRegistry::parser()->forClass($className)->isRunTestsInSeparateProcesses()->isNotEmpty()) { return true; } if (MetadataRegistry::parser()->forMethod($className, $methodName)->isRunInSeparateProcess()->isNotEmpty()) { return true; } return false; } /** * @param class-string<TestCase> $className */ private function shouldAllTestMethodsOfTestClassBeRunInSingleSeparateProcess(string $className): bool { return MetadataRegistry::parser()->forClass($className)->isRunClassInSeparateProcess()->isNotEmpty(); } } phpunit/src/Framework/ExecutionOrderDependency.php 0000644 00000011546 15253321353 0016437 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function array_filter; use function array_map; use function array_values; use function explode; use function in_array; use function str_contains; use PHPUnit\Metadata\DependsOnClass; use PHPUnit\Metadata\DependsOnMethod; use Stringable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExecutionOrderDependency implements Stringable { private string $className = ''; private string $methodName = ''; private readonly bool $shallowClone; private readonly bool $deepClone; public static function invalid(): self { return new self( '', '', false, false, ); } public static function forClass(DependsOnClass $metadata): self { return new self( $metadata->className(), 'class', $metadata->deepClone(), $metadata->shallowClone(), ); } public static function forMethod(DependsOnMethod $metadata): self { return new self( $metadata->className(), $metadata->methodName(), $metadata->deepClone(), $metadata->shallowClone(), ); } /** * @param list<ExecutionOrderDependency> $dependencies * * @return list<ExecutionOrderDependency> */ public static function filterInvalid(array $dependencies): array { return array_values( array_filter( $dependencies, static fn (self $d) => $d->isValid(), ), ); } /** * @param list<ExecutionOrderDependency> $existing * @param list<ExecutionOrderDependency> $additional * * @return list<ExecutionOrderDependency> */ public static function mergeUnique(array $existing, array $additional): array { $existingTargets = array_map( static fn ($dependency) => $dependency->getTarget(), $existing, ); foreach ($additional as $dependency) { $additionalTarget = $dependency->getTarget(); if (in_array($additionalTarget, $existingTargets, true)) { continue; } $existingTargets[] = $additionalTarget; $existing[] = $dependency; } return $existing; } /** * @param list<ExecutionOrderDependency> $left * @param list<ExecutionOrderDependency> $right * * @return list<ExecutionOrderDependency> */ public static function diff(array $left, array $right): array { if ($right === []) { return $left; } if ($left === []) { return []; } $diff = []; $rightTargets = array_map( static fn ($dependency) => $dependency->getTarget(), $right, ); foreach ($left as $dependency) { if (in_array($dependency->getTarget(), $rightTargets, true)) { continue; } $diff[] = $dependency; } return $diff; } public function __construct(string $classOrCallableName, ?string $methodName = null, bool $deepClone = false, bool $shallowClone = false) { $this->deepClone = $deepClone; $this->shallowClone = $shallowClone; if ($classOrCallableName === '') { return; } if (str_contains($classOrCallableName, '::')) { [$this->className, $this->methodName] = explode('::', $classOrCallableName); } else { $this->className = $classOrCallableName; $this->methodName = !empty($methodName) ? $methodName : 'class'; } } public function __toString(): string { return $this->getTarget(); } public function isValid(): bool { // Invalid dependencies can be declared and are skipped by the runner return $this->className !== '' && $this->methodName !== ''; } public function shallowClone(): bool { return $this->shallowClone; } public function deepClone(): bool { return $this->deepClone; } public function targetIsClass(): bool { return $this->methodName === 'class'; } public function getTarget(): string { return $this->isValid() ? $this->className . '::' . $this->methodName : ''; } public function getTargetClassName(): string { return $this->className; } } phpunit/src/Framework/TestSize/Large.php 0000644 00000001451 15253321353 0014277 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Large extends Known { public function isLarge(): true { return true; } public function isGreaterThan(TestSize $other): bool { return !$other->isLarge(); } public function asString(): string { return 'large'; } } phpunit/src/Framework/TestSize/TestSize.php 0000644 00000003056 15253321353 0015022 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ abstract readonly class TestSize { public static function unknown(): self { return new Unknown; } public static function small(): self { return new Small; } public static function medium(): self { return new Medium; } public static function large(): self { return new Large; } /** * @phpstan-assert-if-true Known $this */ public function isKnown(): bool { return false; } /** * @phpstan-assert-if-true Unknown $this */ public function isUnknown(): bool { return false; } /** * @phpstan-assert-if-true Small $this */ public function isSmall(): bool { return false; } /** * @phpstan-assert-if-true Medium $this */ public function isMedium(): bool { return false; } /** * @phpstan-assert-if-true Large $this */ public function isLarge(): bool { return false; } abstract public function asString(): string; } phpunit/src/Framework/TestSize/Small.php 0000644 00000001434 15253321353 0014316 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Small extends Known { public function isSmall(): true { return true; } public function isGreaterThan(TestSize $other): bool { return false; } public function asString(): string { return 'small'; } } phpunit/src/Framework/TestSize/Known.php 0000644 00000001272 15253321353 0014342 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ abstract readonly class Known extends TestSize { public function isKnown(): true { return true; } abstract public function isGreaterThan(self $other): bool; } phpunit/src/Framework/TestSize/Unknown.php 0000644 00000001311 15253321353 0014677 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Unknown extends TestSize { public function isUnknown(): true { return true; } public function asString(): string { return 'unknown'; } } phpunit/src/Framework/TestSize/Medium.php 0000644 00000001453 15253321353 0014467 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestSize; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Medium extends Known { public function isMedium(): true { return true; } public function isGreaterThan(TestSize $other): bool { return $other->isSmall(); } public function asString(): string { return 'medium'; } } phpunit/src/Framework/TestSuite.php 0000644 00000047243 15253321353 0013435 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use const PHP_EOL; use function array_keys; use function array_merge; use function array_pop; use function array_reverse; use function assert; use function call_user_func; use function class_exists; use function count; use function implode; use function is_callable; use function is_file; use function is_subclass_of; use function sprintf; use function str_ends_with; use function str_starts_with; use function trim; use Iterator; use IteratorAggregate; use PHPUnit\Event; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\NoPreviousThrowableException; use PHPUnit\Metadata\Api\Dependencies; use PHPUnit\Metadata\Api\Groups; use PHPUnit\Metadata\Api\HookMethods; use PHPUnit\Metadata\Api\Requirements; use PHPUnit\Metadata\MetadataCollection; use PHPUnit\Runner\Exception as RunnerException; use PHPUnit\Runner\Filter\Factory; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Runner\TestSuiteLoader; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\Util\Filter; use PHPUnit\Util\Reflection; use PHPUnit\Util\Test as TestUtil; use ReflectionClass; use ReflectionMethod; use SebastianBergmann\CodeCoverage\InvalidArgumentException; use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; use Throwable; /** * @template-implements IteratorAggregate<int, Test> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ class TestSuite implements IteratorAggregate, Reorderable, SelfDescribing, Test { /** * @var non-empty-string */ private string $name; /** * @var array<non-empty-string, list<non-empty-string>> */ private array $groups = []; /** * @var ?list<ExecutionOrderDependency> */ private ?array $requiredTests = null; /** * @var list<Test> */ private array $tests = []; /** * @var ?list<ExecutionOrderDependency> */ private ?array $providedTests = null; private ?Factory $iteratorFilter = null; private bool $wasRun = false; /** * @param non-empty-string $name */ public static function empty(string $name): static { return new static($name); } /** * @param ReflectionClass<TestCase> $class * @param list<non-empty-string> $groups */ public static function fromClassReflector(ReflectionClass $class, array $groups = []): static { $testSuite = new static($class->getName()); foreach (Reflection::publicMethodsDeclaredDirectlyInTestClass($class) as $method) { if (!TestUtil::isTestMethod($method)) { continue; } $testSuite->addTestMethod($class, $method, $groups); } if ($testSuite->isEmpty()) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( 'No tests found in class "%s".', $class->getName(), ), ); } return $testSuite; } /** * @param non-empty-string $name */ final private function __construct(string $name) { $this->name = $name; } /** * Returns a string representation of the test suite. */ public function toString(): string { return $this->name(); } /** * Adds a test to the suite. * * @param list<non-empty-string> $groups */ public function addTest(Test $test, array $groups = []): void { if ($test instanceof self) { $this->tests[] = $test; $this->clearCaches(); return; } assert($test instanceof TestCase || $test instanceof PhptTestCase); $class = new ReflectionClass($test); if (!$class->isAbstract()) { $this->tests[] = $test; $this->clearCaches(); if ($this->containsOnlyVirtualGroups($groups)) { $groups[] = 'default'; } if ($test instanceof TestCase) { $id = $test->valueObjectForEvents()->id(); $test->setGroups($groups); } else { $id = $test->valueObjectForEvents()->id(); } foreach ($groups as $group) { if (!isset($this->groups[$group])) { $this->groups[$group] = [$id]; } else { $this->groups[$group][] = $id; } } } } /** * Adds the tests from the given class to the suite. * * @param ReflectionClass<TestCase> $testClass * @param list<non-empty-string> $groups * * @throws Exception */ public function addTestSuite(ReflectionClass $testClass, array $groups = []): void { if ($testClass->isAbstract()) { throw new Exception( sprintf( 'Class %s is abstract', $testClass->getName(), ), ); } if (!$testClass->isSubclassOf(TestCase::class)) { throw new Exception( sprintf( 'Class %s is not a subclass of %s', $testClass->getName(), TestCase::class, ), ); } $this->addTest(self::fromClassReflector($testClass, $groups), $groups); } /** * Wraps both <code>addTest()</code> and <code>addTestSuite</code> * as well as the separate import statements for the user's convenience. * * If the named file cannot be read or there are no new tests that can be * added, a <code>PHPUnit\Framework\WarningTestCase</code> will be created instead, * leaving the current test run untouched. * * @param list<non-empty-string> $groups * * @throws Exception */ public function addTestFile(string $filename, array $groups = []): void { if (str_ends_with($filename, '.phpt') && is_file($filename)) { try { $this->addTest(new PhptTestCase($filename)); } catch (RunnerException $e) { Event\Facade::emitter()->testRunnerTriggeredWarning( $e->getMessage(), ); } return; } try { $this->addTestSuite( (new TestSuiteLoader)->load($filename), $groups, ); } catch (RunnerException $e) { Event\Facade::emitter()->testRunnerTriggeredWarning( $e->getMessage(), ); } } /** * Wrapper for addTestFile() that adds multiple test files. * * @param iterable<string> $fileNames * * @throws Exception */ public function addTestFiles(iterable $fileNames): void { foreach ($fileNames as $filename) { $this->addTestFile((string) $filename); } } /** * Counts the number of test cases that will be run by this test. */ public function count(): int { $numTests = 0; foreach ($this as $test) { $numTests += count($test); } return $numTests; } public function isEmpty(): bool { foreach ($this as $test) { if (count($test) !== 0) { return false; } } return true; } /** * @return non-empty-string */ public function name(): string { return $this->name; } /** * Returns the test groups of the suite. * * @return list<non-empty-string> */ public function groups(): array { return array_keys($this->groups); } /** * @return array<non-empty-string, list<non-empty-string>> */ public function groupDetails(): array { return $this->groups; } /** * @return list<PhptTestCase|TestCase> */ public function collect(): array { $tests = []; foreach ($this as $test) { if ($test instanceof self) { $tests = array_merge($tests, $test->collect()); continue; } assert($test instanceof TestCase || $test instanceof PhptTestCase); $tests[] = $test; } return $tests; } /** * @throws CodeCoverageException * @throws Event\RuntimeException * @throws Exception * @throws InvalidArgumentException * @throws NoPreviousThrowableException * @throws UnintentionallyCoveredCodeException */ public function run(): void { if ($this->wasRun) { // @codeCoverageIgnoreStart throw new Exception('The tests aggregated by this TestSuite were already run'); // @codeCoverageIgnoreEnd } $this->wasRun = true; if ($this->isEmpty()) { return; } $emitter = Event\Facade::emitter(); $testSuiteValueObjectForEvents = Event\TestSuite\TestSuiteBuilder::from($this); $emitter->testSuiteStarted($testSuiteValueObjectForEvents); if (!$this->invokeMethodsBeforeFirstTest($emitter, $testSuiteValueObjectForEvents)) { return; } /** @var list<Test> $tests */ $tests = []; foreach ($this as $test) { $tests[] = $test; } $tests = array_reverse($tests); $this->tests = []; $this->groups = []; while (($test = array_pop($tests)) !== null) { if (TestResultFacade::shouldStop()) { $emitter->testRunnerExecutionAborted(); break; } $test->run(); } $this->invokeMethodsAfterLastTest($emitter); $emitter->testSuiteFinished($testSuiteValueObjectForEvents); } /** * Returns the tests as an enumeration. * * @return list<Test> */ public function tests(): array { return $this->tests; } /** * Set tests of the test suite. * * @param list<Test> $tests */ public function setTests(array $tests): void { $this->tests = $tests; } /** * Mark the test suite as skipped. * * @throws SkippedTestSuiteError */ public function markTestSuiteSkipped(string $message = ''): never { throw new SkippedTestSuiteError($message); } /** * Returns an iterator for this test suite. */ public function getIterator(): Iterator { $iterator = new TestSuiteIterator($this); if ($this->iteratorFilter !== null) { $iterator = $this->iteratorFilter->factory($iterator, $this); } return $iterator; } public function injectFilter(Factory $filter): void { $this->iteratorFilter = $filter; foreach ($this as $test) { if ($test instanceof self) { $test->injectFilter($filter); } } } /** * @return list<ExecutionOrderDependency> */ public function provides(): array { if ($this->providedTests === null) { $this->providedTests = []; if (is_callable($this->sortId(), true)) { $this->providedTests[] = new ExecutionOrderDependency($this->sortId()); } foreach ($this->tests as $test) { if (!($test instanceof Reorderable)) { continue; } $this->providedTests = ExecutionOrderDependency::mergeUnique($this->providedTests, $test->provides()); } } return $this->providedTests; } /** * @return list<ExecutionOrderDependency> */ public function requires(): array { if ($this->requiredTests === null) { $this->requiredTests = []; foreach ($this->tests as $test) { if (!($test instanceof Reorderable)) { continue; } $this->requiredTests = ExecutionOrderDependency::mergeUnique( ExecutionOrderDependency::filterInvalid($this->requiredTests), $test->requires(), ); } $this->requiredTests = ExecutionOrderDependency::diff($this->requiredTests, $this->provides()); } return $this->requiredTests; } public function sortId(): string { return $this->name() . '::class'; } /** * @phpstan-assert-if-true class-string<TestCase> $this->name */ public function isForTestClass(): bool { return class_exists($this->name, false) && is_subclass_of($this->name, TestCase::class); } /** * @param ReflectionClass<TestCase> $class * @param list<non-empty-string> $groups * * @throws Exception */ protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method, array $groups): void { $className = $class->getName(); $methodName = $method->getName(); assert(!empty($methodName)); try { $test = (new TestBuilder)->build($class, $methodName, $groups); } catch (InvalidDataProviderException $e) { Event\Facade::emitter()->testTriggeredPhpunitError( new TestMethod( $className, $methodName, $class->getFileName(), $method->getStartLine(), Event\Code\TestDoxBuilder::fromClassNameAndMethodName( $className, $methodName, ), MetadataCollection::fromArray([]), Event\TestData\TestDataCollection::fromArray([]), ), sprintf( "The data provider specified for %s::%s is invalid\n%s", $className, $methodName, $this->throwableToString($e), ), ); return; } if ($test instanceof TestCase || $test instanceof DataProviderTestSuite) { $test->setDependencies( Dependencies::dependencies($class->getName(), $methodName), ); } $this->addTest( $test, array_merge( $groups, (new Groups)->groups($class->getName(), $methodName), ), ); } private function clearCaches(): void { $this->providedTests = null; $this->requiredTests = null; } /** * @param list<non-empty-string> $groups */ private function containsOnlyVirtualGroups(array $groups): bool { foreach ($groups as $group) { if (!str_starts_with($group, '__phpunit_')) { return false; } } return true; } private function methodDoesNotExistOrIsDeclaredInTestCase(string $methodName): bool { $reflector = new ReflectionClass($this->name); return !$reflector->hasMethod($methodName) || $reflector->getMethod($methodName)->getDeclaringClass()->getName() === TestCase::class; } /** * @throws Exception */ private function throwableToString(Throwable $t): string { $message = $t->getMessage(); if (empty(trim($message))) { $message = '<no message>'; } if ($t instanceof InvalidDataProviderException) { return sprintf( "%s\n%s", $message, Filter::getFilteredStacktrace($t), ); } return sprintf( "%s: %s\n%s", $t::class, $message, Filter::getFilteredStacktrace($t), ); } /** * @throws Exception * @throws NoPreviousThrowableException */ private function invokeMethodsBeforeFirstTest(Event\Emitter $emitter, Event\TestSuite\TestSuite $testSuiteValueObjectForEvents): bool { if (!$this->isForTestClass()) { return true; } $methodsCalledBeforeFirstTest = []; $beforeClassMethods = (new HookMethods)->hookMethods($this->name)['beforeClass']; try { foreach ($beforeClassMethods->methodNamesSortedByPriority() as $beforeClassMethod) { if ($this->methodDoesNotExistOrIsDeclaredInTestCase($beforeClassMethod)) { continue; } if ($missingRequirements = (new Requirements)->requirementsNotSatisfiedFor($this->name, $beforeClassMethod)) { $this->markTestSuiteSkipped(implode(PHP_EOL, $missingRequirements)); } $methodCalledBeforeFirstTest = new Event\Code\ClassMethod( $this->name, $beforeClassMethod, ); $emitter->testBeforeFirstTestMethodCalled( $this->name, $methodCalledBeforeFirstTest, ); $methodsCalledBeforeFirstTest[] = $methodCalledBeforeFirstTest; call_user_func([$this->name, $beforeClassMethod]); } } catch (SkippedTest|SkippedTestSuiteError $e) { $emitter->testSuiteSkipped( $testSuiteValueObjectForEvents, $e->getMessage(), ); return false; } catch (Throwable $t) { assert(isset($methodCalledBeforeFirstTest)); $emitter->testBeforeFirstTestMethodErrored( $this->name, $methodCalledBeforeFirstTest, Event\Code\ThrowableBuilder::from($t), ); if (!empty($methodsCalledBeforeFirstTest)) { $emitter->testBeforeFirstTestMethodFinished( $this->name, ...$methodsCalledBeforeFirstTest, ); } return false; } if (!empty($methodsCalledBeforeFirstTest)) { $emitter->testBeforeFirstTestMethodFinished( $this->name, ...$methodsCalledBeforeFirstTest, ); } return true; } private function invokeMethodsAfterLastTest(Event\Emitter $emitter): void { if (!$this->isForTestClass()) { return; } $methodsCalledAfterLastTest = []; $afterClassMethods = (new HookMethods)->hookMethods($this->name)['afterClass']; foreach ($afterClassMethods->methodNamesSortedByPriority() as $afterClassMethod) { if ($this->methodDoesNotExistOrIsDeclaredInTestCase($afterClassMethod)) { continue; } try { call_user_func([$this->name, $afterClassMethod]); $methodCalledAfterLastTest = new Event\Code\ClassMethod( $this->name, $afterClassMethod, ); $emitter->testAfterLastTestMethodCalled( $this->name, $methodCalledAfterLastTest, ); $methodsCalledAfterLastTest[] = $methodCalledAfterLastTest; } catch (Throwable) { // @todo } } if (!empty($methodsCalledAfterLastTest)) { $emitter->testAfterLastTestMethodFinished( $this->name, ...$methodsCalledAfterLastTest, ); } } } phpunit/src/Framework/Assert.php 0000644 00000220262 15253321353 0012737 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function array_combine; use function array_intersect_key; use function class_exists; use function count; use function file_get_contents; use function interface_exists; use function is_bool; use ArrayAccess; use Countable; use Generator; use PHPUnit\Event; use PHPUnit\Framework\Constraint\ArrayHasKey; use PHPUnit\Framework\Constraint\Callback; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\Constraint\Count; use PHPUnit\Framework\Constraint\DirectoryExists; use PHPUnit\Framework\Constraint\FileExists; use PHPUnit\Framework\Constraint\GreaterThan; use PHPUnit\Framework\Constraint\IsAnything; use PHPUnit\Framework\Constraint\IsEmpty; use PHPUnit\Framework\Constraint\IsEqual; use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; use PHPUnit\Framework\Constraint\IsEqualWithDelta; use PHPUnit\Framework\Constraint\IsFalse; use PHPUnit\Framework\Constraint\IsFinite; use PHPUnit\Framework\Constraint\IsIdentical; use PHPUnit\Framework\Constraint\IsInfinite; use PHPUnit\Framework\Constraint\IsInstanceOf; use PHPUnit\Framework\Constraint\IsJson; use PHPUnit\Framework\Constraint\IsList; use PHPUnit\Framework\Constraint\IsNan; use PHPUnit\Framework\Constraint\IsNull; use PHPUnit\Framework\Constraint\IsReadable; use PHPUnit\Framework\Constraint\IsTrue; use PHPUnit\Framework\Constraint\IsType; use PHPUnit\Framework\Constraint\IsWritable; use PHPUnit\Framework\Constraint\JsonMatches; use PHPUnit\Framework\Constraint\LessThan; use PHPUnit\Framework\Constraint\LogicalAnd; use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\Constraint\LogicalOr; use PHPUnit\Framework\Constraint\LogicalXor; use PHPUnit\Framework\Constraint\ObjectEquals; use PHPUnit\Framework\Constraint\ObjectHasProperty; use PHPUnit\Framework\Constraint\RegularExpression; use PHPUnit\Framework\Constraint\SameSize; use PHPUnit\Framework\Constraint\StringContains; use PHPUnit\Framework\Constraint\StringEndsWith; use PHPUnit\Framework\Constraint\StringEqualsStringIgnoringLineEndings; use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; use PHPUnit\Framework\Constraint\StringStartsWith; use PHPUnit\Framework\Constraint\TraversableContainsEqual; use PHPUnit\Framework\Constraint\TraversableContainsIdentical; use PHPUnit\Framework\Constraint\TraversableContainsOnly; use PHPUnit\Util\Xml\Loader as XmlLoader; use PHPUnit\Util\Xml\XmlException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class Assert { private static int $count = 0; /** * Asserts that two arrays are equal while only considering a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeConsidered * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayIsEqualToArrayOnlyConsideringListOfKeys(array $expected, array $actual, array $keysToBeConsidered, string $message = ''): void { $filteredExpected = []; foreach ($keysToBeConsidered as $key) { if (isset($expected[$key])) { $filteredExpected[$key] = $expected[$key]; } } $filteredActual = []; foreach ($keysToBeConsidered as $key) { if (isset($actual[$key])) { $filteredActual[$key] = $actual[$key]; } } self::assertEquals($filteredExpected, $filteredActual, $message); } /** * Asserts that two arrays are equal while ignoring a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeIgnored * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayIsEqualToArrayIgnoringListOfKeys(array $expected, array $actual, array $keysToBeIgnored, string $message = ''): void { foreach ($keysToBeIgnored as $key) { unset($expected[$key], $actual[$key]); } self::assertEquals($expected, $actual, $message); } /** * Asserts that two arrays are identical while only considering a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeConsidered * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys(array $expected, array $actual, array $keysToBeConsidered, string $message = ''): void { $keysToBeConsidered = array_combine($keysToBeConsidered, $keysToBeConsidered); $expected = array_intersect_key($expected, $keysToBeConsidered); $actual = array_intersect_key($actual, $keysToBeConsidered); self::assertSame($expected, $actual, $message); } /** * Asserts that two arrays are equal while ignoring a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeIgnored * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayIsIdenticalToArrayIgnoringListOfKeys(array $expected, array $actual, array $keysToBeIgnored, string $message = ''): void { foreach ($keysToBeIgnored as $key) { unset($expected[$key], $actual[$key]); } self::assertSame($expected, $actual, $message); } /** * Asserts that an array has a specified key. * * @param array<mixed>|ArrayAccess<array-key, mixed> $array * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { $constraint = new ArrayHasKey($key); self::assertThat($array, $constraint, $message); } /** * Asserts that an array does not have a specified key. * * @param array<mixed>|ArrayAccess<array-key, mixed> $array * * @throws Exception * @throws ExpectationFailedException */ final public static function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { $constraint = new LogicalNot( new ArrayHasKey($key), ); self::assertThat($array, $constraint, $message); } /** * @throws ExpectationFailedException */ final public static function assertIsList(mixed $array, string $message = ''): void { self::assertThat( $array, new IsList, $message, ); } /** * Asserts that a haystack contains a needle. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException */ final public static function assertContains(mixed $needle, iterable $haystack, string $message = ''): void { $constraint = new TraversableContainsIdentical($needle); self::assertThat($haystack, $constraint, $message); } /** * @param iterable<mixed> $haystack * * @throws ExpectationFailedException */ final public static function assertContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void { $constraint = new TraversableContainsEqual($needle); self::assertThat($haystack, $constraint, $message); } /** * Asserts that a haystack does not contain a needle. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException */ final public static function assertNotContains(mixed $needle, iterable $haystack, string $message = ''): void { $constraint = new LogicalNot( new TraversableContainsIdentical($needle), ); self::assertThat($haystack, $constraint, $message); } /** * @param iterable<mixed> $haystack * * @throws ExpectationFailedException */ final public static function assertNotContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void { $constraint = new LogicalNot(new TraversableContainsEqual($needle)); self::assertThat($haystack, $constraint, $message); } /** * Asserts that a haystack contains only values of a given type. * * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' $type * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException */ final public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void { if ($isNativeType === null) { $isNativeType = self::isNativeType($type); } self::assertThat( $haystack, new TraversableContainsOnly( $type, $isNativeType, ), $message, ); } /** * Asserts that a haystack contains only instances of a given class name. * * @param class-string $className * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException */ final public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void { self::assertThat( $haystack, new TraversableContainsOnly( $className, false, ), $message, ); } /** * Asserts that a haystack does not contain only values of a given type. * * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' $type * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException */ final public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void { if ($isNativeType === null) { $isNativeType = self::isNativeType($type); } self::assertThat( $haystack, new LogicalNot( new TraversableContainsOnly( $type, $isNativeType, ), ), $message, ); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param Countable|iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException */ final public static function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { if ($haystack instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$haystack'); } self::assertThat( $haystack, new Count($expectedCount), $message, ); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param Countable|iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException */ final public static function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { if ($haystack instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$haystack'); } $constraint = new LogicalNot( new Count($expectedCount), ); self::assertThat($haystack, $constraint, $message); } /** * Asserts that two variables are equal. * * @throws ExpectationFailedException */ final public static function assertEquals(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new IsEqual($expected); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are equal (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new IsEqualCanonicalizing($expected); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are equal (ignoring case). * * @throws ExpectationFailedException */ final public static function assertEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new IsEqualIgnoringCase($expected); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are equal (with delta). * * @throws ExpectationFailedException */ final public static function assertEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void { $constraint = new IsEqualWithDelta( $expected, $delta, ); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are not equal. * * @throws ExpectationFailedException */ final public static function assertNotEquals(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new LogicalNot( new IsEqual($expected), ); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are not equal (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertNotEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new LogicalNot( new IsEqualCanonicalizing($expected), ); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are not equal (ignoring case). * * @throws ExpectationFailedException */ final public static function assertNotEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void { $constraint = new LogicalNot( new IsEqualIgnoringCase($expected), ); self::assertThat($actual, $constraint, $message); } /** * Asserts that two variables are not equal (with delta). * * @throws ExpectationFailedException */ final public static function assertNotEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void { $constraint = new LogicalNot( new IsEqualWithDelta( $expected, $delta, ), ); self::assertThat($actual, $constraint, $message); } /** * @throws ExpectationFailedException */ final public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void { self::assertThat( $actual, self::objectEquals($expected, $method), $message, ); } /** * @throws ExpectationFailedException */ final public static function assertObjectNotEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void { self::assertThat( $actual, self::logicalNot( self::objectEquals($expected, $method), ), $message, ); } /** * Asserts that a variable is empty. * * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @phpstan-assert empty $actual */ final public static function assertEmpty(mixed $actual, string $message = ''): void { if ($actual instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$actual'); } self::assertThat($actual, self::isEmpty(), $message); } /** * Asserts that a variable is not empty. * * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @phpstan-assert !empty $actual */ final public static function assertNotEmpty(mixed $actual, string $message = ''): void { if ($actual instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$actual'); } self::assertThat($actual, self::logicalNot(self::isEmpty()), $message); } /** * Asserts that a value is greater than another value. * * @throws ExpectationFailedException */ final public static function assertGreaterThan(mixed $expected, mixed $actual, string $message = ''): void { self::assertThat($actual, self::greaterThan($expected), $message); } /** * Asserts that a value is greater than or equal to another value. * * @throws ExpectationFailedException */ final public static function assertGreaterThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void { self::assertThat( $actual, self::greaterThanOrEqual($expected), $message, ); } /** * Asserts that a value is smaller than another value. * * @throws ExpectationFailedException */ final public static function assertLessThan(mixed $expected, mixed $actual, string $message = ''): void { self::assertThat($actual, self::lessThan($expected), $message); } /** * Asserts that a value is smaller than or equal to another value. * * @throws ExpectationFailedException */ final public static function assertLessThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void { self::assertThat($actual, self::lessThanOrEqual($expected), $message); } /** * Asserts that the contents of one file is equal to the contents of another * file. * * @throws ExpectationFailedException */ final public static function assertFileEquals(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new IsEqual(file_get_contents($expected)); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of one file is equal to the contents of another * file (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new IsEqualCanonicalizing( file_get_contents($expected), ); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of one file is equal to the contents of another * file (ignoring case). * * @throws ExpectationFailedException */ final public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new IsEqualIgnoringCase(file_get_contents($expected)); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of one file is not equal to the contents of * another file. * * @throws ExpectationFailedException */ final public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new LogicalNot( new IsEqual(file_get_contents($expected)), ); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of one file is not equal to the contents of another * file (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new LogicalNot( new IsEqualCanonicalizing(file_get_contents($expected)), ); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of one file is not equal to the contents of another * file (ignoring case). * * @throws ExpectationFailedException */ final public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void { self::assertFileExists($expected, $message); self::assertFileExists($actual, $message); $constraint = new LogicalNot( new IsEqualIgnoringCase(file_get_contents($expected)), ); self::assertThat(file_get_contents($actual), $constraint, $message); } /** * Asserts that the contents of a string is equal * to the contents of a file. * * @throws ExpectationFailedException */ final public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new IsEqual(file_get_contents($expectedFile)); self::assertThat($actualString, $constraint, $message); } /** * Asserts that the contents of a string is equal * to the contents of a file (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile)); self::assertThat($actualString, $constraint, $message); } /** * Asserts that the contents of a string is equal * to the contents of a file (ignoring case). * * @throws ExpectationFailedException */ final public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile)); self::assertThat($actualString, $constraint, $message); } /** * Asserts that the contents of a string is not equal * to the contents of a file. * * @throws ExpectationFailedException */ final public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new LogicalNot( new IsEqual(file_get_contents($expectedFile)), ); self::assertThat($actualString, $constraint, $message); } /** * Asserts that the contents of a string is not equal * to the contents of a file (canonicalizing). * * @throws ExpectationFailedException */ final public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new LogicalNot( new IsEqualCanonicalizing(file_get_contents($expectedFile)), ); self::assertThat($actualString, $constraint, $message); } /** * Asserts that the contents of a string is not equal * to the contents of a file (ignoring case). * * @throws ExpectationFailedException */ final public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void { self::assertFileExists($expectedFile, $message); $constraint = new LogicalNot( new IsEqualIgnoringCase(file_get_contents($expectedFile)), ); self::assertThat($actualString, $constraint, $message); } /** * Asserts that a file/dir is readable. * * @throws ExpectationFailedException */ final public static function assertIsReadable(string $filename, string $message = ''): void { self::assertThat($filename, new IsReadable, $message); } /** * Asserts that a file/dir exists and is not readable. * * @throws ExpectationFailedException */ final public static function assertIsNotReadable(string $filename, string $message = ''): void { self::assertThat($filename, new LogicalNot(new IsReadable), $message); } /** * Asserts that a file/dir exists and is writable. * * @throws ExpectationFailedException */ final public static function assertIsWritable(string $filename, string $message = ''): void { self::assertThat($filename, new IsWritable, $message); } /** * Asserts that a file/dir exists and is not writable. * * @throws ExpectationFailedException */ final public static function assertIsNotWritable(string $filename, string $message = ''): void { self::assertThat($filename, new LogicalNot(new IsWritable), $message); } /** * Asserts that a directory exists. * * @throws ExpectationFailedException */ final public static function assertDirectoryExists(string $directory, string $message = ''): void { self::assertThat($directory, new DirectoryExists, $message); } /** * Asserts that a directory does not exist. * * @throws ExpectationFailedException */ final public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void { self::assertThat($directory, new LogicalNot(new DirectoryExists), $message); } /** * Asserts that a directory exists and is readable. * * @throws ExpectationFailedException */ final public static function assertDirectoryIsReadable(string $directory, string $message = ''): void { self::assertDirectoryExists($directory, $message); self::assertIsReadable($directory, $message); } /** * Asserts that a directory exists and is not readable. * * @throws ExpectationFailedException */ final public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void { self::assertDirectoryExists($directory, $message); self::assertIsNotReadable($directory, $message); } /** * Asserts that a directory exists and is writable. * * @throws ExpectationFailedException */ final public static function assertDirectoryIsWritable(string $directory, string $message = ''): void { self::assertDirectoryExists($directory, $message); self::assertIsWritable($directory, $message); } /** * Asserts that a directory exists and is not writable. * * @throws ExpectationFailedException */ final public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void { self::assertDirectoryExists($directory, $message); self::assertIsNotWritable($directory, $message); } /** * Asserts that a file exists. * * @throws ExpectationFailedException */ final public static function assertFileExists(string $filename, string $message = ''): void { self::assertThat($filename, new FileExists, $message); } /** * Asserts that a file does not exist. * * @throws ExpectationFailedException */ final public static function assertFileDoesNotExist(string $filename, string $message = ''): void { self::assertThat($filename, new LogicalNot(new FileExists), $message); } /** * Asserts that a file exists and is readable. * * @throws ExpectationFailedException */ final public static function assertFileIsReadable(string $file, string $message = ''): void { self::assertFileExists($file, $message); self::assertIsReadable($file, $message); } /** * Asserts that a file exists and is not readable. * * @throws ExpectationFailedException */ final public static function assertFileIsNotReadable(string $file, string $message = ''): void { self::assertFileExists($file, $message); self::assertIsNotReadable($file, $message); } /** * Asserts that a file exists and is writable. * * @throws ExpectationFailedException */ final public static function assertFileIsWritable(string $file, string $message = ''): void { self::assertFileExists($file, $message); self::assertIsWritable($file, $message); } /** * Asserts that a file exists and is not writable. * * @throws ExpectationFailedException */ final public static function assertFileIsNotWritable(string $file, string $message = ''): void { self::assertFileExists($file, $message); self::assertIsNotWritable($file, $message); } /** * Asserts that a condition is true. * * @throws ExpectationFailedException * * @phpstan-assert true $condition */ final public static function assertTrue(mixed $condition, string $message = ''): void { self::assertThat($condition, self::isTrue(), $message); } /** * Asserts that a condition is not true. * * @throws ExpectationFailedException * * @phpstan-assert !true $condition */ final public static function assertNotTrue(mixed $condition, string $message = ''): void { self::assertThat($condition, self::logicalNot(self::isTrue()), $message); } /** * Asserts that a condition is false. * * @throws ExpectationFailedException * * @phpstan-assert false $condition */ final public static function assertFalse(mixed $condition, string $message = ''): void { self::assertThat($condition, self::isFalse(), $message); } /** * Asserts that a condition is not false. * * @throws ExpectationFailedException * * @phpstan-assert !false $condition */ final public static function assertNotFalse(mixed $condition, string $message = ''): void { self::assertThat($condition, self::logicalNot(self::isFalse()), $message); } /** * Asserts that a variable is null. * * @throws ExpectationFailedException * * @phpstan-assert null $actual */ final public static function assertNull(mixed $actual, string $message = ''): void { self::assertThat($actual, self::isNull(), $message); } /** * Asserts that a variable is not null. * * @throws ExpectationFailedException * * @phpstan-assert !null $actual */ final public static function assertNotNull(mixed $actual, string $message = ''): void { self::assertThat($actual, self::logicalNot(self::isNull()), $message); } /** * Asserts that a variable is finite. * * @throws ExpectationFailedException */ final public static function assertFinite(mixed $actual, string $message = ''): void { self::assertThat($actual, self::isFinite(), $message); } /** * Asserts that a variable is infinite. * * @throws ExpectationFailedException */ final public static function assertInfinite(mixed $actual, string $message = ''): void { self::assertThat($actual, self::isInfinite(), $message); } /** * Asserts that a variable is nan. * * @throws ExpectationFailedException */ final public static function assertNan(mixed $actual, string $message = ''): void { self::assertThat($actual, self::isNan(), $message); } /** * Asserts that an object has a specified property. * * @throws ExpectationFailedException */ final public static function assertObjectHasProperty(string $propertyName, object $object, string $message = ''): void { self::assertThat( $object, new ObjectHasProperty($propertyName), $message, ); } /** * Asserts that an object does not have a specified property. * * @throws ExpectationFailedException */ final public static function assertObjectNotHasProperty(string $propertyName, object $object, string $message = ''): void { self::assertThat( $object, new LogicalNot( new ObjectHasProperty($propertyName), ), $message, ); } /** * Asserts that two variables have the same type and value. * Used on objects, it asserts that two variables reference * the same object. * * @template ExpectedType * * @param ExpectedType $expected * * @throws ExpectationFailedException * * @phpstan-assert =ExpectedType $actual */ final public static function assertSame(mixed $expected, mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsIdentical($expected), $message, ); } /** * Asserts that two variables do not have the same type and value. * Used on objects, it asserts that two variables do not reference * the same object. * * @throws ExpectationFailedException */ final public static function assertNotSame(mixed $expected, mixed $actual, string $message = ''): void { if (is_bool($expected) && is_bool($actual)) { self::assertNotEquals($expected, $actual, $message); } self::assertThat( $actual, new LogicalNot( new IsIdentical($expected), ), $message, ); } /** * Asserts that a variable is of a given type. * * @template ExpectedType of object * * @param class-string<ExpectedType> $expected * * @throws Exception * @throws ExpectationFailedException * @throws UnknownClassOrInterfaceException * * @phpstan-assert =ExpectedType $actual */ final public static function assertInstanceOf(string $expected, mixed $actual, string $message = ''): void { if (!class_exists($expected) && !interface_exists($expected)) { throw new UnknownClassOrInterfaceException($expected); } self::assertThat( $actual, new IsInstanceOf($expected), $message, ); } /** * Asserts that a variable is not of a given type. * * @template ExpectedType of object * * @param class-string<ExpectedType> $expected * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !ExpectedType $actual */ final public static function assertNotInstanceOf(string $expected, mixed $actual, string $message = ''): void { if (!class_exists($expected) && !interface_exists($expected)) { throw new UnknownClassOrInterfaceException($expected); } self::assertThat( $actual, new LogicalNot( new IsInstanceOf($expected), ), $message, ); } /** * Asserts that a variable is of type array. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert array $actual */ final public static function assertIsArray(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_ARRAY), $message, ); } /** * Asserts that a variable is of type bool. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert bool $actual */ final public static function assertIsBool(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_BOOL), $message, ); } /** * Asserts that a variable is of type float. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert float $actual */ final public static function assertIsFloat(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_FLOAT), $message, ); } /** * Asserts that a variable is of type int. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert int $actual */ final public static function assertIsInt(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_INT), $message, ); } /** * Asserts that a variable is of type numeric. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert numeric $actual */ final public static function assertIsNumeric(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_NUMERIC), $message, ); } /** * Asserts that a variable is of type object. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert object $actual */ final public static function assertIsObject(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_OBJECT), $message, ); } /** * Asserts that a variable is of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert resource $actual */ final public static function assertIsResource(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_RESOURCE), $message, ); } /** * Asserts that a variable is of type resource and is closed. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert resource $actual */ final public static function assertIsClosedResource(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_CLOSED_RESOURCE), $message, ); } /** * Asserts that a variable is of type string. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert string $actual */ final public static function assertIsString(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_STRING), $message, ); } /** * Asserts that a variable is of type scalar. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert scalar $actual */ final public static function assertIsScalar(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_SCALAR), $message, ); } /** * Asserts that a variable is of type callable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert callable $actual */ final public static function assertIsCallable(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_CALLABLE), $message, ); } /** * Asserts that a variable is of type iterable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert iterable $actual */ final public static function assertIsIterable(mixed $actual, string $message = ''): void { self::assertThat( $actual, new IsType(IsType::TYPE_ITERABLE), $message, ); } /** * Asserts that a variable is not of type array. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !array $actual */ final public static function assertIsNotArray(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_ARRAY)), $message, ); } /** * Asserts that a variable is not of type bool. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !bool $actual */ final public static function assertIsNotBool(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_BOOL)), $message, ); } /** * Asserts that a variable is not of type float. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !float $actual */ final public static function assertIsNotFloat(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_FLOAT)), $message, ); } /** * Asserts that a variable is not of type int. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !int $actual */ final public static function assertIsNotInt(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_INT)), $message, ); } /** * Asserts that a variable is not of type numeric. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !numeric $actual */ final public static function assertIsNotNumeric(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_NUMERIC)), $message, ); } /** * Asserts that a variable is not of type object. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !object $actual */ final public static function assertIsNotObject(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_OBJECT)), $message, ); } /** * Asserts that a variable is not of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !resource $actual */ final public static function assertIsNotResource(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_RESOURCE)), $message, ); } /** * Asserts that a variable is not of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !resource $actual */ final public static function assertIsNotClosedResource(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)), $message, ); } /** * Asserts that a variable is not of type string. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !string $actual */ final public static function assertIsNotString(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_STRING)), $message, ); } /** * Asserts that a variable is not of type scalar. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !scalar $actual */ final public static function assertIsNotScalar(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_SCALAR)), $message, ); } /** * Asserts that a variable is not of type callable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !callable $actual */ final public static function assertIsNotCallable(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_CALLABLE)), $message, ); } /** * Asserts that a variable is not of type iterable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !iterable $actual */ final public static function assertIsNotIterable(mixed $actual, string $message = ''): void { self::assertThat( $actual, new LogicalNot(new IsType(IsType::TYPE_ITERABLE)), $message, ); } /** * Asserts that a string matches a given regular expression. * * @throws ExpectationFailedException */ final public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void { self::assertThat($string, new RegularExpression($pattern), $message); } /** * Asserts that a string does not match a given regular expression. * * @throws ExpectationFailedException */ final public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void { self::assertThat( $string, new LogicalNot( new RegularExpression($pattern), ), $message, ); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is the same. * * @param Countable|iterable<mixed> $expected * @param Countable|iterable<mixed> $actual * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException */ final public static function assertSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { if ($expected instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$expected'); } if ($actual instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$actual'); } self::assertThat( $actual, new SameSize($expected), $message, ); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is not the same. * * @param Countable|iterable<mixed> $expected * @param Countable|iterable<mixed> $actual * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException */ final public static function assertNotSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { if ($expected instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$expected'); } if ($actual instanceof Generator) { throw GeneratorNotSupportedException::fromParameterName('$actual'); } self::assertThat( $actual, new LogicalNot( new SameSize($expected), ), $message, ); } /** * @throws ExpectationFailedException */ final public static function assertStringContainsStringIgnoringLineEndings(string $needle, string $haystack, string $message = ''): void { self::assertThat($haystack, new StringContains($needle, false, true), $message); } /** * Asserts that two strings are equal except for line endings. * * @throws ExpectationFailedException */ final public static function assertStringEqualsStringIgnoringLineEndings(string $expected, string $actual, string $message = ''): void { self::assertThat($actual, new StringEqualsStringIgnoringLineEndings($expected), $message); } /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException */ final public static function assertFileMatchesFormat(string $format, string $actualFile, string $message = ''): void { self::assertFileExists($actualFile, $message); self::assertThat( file_get_contents($actualFile), new StringMatchesFormatDescription($format), $message, ); } /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException */ final public static function assertFileMatchesFormatFile(string $formatFile, string $actualFile, string $message = ''): void { self::assertFileExists($formatFile, $message); self::assertFileExists($actualFile, $message); $formatDescription = file_get_contents($formatFile); self::assertIsString($formatDescription); self::assertThat( file_get_contents($actualFile), new StringMatchesFormatDescription($formatDescription), $message, ); } /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException */ final public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void { self::assertThat($string, new StringMatchesFormatDescription($format), $message); } /** * Asserts that a string does not match a given format string. * * @throws ExpectationFailedException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 */ final public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( null, 'assertStringNotMatchesFormat() is deprecated and will be removed in PHPUnit 12 without replacement.', ); self::assertThat( $string, new LogicalNot( new StringMatchesFormatDescription($format), ), $message, ); } /** * Asserts that a string matches a given format file. * * @throws ExpectationFailedException */ final public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void { self::assertFileExists($formatFile, $message); $formatDescription = file_get_contents($formatFile); self::assertIsString($formatDescription); self::assertThat( $string, new StringMatchesFormatDescription( $formatDescription, ), $message, ); } /** * Asserts that a string does not match a given format string. * * @throws ExpectationFailedException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 */ final public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( null, 'assertStringNotMatchesFormatFile() is deprecated and will be removed in PHPUnit 12 without replacement.', ); self::assertFileExists($formatFile, $message); $formatDescription = file_get_contents($formatFile); self::assertIsString($formatDescription); self::assertThat( $string, new LogicalNot( new StringMatchesFormatDescription( $formatDescription, ), ), $message, ); } /** * Asserts that a string starts with a given prefix. * * @param non-empty-string $prefix * * @throws ExpectationFailedException * @throws InvalidArgumentException */ final public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void { self::assertThat($string, new StringStartsWith($prefix), $message); } /** * Asserts that a string starts not with a given prefix. * * @param non-empty-string $prefix * * @throws ExpectationFailedException * @throws InvalidArgumentException */ final public static function assertStringStartsNotWith(string $prefix, string $string, string $message = ''): void { self::assertThat( $string, new LogicalNot( new StringStartsWith($prefix), ), $message, ); } /** * @throws ExpectationFailedException */ final public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void { $constraint = new StringContains($needle); self::assertThat($haystack, $constraint, $message); } /** * @throws ExpectationFailedException */ final public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void { $constraint = new StringContains($needle, true); self::assertThat($haystack, $constraint, $message); } /** * @throws ExpectationFailedException */ final public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void { $constraint = new LogicalNot(new StringContains($needle)); self::assertThat($haystack, $constraint, $message); } /** * @throws ExpectationFailedException */ final public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void { $constraint = new LogicalNot(new StringContains($needle, true)); self::assertThat($haystack, $constraint, $message); } /** * Asserts that a string ends with a given suffix. * * @param non-empty-string $suffix * * @throws ExpectationFailedException * @throws InvalidArgumentException */ final public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void { self::assertThat($string, new StringEndsWith($suffix), $message); } /** * Asserts that a string ends not with a given suffix. * * @param non-empty-string $suffix * * @throws ExpectationFailedException * @throws InvalidArgumentException */ final public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void { self::assertThat( $string, new LogicalNot( new StringEndsWith($suffix), ), $message, ); } /** * Asserts that two XML files are equal. * * @throws Exception * @throws ExpectationFailedException * @throws XmlException */ final public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void { $expected = (new XmlLoader)->loadFile($expectedFile); $actual = (new XmlLoader)->loadFile($actualFile); self::assertEquals($expected, $actual, $message); } /** * Asserts that two XML files are not equal. * * @throws \PHPUnit\Util\Exception * @throws ExpectationFailedException */ final public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void { $expected = (new XmlLoader)->loadFile($expectedFile); $actual = (new XmlLoader)->loadFile($actualFile); self::assertNotEquals($expected, $actual, $message); } /** * Asserts that two XML documents are equal. * * @throws ExpectationFailedException * @throws XmlException */ final public static function assertXmlStringEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void { $expected = (new XmlLoader)->loadFile($expectedFile); $actual = (new XmlLoader)->load($actualXml); self::assertEquals($expected, $actual, $message); } /** * Asserts that two XML documents are not equal. * * @throws ExpectationFailedException * @throws XmlException */ final public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void { $expected = (new XmlLoader)->loadFile($expectedFile); $actual = (new XmlLoader)->load($actualXml); self::assertNotEquals($expected, $actual, $message); } /** * Asserts that two XML documents are equal. * * @throws ExpectationFailedException * @throws XmlException */ final public static function assertXmlStringEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void { $expected = (new XmlLoader)->load($expectedXml); $actual = (new XmlLoader)->load($actualXml); self::assertEquals($expected, $actual, $message); } /** * Asserts that two XML documents are not equal. * * @throws ExpectationFailedException * @throws XmlException */ final public static function assertXmlStringNotEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void { $expected = (new XmlLoader)->load($expectedXml); $actual = (new XmlLoader)->load($actualXml); self::assertNotEquals($expected, $actual, $message); } /** * Evaluates a PHPUnit\Framework\Constraint matcher object. * * @throws ExpectationFailedException */ final public static function assertThat(mixed $value, Constraint $constraint, string $message = ''): void { self::$count += count($constraint); $constraint->evaluate($value, $message); } /** * Asserts that a string is a valid JSON string. * * @throws ExpectationFailedException */ final public static function assertJson(string $actual, string $message = ''): void { self::assertThat($actual, self::isJson(), $message); } /** * Asserts that two given JSON encoded objects or arrays are equal. * * @throws ExpectationFailedException */ final public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void { self::assertJson($expectedJson, $message); self::assertJson($actualJson, $message); self::assertThat($actualJson, new JsonMatches($expectedJson), $message); } /** * Asserts that two given JSON encoded objects or arrays are not equal. * * @throws ExpectationFailedException */ final public static function assertJsonStringNotEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void { self::assertJson($expectedJson, $message); self::assertJson($actualJson, $message); self::assertThat( $actualJson, new LogicalNot( new JsonMatches($expectedJson), ), $message, ); } /** * Asserts that the generated JSON encoded object and the content of the given file are equal. * * @throws ExpectationFailedException */ final public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void { self::assertFileExists($expectedFile, $message); $expectedJson = file_get_contents($expectedFile); self::assertIsString($expectedJson); self::assertJson($expectedJson, $message); self::assertJson($actualJson, $message); self::assertThat($actualJson, new JsonMatches($expectedJson), $message); } /** * Asserts that the generated JSON encoded object and the content of the given file are not equal. * * @throws ExpectationFailedException */ final public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void { self::assertFileExists($expectedFile, $message); $expectedJson = file_get_contents($expectedFile); self::assertIsString($expectedJson); self::assertJson($expectedJson, $message); self::assertJson($actualJson, $message); self::assertThat( $actualJson, new LogicalNot( new JsonMatches($expectedJson), ), $message, ); } /** * Asserts that two JSON files are equal. * * @throws ExpectationFailedException */ final public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void { self::assertFileExists($expectedFile, $message); $expectedJson = file_get_contents($expectedFile); self::assertIsString($expectedJson); self::assertJson($expectedJson, $message); self::assertFileExists($actualFile, $message); $actualJson = file_get_contents($actualFile); self::assertIsString($actualJson); self::assertJson($actualJson, $message); $constraintExpected = new JsonMatches( $expectedJson, ); $constraintActual = new JsonMatches($actualJson); self::assertThat($expectedJson, $constraintActual, $message); self::assertThat($actualJson, $constraintExpected, $message); } /** * Asserts that two JSON files are not equal. * * @throws ExpectationFailedException */ final public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void { self::assertFileExists($expectedFile, $message); $expectedJson = file_get_contents($expectedFile); self::assertIsString($expectedJson); self::assertJson($expectedJson, $message); self::assertFileExists($actualFile, $message); $actualJson = file_get_contents($actualFile); self::assertIsString($actualJson); self::assertJson($actualJson, $message); $constraintExpected = new JsonMatches( $expectedJson, ); $constraintActual = new JsonMatches($actualJson); self::assertThat($expectedJson, new LogicalNot($constraintActual), $message); self::assertThat($actualJson, new LogicalNot($constraintExpected), $message); } /** * @throws Exception */ final public static function logicalAnd(mixed ...$constraints): LogicalAnd { return LogicalAnd::fromConstraints(...$constraints); } final public static function logicalOr(mixed ...$constraints): LogicalOr { return LogicalOr::fromConstraints(...$constraints); } final public static function logicalNot(Constraint $constraint): LogicalNot { return new LogicalNot($constraint); } final public static function logicalXor(mixed ...$constraints): LogicalXor { return LogicalXor::fromConstraints(...$constraints); } final public static function anything(): IsAnything { return new IsAnything; } final public static function isTrue(): IsTrue { return new IsTrue; } /** * @template CallbackInput of mixed * * @param callable(CallbackInput $callback): bool $callback * * @return Callback<CallbackInput> */ final public static function callback(callable $callback): Callback { return new Callback($callback); } final public static function isFalse(): IsFalse { return new IsFalse; } final public static function isJson(): IsJson { return new IsJson; } final public static function isNull(): IsNull { return new IsNull; } final public static function isFinite(): IsFinite { return new IsFinite; } final public static function isInfinite(): IsInfinite { return new IsInfinite; } final public static function isNan(): IsNan { return new IsNan; } final public static function containsEqual(mixed $value): TraversableContainsEqual { return new TraversableContainsEqual($value); } final public static function containsIdentical(mixed $value): TraversableContainsIdentical { return new TraversableContainsIdentical($value); } /** * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' $type * * @throws Exception */ final public static function containsOnly(string $type): TraversableContainsOnly { return new TraversableContainsOnly($type); } /** * @param class-string $className * * @throws Exception */ final public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly { return new TraversableContainsOnly($className, false); } final public static function arrayHasKey(int|string $key): ArrayHasKey { return new ArrayHasKey($key); } final public static function isList(): IsList { return new IsList; } final public static function equalTo(mixed $value): IsEqual { return new IsEqual($value); } final public static function equalToCanonicalizing(mixed $value): IsEqualCanonicalizing { return new IsEqualCanonicalizing($value); } final public static function equalToIgnoringCase(mixed $value): IsEqualIgnoringCase { return new IsEqualIgnoringCase($value); } final public static function equalToWithDelta(mixed $value, float $delta): IsEqualWithDelta { return new IsEqualWithDelta($value, $delta); } final public static function isEmpty(): IsEmpty { return new IsEmpty; } final public static function isWritable(): IsWritable { return new IsWritable; } final public static function isReadable(): IsReadable { return new IsReadable; } final public static function directoryExists(): DirectoryExists { return new DirectoryExists; } final public static function fileExists(): FileExists { return new FileExists; } final public static function greaterThan(mixed $value): GreaterThan { return new GreaterThan($value); } final public static function greaterThanOrEqual(mixed $value): LogicalOr { return self::logicalOr( new IsEqual($value), new GreaterThan($value), ); } final public static function identicalTo(mixed $value): IsIdentical { return new IsIdentical($value); } /** * @throws UnknownClassOrInterfaceException */ final public static function isInstanceOf(string $className): IsInstanceOf { return new IsInstanceOf($className); } /** * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' $type * * @throws Exception */ final public static function isType(string $type): IsType { return new IsType($type); } final public static function lessThan(mixed $value): LessThan { return new LessThan($value); } final public static function lessThanOrEqual(mixed $value): LogicalOr { return self::logicalOr( new IsEqual($value), new LessThan($value), ); } final public static function matchesRegularExpression(string $pattern): RegularExpression { return new RegularExpression($pattern); } final public static function matches(string $string): StringMatchesFormatDescription { return new StringMatchesFormatDescription($string); } /** * @param non-empty-string $prefix * * @throws InvalidArgumentException */ final public static function stringStartsWith(string $prefix): StringStartsWith { return new StringStartsWith($prefix); } final public static function stringContains(string $string, bool $case = true): StringContains { return new StringContains($string, $case); } /** * @param non-empty-string $suffix * * @throws InvalidArgumentException */ final public static function stringEndsWith(string $suffix): StringEndsWith { return new StringEndsWith($suffix); } final public static function stringEqualsStringIgnoringLineEndings(string $string): StringEqualsStringIgnoringLineEndings { return new StringEqualsStringIgnoringLineEndings($string); } final public static function countOf(int $count): Count { return new Count($count); } final public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals { return new ObjectEquals($object, $method); } /** * Fails a test with the given message. * * @throws AssertionFailedError */ final public static function fail(string $message = ''): never { self::$count++; throw new AssertionFailedError($message); } /** * Mark the test as incomplete. * * @throws IncompleteTestError */ final public static function markTestIncomplete(string $message = ''): never { throw new IncompleteTestError($message); } /** * Mark the test as skipped. * * @throws SkippedWithMessageException */ final public static function markTestSkipped(string $message = ''): never { throw new SkippedWithMessageException($message); } /** * Return the current assertion count. */ final public static function getCount(): int { return self::$count; } /** * Reset the assertion counter. */ final public static function resetCount(): void { self::$count = 0; } private static function isNativeType(string $type): bool { return match ($type) { 'numeric', 'integer', 'int', 'iterable', 'float', 'string', 'boolean', 'bool', 'null', 'array', 'object', 'resource', 'scalar' => true, default => false, }; } } phpunit/src/Framework/MockObject/MockBuilder.php 0000644 00000037612 15253321353 0015723 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use const DEBUG_BACKTRACE_IGNORE_ARGS; use function array_merge; use function assert; use function debug_backtrace; use function trait_exists; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\Exception; use PHPUnit\Framework\InvalidArgumentException; use PHPUnit\Framework\MockObject\Generator\CannotUseAddMethodsException; use PHPUnit\Framework\MockObject\Generator\ClassIsEnumerationException; use PHPUnit\Framework\MockObject\Generator\ClassIsFinalException; use PHPUnit\Framework\MockObject\Generator\DuplicateMethodException; use PHPUnit\Framework\MockObject\Generator\Generator; use PHPUnit\Framework\MockObject\Generator\InvalidMethodNameException; use PHPUnit\Framework\MockObject\Generator\NameAlreadyInUseException; use PHPUnit\Framework\MockObject\Generator\OriginalConstructorInvocationRequiredException; use PHPUnit\Framework\MockObject\Generator\ReflectionException; use PHPUnit\Framework\MockObject\Generator\RuntimeException; use PHPUnit\Framework\MockObject\Generator\UnknownTypeException; use PHPUnit\Framework\TestCase; use ReflectionClass; /** * @template MockedType * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class MockBuilder { private readonly TestCase $testCase; /** * @var class-string|trait-string */ private readonly string $type; /** * @var list<non-empty-string> */ private array $methods = []; private bool $emptyMethodsArray = false; /** * @var ?class-string */ private ?string $mockClassName = null; /** * @var array<mixed> */ private array $constructorArgs = []; private bool $originalConstructor = true; private bool $originalClone = true; private bool $autoload = true; private bool $cloneArguments = false; private bool $callOriginalMethods = false; private ?object $proxyTarget = null; private bool $allowMockingUnknownTypes = true; private bool $returnValueGeneration = true; private readonly Generator $generator; /** * @param class-string|trait-string $type */ public function __construct(TestCase $testCase, string $type) { $this->testCase = $testCase; $this->type = $type; $this->generator = new Generator; } /** * Creates a mock object using a fluent interface. * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws DuplicateMethodException * @throws InvalidArgumentException * @throws InvalidMethodNameException * @throws NameAlreadyInUseException * @throws OriginalConstructorInvocationRequiredException * @throws ReflectionException * @throws RuntimeException * @throws UnknownTypeException * * @return MockedType&MockObject */ public function getMock(): MockObject { $object = $this->generator->testDouble( $this->type, true, true, !$this->emptyMethodsArray ? $this->methods : null, $this->constructorArgs, $this->mockClassName ?? '', $this->originalConstructor, $this->originalClone, $this->autoload, $this->cloneArguments, $this->callOriginalMethods, $this->proxyTarget, $this->allowMockingUnknownTypes, $this->returnValueGeneration, ); assert($object instanceof $this->type); assert($object instanceof MockObject); $this->testCase->registerMockObject($object); return $object; } /** * Creates a mock object for an abstract class using a fluent interface. * * @throws Exception * @throws ReflectionException * @throws RuntimeException * * @return MockedType&MockObject * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5305 */ public function getMockForAbstractClass(): MockObject { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::getMockForAbstractClass() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $object = $this->generator->mockObjectForAbstractClass( $this->type, $this->constructorArgs, $this->mockClassName ?? '', $this->originalConstructor, $this->originalClone, $this->autoload, $this->methods, $this->cloneArguments, ); assert($object instanceof MockObject); $this->testCase->registerMockObject($object); return $object; } /** * Creates a mock object for a trait using a fluent interface. * * @throws Exception * @throws ReflectionException * @throws RuntimeException * * @return MockedType&MockObject * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5306 */ public function getMockForTrait(): MockObject { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::getMockForTrait() is deprecated and will be removed in PHPUnit 12 without replacement.', ); assert(trait_exists($this->type)); $object = $this->generator->mockObjectForTrait( $this->type, $this->constructorArgs, $this->mockClassName ?? '', $this->originalConstructor, $this->originalClone, $this->autoload, $this->methods, $this->cloneArguments, ); assert($object instanceof MockObject); $this->testCase->registerMockObject($object); return $object; } /** * Specifies the subset of methods to mock, requiring each to exist in the class. * * @param list<non-empty-string> $methods * * @throws CannotUseOnlyMethodsException * @throws ReflectionException * * @return $this */ public function onlyMethods(array $methods): self { if (empty($methods)) { $this->emptyMethodsArray = true; return $this; } try { $reflector = new ReflectionClass($this->type); // @codeCoverageIgnoreStart /** @phpstan-ignore catch.neverThrown */ } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); // @codeCoverageIgnoreEnd } foreach ($methods as $method) { if (!$reflector->hasMethod($method)) { throw new CannotUseOnlyMethodsException($this->type, $method); } } $this->methods = array_merge($this->methods, $methods); return $this; } /** * Specifies methods that don't exist in the class which you want to mock. * * @param list<non-empty-string> $methods * * @throws CannotUseAddMethodsException * @throws ReflectionException * @throws RuntimeException * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5320 */ public function addMethods(array $methods): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::addMethods() is deprecated and will be removed in PHPUnit 12 without replacement.', ); if (empty($methods)) { $this->emptyMethodsArray = true; return $this; } try { $reflector = new ReflectionClass($this->type); // @codeCoverageIgnoreStart /** @phpstan-ignore catch.neverThrown */ } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); // @codeCoverageIgnoreEnd } foreach ($methods as $method) { if ($reflector->hasMethod($method)) { throw new CannotUseAddMethodsException($this->type, $method); } } $this->methods = array_merge($this->methods, $methods); return $this; } /** * Specifies the arguments for the constructor. * * @param array<mixed> $arguments * * @return $this */ public function setConstructorArgs(array $arguments): self { $this->constructorArgs = $arguments; return $this; } /** * Specifies the name for the mock class. * * @param class-string $name * * @return $this */ public function setMockClassName(string $name): self { $this->mockClassName = $name; return $this; } /** * Disables the invocation of the original constructor. * * @return $this */ public function disableOriginalConstructor(): self { $this->originalConstructor = false; return $this; } /** * Enables the invocation of the original constructor. * * @return $this */ public function enableOriginalConstructor(): self { $this->originalConstructor = true; return $this; } /** * Disables the invocation of the original clone constructor. * * @return $this */ public function disableOriginalClone(): self { $this->originalClone = false; return $this; } /** * Enables the invocation of the original clone constructor. * * @return $this */ public function enableOriginalClone(): self { $this->originalClone = true; return $this; } /** * Disables the use of class autoloading while creating the mock object. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5309 * * @codeCoverageIgnore */ public function disableAutoload(): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::disableAutoload() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->autoload = false; return $this; } /** * Enables the use of class autoloading while creating the mock object. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5309 */ public function enableAutoload(): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::enableAutoload() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->autoload = true; return $this; } /** * Disables the cloning of arguments passed to mocked methods. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5315 */ public function disableArgumentCloning(): self { if (!$this->calledFromTestCase()) { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::disableArgumentCloning() is deprecated and will be removed in PHPUnit 12 without replacement.', ); } $this->cloneArguments = false; return $this; } /** * Enables the cloning of arguments passed to mocked methods. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5315 */ public function enableArgumentCloning(): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::enableArgumentCloning() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->cloneArguments = true; return $this; } /** * Enables the invocation of the original methods. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 * * @codeCoverageIgnore */ public function enableProxyingToOriginalMethods(): self { if (!$this->calledFromTestCase()) { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::enableProxyingToOriginalMethods() is deprecated and will be removed in PHPUnit 12 without replacement.', ); } $this->callOriginalMethods = true; return $this; } /** * Disables the invocation of the original methods. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 */ public function disableProxyingToOriginalMethods(): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::disableProxyingToOriginalMethods() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->callOriginalMethods = false; $this->proxyTarget = null; return $this; } /** * Sets the proxy target. * * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5307 * * @codeCoverageIgnore */ public function setProxyTarget(object $object): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::setProxyTarget() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->proxyTarget = $object; return $this; } /** * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5308 */ public function allowMockingUnknownTypes(): self { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::allowMockingUnknownTypes() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $this->allowMockingUnknownTypes = true; return $this; } /** * @return $this * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5308 */ public function disallowMockingUnknownTypes(): self { if (!$this->calledFromTestCase()) { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $this->testCase->valueObjectForEvents(), 'MockBuilder::disallowMockingUnknownTypes() is deprecated and will be removed in PHPUnit 12 without replacement.', ); } $this->allowMockingUnknownTypes = false; return $this; } /** * @return $this */ public function enableAutoReturnValueGeneration(): self { $this->returnValueGeneration = true; return $this; } /** * @return $this */ public function disableAutoReturnValueGeneration(): self { $this->returnValueGeneration = false; return $this; } private function calledFromTestCase(): bool { $caller = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, limit: 3)[2]; return isset($caller['class']) && $caller['class'] === TestCase::class; } } phpunit/src/Framework/MockObject/Exception/MethodCannotBeConfiguredException.php 0000644 00000001657 15253321353 0024200 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MethodCannotBeConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $method) { parent::__construct( sprintf( 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', $method, ), ); } } phpunit/src/Framework/MockObject/Exception/Exception.php 0000644 00000001055 15253321353 0017407 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends Throwable { } phpunit/src/Framework/MockObject/Exception/BadMethodCallException.php 0000644 00000001117 15253321353 0021752 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class BadMethodCallException extends \BadMethodCallException implements Exception { } phpunit/src/Framework/MockObject/Exception/ReturnValueNotConfiguredException.php 0000644 00000001701 15253321353 0024271 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReturnValueNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(Invocation $invocation) { parent::__construct( sprintf( 'No return value is configured for %s::%s() and return value generation is disabled', $invocation->className(), $invocation->methodName(), ), ); } } phpunit/src/Framework/MockObject/Exception/MethodNameAlreadyConfiguredException.php 0000644 00000001322 15253321353 0024656 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MethodNameAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct('Method name is already configured'); } } phpunit/src/Framework/MockObject/Exception/CannotCloneTestDoubleForReadonlyClassException.php 0000644 00000001461 15253321353 0026662 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final class CannotCloneTestDoubleForReadonlyClassException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct( 'Cloning test doubles for readonly classes is not supported on PHP 8.2', ); } } phpunit/src/Framework/MockObject/Exception/MethodNameNotConfiguredException.php 0000644 00000001312 15253321353 0024034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MethodNameNotConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct('Method name is not configured'); } } phpunit/src/Framework/MockObject/Exception/MatcherAlreadyRegisteredException.php 0000644 00000001515 15253321353 0024234 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MatcherAlreadyRegisteredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $id) { parent::__construct( sprintf( 'Matcher with id <%s> is already registered', $id, ), ); } } phpunit/src/Framework/MockObject/Exception/NeverReturningMethodException.php 0000644 00000001634 15253321353 0023451 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class NeverReturningMethodException extends RuntimeException implements Exception { /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { parent::__construct( sprintf( 'Method %s::%s() is declared to never return', $className, $methodName, ), ); } } phpunit/src/Framework/MockObject/Exception/IncompatibleReturnValueException.php 0000644 00000002016 15253321353 0024131 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function get_debug_type; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IncompatibleReturnValueException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(ConfigurableMethod $method, mixed $value) { parent::__construct( sprintf( 'Method %s may not return value of type %s, its declared return type is "%s"', $method->name(), get_debug_type($value), $method->returnTypeDeclaration(), ), ); } } phpunit/src/Framework/MockObject/Exception/RuntimeException.php 0000644 00000001103 15253321353 0020745 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class RuntimeException extends \RuntimeException implements Exception { } phpunit/src/Framework/MockObject/Exception/MatchBuilderNotFoundException.php 0000644 00000001525 15253321353 0023352 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MatchBuilderNotFoundException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $id) { parent::__construct( sprintf( 'No builder found for match builder identification <%s>', $id, ), ); } } phpunit/src/Framework/MockObject/Exception/ReflectionException.php 0000644 00000001134 15253321353 0021420 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReflectionException extends RuntimeException implements Exception { } phpunit/src/Framework/MockObject/Exception/CannotUseOnlyMethodsException.php 0000644 00000001653 15253321353 0023421 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CannotUseOnlyMethodsException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $type, string $methodName) { parent::__construct( sprintf( 'Trying to configure method "%s" with onlyMethods(), but it does not exist in class "%s"', $methodName, $type, ), ); } } phpunit/src/Framework/MockObject/Exception/MethodParametersAlreadyConfiguredException.php 0000644 00000001333 15253321353 0026103 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MethodParametersAlreadyConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct('Method parameters already configured'); } } phpunit/src/Framework/MockObject/Exception/NoMoreReturnValuesConfiguredException.php 0000644 00000002000 15253321353 0025104 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoMoreReturnValuesConfiguredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(Invocation $invocation, int $numberOfConfiguredReturnValues) { parent::__construct( sprintf( 'Only %d return values have been configured for %s::%s()', $numberOfConfiguredReturnValues, $invocation->className(), $invocation->methodName(), ), ); } } phpunit/src/Framework/MockObject/Generator/MockMethod.php 0000644 00000026746 15253321353 0017511 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function count; use function explode; use function implode; use function is_object; use function is_string; use function preg_match; use function preg_replace; use function sprintf; use function strlen; use function strpos; use function substr; use function substr_count; use function trim; use function var_export; use ReflectionMethod; use ReflectionParameter; use SebastianBergmann\Type\ReflectionMapper; use SebastianBergmann\Type\Type; use SebastianBergmann\Type\UnknownType; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MockMethod { use TemplateLoader; /** * @var class-string */ private readonly string $className; /** * @var non-empty-string */ private readonly string $methodName; private readonly bool $cloneArguments; private readonly string $modifier; private readonly string $argumentsForDeclaration; private readonly string $argumentsForCall; private readonly Type $returnType; private readonly string $reference; private readonly bool $callOriginalMethod; private readonly bool $static; private readonly ?string $deprecation; /** * @var array<int, mixed> */ private readonly array $defaultParameterValues; /** * @var non-negative-int */ private readonly int $numberOfParameters; /** * @throws ReflectionException * @throws RuntimeException */ public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self { if ($method->isPrivate()) { $modifier = 'private'; } elseif ($method->isProtected()) { $modifier = 'protected'; } else { $modifier = 'public'; } if ($method->isStatic()) { $modifier .= ' static'; } if ($method->returnsReference()) { $reference = '&'; } else { $reference = ''; } $docComment = $method->getDocComment(); if (is_string($docComment) && preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation)) { $deprecation = trim(preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1])); } else { $deprecation = null; } return new self( $method->getDeclaringClass()->getName(), $method->getName(), $cloneArguments, $modifier, self::methodParametersForDeclaration($method), self::methodParametersForCall($method), self::methodParametersDefaultValues($method), count($method->getParameters()), (new ReflectionMapper)->fromReturnType($method), $reference, $callOriginalMethod, $method->isStatic(), $deprecation, ); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function fromName(string $className, string $methodName, bool $cloneArguments): self { return new self( $className, $methodName, $cloneArguments, 'public', '', '', [], 0, new UnknownType, '', false, false, null, ); } /** * @param class-string $className * @param non-empty-string $methodName * @param array<int, mixed> $defaultParameterValues * @param non-negative-int $numberOfParameters */ private function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, array $defaultParameterValues, int $numberOfParameters, Type $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation) { $this->className = $className; $this->methodName = $methodName; $this->cloneArguments = $cloneArguments; $this->modifier = $modifier; $this->argumentsForDeclaration = $argumentsForDeclaration; $this->argumentsForCall = $argumentsForCall; $this->defaultParameterValues = $defaultParameterValues; $this->numberOfParameters = $numberOfParameters; $this->returnType = $returnType; $this->reference = $reference; $this->callOriginalMethod = $callOriginalMethod; $this->static = $static; $this->deprecation = $deprecation; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @throws RuntimeException */ public function generateCode(): string { if ($this->static) { $templateFile = 'doubled_static_method.tpl'; } else { $templateFile = sprintf( '%s_method.tpl', $this->callOriginalMethod ? 'proxied' : 'doubled', ); } $deprecation = $this->deprecation; $returnResult = ''; if (!$this->returnType->isNever() && !$this->returnType->isVoid()) { $returnResult = <<<'EOT' return $__phpunit_result; EOT; } if (null !== $this->deprecation) { $deprecation = "The {$this->className}::{$this->methodName} method is deprecated ({$this->deprecation})."; $deprecationTemplate = $this->loadTemplate('deprecation.tpl'); $deprecationTemplate->setVar( [ 'deprecation' => var_export($deprecation, true), ], ); $deprecation = $deprecationTemplate->render(); } $template = $this->loadTemplate($templateFile); $template->setVar( [ 'arguments_decl' => $this->argumentsForDeclaration, 'arguments_call' => $this->argumentsForCall, 'return_declaration' => !empty($this->returnType->asString()) ? (': ' . $this->returnType->asString()) : '', 'return_type' => $this->returnType->asString(), 'arguments_count' => !empty($this->argumentsForCall) ? substr_count($this->argumentsForCall, ',') + 1 : 0, 'class_name' => $this->className, 'method_name' => $this->methodName, 'modifier' => $this->modifier, 'reference' => $this->reference, 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', 'deprecation' => $deprecation, 'return_result' => $returnResult, ], ); return $template->render(); } public function returnType(): Type { return $this->returnType; } /** * @return array<int, mixed> */ public function defaultParameterValues(): array { return $this->defaultParameterValues; } /** * @return non-negative-int */ public function numberOfParameters(): int { return $this->numberOfParameters; } /** * Returns the parameters of a function or method. * * @throws RuntimeException */ private static function methodParametersForDeclaration(ReflectionMethod $method): string { $parameters = []; $types = (new ReflectionMapper)->fromParameterTypes($method); foreach ($method->getParameters() as $i => $parameter) { $name = '$' . $parameter->getName(); /* Note: PHP extensions may use empty names for reference arguments * or "..." for methods taking a variable number of arguments. */ if ($name === '$' || $name === '$...') { $name = '$arg' . $i; } $default = ''; $reference = ''; $typeDeclaration = ''; if (!$types[$i]->type()->isUnknown()) { $typeDeclaration = $types[$i]->type()->asString() . ' '; } if ($parameter->isPassedByReference()) { $reference = '&'; } if ($parameter->isVariadic()) { $name = '...' . $name; } elseif ($parameter->isDefaultValueAvailable()) { $default = ' = ' . self::exportDefaultValue($parameter); } elseif ($parameter->isOptional()) { $default = ' = null'; } $parameters[] = $typeDeclaration . $reference . $name . $default; } return implode(', ', $parameters); } /** * Returns the parameters of a function or method. * * @throws ReflectionException */ private static function methodParametersForCall(ReflectionMethod $method): string { $parameters = []; foreach ($method->getParameters() as $i => $parameter) { $name = '$' . $parameter->getName(); /* Note: PHP extensions may use empty names for reference arguments * or "..." for methods taking a variable number of arguments. */ if ($name === '$' || $name === '$...') { $name = '$arg' . $i; } if ($parameter->isVariadic()) { continue; } if ($parameter->isPassedByReference()) { $parameters[] = '&' . $name; } else { $parameters[] = $name; } } return implode(', ', $parameters); } /** * @throws ReflectionException */ private static function exportDefaultValue(ReflectionParameter $parameter): string { try { $defaultValue = $parameter->getDefaultValue(); if (!is_object($defaultValue)) { return var_export($defaultValue, true); } $parameterAsString = $parameter->__toString(); return explode( ' = ', substr( substr( $parameterAsString, strpos($parameterAsString, '<optional> ') + strlen('<optional> '), ), 0, -2, ), )[1]; // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd } /** * @return array<int, mixed> */ private static function methodParametersDefaultValues(ReflectionMethod $method): array { $result = []; foreach ($method->getParameters() as $i => $parameter) { if (!$parameter->isDefaultValueAvailable()) { continue; } $result[$i] = $parameter->getDefaultValue(); } return $result; } } phpunit/src/Framework/MockObject/Generator/MockType.php 0000644 00000001150 15253321353 0017170 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface MockType { /** * @return class-string */ public function generate(): string; } phpunit/src/Framework/MockObject/Generator/Exception/InvalidMethodNameException.php 0000644 00000001531 15253321353 0024605 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidMethodNameException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $method) { parent::__construct( sprintf( 'Cannot double method with invalid name "%s"', $method, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/Exception.php 0000644 00000001155 15253321353 0021336 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use PHPUnit\Framework\MockObject\Exception as BaseException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends BaseException { } phpunit/src/Framework/MockObject/Generator/Exception/ClassIsFinalException.php 0000644 00000001543 15253321353 0023573 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ClassIsFinalException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $className) { parent::__construct( sprintf( 'Class "%s" is declared "final" and cannot be doubled', $className, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/ClassIsEnumerationException.php 0000644 00000001547 15253321353 0025034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ClassIsEnumerationException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $className) { parent::__construct( sprintf( 'Class "%s" is an enumeration and cannot be doubled', $className, ), ); } } src/Framework/MockObject/Generator/Exception/OriginalConstructorInvocationRequiredException.php 0000644 00000001414 15253321353 0030743 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class OriginalConstructorInvocationRequiredException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct('Proxying to original methods requires invoking the original constructor'); } } phpunit/src/Framework/MockObject/Generator/Exception/UnknownClassException.php 0000644 00000001510 15253321353 0023677 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class UnknownClassException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $className) { parent::__construct( sprintf( 'Class "%s" does not exist', $className, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/SoapExtensionNotAvailableException.php 0000644 00000001422 15253321353 0026335 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SoapExtensionNotAvailableException extends \PHPUnit\Framework\Exception implements Exception { public function __construct() { parent::__construct( 'The SOAP extension is required to generate a test double from WSDL', ); } } phpunit/src/Framework/MockObject/Generator/Exception/CannotUseAddMethodsException.php 0000644 00000001742 15253321353 0025115 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CannotUseAddMethodsException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $type, string $methodName) { parent::__construct( sprintf( 'Trying to configure method "%s" with addMethods(), but it exists in class "%s". Use onlyMethods() for methods that exist in the class', $methodName, $type, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/NameAlreadyInUseException.php 0000644 00000001606 15253321353 0024406 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NameAlreadyInUseException extends \PHPUnit\Framework\Exception implements Exception { /** * @param class-string|trait-string $name */ public function __construct(string $name) { parent::__construct( sprintf( 'The name "%s" is already in use', $name, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/UnknownTypeException.php 0000644 00000001512 15253321353 0023555 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class UnknownTypeException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $type) { parent::__construct( sprintf( 'Class or interface "%s" does not exist', $type, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/RuntimeException.php 0000644 00000001130 15253321353 0022673 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class RuntimeException extends \PHPUnit\Framework\Exception implements Exception { } phpunit/src/Framework/MockObject/Generator/Exception/UnknownTraitException.php 0000644 00000001623 15253321353 0023722 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 */ final class UnknownTraitException extends \PHPUnit\Framework\Exception implements Exception { public function __construct(string $traitName) { parent::__construct( sprintf( 'Trait "%s" does not exist', $traitName, ), ); } } phpunit/src/Framework/MockObject/Generator/Exception/ReflectionException.php 0000644 00000001133 15253321353 0023345 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReflectionException extends \PHPUnit\Framework\Exception implements Exception { } phpunit/src/Framework/MockObject/Generator/Exception/DuplicateMethodException.php 0000644 00000002163 15253321353 0024332 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function array_diff_assoc; use function array_unique; use function implode; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DuplicateMethodException extends \PHPUnit\Framework\Exception implements Exception { /** * @param list<string> $methods */ public function __construct(array $methods) { parent::__construct( sprintf( 'Cannot double using a method list that contains duplicates: "%s" (duplicate: "%s")', implode(', ', $methods), implode(', ', array_unique(array_diff_assoc($methods, array_unique($methods)))), ), ); } } phpunit/src/Framework/MockObject/Generator/TemplateLoader.php 0000644 00000001717 15253321353 0020350 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use SebastianBergmann\Template\Template; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait TemplateLoader { /** * @var array<string,Template> */ private static array $templates = []; private function loadTemplate(string $template): Template { $filename = __DIR__ . '/templates/' . $template; if (!isset(self::$templates[$filename])) { self::$templates[$filename] = new Template($filename); } return self::$templates[$filename]; } } phpunit/src/Framework/MockObject/Generator/Generator.php 0000644 00000112524 15253321353 0017373 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use const PHP_EOL; use const PHP_MAJOR_VERSION; use const PHP_MINOR_VERSION; use const PREG_OFFSET_CAPTURE; use const WSDL_CACHE_NONE; use function array_merge; use function array_pop; use function array_unique; use function assert; use function class_exists; use function count; use function explode; use function extension_loaded; use function implode; use function in_array; use function interface_exists; use function is_array; use function is_object; use function md5; use function mt_rand; use function preg_match; use function preg_match_all; use function range; use function serialize; use function sort; use function sprintf; use function str_contains; use function str_replace; use function strlen; use function strpos; use function substr; use function trait_exists; use Exception; use Iterator; use IteratorAggregate; use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException; use PHPUnit\Event\Code\TestMethodBuilder; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\InvalidArgumentException; use PHPUnit\Framework\MockObject\ConfigurableMethod; use PHPUnit\Framework\MockObject\DoubledCloneMethod; use PHPUnit\Framework\MockObject\ErrorCloneMethod; use PHPUnit\Framework\MockObject\GeneratedAsMockObject; use PHPUnit\Framework\MockObject\GeneratedAsTestStub; use PHPUnit\Framework\MockObject\Method; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObjectApi; use PHPUnit\Framework\MockObject\MockObjectInternal; use PHPUnit\Framework\MockObject\MutableStubApi; use PHPUnit\Framework\MockObject\ProxiedCloneMethod; use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\StubApi; use PHPUnit\Framework\MockObject\StubInternal; use PHPUnit\Framework\MockObject\TestDoubleState; use ReflectionClass; use ReflectionMethod; use ReflectionObject; use SoapClient; use SoapFault; use Throwable; use Traversable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Generator { use TemplateLoader; /** * @var array<non-empty-string, true> */ private const EXCLUDED_METHOD_NAMES = [ '__CLASS__' => true, '__DIR__' => true, '__FILE__' => true, '__FUNCTION__' => true, '__LINE__' => true, '__METHOD__' => true, '__NAMESPACE__' => true, '__TRAIT__' => true, '__clone' => true, '__halt_compiler' => true, ]; /** * @var array<non-empty-string, MockClass> */ private static array $cache = []; /** * Returns a test double for the specified class. * * @param ?list<non-empty-string> $methods * @param list<mixed> $arguments * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws DuplicateMethodException * @throws InvalidMethodNameException * @throws NameAlreadyInUseException * @throws OriginalConstructorInvocationRequiredException * @throws ReflectionException * @throws RuntimeException * @throws UnknownTypeException */ public function testDouble(string $type, bool $mockObject, bool $markAsMockObject, ?array $methods = [], array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false, ?object $proxyTarget = null, bool $allowMockingUnknownTypes = true, bool $returnValueGeneration = true): MockObject|Stub { if ($type === Traversable::class) { $type = Iterator::class; } if (!$allowMockingUnknownTypes) { $this->ensureKnownType($type, $callAutoload); } $this->ensureValidMethods($methods); $this->ensureNameForTestDoubleClassIsAvailable($mockClassName); if (!$callOriginalConstructor && $callOriginalMethods) { throw new OriginalConstructorInvocationRequiredException; } $mock = $this->generate( $type, $mockObject, $markAsMockObject, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, ); $object = $this->getObject( $mock, $type, $callOriginalConstructor, $arguments, $callOriginalMethods, $proxyTarget, $returnValueGeneration, ); assert($object instanceof $type); if ($mockObject) { assert($object instanceof MockObject); } else { assert($object instanceof Stub); } return $object; } /** * @param list<class-string> $interfaces * * @throws RuntimeException * @throws UnknownTypeException */ public function testDoubleForInterfaceIntersection(array $interfaces, bool $mockObject, bool $callAutoload = true, bool $returnValueGeneration = true): MockObject|Stub { if (count($interfaces) < 2) { throw new RuntimeException('At least two interfaces must be specified'); } foreach ($interfaces as $interface) { if (!interface_exists($interface, $callAutoload)) { throw new UnknownTypeException($interface); } } sort($interfaces); $methods = []; foreach ($interfaces as $interface) { $methods = array_merge($methods, $this->namesOfMethodsIn($interface)); } if (count(array_unique($methods)) < count($methods)) { throw new RuntimeException('Interfaces must not declare the same method'); } $unqualifiedNames = []; foreach ($interfaces as $interface) { $parts = explode('\\', $interface); $unqualifiedNames[] = array_pop($parts); } sort($unqualifiedNames); do { $intersectionName = sprintf( 'Intersection_%s_%s', implode('_', $unqualifiedNames), substr(md5((string) mt_rand()), 0, 8), ); } while (interface_exists($intersectionName, false)); $template = $this->loadTemplate('intersection.tpl'); $template->setVar( [ 'intersection' => $intersectionName, 'interfaces' => implode(', ', $interfaces), ], ); eval($template->render()); return $this->testDouble( $intersectionName, $mockObject, $mockObject, returnValueGeneration: $returnValueGeneration, ); } /** * Returns a mock object for the specified abstract class with all abstract * methods of the class mocked. * * Concrete methods to mock can be specified with the $mockedMethods parameter. * * @param list<mixed> $arguments * @param ?list<non-empty-string> $mockedMethods * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws DuplicateMethodException * @throws InvalidArgumentException * @throws InvalidMethodNameException * @throws NameAlreadyInUseException * @throws OriginalConstructorInvocationRequiredException * @throws ReflectionException * @throws RuntimeException * @throws UnknownClassException * @throws UnknownTypeException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5241 */ public function mockObjectForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, ?array $mockedMethods = null, bool $cloneArguments = true): MockObject { if (class_exists($originalClassName, $callAutoload) || interface_exists($originalClassName, $callAutoload)) { $reflector = $this->reflectClass($originalClassName); $methods = $mockedMethods; foreach ($reflector->getMethods() as $method) { if ($method->isAbstract() && !in_array($method->getName(), $methods ?? [], true)) { $methods[] = $method->getName(); } } if (empty($methods)) { $methods = null; } $mockObject = $this->testDouble( $originalClassName, true, true, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments, ); assert($mockObject instanceof $originalClassName); assert($mockObject instanceof MockObject); return $mockObject; } throw new UnknownClassException($originalClassName); } /** * Returns a mock object for the specified trait with all abstract methods * of the trait mocked. Concrete methods to mock can be specified with the * `$mockedMethods` parameter. * * @param trait-string $traitName * @param list<mixed> $arguments * @param ?list<non-empty-string> $mockedMethods * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws DuplicateMethodException * @throws InvalidArgumentException * @throws InvalidMethodNameException * @throws NameAlreadyInUseException * @throws OriginalConstructorInvocationRequiredException * @throws ReflectionException * @throws RuntimeException * @throws UnknownClassException * @throws UnknownTraitException * @throws UnknownTypeException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 */ public function mockObjectForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, ?array $mockedMethods = null, bool $cloneArguments = true): MockObject { if (!trait_exists($traitName, $callAutoload)) { throw new UnknownTraitException($traitName); } $className = $this->generateClassName( $traitName, '', 'Trait_', ); $classTemplate = $this->loadTemplate('trait_class.tpl'); $classTemplate->setVar( [ 'prologue' => 'abstract ', 'class_name' => $className['className'], 'trait_name' => $traitName, ], ); $mockTrait = new MockTrait($classTemplate->render(), $className['className']); $mockTrait->generate(); return $this->mockObjectForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments); } /** * Returns an object for the specified trait. * * @param trait-string $traitName * @param list<mixed> $arguments * * @throws ReflectionException * @throws RuntimeException * @throws UnknownTraitException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5244 */ public function objectForTrait(string $traitName, string $traitClassName = '', bool $callAutoload = true, bool $callOriginalConstructor = false, array $arguments = []): object { if (!trait_exists($traitName, $callAutoload)) { throw new UnknownTraitException($traitName); } $className = $this->generateClassName( $traitName, $traitClassName, 'Trait_', ); $classTemplate = $this->loadTemplate('trait_class.tpl'); $classTemplate->setVar( [ 'prologue' => '', 'class_name' => $className['className'], 'trait_name' => $traitName, ], ); return $this->getObject( new MockTrait( $classTemplate->render(), $className['className'], ), '', $callOriginalConstructor, $arguments, ); } /** * @param ?list<non-empty-string> $methods * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws ReflectionException * @throws RuntimeException * * @todo This method is only public because it is used to test generated code in PHPT tests * * @see https://github.com/sebastianbergmann/phpunit/issues/5476 */ public function generate(string $type, bool $mockObject, bool $markAsMockObject, ?array $methods = null, string $mockClassName = '', bool $callOriginalClone = true, bool $callAutoload = true, bool $cloneArguments = true, bool $callOriginalMethods = false): MockClass { if ($mockClassName !== '') { return $this->generateCodeForTestDoubleClass( $type, $mockObject, $markAsMockObject, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, ); } $key = md5( $type . ($mockObject ? 'MockObject' : 'TestStub') . ($markAsMockObject ? 'MockObject' : 'TestStub') . serialize($methods) . serialize($callOriginalClone) . serialize($cloneArguments) . serialize($callOriginalMethods), ); if (!isset(self::$cache[$key])) { self::$cache[$key] = $this->generateCodeForTestDoubleClass( $type, $mockObject, $markAsMockObject, $methods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, ); } return self::$cache[$key]; } /** * @param non-empty-string $wsdlFile * @param class-string $className * @param list<non-empty-string> $methods * @param array<mixed> $options * * @throws RuntimeException * @throws SoapExtensionNotAvailableException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5242 */ public function generateClassFromWsdl(string $wsdlFile, string $className, array $methods = [], array $options = []): string { if (!extension_loaded('soap')) { throw new SoapExtensionNotAvailableException; } $options['cache_wsdl'] = WSDL_CACHE_NONE; try { $client = new SoapClient($wsdlFile, $options); $_methods = array_unique($client->__getFunctions()); unset($client); } catch (SoapFault $e) { throw new RuntimeException( $e->getMessage(), $e->getCode(), $e, ); } sort($_methods); $methodTemplate = $this->loadTemplate('wsdl_method.tpl'); $methodsBuffer = ''; foreach ($_methods as $method) { preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(/', $method, $matches, PREG_OFFSET_CAPTURE); $lastFunction = array_pop($matches[0]); $nameStart = $lastFunction[1]; $nameEnd = $nameStart + strlen($lastFunction[0]) - 1; $name = str_replace('(', '', $lastFunction[0]); if (empty($methods) || in_array($name, $methods, true)) { $arguments = explode( ',', str_replace(')', '', substr($method, $nameEnd + 1)), ); foreach (range(0, count($arguments) - 1) as $i) { $parameterStart = strpos($arguments[$i], '$'); if (!$parameterStart) { continue; } $arguments[$i] = substr($arguments[$i], $parameterStart); } $methodTemplate->setVar( [ 'method_name' => $name, 'arguments' => implode(', ', $arguments), ], ); $methodsBuffer .= $methodTemplate->render(); } } $optionsBuffer = '['; foreach ($options as $key => $value) { $optionsBuffer .= $key . ' => ' . $value; } $optionsBuffer .= ']'; $classTemplate = $this->loadTemplate('wsdl_class.tpl'); $namespace = ''; if (str_contains($className, '\\')) { $parts = explode('\\', $className); $className = array_pop($parts); $namespace = 'namespace ' . implode('\\', $parts) . ';' . "\n\n"; } $classTemplate->setVar( [ 'namespace' => $namespace, 'class_name' => $className, 'wsdl' => $wsdlFile, 'options' => $optionsBuffer, 'methods' => $methodsBuffer, ], ); return $classTemplate->render(); } /** * @throws ReflectionException * * @return list<MockMethod> */ public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array { $class = $this->reflectClass($className); $methods = []; foreach ($class->getMethods() as $method) { if (($method->isPublic() || $method->isAbstract()) && $this->canMethodBeDoubled($method)) { $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); } } return $methods; } /** * @param class-string $interfaceName * * @throws ReflectionException * * @return list<ReflectionMethod> */ private function userDefinedInterfaceMethods(string $interfaceName): array { $interface = $this->reflectClass($interfaceName); $methods = []; foreach ($interface->getMethods() as $method) { if (!$method->isUserDefined()) { continue; } $methods[] = $method; } return $methods; } /** * @param array<mixed> $arguments * * @throws ReflectionException * @throws RuntimeException */ private function getObject(MockType $mockClass, string $type = '', bool $callOriginalConstructor = false, array $arguments = [], bool $callOriginalMethods = false, ?object $proxyTarget = null, bool $returnValueGeneration = true): object { $className = $mockClass->generate(); try { $object = (new ReflectionClass($className))->newInstanceWithoutConstructor(); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); // @codeCoverageIgnoreEnd } $reflector = new ReflectionObject($object); if ($object instanceof StubInternal && $mockClass instanceof MockClass) { /** * @noinspection PhpUnhandledExceptionInspection */ $reflector->getProperty('__phpunit_state')->setValue( $object, new TestDoubleState($mockClass->configurableMethods(), $returnValueGeneration), ); if ($callOriginalMethods) { $this->instantiateProxyTarget($proxyTarget, $object, $type, $arguments); } } if ($callOriginalConstructor && $reflector->getConstructor() !== null) { try { $reflector->getConstructor()->invokeArgs($object, $arguments); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); // @codeCoverageIgnoreEnd } } return $object; } /** * @param ?list<non-empty-string> $explicitMethods * * @throws ClassIsEnumerationException * @throws ClassIsFinalException * @throws ReflectionException * @throws RuntimeException */ private function generateCodeForTestDoubleClass(string $type, bool $mockObject, bool $markAsMockObject, ?array $explicitMethods, string $mockClassName, bool $callOriginalClone, bool $callAutoload, bool $cloneArguments, bool $callOriginalMethods): MockClass { $classTemplate = $this->loadTemplate('test_double_class.tpl'); $additionalInterfaces = []; $doubledCloneMethod = false; $proxiedCloneMethod = false; $isClass = false; $isReadonly = false; $isInterface = false; $class = null; $mockMethods = new MockMethodSet; $testDoubleClassPrefix = $mockObject ? 'MockObject_' : 'TestStub_'; $_mockClassName = $this->generateClassName( $type, $mockClassName, $testDoubleClassPrefix, ); if (class_exists($_mockClassName['fullClassName'], $callAutoload)) { $isClass = true; } elseif (interface_exists($_mockClassName['fullClassName'], $callAutoload)) { $isInterface = true; } if (!$isClass && !$isInterface) { $prologue = 'class ' . $_mockClassName['originalClassName'] . "\n{\n}\n\n"; if (!empty($_mockClassName['namespaceName'])) { $prologue = 'namespace ' . $_mockClassName['namespaceName'] . " {\n\n" . $prologue . "}\n\n" . "namespace {\n\n"; $epilogue = "\n\n}"; } $doubledCloneMethod = true; } else { $class = $this->reflectClass($_mockClassName['fullClassName']); if ($class->isEnum()) { throw new ClassIsEnumerationException($_mockClassName['fullClassName']); } if ($class->isFinal()) { throw new ClassIsFinalException($_mockClassName['fullClassName']); } if ($class->isReadOnly()) { $isReadonly = true; } // @see https://github.com/sebastianbergmann/phpunit/issues/2995 if ($isInterface && $class->implementsInterface(Throwable::class)) { $actualClassName = Exception::class; $additionalInterfaces[] = $class->getName(); $isInterface = false; $class = $this->reflectClass($actualClassName); foreach ($this->userDefinedInterfaceMethods($_mockClassName['fullClassName']) as $method) { $methodName = $method->getName(); if ($class->hasMethod($methodName)) { $classMethod = $class->getMethod($methodName); if (!$this->canMethodBeDoubled($classMethod)) { continue; } } $mockMethods->addMethods( MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments), ); } $_mockClassName = $this->generateClassName( $actualClassName, $_mockClassName['className'], $testDoubleClassPrefix, ); } // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103 if ($isInterface && $class->implementsInterface(Traversable::class) && !$class->implementsInterface(Iterator::class) && !$class->implementsInterface(IteratorAggregate::class)) { $additionalInterfaces[] = Iterator::class; $mockMethods->addMethods( ...$this->mockClassMethods(Iterator::class, $callOriginalMethods, $cloneArguments), ); } if ($class->hasMethod('__clone')) { $cloneMethod = $class->getMethod('__clone'); if (!$cloneMethod->isFinal()) { if ($callOriginalClone && !$isInterface) { $proxiedCloneMethod = true; } else { $doubledCloneMethod = true; } } } else { $doubledCloneMethod = true; } } if ($isClass && $explicitMethods === []) { $mockMethods->addMethods( ...$this->mockClassMethods($_mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments), ); } if ($isInterface && ($explicitMethods === [] || $explicitMethods === null)) { $mockMethods->addMethods( ...$this->interfaceMethods($_mockClassName['fullClassName'], $cloneArguments), ); } if (is_array($explicitMethods)) { foreach ($explicitMethods as $methodName) { if ($class !== null && $class->hasMethod($methodName)) { $method = $class->getMethod($methodName); if ($this->canMethodBeDoubled($method)) { $mockMethods->addMethods( MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments), ); } } else { $mockMethods->addMethods( MockMethod::fromName( $_mockClassName['fullClassName'], $methodName, $cloneArguments, ), ); } } } $mockedMethods = ''; $configurable = []; foreach ($mockMethods->asArray() as $mockMethod) { $mockedMethods .= $mockMethod->generateCode(); $configurable[] = new ConfigurableMethod( $mockMethod->methodName(), $mockMethod->defaultParameterValues(), $mockMethod->numberOfParameters(), $mockMethod->returnType(), ); } /** @var trait-string[] $traits */ $traits = []; $isPhp82 = PHP_MAJOR_VERSION === 8 && PHP_MINOR_VERSION === 2; if (!$isReadonly && $isPhp82) { // @codeCoverageIgnoreStart $traits[] = MutableStubApi::class; // @codeCoverageIgnoreEnd } else { $traits[] = StubApi::class; } if ($mockObject) { $traits[] = MockObjectApi::class; } if ($markAsMockObject) { $traits[] = GeneratedAsMockObject::class; } else { $traits[] = GeneratedAsTestStub::class; } if ($mockMethods->hasMethod('method') || (isset($class) && $class->hasMethod('method'))) { $message = sprintf( '%s %s has a method named "method". Doubling %s that have a method named "method" is deprecated. Support for this will be removed in PHPUnit 12.', ($isInterface) ? 'Interface' : 'Class', isset($class) ? $class->getName() : $type, ($isInterface) ? 'interfaces' : 'classes', ); try { EventFacade::emitter()->testTriggeredPhpunitDeprecation( TestMethodBuilder::fromCallStack(), $message, ); } catch (NoTestCaseObjectOnCallStackException) { EventFacade::emitter()->testRunnerTriggeredDeprecation($message); } } if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) { $traits[] = Method::class; } if ($isPhp82 && $isReadonly) { // @codeCoverageIgnoreStart $traits[] = ErrorCloneMethod::class; // @codeCoverageIgnoreEnd } else { if ($doubledCloneMethod) { $traits[] = DoubledCloneMethod::class; } elseif ($proxiedCloneMethod) { $traits[] = ProxiedCloneMethod::class; } } $useStatements = ''; foreach ($traits as $trait) { $useStatements .= sprintf( ' use %s;' . PHP_EOL, $trait, ); } unset($traits); $classTemplate->setVar( [ 'prologue' => $prologue ?? '', 'epilogue' => $epilogue ?? '', 'class_declaration' => $this->generateTestDoubleClassDeclaration( $mockObject, $_mockClassName, $isInterface, $additionalInterfaces, $isReadonly, ), 'use_statements' => $useStatements, 'mock_class_name' => $_mockClassName['className'], 'mocked_methods' => $mockedMethods, ], ); return new MockClass( $classTemplate->render(), $_mockClassName['className'], $configurable, ); } /** * @return array{className: non-empty-string, originalClassName: non-empty-string, fullClassName: non-empty-string, namespaceName: string} */ private function generateClassName(string $type, string $className, string $prefix): array { if ($type[0] === '\\') { $type = substr($type, 1); } $classNameParts = explode('\\', $type); if (count($classNameParts) > 1) { $type = array_pop($classNameParts); $namespaceName = implode('\\', $classNameParts); $fullClassName = $namespaceName . '\\' . $type; } else { $namespaceName = ''; $fullClassName = $type; } if ($className === '') { do { $className = $prefix . $type . '_' . substr(md5((string) mt_rand()), 0, 8); } while (class_exists($className, false)); } return [ 'className' => $className, 'originalClassName' => $type, 'fullClassName' => $fullClassName, 'namespaceName' => $namespaceName, ]; } /** * @param array{className: non-empty-string, originalClassName: non-empty-string, fullClassName: non-empty-string, namespaceName: string} $mockClassName * @param list<class-string> $additionalInterfaces */ private function generateTestDoubleClassDeclaration(bool $mockObject, array $mockClassName, bool $isInterface, array $additionalInterfaces, bool $isReadonly): string { if ($mockObject) { $additionalInterfaces[] = MockObjectInternal::class; } else { $additionalInterfaces[] = StubInternal::class; } if ($isReadonly) { $buffer = 'readonly class '; } else { $buffer = 'class '; } $interfaces = implode(', ', $additionalInterfaces); if ($isInterface) { $buffer .= sprintf( '%s implements %s', $mockClassName['className'], $interfaces, ); if (!in_array($mockClassName['originalClassName'], $additionalInterfaces, true)) { $buffer .= ', '; if (!empty($mockClassName['namespaceName'])) { $buffer .= $mockClassName['namespaceName'] . '\\'; } $buffer .= $mockClassName['originalClassName']; } } else { $buffer .= sprintf( '%s extends %s%s implements %s', $mockClassName['className'], !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '', $mockClassName['originalClassName'], $interfaces, ); } return $buffer; } private function canMethodBeDoubled(ReflectionMethod $method): bool { if ($method->isConstructor()) { return false; } if ($method->isDestructor()) { return false; } if ($method->isFinal()) { return false; } if ($method->isPrivate()) { return false; } return !$this->isMethodNameExcluded($method->getName()); } private function isMethodNameExcluded(string $name): bool { return isset(self::EXCLUDED_METHOD_NAMES[$name]); } /** * @throws UnknownTypeException */ private function ensureKnownType(string $type, bool $callAutoload): void { if (!class_exists($type, $callAutoload) && !interface_exists($type, $callAutoload)) { throw new UnknownTypeException($type); } } /** * @param ?list<non-empty-string> $methods * * @throws DuplicateMethodException * @throws InvalidMethodNameException */ private function ensureValidMethods(?array $methods): void { if ($methods === null) { return; } foreach ($methods as $method) { if (!preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', (string) $method)) { throw new InvalidMethodNameException((string) $method); } } if ($methods !== array_unique($methods)) { throw new DuplicateMethodException($methods); } } /** * @throws NameAlreadyInUseException * @throws ReflectionException */ private function ensureNameForTestDoubleClassIsAvailable(string $className): void { if ($className === '') { return; } if (class_exists($className, false) || interface_exists($className, false) || trait_exists($className, false)) { throw new NameAlreadyInUseException($className); } } /** * @param class-string $type * @param array<mixed> $arguments * * @throws ReflectionException */ private function instantiateProxyTarget(?object $proxyTarget, object $object, string $type, array $arguments): void { if (!is_object($proxyTarget)) { assert(class_exists($type)); if (count($arguments) === 0) { $proxyTarget = new $type; } else { $class = new ReflectionClass($type); try { $proxyTarget = $class->newInstanceArgs($arguments); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd } } $object->__phpunit_state()->setProxyTarget($proxyTarget); } /** * @param class-string $className * * @throws ReflectionException * * @phpstan-ignore missingType.generics */ private function reflectClass(string $className): ReflectionClass { try { $class = new ReflectionClass($className); // @codeCoverageIgnoreStart /** @phpstan-ignore catch.neverThrown */ } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd return $class; } /** * @param class-string $classOrInterfaceName * * @throws ReflectionException * * @return list<string> */ private function namesOfMethodsIn(string $classOrInterfaceName): array { $class = $this->reflectClass($classOrInterfaceName); $methods = []; foreach ($class->getMethods() as $method) { if ($method->isPublic() || $method->isAbstract()) { $methods[] = $method->getName(); } } return $methods; } /** * @param class-string $interfaceName * * @throws ReflectionException * * @return list<MockMethod> */ private function interfaceMethods(string $interfaceName, bool $cloneArguments): array { $class = $this->reflectClass($interfaceName); $methods = []; foreach ($class->getMethods() as $method) { $methods[] = MockMethod::fromReflection($method, false, $cloneArguments); } return $methods; } } phpunit/src/Framework/MockObject/Generator/templates/wsdl_method.tpl 0000644 00000000074 15253321353 0021760 0 ustar 00 public function {method_name}({arguments}) { } phpunit/src/Framework/MockObject/Generator/templates/deprecation.tpl 0000644 00000000073 15253321353 0021743 0 ustar 00 @trigger_error({deprecation}, E_USER_DEPRECATED); phpunit/src/Framework/MockObject/Generator/templates/trait_class.tpl 0000644 00000000121 15253321353 0021750 0 ustar 00 declare(strict_types=1); {prologue}class {class_name} { use {trait_name}; } phpunit/src/Framework/MockObject/Generator/templates/wsdl_class.tpl 0000644 00000000315 15253321353 0021603 0 ustar 00 declare(strict_types=1); {namespace}class {class_name} extends \SoapClient { public function __construct($wsdl, array $options) { parent::__construct('{wsdl}', $options); } {methods}} phpunit/src/Framework/MockObject/Generator/templates/test_double_class.tpl 0000644 00000000146 15253321353 0023145 0 ustar 00 declare(strict_types=1); {prologue}{class_declaration} { {use_statements}{mocked_methods}}{epilogue} phpunit/src/Framework/MockObject/Generator/templates/doubled_method.tpl 0000644 00000003070 15253321353 0022424 0 ustar 00 {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} {{deprecation} $__phpunit_definedVariables = get_defined_vars(); $__phpunit_namedVariadicParameters = []; foreach ($__phpunit_definedVariables as $__phpunit_definedVariableName => $__phpunit_definedVariableValue) { if ((new ReflectionParameter([__CLASS__, __FUNCTION__], $__phpunit_definedVariableName))->isVariadic()) { foreach ($__phpunit_definedVariableValue as $__phpunit_key => $__phpunit_namedValue) { if (is_string($__phpunit_key)) { $__phpunit_namedVariadicParameters[$__phpunit_key] = $__phpunit_namedValue; } } } } $__phpunit_arguments = [{arguments_call}]; $__phpunit_count = func_num_args(); if ($__phpunit_count > {arguments_count}) { $__phpunit_arguments_tmp = func_get_args(); for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; } } $__phpunit_arguments = array_merge($__phpunit_arguments, $__phpunit_namedVariadicParameters); $__phpunit_result = $this->__phpunit_getInvocationHandler()->invoke( new \PHPUnit\Framework\MockObject\Invocation( '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} ) );{return_result} } phpunit/src/Framework/MockObject/Generator/templates/proxied_method.tpl 0000644 00000003242 15253321353 0022461 0 ustar 00 {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} { $__phpunit_definedVariables = get_defined_vars(); $__phpunit_namedVariadicParameters = []; foreach ($__phpunit_definedVariables as $__phpunit_definedVariableName => $__phpunit_definedVariableValue) { if ((new ReflectionParameter([__CLASS__, __FUNCTION__], $__phpunit_definedVariableName))->isVariadic()) { foreach ($__phpunit_definedVariableValue as $__phpunit_key => $__phpunit_namedValue) { if (is_string($__phpunit_key)) { $__phpunit_namedVariadicParameters[$__phpunit_key] = $__phpunit_namedValue; } } } } $__phpunit_arguments = [{arguments_call}]; $__phpunit_count = func_num_args(); if ($__phpunit_count > {arguments_count}) { $__phpunit_arguments_tmp = func_get_args(); for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; } } $__phpunit_arguments = array_merge($__phpunit_arguments, $__phpunit_namedVariadicParameters); $this->__phpunit_getInvocationHandler()->invoke( new \PHPUnit\Framework\MockObject\Invocation( '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}, true ) ); $__phpunit_result = call_user_func_array([$this->__phpunit_state()->proxyTarget(), "{method_name}"], $__phpunit_arguments);{return_result} } phpunit/src/Framework/MockObject/Generator/templates/doubled_static_method.tpl 0000644 00000000356 15253321353 0023777 0 ustar 00 {modifier} function {reference}{method_name}({arguments_decl}){return_declaration} { throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object'); } phpunit/src/Framework/MockObject/Generator/templates/intersection.tpl 0000644 00000000114 15253321353 0022150 0 ustar 00 declare(strict_types=1); interface {intersection} extends {interfaces} { } phpunit/src/Framework/MockObject/Generator/MockMethodSet.php 0000644 00000002250 15253321353 0020145 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function array_key_exists; use function array_values; use function strtolower; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MockMethodSet { /** * @var array<string,MockMethod> */ private array $methods = []; public function addMethods(MockMethod ...$methods): void { foreach ($methods as $method) { $this->methods[strtolower($method->methodName())] = $method; } } /** * @return list<MockMethod> */ public function asArray(): array { return array_values($this->methods); } public function hasMethod(string $methodName): bool { return array_key_exists(strtolower($methodName), $this->methods); } } phpunit/src/Framework/MockObject/Generator/MockClass.php 0000644 00000003254 15253321353 0017323 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function class_exists; use PHPUnit\Framework\MockObject\ConfigurableMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MockClass implements MockType { private string $classCode; /** * @var class-string */ private string $mockName; /** * @var list<ConfigurableMethod> */ private array $configurableMethods; /** * @param class-string $mockName * @param list<ConfigurableMethod> $configurableMethods */ public function __construct(string $classCode, string $mockName, array $configurableMethods) { $this->classCode = $classCode; $this->mockName = $mockName; $this->configurableMethods = $configurableMethods; } /** * @return class-string */ public function generate(): string { if (!class_exists($this->mockName, false)) { eval($this->classCode); } return $this->mockName; } public function classCode(): string { return $this->classCode; } /** * @return list<ConfigurableMethod> */ public function configurableMethods(): array { return $this->configurableMethods; } } phpunit/src/Framework/MockObject/Generator/MockTrait.php 0000644 00000002272 15253321353 0017340 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Generator; use function class_exists; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 */ final readonly class MockTrait implements MockType { private string $classCode; /** * @var class-string */ private string $mockName; /** * @param class-string $mockName */ public function __construct(string $classCode, string $mockName) { $this->classCode = $classCode; $this->mockName = $mockName; } /** * @return class-string */ public function generate(): string { if (!class_exists($this->mockName, false)) { eval($this->classCode); } return $this->mockName; } } phpunit/src/Framework/MockObject/ConfigurableMethod.php 0000644 00000004013 15253321353 0017251 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use SebastianBergmann\Type\Type; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ConfigurableMethod { /** * @var non-empty-string */ private string $name; /** * @var array<int, mixed> */ private array $defaultParameterValues; /** * @var non-negative-int */ private int $numberOfParameters; private Type $returnType; /** * @param non-empty-string $name * @param array<int, mixed> $defaultParameterValues * @param non-negative-int $numberOfParameters */ public function __construct(string $name, array $defaultParameterValues, int $numberOfParameters, Type $returnType) { $this->name = $name; $this->defaultParameterValues = $defaultParameterValues; $this->numberOfParameters = $numberOfParameters; $this->returnType = $returnType; } /** * @return non-empty-string */ public function name(): string { return $this->name; } /** * @return array<int, mixed> */ public function defaultParameterValues(): array { return $this->defaultParameterValues; } /** * @return non-negative-int */ public function numberOfParameters(): int { return $this->numberOfParameters; } public function mayReturn(mixed $value): bool { return $this->returnType->isAssignable(Type::fromValue($value, false)); } public function returnTypeDeclaration(): string { return $this->returnType->asString(); } } phpunit/src/Framework/MockObject/Runtime/ReturnValueGenerator.php 0000644 00000016655 15253321353 0021275 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function array_keys; use function array_map; use function explode; use function in_array; use function interface_exists; use function sprintf; use function str_contains; use function str_ends_with; use function str_starts_with; use function substr; use PHPUnit\Framework\MockObject\Generator\Generator; use ReflectionClass; use stdClass; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReturnValueGenerator { /** * @param class-string $className * @param non-empty-string $methodName * @param class-string $stubClassName * * @throws Exception */ public function generate(string $className, string $methodName, string $stubClassName, string $returnType): mixed { $intersection = false; $union = false; if (str_contains($returnType, '|')) { $types = explode('|', $returnType); $union = true; foreach (array_keys($types) as $key) { if (str_starts_with($types[$key], '(') && str_ends_with($types[$key], ')')) { $types[$key] = substr($types[$key], 1, -1); } } } elseif (str_contains($returnType, '&')) { $types = explode('&', $returnType); $intersection = true; } else { $types = [$returnType]; } if (!$intersection) { $lowerTypes = array_map('strtolower', $types); if (in_array('', $lowerTypes, true) || in_array('null', $lowerTypes, true) || in_array('mixed', $lowerTypes, true) || in_array('void', $lowerTypes, true)) { return null; } if (in_array('true', $lowerTypes, true)) { return true; } if (in_array('false', $lowerTypes, true) || in_array('bool', $lowerTypes, true)) { return false; } if (in_array('float', $lowerTypes, true)) { return 0.0; } if (in_array('int', $lowerTypes, true)) { return 0; } if (in_array('string', $lowerTypes, true)) { return ''; } if (in_array('array', $lowerTypes, true)) { return []; } if (in_array('static', $lowerTypes, true)) { return $this->newInstanceOf($stubClassName, $className, $methodName); } if (in_array('object', $lowerTypes, true)) { return new stdClass; } if (in_array('callable', $lowerTypes, true) || in_array('closure', $lowerTypes, true)) { return static function (): void { }; } if (in_array('traversable', $lowerTypes, true) || in_array('generator', $lowerTypes, true) || in_array('iterable', $lowerTypes, true)) { $generator = static function (): \Generator { yield from []; }; return $generator(); } if (!$union) { return $this->testDoubleFor($returnType, $className, $methodName); } } if ($union) { foreach ($types as $type) { if (str_contains($type, '&')) { $_types = explode('&', $type); if ($this->onlyInterfaces($_types)) { return $this->testDoubleForIntersectionOfInterfaces($_types, $className, $methodName); } } } } if ($intersection && $this->onlyInterfaces($types)) { return $this->testDoubleForIntersectionOfInterfaces($types, $className, $methodName); } $reason = ''; if ($union) { $reason = ' because the declared return type is a union'; } elseif ($intersection) { $reason = ' because the declared return type is an intersection'; } throw new RuntimeException( sprintf( 'Return value for %s::%s() cannot be generated%s, please configure a return value for this method', $className, $methodName, $reason, ), ); } /** * @param non-empty-list<string> $types */ private function onlyInterfaces(array $types): bool { foreach ($types as $type) { if (!interface_exists($type)) { return false; } } return true; } /** * @param class-string $stubClassName * @param class-string $className * @param non-empty-string $methodName * * @throws RuntimeException */ private function newInstanceOf(string $stubClassName, string $className, string $methodName): Stub { try { return (new ReflectionClass($stubClassName))->newInstanceWithoutConstructor(); // @codeCoverageIgnoreStart } catch (Throwable $t) { throw new RuntimeException( sprintf( 'Return value for %s::%s() cannot be generated: %s', $className, $methodName, $t->getMessage(), ), ); // @codeCoverageIgnoreEnd } } /** * @param class-string $type * @param class-string $className * @param non-empty-string $methodName * * @throws RuntimeException */ private function testDoubleFor(string $type, string $className, string $methodName): Stub { try { return (new Generator)->testDouble($type, false, false, [], [], '', false); // @codeCoverageIgnoreStart } catch (Throwable $t) { throw new RuntimeException( sprintf( 'Return value for %s::%s() cannot be generated: %s', $className, $methodName, $t->getMessage(), ), ); // @codeCoverageIgnoreEnd } } /** * @param non-empty-list<string> $types * @param class-string $className * @param non-empty-string $methodName * * @throws RuntimeException */ private function testDoubleForIntersectionOfInterfaces(array $types, string $className, string $methodName): Stub { try { return (new Generator)->testDoubleForInterfaceIntersection($types, false); // @codeCoverageIgnoreStart } catch (Throwable $t) { throw new RuntimeException( sprintf( 'Return value for %s::%s() cannot be generated: %s', $className, $methodName, $t->getMessage(), ), ); // @codeCoverageIgnoreEnd } } } phpunit/src/Framework/MockObject/Runtime/Interface/MockObjectInternal.php 0000644 00000001275 15253321353 0022557 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface MockObjectInternal extends MockObject, StubInternal { public function __phpunit_hasMatchers(): bool; public function __phpunit_verify(bool $unsetInvocationMocker = true): void; } phpunit/src/Framework/MockObject/Runtime/Interface/MockObject.php 0000644 00000001263 15253321353 0021057 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; use PHPUnit\Framework\MockObject\Rule\InvocationOrder; /** * @method InvocationMocker method($constraint) * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObject extends Stub { public function expects(InvocationOrder $invocationRule): InvocationMocker; } phpunit/src/Framework/MockObject/Runtime/Interface/StubInternal.php 0000644 00000001440 15253321353 0021446 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface StubInternal extends Stub { public function __phpunit_state(): TestDoubleState; public function __phpunit_getInvocationHandler(): InvocationHandler; public function __phpunit_unsetInvocationMocker(): void; public function __phpunit_wasGeneratedAsMockObject(): bool; } phpunit/src/Framework/MockObject/Runtime/Interface/Stub.php 0000644 00000001033 15253321353 0017747 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use PHPUnit\Framework\MockObject\Builder\InvocationStubber; /** * @method InvocationStubber method($constraint) * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Stub { } phpunit/src/Framework/MockObject/Runtime/Builder/MethodNameMatch.php 0000644 00000001446 15253321353 0021526 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; use PHPUnit\Framework\Constraint\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface MethodNameMatch extends ParametersMatch { /** * Adds a new method name match and returns the parameter match object for * further matching possibilities. */ public function method(Constraint|string $constraint): self; } phpunit/src/Framework/MockObject/Runtime/Builder/InvocationMocker.php 0000644 00000021614 15253321353 0022001 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; use function array_flip; use function array_key_exists; use function array_map; use function array_merge; use function array_pop; use function assert; use function count; use function is_string; use function range; use function strtolower; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\InvalidArgumentException; use PHPUnit\Framework\MockObject\ConfigurableMethod; use PHPUnit\Framework\MockObject\IncompatibleReturnValueException; use PHPUnit\Framework\MockObject\InvocationHandler; use PHPUnit\Framework\MockObject\Matcher; use PHPUnit\Framework\MockObject\MatcherAlreadyRegisteredException; use PHPUnit\Framework\MockObject\MethodCannotBeConfiguredException; use PHPUnit\Framework\MockObject\MethodNameAlreadyConfiguredException; use PHPUnit\Framework\MockObject\MethodNameNotConfiguredException; use PHPUnit\Framework\MockObject\MethodParametersAlreadyConfiguredException; use PHPUnit\Framework\MockObject\Rule; use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls; use PHPUnit\Framework\MockObject\Stub\Exception; use PHPUnit\Framework\MockObject\Stub\ReturnArgument; use PHPUnit\Framework\MockObject\Stub\ReturnCallback; use PHPUnit\Framework\MockObject\Stub\ReturnReference; use PHPUnit\Framework\MockObject\Stub\ReturnSelf; use PHPUnit\Framework\MockObject\Stub\ReturnStub; use PHPUnit\Framework\MockObject\Stub\ReturnValueMap; use PHPUnit\Framework\MockObject\Stub\Stub; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class InvocationMocker implements InvocationStubber, MethodNameMatch { private readonly InvocationHandler $invocationHandler; private readonly Matcher $matcher; /** * @var list<ConfigurableMethod> */ private readonly array $configurableMethods; /** * @var ?array<string, int> */ private ?array $configurableMethodNames = null; public function __construct(InvocationHandler $handler, Matcher $matcher, ConfigurableMethod ...$configurableMethods) { $this->invocationHandler = $handler; $this->matcher = $matcher; $this->configurableMethods = $configurableMethods; } /** * @throws MatcherAlreadyRegisteredException * * @return $this */ public function id(string $id): self { $this->invocationHandler->registerMatcher($id, $this->matcher); return $this; } /** * @return $this */ public function will(Stub $stub): Identity { $this->matcher->setStub($stub); return $this; } /** * @throws IncompatibleReturnValueException */ public function willReturn(mixed $value, mixed ...$nextValues): self { if (count($nextValues) === 0) { $this->ensureTypeOfReturnValues([$value]); $stub = $value instanceof Stub ? $value : new ReturnStub($value); return $this->will($stub); } $values = array_merge([$value], $nextValues); $this->ensureTypeOfReturnValues($values); $stub = new ConsecutiveCalls($values); return $this->will($stub); } public function willReturnReference(mixed &$reference): self { $stub = new ReturnReference($reference); return $this->will($stub); } public function willReturnMap(array $valueMap): self { $method = $this->configuredMethod(); assert($method instanceof ConfigurableMethod); $numberOfParameters = $method->numberOfParameters(); $defaultValues = $method->defaultParameterValues(); $hasDefaultValues = !empty($defaultValues); $_valueMap = []; foreach ($valueMap as $mapping) { $numberOfConfiguredParameters = count($mapping) - 1; if ($numberOfConfiguredParameters === $numberOfParameters || !$hasDefaultValues) { $_valueMap[] = $mapping; continue; } $_mapping = []; $returnValue = array_pop($mapping); foreach (range(0, $numberOfParameters - 1) as $i) { if (isset($mapping[$i])) { $_mapping[] = $mapping[$i]; continue; } if (isset($defaultValues[$i])) { $_mapping[] = $defaultValues[$i]; } } $_mapping[] = $returnValue; $_valueMap[] = $_mapping; } $stub = new ReturnValueMap($_valueMap); return $this->will($stub); } public function willReturnArgument(int $argumentIndex): self { $stub = new ReturnArgument($argumentIndex); return $this->will($stub); } public function willReturnCallback(callable $callback): self { $stub = new ReturnCallback($callback); return $this->will($stub); } public function willReturnSelf(): self { $stub = new ReturnSelf; return $this->will($stub); } public function willReturnOnConsecutiveCalls(mixed ...$values): self { $stub = new ConsecutiveCalls($values); return $this->will($stub); } public function willThrowException(Throwable $exception): self { $stub = new Exception($exception); return $this->will($stub); } /** * @return $this */ public function after(string $id): self { $this->matcher->setAfterMatchBuilderId($id); return $this; } /** * @throws \PHPUnit\Framework\Exception * @throws MethodNameNotConfiguredException * @throws MethodParametersAlreadyConfiguredException * * @return $this */ public function with(mixed ...$arguments): self { $this->ensureParametersCanBeConfigured(); $this->matcher->setParametersRule(new Rule\Parameters($arguments)); return $this; } /** * @throws MethodNameNotConfiguredException * @throws MethodParametersAlreadyConfiguredException * * @return $this */ public function withAnyParameters(): self { $this->ensureParametersCanBeConfigured(); $this->matcher->setParametersRule(new Rule\AnyParameters); return $this; } /** * @throws InvalidArgumentException * @throws MethodCannotBeConfiguredException * @throws MethodNameAlreadyConfiguredException * * @return $this */ public function method(Constraint|string $constraint): self { if ($this->matcher->hasMethodNameRule()) { throw new MethodNameAlreadyConfiguredException; } if (is_string($constraint)) { $this->configurableMethodNames ??= array_flip( array_map( static fn (ConfigurableMethod $configurable) => strtolower($configurable->name()), $this->configurableMethods, ), ); if (!array_key_exists(strtolower($constraint), $this->configurableMethodNames)) { throw new MethodCannotBeConfiguredException($constraint); } } $this->matcher->setMethodNameRule(new Rule\MethodName($constraint)); return $this; } /** * @throws MethodNameNotConfiguredException * @throws MethodParametersAlreadyConfiguredException */ private function ensureParametersCanBeConfigured(): void { if (!$this->matcher->hasMethodNameRule()) { throw new MethodNameNotConfiguredException; } if ($this->matcher->hasParametersRule()) { throw new MethodParametersAlreadyConfiguredException; } } private function configuredMethod(): ?ConfigurableMethod { $configuredMethod = null; foreach ($this->configurableMethods as $configurableMethod) { if ($this->matcher->methodNameRule()->matchesName($configurableMethod->name())) { if ($configuredMethod !== null) { return null; } $configuredMethod = $configurableMethod; } } return $configuredMethod; } /** * @param array<mixed> $values * * @throws IncompatibleReturnValueException */ private function ensureTypeOfReturnValues(array $values): void { $configuredMethod = $this->configuredMethod(); if ($configuredMethod === null) { return; } foreach ($values as $value) { if (!$configuredMethod->mayReturn($value)) { throw new IncompatibleReturnValueException( $configuredMethod, $value, ); } } } } phpunit/src/Framework/MockObject/Runtime/Builder/InvocationStubber.php 0000644 00000002175 15253321353 0022170 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; use PHPUnit\Framework\MockObject\Stub\Stub; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface InvocationStubber { public function will(Stub $stub): Identity; public function willReturn(mixed $value, mixed ...$nextValues): self; public function willReturnReference(mixed &$reference): self; /** * @param array<int, array<int, mixed>> $valueMap */ public function willReturnMap(array $valueMap): self; public function willReturnArgument(int $argumentIndex): self; public function willReturnCallback(callable $callback): self; public function willReturnSelf(): self; public function willReturnOnConsecutiveCalls(mixed ...$values): self; public function willThrowException(Throwable $exception): self; } phpunit/src/Framework/MockObject/Runtime/Builder/ParametersMatch.php 0000644 00000003153 15253321353 0021605 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface ParametersMatch extends Stub { /** * Defines the expectation which must occur before the current is valid. */ public function after(string $id): Stub; /** * Sets the parameters to match for, each parameter to this function will * be part of match. To perform specific matches or constraints create a * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter. * If the parameter value is not a constraint it will use the * PHPUnit\Framework\Constraint\IsEqual for the value. * * Some examples: * <code> * // match first parameter with value 2 * $b->with(2); * // match first parameter with value 'smock' and second identical to 42 * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42)); * </code> */ public function with(mixed ...$arguments): self; /** * Sets a rule which allows any kind of parameters. * * Some examples: * <code> * // match any number of parameters * $b->withAnyParameters(); * </code> */ public function withAnyParameters(): self; } phpunit/src/Framework/MockObject/Runtime/Builder/Identity.php 0000644 00000001304 15253321353 0020312 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Identity { /** * Sets the identification of the expectation to $id. * * @note The identifier is unique per mock object. */ public function id(string $id): self; } phpunit/src/Framework/MockObject/Runtime/Builder/Stub.php 0000644 00000001457 15253321353 0017447 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Builder; use PHPUnit\Framework\MockObject\Stub\Stub as BaseStub; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Stub extends Identity { /** * Stubs the matching method with the stub object $stub. Any invocations of * the matched method will now be handled by the stub instead. */ public function will(BaseStub $stub): Identity; } phpunit/src/Framework/MockObject/Runtime/Api/MockObjectApi.php 0000644 00000005430 15253321353 0020322 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function assert; use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException; use PHPUnit\Event\Code\TestMethodBuilder; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\MockObject\Builder\InvocationMocker as InvocationMockerBuilder; use PHPUnit\Framework\MockObject\Rule\InvocationOrder; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait MockObjectApi { /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_hasMatchers(): bool { return $this->__phpunit_getInvocationHandler()->hasMatchers(); } /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_verify(bool $unsetInvocationMocker = true): void { $this->__phpunit_getInvocationHandler()->verify(); if ($unsetInvocationMocker) { $this->__phpunit_unsetInvocationMocker(); } } abstract public function __phpunit_state(): TestDoubleState; abstract public function __phpunit_getInvocationHandler(): InvocationHandler; abstract public function __phpunit_unsetInvocationMocker(): void; public function expects(InvocationOrder $matcher): InvocationMockerBuilder { assert($this instanceof StubInternal); if (!$this->__phpunit_wasGeneratedAsMockObject()) { $message = 'Expectations configured on test doubles that are created as test stubs are no longer verified since PHPUnit 10. Test doubles that are created as test stubs will no longer have the expects() method in PHPUnit 12. Update your test code to use createMock() instead of createStub(), for example.'; try { $test = TestMethodBuilder::fromCallStack(); if (!$this->__phpunit_state()->wasDeprecationAlreadyEmittedFor($test->id())) { EventFacade::emitter()->testTriggeredPhpunitDeprecation( $test, $message, ); $this->__phpunit_state()->deprecationWasEmittedFor($test->id()); } // @codeCoverageIgnoreStart } catch (NoTestCaseObjectOnCallStackException) { EventFacade::emitter()->testRunnerTriggeredDeprecation($message); // @codeCoverageIgnoreEnd } } return $this->__phpunit_getInvocationHandler()->expects($matcher); } } phpunit/src/Framework/MockObject/Runtime/Api/ProxiedCloneMethod.php 0000644 00000001432 15253321353 0021402 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait ProxiedCloneMethod { public function __clone(): void { $this->__phpunit_state = clone $this->__phpunit_state; $this->__phpunit_state()->cloneInvocationHandler(); parent::__clone(); } abstract public function __phpunit_state(): TestDoubleState; } phpunit/src/Framework/MockObject/Runtime/Api/GeneratedAsTestStub.php 0000644 00000001163 15253321353 0021527 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait GeneratedAsTestStub { public function __phpunit_wasGeneratedAsMockObject(): false { return false; } } phpunit/src/Framework/MockObject/Runtime/Api/GeneratedAsMockObject.php 0000644 00000001163 15253321353 0021772 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait GeneratedAsMockObject { public function __phpunit_wasGeneratedAsMockObject(): true { return true; } } phpunit/src/Framework/MockObject/Runtime/Api/MutableStubApi.php 0000644 00000002107 15253321353 0020527 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ trait MutableStubApi { private TestDoubleState $__phpunit_state; public function __phpunit_state(): TestDoubleState { return $this->__phpunit_state; } /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_getInvocationHandler(): InvocationHandler { return $this->__phpunit_state()->invocationHandler(); } /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_unsetInvocationMocker(): void { $this->__phpunit_state()->unsetInvocationHandler(); } } phpunit/src/Framework/MockObject/Runtime/Api/DoubledCloneMethod.php 0000644 00000001376 15253321353 0021355 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait DoubledCloneMethod { public function __clone(): void { $this->__phpunit_state = clone $this->__phpunit_state; $this->__phpunit_state()->cloneInvocationHandler(); } abstract public function __phpunit_state(): TestDoubleState; } phpunit/src/Framework/MockObject/Runtime/Api/Method.php 0000644 00000002016 15253321353 0017065 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function call_user_func_array; use function func_get_args; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait Method { abstract public function __phpunit_getInvocationHandler(): InvocationHandler; public function method(): InvocationMocker { $expects = $this->__phpunit_getInvocationHandler()->expects(new AnyInvokedCount); return call_user_func_array( [$expects, 'method'], func_get_args(), ); } } phpunit/src/Framework/MockObject/Runtime/Api/ErrorCloneMethod.php 0000644 00000001232 15253321353 0021057 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ trait ErrorCloneMethod { public function __clone(): void { throw new CannotCloneTestDoubleForReadonlyClassException; } } phpunit/src/Framework/MockObject/Runtime/Api/TestDoubleState.php 0000644 00000005016 15253321353 0020723 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function assert; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestDoubleState { /** * @var array<non-empty-string, true> */ private static array $deprecationEmittedForTest = []; /** * @var list<ConfigurableMethod> */ private readonly array $configurableMethods; private readonly bool $generateReturnValues; private ?InvocationHandler $invocationHandler = null; private ?object $proxyTarget = null; /** * @param list<ConfigurableMethod> $configurableMethods */ public function __construct(array $configurableMethods, bool $generateReturnValues) { $this->configurableMethods = $configurableMethods; $this->generateReturnValues = $generateReturnValues; } public function invocationHandler(): InvocationHandler { if ($this->invocationHandler !== null) { return $this->invocationHandler; } $this->invocationHandler = new InvocationHandler( $this->configurableMethods, $this->generateReturnValues, ); return $this->invocationHandler; } public function cloneInvocationHandler(): void { if ($this->invocationHandler === null) { return; } $this->invocationHandler = clone $this->invocationHandler; } public function unsetInvocationHandler(): void { $this->invocationHandler = null; } public function setProxyTarget(object $proxyTarget): void { $this->proxyTarget = $proxyTarget; } public function proxyTarget(): object { assert($this->proxyTarget !== null); return $this->proxyTarget; } /** * @param non-empty-string $testId */ public function deprecationWasEmittedFor(string $testId): void { self::$deprecationEmittedForTest[$testId] = true; } /** * @param non-empty-string $testId */ public function wasDeprecationAlreadyEmittedFor(string $testId): bool { return isset(self::$deprecationEmittedForTest[$testId]); } } phpunit/src/Framework/MockObject/Runtime/Api/StubApi.php 0000644 00000002057 15253321353 0017221 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This trait is not covered by the backward compatibility promise for PHPUnit */ trait StubApi { private readonly TestDoubleState $__phpunit_state; public function __phpunit_state(): TestDoubleState { return $this->__phpunit_state; } /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_getInvocationHandler(): InvocationHandler { return $this->__phpunit_state()->invocationHandler(); } /** @noinspection MagicMethodsValidityInspection */ public function __phpunit_unsetInvocationMocker(): void { $this->__phpunit_state()->unsetInvocationHandler(); } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnSelf.php 0000644 00000001441 15253321353 0020143 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; use PHPUnit\Framework\MockObject\RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReturnSelf implements Stub { /** * @throws RuntimeException */ public function invoke(Invocation $invocation): object { return $invocation->object(); } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnCallback.php 0000644 00000001662 15253321353 0020753 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use function call_user_func_array; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReturnCallback implements Stub { /** * @var callable */ private $callback; public function __construct(callable $callback) { $this->callback = $callback; } public function invoke(Invocation $invocation): mixed { return call_user_func_array($this->callback, $invocation->parameters()); } } phpunit/src/Framework/MockObject/Runtime/Stub/Exception.php 0000644 00000001604 15253321353 0020011 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Exception implements Stub { private Throwable $exception; public function __construct(Throwable $exception) { $this->exception = $exception; } /** * @throws Throwable */ public function invoke(Invocation $invocation): never { throw $this->exception; } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnValueMap.php 0000644 00000002520 15253321353 0020763 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use function array_pop; use function count; use function is_array; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ReturnValueMap implements Stub { /** * @var array<mixed> */ private array $valueMap; /** * @param array<mixed> $valueMap */ public function __construct(array $valueMap) { $this->valueMap = $valueMap; } public function invoke(Invocation $invocation): mixed { $parameterCount = count($invocation->parameters()); foreach ($this->valueMap as $map) { if (!is_array($map) || $parameterCount !== (count($map) - 1)) { continue; } $return = array_pop($map); if ($invocation->parameters() === $map) { return $return; } } return null; } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnArgument.php 0000644 00000001575 15253321353 0021044 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ReturnArgument implements Stub { private int $argumentIndex; public function __construct(int $argumentIndex) { $this->argumentIndex = $argumentIndex; } public function invoke(Invocation $invocation): mixed { return $invocation->parameters()[$this->argumentIndex] ?? null; } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnReference.php 0000644 00000001504 15253321353 0021150 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReturnReference implements Stub { private mixed $reference; public function __construct(mixed &$reference) { $this->reference = &$reference; } public function invoke(Invocation $invocation): mixed { return $this->reference; } } phpunit/src/Framework/MockObject/Runtime/Stub/ReturnStub.php 0000644 00000001462 15253321353 0020172 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ReturnStub implements Stub { private mixed $value; public function __construct(mixed $value) { $this->value = $value; } public function invoke(Invocation $invocation): mixed { return $this->value; } } phpunit/src/Framework/MockObject/Runtime/Stub/Stub.php 0000644 00000001344 15253321353 0016771 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Invocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Stub { /** * Fakes the processing of the invocation $invocation by returning a * specific value. */ public function invoke(Invocation $invocation): mixed; } phpunit/src/Framework/MockObject/Runtime/Stub/ConsecutiveCalls.php 0000644 00000003046 15253321353 0021323 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Stub; use function array_shift; use function count; use PHPUnit\Framework\MockObject\Invocation; use PHPUnit\Framework\MockObject\NoMoreReturnValuesConfiguredException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ConsecutiveCalls implements Stub { /** * @var array<mixed> */ private array $stack; private int $numberOfConfiguredReturnValues; /** * @param array<mixed> $stack */ public function __construct(array $stack) { $this->stack = $stack; $this->numberOfConfiguredReturnValues = count($stack); } /** * @throws NoMoreReturnValuesConfiguredException */ public function invoke(Invocation $invocation): mixed { if (empty($this->stack)) { throw new NoMoreReturnValuesConfiguredException( $invocation, $this->numberOfConfiguredReturnValues, ); } $value = array_shift($this->stack); if ($value instanceof Stub) { $value = $value->invoke($invocation); } return $value; } } phpunit/src/Framework/MockObject/Runtime/Invocation.php 0000644 00000007602 15253321353 0017253 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function array_map; use function implode; use function is_object; use function sprintf; use function str_starts_with; use function strtolower; use function substr; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Util\Cloner; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Invocation implements SelfDescribing { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @var array<mixed> */ private array $parameters; private string $returnType; private bool $isReturnTypeNullable; private bool $proxiedCall; private MockObjectInternal|StubInternal $object; /** * @param class-string $className * @param non-empty-string $methodName * @param array<mixed> $parameters */ public function __construct(string $className, string $methodName, array $parameters, string $returnType, MockObjectInternal|StubInternal $object, bool $cloneObjects = false, bool $proxiedCall = false) { $this->className = $className; $this->methodName = $methodName; $this->object = $object; $this->proxiedCall = $proxiedCall; if (strtolower($methodName) === '__tostring') { $returnType = 'string'; } if (str_starts_with($returnType, '?')) { $returnType = substr($returnType, 1); $this->isReturnTypeNullable = true; } else { $this->isReturnTypeNullable = false; } $this->returnType = $returnType; if (!$cloneObjects) { $this->parameters = $parameters; return; } foreach ($parameters as $key => $value) { if (is_object($value)) { $parameters[$key] = Cloner::clone($value); } } $this->parameters = $parameters; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @return array<mixed> */ public function parameters(): array { return $this->parameters; } /** * @throws Exception */ public function generateReturnValue(): mixed { if ($this->returnType === 'never') { throw new NeverReturningMethodException( $this->className, $this->methodName, ); } if ($this->isReturnTypeNullable || $this->proxiedCall) { return null; } return (new ReturnValueGenerator)->generate( $this->className, $this->methodName, $this->object::class, $this->returnType, ); } public function toString(): string { return sprintf( '%s::%s(%s)%s', $this->className, $this->methodName, implode( ', ', array_map( [Exporter::class, 'shortenedExport'], $this->parameters, ), ), $this->returnType ? sprintf(': %s', $this->returnType) : '', ); } public function object(): MockObjectInternal|StubInternal { return $this->object; } } phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastCount.php 0000644 00000003717 15253321353 0021742 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvokedAtLeastCount extends InvocationOrder { private readonly int $requiredInvocations; public function __construct(int $requiredInvocations) { $this->requiredInvocations = $requiredInvocations; } public function toString(): string { return sprintf( 'invoked at least %d time%s', $this->requiredInvocations, $this->requiredInvocations !== 1 ? 's' : '', ); } /** * Verifies that the current expectation is valid. If everything is OK the * code should just return, if not it must throw an exception. * * @throws ExpectationFailedException */ public function verify(): void { $actualInvocations = $this->numberOfInvocations(); if ($actualInvocations < $this->requiredInvocations) { throw new ExpectationFailedException( sprintf( 'Expected invocation at least %d time%s but it occurred %d time%s.', $this->requiredInvocations, $this->requiredInvocations !== 1 ? 's' : '', $actualInvocations, $actualInvocations !== 1 ? 's' : '', ), ); } } public function matches(BaseInvocation $invocation): bool { return true; } } phpunit/src/Framework/MockObject/Runtime/Rule/InvokedCount.php 0000644 00000005262 15253321353 0020461 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvokedCount extends InvocationOrder { private readonly int $expectedCount; public function __construct(int $expectedCount) { $this->expectedCount = $expectedCount; } public function isNever(): bool { return $this->expectedCount === 0; } public function toString(): string { return sprintf( 'invoked %d time%s', $this->expectedCount, $this->expectedCount !== 1 ? 's' : '', ); } public function matches(BaseInvocation $invocation): bool { return true; } /** * Verifies that the current expectation is valid. If everything is OK the * code should just return, if not it must throw an exception. * * @throws ExpectationFailedException */ public function verify(): void { $actualCount = $this->numberOfInvocations(); if ($actualCount !== $this->expectedCount) { throw new ExpectationFailedException( sprintf( 'Method was expected to be called %d time%s, actually called %d time%s.', $this->expectedCount, $this->expectedCount !== 1 ? 's' : '', $actualCount, $actualCount !== 1 ? 's' : '', ), ); } } /** * @throws ExpectationFailedException */ protected function invokedDo(BaseInvocation $invocation): void { $count = $this->numberOfInvocations(); if ($count > $this->expectedCount) { $message = $invocation->toString() . ' '; $message .= match ($this->expectedCount) { 0 => 'was not expected to be called.', 1 => 'was not expected to be called more than once.', default => sprintf( 'was not expected to be called more than %d times.', $this->expectedCount, ), }; throw new ExpectationFailedException($message); } } } phpunit/src/Framework/MockObject/Runtime/Rule/ParametersRule.php 0000644 00000001353 15253321353 0021001 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ParametersRule { /** * @throws ExpectationFailedException if the invocation violates the rule */ public function apply(BaseInvocation $invocation): void; public function verify(): void; } phpunit/src/Framework/MockObject/Runtime/Rule/AnyInvokedCount.php 0000644 00000001540 15253321353 0021124 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class AnyInvokedCount extends InvocationOrder { public function toString(): string { return 'invoked zero or more times'; } public function verify(): void { } public function matches(BaseInvocation $invocation): bool { return true; } } phpunit/src/Framework/MockObject/Runtime/Rule/AnyParameters.php 0000644 00000001350 15253321353 0020616 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class AnyParameters implements ParametersRule { public function apply(BaseInvocation $invocation): void { } public function verify(): void { } } phpunit/src/Framework/MockObject/Runtime/Rule/MethodName.php 0000644 00000003176 15253321353 0020074 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function is_string; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\InvalidArgumentException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; use PHPUnit\Framework\MockObject\MethodNameConstraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MethodName { private Constraint $constraint; /** * @throws InvalidArgumentException */ public function __construct(Constraint|string $constraint) { if (is_string($constraint)) { $constraint = new MethodNameConstraint($constraint); } $this->constraint = $constraint; } public function toString(): string { return 'method name ' . $this->constraint->toString(); } /** * @throws ExpectationFailedException */ public function matches(BaseInvocation $invocation): bool { return $this->matchesName($invocation->methodName()); } /** * @throws ExpectationFailedException */ public function matchesName(string $methodName): bool { return (bool) $this->constraint->evaluate($methodName, '', true); } } phpunit/src/Framework/MockObject/Runtime/Rule/Parameters.php 0000644 00000010270 15253321353 0020147 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function count; use function sprintf; use Exception; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\Constraint\IsAnything; use PHPUnit\Framework\Constraint\IsEqual; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Parameters implements ParametersRule { /** * @var list<Constraint> */ private array $parameters = []; private ?BaseInvocation $invocation = null; private null|bool|ExpectationFailedException $parameterVerificationResult; /** * @param array<mixed> $parameters * * @throws \PHPUnit\Framework\Exception */ public function __construct(array $parameters) { foreach ($parameters as $parameter) { if (!($parameter instanceof Constraint)) { $parameter = new IsEqual( $parameter, ); } $this->parameters[] = $parameter; } } /** * @throws Exception */ public function apply(BaseInvocation $invocation): void { $this->invocation = $invocation; $this->parameterVerificationResult = null; try { $this->parameterVerificationResult = $this->doVerify(); } catch (ExpectationFailedException $e) { $this->parameterVerificationResult = $e; throw $this->parameterVerificationResult; } } /** * Checks if the invocation $invocation matches the current rules. If it * does the rule will get the invoked() method called which should check * if an expectation is met. * * @throws ExpectationFailedException */ public function verify(): void { $this->doVerify(); } /** * @throws ExpectationFailedException */ private function doVerify(): bool { if (isset($this->parameterVerificationResult)) { return $this->guardAgainstDuplicateEvaluationOfParameterConstraints(); } if ($this->invocation === null) { throw new ExpectationFailedException('Mocked method does not exist.'); } if (count($this->invocation->parameters()) < count($this->parameters)) { $message = 'Parameter count for invocation %s is too low.'; // The user called `->with($this->anything())`, but may have meant // `->withAnyParameters()`. // // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199 if (count($this->parameters) === 1 && $this->parameters[0]::class === IsAnything::class) { $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead."; } throw new ExpectationFailedException( sprintf($message, $this->invocation->toString()), ); } foreach ($this->parameters as $i => $parameter) { $parameter->evaluate( $this->invocation->parameters()[$i], sprintf( 'Parameter %s for invocation %s does not match expected ' . 'value.', $i, $this->invocation->toString(), ), ); } return true; } /** * @throws ExpectationFailedException */ private function guardAgainstDuplicateEvaluationOfParameterConstraints(): bool { if ($this->parameterVerificationResult instanceof ExpectationFailedException) { throw $this->parameterVerificationResult; } return (bool) $this->parameterVerificationResult; } } phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtMostCount.php 0000644 00000003703 15253321353 0021607 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvokedAtMostCount extends InvocationOrder { private readonly int $allowedInvocations; public function __construct(int $allowedInvocations) { $this->allowedInvocations = $allowedInvocations; } public function toString(): string { return sprintf( 'invoked at most %d time%s', $this->allowedInvocations, $this->allowedInvocations !== 1 ? 's' : '', ); } /** * Verifies that the current expectation is valid. If everything is OK the * code should just return, if not it must throw an exception. * * @throws ExpectationFailedException */ public function verify(): void { $actualInvocations = $this->numberOfInvocations(); if ($actualInvocations > $this->allowedInvocations) { throw new ExpectationFailedException( sprintf( 'Expected invocation at most %d time%s but it occurred %d time%s.', $this->allowedInvocations, $this->allowedInvocations !== 1 ? 's' : '', $actualInvocations, $actualInvocations !== 1 ? 's' : '', ), ); } } public function matches(BaseInvocation $invocation): bool { return true; } } phpunit/src/Framework/MockObject/Runtime/Rule/InvokedAtLeastOnce.php 0000644 00000002504 15253321353 0021527 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvokedAtLeastOnce extends InvocationOrder { public function toString(): string { return 'invoked at least once'; } /** * Verifies that the current expectation is valid. If everything is OK the * code should just return, if not it must throw an exception. * * @throws ExpectationFailedException */ public function verify(): void { $count = $this->numberOfInvocations(); if ($count < 1) { throw new ExpectationFailedException( 'Expected invocation at least once but it never occurred.', ); } } public function matches(BaseInvocation $invocation): bool { return true; } } phpunit/src/Framework/MockObject/Runtime/Rule/InvocationOrder.php 0000644 00000002475 15253321353 0021161 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject\Rule; use function count; use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; use PHPUnit\Framework\SelfDescribing; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract class InvocationOrder implements SelfDescribing { /** * @var list<BaseInvocation> */ private array $invocations = []; public function numberOfInvocations(): int { return count($this->invocations); } public function hasBeenInvoked(): bool { return count($this->invocations) > 0; } final public function invoked(BaseInvocation $invocation): void { $this->invocations[] = $invocation; $this->invokedDo($invocation); } abstract public function matches(BaseInvocation $invocation): bool; abstract public function verify(): void; protected function invokedDo(BaseInvocation $invocation): void { } } phpunit/src/Framework/MockObject/Runtime/InvocationHandler.php 0000644 00000007572 15253321353 0020557 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function strtolower; use Exception; use PHPUnit\Framework\MockObject\Builder\InvocationMocker; use PHPUnit\Framework\MockObject\Rule\InvocationOrder; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvocationHandler { /** * @var list<Matcher> */ private array $matchers = []; /** * @var array<string,Matcher> */ private array $matcherMap = []; /** * @var list<ConfigurableMethod> */ private readonly array $configurableMethods; private readonly bool $returnValueGeneration; /** * @param list<ConfigurableMethod> $configurableMethods */ public function __construct(array $configurableMethods, bool $returnValueGeneration) { $this->configurableMethods = $configurableMethods; $this->returnValueGeneration = $returnValueGeneration; } public function hasMatchers(): bool { foreach ($this->matchers as $matcher) { if ($matcher->hasMatchers()) { return true; } } return false; } /** * Looks up the match builder with identification $id and returns it. */ public function lookupMatcher(string $id): ?Matcher { return $this->matcherMap[$id] ?? null; } /** * Registers a matcher with the identification $id. The matcher can later be * looked up using lookupMatcher() to figure out if it has been invoked. * * @throws MatcherAlreadyRegisteredException */ public function registerMatcher(string $id, Matcher $matcher): void { if (isset($this->matcherMap[$id])) { throw new MatcherAlreadyRegisteredException($id); } $this->matcherMap[$id] = $matcher; } public function expects(InvocationOrder $rule): InvocationMocker { $matcher = new Matcher($rule); $this->addMatcher($matcher); return new InvocationMocker( $this, $matcher, ...$this->configurableMethods, ); } /** * @throws \PHPUnit\Framework\MockObject\Exception * @throws Exception */ public function invoke(Invocation $invocation): mixed { $exception = null; $hasReturnValue = false; $returnValue = null; foreach ($this->matchers as $match) { try { if ($match->matches($invocation)) { $value = $match->invoked($invocation); if (!$hasReturnValue) { $returnValue = $value; $hasReturnValue = true; } } } catch (Exception $e) { $exception = $e; } } if ($exception !== null) { throw $exception; } if ($hasReturnValue) { return $returnValue; } if (!$this->returnValueGeneration) { if (strtolower($invocation->methodName()) === '__tostring') { return ''; } throw new ReturnValueNotConfiguredException($invocation); } return $invocation->generateReturnValue(); } /** * @throws Throwable */ public function verify(): void { foreach ($this->matchers as $matcher) { $matcher->verify(); } } private function addMatcher(Matcher $matcher): void { $this->matchers[] = $matcher; } } phpunit/src/Framework/MockObject/Runtime/Matcher.php 0000644 00000014535 15253321353 0016530 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount; use PHPUnit\Framework\MockObject\Rule\AnyParameters; use PHPUnit\Framework\MockObject\Rule\InvocationOrder; use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount; use PHPUnit\Framework\MockObject\Rule\InvokedCount; use PHPUnit\Framework\MockObject\Rule\MethodName; use PHPUnit\Framework\MockObject\Rule\ParametersRule; use PHPUnit\Framework\MockObject\Stub\Stub; use PHPUnit\Util\ThrowableToStringMapper; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Matcher { private readonly InvocationOrder $invocationRule; private ?string $afterMatchBuilderId = null; private ?MethodName $methodNameRule = null; private ?ParametersRule $parametersRule = null; private ?Stub $stub = null; public function __construct(InvocationOrder $rule) { $this->invocationRule = $rule; } public function hasMatchers(): bool { return !$this->invocationRule instanceof AnyInvokedCount; } public function hasMethodNameRule(): bool { return $this->methodNameRule !== null; } public function methodNameRule(): MethodName { return $this->methodNameRule; } public function setMethodNameRule(MethodName $rule): void { $this->methodNameRule = $rule; } public function hasParametersRule(): bool { return $this->parametersRule !== null; } public function setParametersRule(ParametersRule $rule): void { $this->parametersRule = $rule; } public function setStub(Stub $stub): void { $this->stub = $stub; } public function setAfterMatchBuilderId(string $id): void { $this->afterMatchBuilderId = $id; } /** * @throws Exception * @throws ExpectationFailedException * @throws MatchBuilderNotFoundException * @throws MethodNameNotConfiguredException * @throws RuntimeException */ public function invoked(Invocation $invocation): mixed { if ($this->methodNameRule === null) { throw new MethodNameNotConfiguredException; } if ($this->afterMatchBuilderId !== null) { $matcher = $invocation->object() ->__phpunit_getInvocationHandler() ->lookupMatcher($this->afterMatchBuilderId); if (!$matcher) { throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); } } $this->invocationRule->invoked($invocation); try { $this->parametersRule?->apply($invocation); } catch (ExpectationFailedException $e) { throw new ExpectationFailedException( sprintf( "Expectation failed for %s when %s\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), $e->getMessage(), ), $e->getComparisonFailure(), ); } if ($this->stub) { return $this->stub->invoke($invocation); } return $invocation->generateReturnValue(); } /** * @throws ExpectationFailedException * @throws MatchBuilderNotFoundException * @throws MethodNameNotConfiguredException * @throws RuntimeException */ public function matches(Invocation $invocation): bool { if ($this->afterMatchBuilderId !== null) { $matcher = $invocation->object() ->__phpunit_getInvocationHandler() ->lookupMatcher($this->afterMatchBuilderId); if (!$matcher) { throw new MatchBuilderNotFoundException($this->afterMatchBuilderId); } if (!$matcher->invocationRule->hasBeenInvoked()) { return false; } } if ($this->methodNameRule === null) { throw new MethodNameNotConfiguredException; } if (!$this->invocationRule->matches($invocation)) { return false; } try { if (!$this->methodNameRule->matches($invocation)) { return false; } } catch (ExpectationFailedException $e) { throw new ExpectationFailedException( sprintf( "Expectation failed for %s when %s\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), $e->getMessage(), ), $e->getComparisonFailure(), ); } return true; } /** * @throws ExpectationFailedException * @throws MethodNameNotConfiguredException */ public function verify(): void { if ($this->methodNameRule === null) { throw new MethodNameNotConfiguredException; } try { $this->invocationRule->verify(); if ($this->parametersRule === null) { $this->parametersRule = new AnyParameters; } $invocationIsAny = $this->invocationRule instanceof AnyInvokedCount; $invocationIsNever = $this->invocationRule instanceof InvokedCount && $this->invocationRule->isNever(); $invocationIsAtMost = $this->invocationRule instanceof InvokedAtMostCount; if (!$invocationIsAny && !$invocationIsNever && !$invocationIsAtMost) { $this->parametersRule->verify(); } } catch (ExpectationFailedException $e) { throw new ExpectationFailedException( sprintf( "Expectation failed for %s when %s.\n%s", $this->methodNameRule->toString(), $this->invocationRule->toString(), ThrowableToStringMapper::map($e), ), ); } } } phpunit/src/Framework/MockObject/Runtime/MethodNameConstraint.php 0000644 00000002055 15253321353 0021225 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\MockObject; use function sprintf; use function strtolower; use PHPUnit\Framework\Constraint\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MethodNameConstraint extends Constraint { private string $methodName; public function __construct(string $methodName) { $this->methodName = $methodName; } public function toString(): string { return sprintf( 'is "%s"', $this->methodName, ); } protected function matches(mixed $other): bool { return strtolower($this->methodName) === strtolower((string) $other); } } phpunit/src/Framework/TestSuiteIterator.php 0000644 00000003535 15253321353 0015143 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function assert; use function count; use RecursiveIterator; /** * @template-implements RecursiveIterator<int, Test> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestSuiteIterator implements RecursiveIterator { private int $position = 0; /** * @var list<Test> */ private readonly array $tests; public function __construct(TestSuite $testSuite) { $this->tests = $testSuite->tests(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->tests); } public function key(): int { return $this->position; } public function current(): Test { return $this->tests[$this->position]; } public function next(): void { $this->position++; } /** * @throws NoChildTestSuiteException */ public function getChildren(): self { if (!$this->hasChildren()) { throw new NoChildTestSuiteException( 'The current item is not a TestSuite instance and therefore does not have any children.', ); } $current = $this->current(); assert($current instanceof TestSuite); return new self($current); } public function hasChildren(): bool { return $this->valid() && $this->current() instanceof TestSuite; } } phpunit/src/Framework/SelfDescribing.php 0000644 00000001163 15253321353 0014356 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface SelfDescribing { /** * Returns a string representation of the object. */ public function toString(): string; } phpunit/src/Framework/Exception/PhptAssertionFailedError.php 0000644 00000003301 15253321353 0020347 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class PhptAssertionFailedError extends AssertionFailedError { private readonly string $syntheticFile; private readonly int $syntheticLine; /** * @var list<array{file: string, line: int, function: string, type: string}> */ private readonly array $syntheticTrace; private readonly string $diff; /** * @param list<array{file: string, line: int, function: string, type: string}> $trace */ public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff) { parent::__construct($message, $code); $this->syntheticFile = $file; $this->syntheticLine = $line; $this->syntheticTrace = $trace; $this->diff = $diff; } public function syntheticFile(): string { return $this->syntheticFile; } public function syntheticLine(): int { return $this->syntheticLine; } /** * @return list<array{file: string, line: int, function: string, type: string}> */ public function syntheticTrace(): array { return $this->syntheticTrace; } public function diff(): string { return $this->diff; } } phpunit/src/Framework/Exception/InvalidDataProviderException.php 0000644 00000001047 15253321353 0021204 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidDataProviderException extends Exception { } phpunit/src/Framework/Exception/InvalidDependencyException.php 0000644 00000001107 15253321353 0020673 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidDependencyException extends AssertionFailedError implements SkippedTest { } phpunit/src/Framework/Exception/Exception.php 0000644 00000004620 15253321353 0015370 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function array_keys; use function get_object_vars; use RuntimeException; use Throwable; /** * Base class for all PHPUnit Framework exceptions. * * Ensures that exceptions thrown during a test run do not leave stray * references behind. * * Every Exception contains a stack trace. Each stack frame contains the 'args' * of the called function. The function arguments can contain references to * instantiated objects. The references prevent the objects from being * destructed (until test results are eventually printed), so memory cannot be * freed up. * * With enabled process isolation, test results are serialized in the child * process and unserialized in the parent process. The stack trace of Exceptions * may contain objects that cannot be serialized or unserialized (e.g., PDO * connections). Unserializing user-space objects from the child process into * the parent would break the intended encapsulation of process isolation. * * @see http://fabien.potencier.org/article/9/php-serialization-stack-traces-and-exceptions * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ class Exception extends RuntimeException implements \PHPUnit\Exception { /** * @var list<array{file: string, line: int, function: string}> */ protected array $serializableTrace; public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->serializableTrace = $this->getTrace(); foreach (array_keys($this->serializableTrace) as $key) { unset($this->serializableTrace[$key]['args']); } } public function __sleep(): array { return array_keys(get_object_vars($this)); } /** * Returns the serializable trace (without 'args'). * * @return list<array{file: string, line: int, function: string}> */ public function getSerializableTrace(): array { return $this->serializableTrace; } } phpunit/src/Framework/Exception/Skipped/SkippedTestSuiteError.php 0000644 00000001102 15253321353 0021304 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest { } phpunit/src/Framework/Exception/Skipped/SkippedWithMessageException.php 0000644 00000001110 15253321353 0022437 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SkippedWithMessageException extends AssertionFailedError implements SkippedTest { } phpunit/src/Framework/Exception/Skipped/SkippedTest.php 0000644 00000001044 15253321353 0017265 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface SkippedTest extends Throwable { } phpunit/src/Framework/Exception/GeneratorNotSupportedException.php 0000644 00000001554 15253321353 0021631 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class GeneratorNotSupportedException extends InvalidArgumentException { public static function fromParameterName(string $parameterName): self { return new self( sprintf( 'Passing an argument of type Generator for the %s parameter is not supported', $parameterName, ), ); } } phpunit/src/Framework/Exception/CodeCoverageException.php 0000644 00000001032 15253321353 0017631 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ class CodeCoverageException extends Exception { } phpunit/src/Framework/Exception/Incomplete/IncompleteTest.php 0000644 00000001047 15253321353 0020470 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface IncompleteTest extends Throwable { } phpunit/src/Framework/Exception/Incomplete/IncompleteTestError.php 0000644 00000001103 15253321353 0021473 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IncompleteTestError extends AssertionFailedError implements IncompleteTest { } phpunit/src/Framework/Exception/UnknownClassOrInterfaceException.php 0000644 00000001450 15253321353 0022056 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class UnknownClassOrInterfaceException extends InvalidArgumentException { public function __construct(string $name) { parent::__construct( sprintf( 'Class or interface "%s" does not exist', $name, ), ); } } phpunit/src/Framework/Exception/InvalidCoversTargetException.php 0000644 00000001063 15253321353 0021226 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidCoversTargetException extends CodeCoverageException { } phpunit/src/Framework/Exception/UnknownTypeException.php 0000644 00000001414 15253321353 0017610 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class UnknownTypeException extends InvalidArgumentException { public function __construct(string $name) { parent::__construct( sprintf( 'Type "%s" is not known', $name, ), ); } } phpunit/src/Framework/Exception/EmptyStringException.php 0000644 00000001056 15253321353 0017576 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class EmptyStringException extends InvalidArgumentException { } phpunit/src/Framework/Exception/InvalidArgumentException.php 0000644 00000001046 15253321353 0020401 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract class InvalidArgumentException extends Exception { } phpunit/src/Framework/Exception/AssertionFailedError.php 0000644 00000001326 15253321353 0017520 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ class AssertionFailedError extends Exception implements SelfDescribing { /** * Wrapper for getMessage() which is declared as final. */ public function toString(): string { return $this->getMessage(); } } phpunit/src/Framework/Exception/ProcessIsolationException.php 0000644 00000001044 15253321353 0020606 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ProcessIsolationException extends Exception { } phpunit/src/Framework/Exception/ExpectationFailedException.php 0000644 00000002415 15253321353 0020701 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Exception; use SebastianBergmann\Comparator\ComparisonFailure; /** * Exception for expectations which failed their check. * * The exception contains the error message and optionally a * SebastianBergmann\Comparator\ComparisonFailure which is used to * generate diff output of the failed expectations. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExpectationFailedException extends AssertionFailedError { protected ?ComparisonFailure $comparisonFailure = null; public function __construct(string $message, ?ComparisonFailure $comparisonFailure = null, ?Exception $previous = null) { $this->comparisonFailure = $comparisonFailure; parent::__construct($message, 0, $previous); } public function getComparisonFailure(): ?ComparisonFailure { return $this->comparisonFailure; } } phpunit/src/Framework/Exception/NoChildTestSuiteException.php 0000644 00000001044 15253321353 0020500 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoChildTestSuiteException extends Exception { } src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareParameterTypeException.php 0000644 00000001610 15253321353 0030341 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ComparisonMethodDoesNotDeclareParameterTypeException extends Exception { public function __construct(string $className, string $methodName) { parent::__construct( sprintf( 'Parameter of comparison method %s::%s() does not have a declared type.', $className, $methodName, ), ); } } src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareExactlyOneParameterException.php 0000644 00000001612 15253321353 0031475 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ComparisonMethodDoesNotDeclareExactlyOneParameterException extends Exception { public function __construct(string $className, string $methodName) { parent::__construct( sprintf( 'Comparison method %s::%s() does not declare exactly one parameter.', $className, $methodName, ), ); } } src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotDeclareBoolReturnTypeException.php 0000644 00000001600 15253321353 0030513 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ComparisonMethodDoesNotDeclareBoolReturnTypeException extends Exception { public function __construct(string $className, string $methodName) { parent::__construct( sprintf( 'Comparison method %s::%s() does not declare bool return type.', $className, $methodName, ), ); } } phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotAcceptParameterTypeException.php0000644 00000001651 15253321353 0030265 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ComparisonMethodDoesNotAcceptParameterTypeException extends Exception { public function __construct(string $className, string $methodName, string $type) { parent::__construct( sprintf( '%s is not an accepted argument type for comparison method %s::%s().', $type, $className, $methodName, ), ); } } phpunit/src/Framework/Exception/ObjectEquals/ComparisonMethodDoesNotExistException.php 0000644 00000001535 15253321353 0025460 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ComparisonMethodDoesNotExistException extends Exception { public function __construct(string $className, string $methodName) { parent::__construct( sprintf( 'Comparison method %s::%s() does not exist.', $className, $methodName, ), ); } } phpunit/src/Framework/Exception/ObjectEquals/ActualValueIsNotAnObjectException.php 0000644 00000001257 15253321353 0024466 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ActualValueIsNotAnObjectException extends Exception { public function __construct() { parent::__construct( 'Actual value is not an object', ); } } phpunit/src/Framework/Assert/Functions.php 0000644 00000260612 15253321353 0014712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function func_get_args; use function function_exists; use ArrayAccess; use Countable; use PHPUnit\Framework\Constraint\ArrayHasKey; use PHPUnit\Framework\Constraint\Callback; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\Constraint\Count; use PHPUnit\Framework\Constraint\DirectoryExists; use PHPUnit\Framework\Constraint\FileExists; use PHPUnit\Framework\Constraint\GreaterThan; use PHPUnit\Framework\Constraint\IsAnything; use PHPUnit\Framework\Constraint\IsEmpty; use PHPUnit\Framework\Constraint\IsEqual; use PHPUnit\Framework\Constraint\IsEqualCanonicalizing; use PHPUnit\Framework\Constraint\IsEqualIgnoringCase; use PHPUnit\Framework\Constraint\IsEqualWithDelta; use PHPUnit\Framework\Constraint\IsFalse; use PHPUnit\Framework\Constraint\IsFinite; use PHPUnit\Framework\Constraint\IsIdentical; use PHPUnit\Framework\Constraint\IsInfinite; use PHPUnit\Framework\Constraint\IsInstanceOf; use PHPUnit\Framework\Constraint\IsJson; use PHPUnit\Framework\Constraint\IsList; use PHPUnit\Framework\Constraint\IsNan; use PHPUnit\Framework\Constraint\IsNull; use PHPUnit\Framework\Constraint\IsReadable; use PHPUnit\Framework\Constraint\IsTrue; use PHPUnit\Framework\Constraint\IsType; use PHPUnit\Framework\Constraint\IsWritable; use PHPUnit\Framework\Constraint\LessThan; use PHPUnit\Framework\Constraint\LogicalAnd; use PHPUnit\Framework\Constraint\LogicalNot; use PHPUnit\Framework\Constraint\LogicalOr; use PHPUnit\Framework\Constraint\LogicalXor; use PHPUnit\Framework\Constraint\ObjectEquals; use PHPUnit\Framework\Constraint\RegularExpression; use PHPUnit\Framework\Constraint\StringContains; use PHPUnit\Framework\Constraint\StringEndsWith; use PHPUnit\Framework\Constraint\StringEqualsStringIgnoringLineEndings; use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; use PHPUnit\Framework\Constraint\StringStartsWith; use PHPUnit\Framework\Constraint\TraversableContainsEqual; use PHPUnit\Framework\Constraint\TraversableContainsIdentical; use PHPUnit\Framework\Constraint\TraversableContainsOnly; use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; use PHPUnit\Framework\MockObject\Stub\ReturnStub; use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; use PHPUnit\Util\Xml\XmlException; use Throwable; if (!function_exists('PHPUnit\Framework\assertArrayIsEqualToArrayOnlyConsideringListOfKeys')) { /** * Asserts that two arrays are equal while only considering a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeConsidered * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys */ function assertArrayIsEqualToArrayOnlyConsideringListOfKeys(array $expected, array $actual, array $keysToBeConsidered, string $message = ''): void { Assert::assertArrayIsEqualToArrayOnlyConsideringListOfKeys(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertArrayIsEqualToArrayIgnoringListOfKeys')) { /** * Asserts that two arrays are equal while ignoring a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeIgnored * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayIsEqualToArrayIgnoringListOfKeys */ function assertArrayIsEqualToArrayIgnoringListOfKeys(array $expected, array $actual, array $keysToBeIgnored, string $message = ''): void { Assert::assertArrayIsEqualToArrayIgnoringListOfKeys(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys')) { /** * Asserts that two arrays are identical while only considering a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeConsidered * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys */ function assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys(array $expected, array $actual, array $keysToBeConsidered, string $message = ''): void { Assert::assertArrayIsIdenticalToArrayOnlyConsideringListOfKeys(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertArrayIsIdenticalToArrayIgnoringListOfKeys')) { /** * Asserts that two arrays are equal while ignoring a list of keys. * * @param array<mixed> $expected * @param array<mixed> $actual * @param non-empty-list<array-key> $keysToBeIgnored * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayIsIdenticalToArrayIgnoringListOfKeys */ function assertArrayIsIdenticalToArrayIgnoringListOfKeys(array $expected, array $actual, array $keysToBeIgnored, string $message = ''): void { Assert::assertArrayIsIdenticalToArrayIgnoringListOfKeys(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertArrayHasKey')) { /** * Asserts that an array has a specified key. * * @param array<mixed>|ArrayAccess<array-key, mixed> $array * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayHasKey */ function assertArrayHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { Assert::assertArrayHasKey(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertArrayNotHasKey')) { /** * Asserts that an array does not have a specified key. * * @param array<mixed>|ArrayAccess<array-key, mixed> $array * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertArrayNotHasKey */ function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { Assert::assertArrayNotHasKey(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsList')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsList */ function assertIsList(mixed $array, string $message = ''): void { Assert::assertIsList(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertContains')) { /** * Asserts that a haystack contains a needle. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertContains */ function assertContains(mixed $needle, iterable $haystack, string $message = ''): void { Assert::assertContains(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertContainsEquals')) { /** * @param iterable<mixed> $haystack * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertContainsEquals */ function assertContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void { Assert::assertContainsEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotContains')) { /** * Asserts that a haystack does not contain a needle. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotContains */ function assertNotContains(mixed $needle, iterable $haystack, string $message = ''): void { Assert::assertNotContains(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotContainsEquals')) { /** * @param iterable<mixed> $haystack * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotContainsEquals */ function assertNotContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void { Assert::assertNotContainsEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertContainsOnly')) { /** * Asserts that a haystack contains only values of a given type. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertContainsOnly */ function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void { Assert::assertContainsOnly(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertContainsOnlyInstancesOf')) { /** * Asserts that a haystack contains only instances of a given class name. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertContainsOnlyInstancesOf */ function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void { Assert::assertContainsOnlyInstancesOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotContainsOnly')) { /** * Asserts that a haystack does not contain only values of a given type. * * @param iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotContainsOnly */ function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void { Assert::assertNotContainsOnly(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertCount')) { /** * Asserts the number of elements of an array, Countable or Traversable. * * @param Countable|iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertCount */ function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { Assert::assertCount(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotCount')) { /** * Asserts the number of elements of an array, Countable or Traversable. * * @param Countable|iterable<mixed> $haystack * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotCount */ function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { Assert::assertNotCount(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertEquals')) { /** * Asserts that two variables are equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertEquals */ function assertEquals(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertEqualsCanonicalizing')) { /** * Asserts that two variables are equal (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertEqualsCanonicalizing */ function assertEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertEqualsCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertEqualsIgnoringCase')) { /** * Asserts that two variables are equal (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertEqualsIgnoringCase */ function assertEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertEqualsIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertEqualsWithDelta')) { /** * Asserts that two variables are equal (with delta). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertEqualsWithDelta */ function assertEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void { Assert::assertEqualsWithDelta(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotEquals')) { /** * Asserts that two variables are not equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotEquals */ function assertNotEquals(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertNotEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotEqualsCanonicalizing')) { /** * Asserts that two variables are not equal (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotEqualsCanonicalizing */ function assertNotEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertNotEqualsCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotEqualsIgnoringCase')) { /** * Asserts that two variables are not equal (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotEqualsIgnoringCase */ function assertNotEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertNotEqualsIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotEqualsWithDelta')) { /** * Asserts that two variables are not equal (with delta). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotEqualsWithDelta */ function assertNotEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void { Assert::assertNotEqualsWithDelta(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertObjectEquals')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertObjectEquals */ function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void { Assert::assertObjectEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertObjectNotEquals')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertObjectNotEquals */ function assertObjectNotEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void { Assert::assertObjectNotEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertEmpty')) { /** * Asserts that a variable is empty. * * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @phpstan-assert empty $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertEmpty */ function assertEmpty(mixed $actual, string $message = ''): void { Assert::assertEmpty(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotEmpty')) { /** * Asserts that a variable is not empty. * * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @phpstan-assert !empty $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotEmpty */ function assertNotEmpty(mixed $actual, string $message = ''): void { Assert::assertNotEmpty(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertGreaterThan')) { /** * Asserts that a value is greater than another value. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertGreaterThan */ function assertGreaterThan(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertGreaterThan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertGreaterThanOrEqual')) { /** * Asserts that a value is greater than or equal to another value. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertGreaterThanOrEqual */ function assertGreaterThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertGreaterThanOrEqual(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertLessThan')) { /** * Asserts that a value is smaller than another value. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertLessThan */ function assertLessThan(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertLessThan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertLessThanOrEqual')) { /** * Asserts that a value is smaller than or equal to another value. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertLessThanOrEqual */ function assertLessThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertLessThanOrEqual(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileEquals')) { /** * Asserts that the contents of one file is equal to the contents of another * file. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileEquals */ function assertFileEquals(string $expected, string $actual, string $message = ''): void { Assert::assertFileEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileEqualsCanonicalizing')) { /** * Asserts that the contents of one file is equal to the contents of another * file (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileEqualsCanonicalizing */ function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void { Assert::assertFileEqualsCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileEqualsIgnoringCase')) { /** * Asserts that the contents of one file is equal to the contents of another * file (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileEqualsIgnoringCase */ function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void { Assert::assertFileEqualsIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileNotEquals')) { /** * Asserts that the contents of one file is not equal to the contents of * another file. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileNotEquals */ function assertFileNotEquals(string $expected, string $actual, string $message = ''): void { Assert::assertFileNotEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileNotEqualsCanonicalizing')) { /** * Asserts that the contents of one file is not equal to the contents of another * file (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileNotEqualsCanonicalizing */ function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void { Assert::assertFileNotEqualsCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileNotEqualsIgnoringCase')) { /** * Asserts that the contents of one file is not equal to the contents of another * file (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileNotEqualsIgnoringCase */ function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void { Assert::assertFileNotEqualsIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEqualsFile')) { /** * Asserts that the contents of a string is equal * to the contents of a file. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEqualsFile */ function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringEqualsFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEqualsFileCanonicalizing')) { /** * Asserts that the contents of a string is equal * to the contents of a file (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEqualsFileCanonicalizing */ function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringEqualsFileCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEqualsFileIgnoringCase')) { /** * Asserts that the contents of a string is equal * to the contents of a file (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEqualsFileIgnoringCase */ function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringEqualsFileIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFile')) { /** * Asserts that the contents of a string is not equal * to the contents of a file. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotEqualsFile */ function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringNotEqualsFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileCanonicalizing')) { /** * Asserts that the contents of a string is not equal * to the contents of a file (canonicalizing). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotEqualsFileCanonicalizing */ function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringNotEqualsFileCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotEqualsFileIgnoringCase')) { /** * Asserts that the contents of a string is not equal * to the contents of a file (ignoring case). * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotEqualsFileIgnoringCase */ function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void { Assert::assertStringNotEqualsFileIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsReadable')) { /** * Asserts that a file/dir is readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsReadable */ function assertIsReadable(string $filename, string $message = ''): void { Assert::assertIsReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotReadable')) { /** * Asserts that a file/dir exists and is not readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotReadable */ function assertIsNotReadable(string $filename, string $message = ''): void { Assert::assertIsNotReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsWritable')) { /** * Asserts that a file/dir exists and is writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsWritable */ function assertIsWritable(string $filename, string $message = ''): void { Assert::assertIsWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotWritable')) { /** * Asserts that a file/dir exists and is not writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotWritable */ function assertIsNotWritable(string $filename, string $message = ''): void { Assert::assertIsNotWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryExists')) { /** * Asserts that a directory exists. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryExists */ function assertDirectoryExists(string $directory, string $message = ''): void { Assert::assertDirectoryExists(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryDoesNotExist')) { /** * Asserts that a directory does not exist. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryDoesNotExist */ function assertDirectoryDoesNotExist(string $directory, string $message = ''): void { Assert::assertDirectoryDoesNotExist(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryIsReadable')) { /** * Asserts that a directory exists and is readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryIsReadable */ function assertDirectoryIsReadable(string $directory, string $message = ''): void { Assert::assertDirectoryIsReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotReadable')) { /** * Asserts that a directory exists and is not readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryIsNotReadable */ function assertDirectoryIsNotReadable(string $directory, string $message = ''): void { Assert::assertDirectoryIsNotReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryIsWritable')) { /** * Asserts that a directory exists and is writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryIsWritable */ function assertDirectoryIsWritable(string $directory, string $message = ''): void { Assert::assertDirectoryIsWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDirectoryIsNotWritable')) { /** * Asserts that a directory exists and is not writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDirectoryIsNotWritable */ function assertDirectoryIsNotWritable(string $directory, string $message = ''): void { Assert::assertDirectoryIsNotWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileExists')) { /** * Asserts that a file exists. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileExists */ function assertFileExists(string $filename, string $message = ''): void { Assert::assertFileExists(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileDoesNotExist')) { /** * Asserts that a file does not exist. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileDoesNotExist */ function assertFileDoesNotExist(string $filename, string $message = ''): void { Assert::assertFileDoesNotExist(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileIsReadable')) { /** * Asserts that a file exists and is readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileIsReadable */ function assertFileIsReadable(string $file, string $message = ''): void { Assert::assertFileIsReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileIsNotReadable')) { /** * Asserts that a file exists and is not readable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileIsNotReadable */ function assertFileIsNotReadable(string $file, string $message = ''): void { Assert::assertFileIsNotReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileIsWritable')) { /** * Asserts that a file exists and is writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileIsWritable */ function assertFileIsWritable(string $file, string $message = ''): void { Assert::assertFileIsWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileIsNotWritable')) { /** * Asserts that a file exists and is not writable. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileIsNotWritable */ function assertFileIsNotWritable(string $file, string $message = ''): void { Assert::assertFileIsNotWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertTrue')) { /** * Asserts that a condition is true. * * @throws ExpectationFailedException * * @phpstan-assert true $condition * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertTrue */ function assertTrue(mixed $condition, string $message = ''): void { Assert::assertTrue(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotTrue')) { /** * Asserts that a condition is not true. * * @throws ExpectationFailedException * * @phpstan-assert !true $condition * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotTrue */ function assertNotTrue(mixed $condition, string $message = ''): void { Assert::assertNotTrue(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFalse')) { /** * Asserts that a condition is false. * * @throws ExpectationFailedException * * @phpstan-assert false $condition * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFalse */ function assertFalse(mixed $condition, string $message = ''): void { Assert::assertFalse(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotFalse')) { /** * Asserts that a condition is not false. * * @throws ExpectationFailedException * * @phpstan-assert !false $condition * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotFalse */ function assertNotFalse(mixed $condition, string $message = ''): void { Assert::assertNotFalse(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNull')) { /** * Asserts that a variable is null. * * @throws ExpectationFailedException * * @phpstan-assert null $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNull */ function assertNull(mixed $actual, string $message = ''): void { Assert::assertNull(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotNull')) { /** * Asserts that a variable is not null. * * @throws ExpectationFailedException * * @phpstan-assert !null $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotNull */ function assertNotNull(mixed $actual, string $message = ''): void { Assert::assertNotNull(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFinite')) { /** * Asserts that a variable is finite. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFinite */ function assertFinite(mixed $actual, string $message = ''): void { Assert::assertFinite(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertInfinite')) { /** * Asserts that a variable is infinite. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertInfinite */ function assertInfinite(mixed $actual, string $message = ''): void { Assert::assertInfinite(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNan')) { /** * Asserts that a variable is nan. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNan */ function assertNan(mixed $actual, string $message = ''): void { Assert::assertNan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertObjectHasProperty')) { /** * Asserts that an object has a specified property. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertObjectHasProperty */ function assertObjectHasProperty(string $propertyName, object $object, string $message = ''): void { Assert::assertObjectHasProperty(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertObjectNotHasProperty')) { /** * Asserts that an object does not have a specified property. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertObjectNotHasProperty */ function assertObjectNotHasProperty(string $propertyName, object $object, string $message = ''): void { Assert::assertObjectNotHasProperty(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertSame')) { /** * Asserts that two variables have the same type and value. * Used on objects, it asserts that two variables reference * the same object. * * @template ExpectedType * * @param ExpectedType $expected * * @throws ExpectationFailedException * * @phpstan-assert =ExpectedType $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertSame */ function assertSame(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertSame(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotSame')) { /** * Asserts that two variables do not have the same type and value. * Used on objects, it asserts that two variables do not reference * the same object. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotSame */ function assertNotSame(mixed $expected, mixed $actual, string $message = ''): void { Assert::assertNotSame(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertInstanceOf')) { /** * Asserts that a variable is of a given type. * * @template ExpectedType of object * * @param class-string<ExpectedType> $expected * * @throws Exception * @throws ExpectationFailedException * @throws UnknownClassOrInterfaceException * * @phpstan-assert =ExpectedType $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertInstanceOf */ function assertInstanceOf(string $expected, mixed $actual, string $message = ''): void { Assert::assertInstanceOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotInstanceOf')) { /** * Asserts that a variable is not of a given type. * * @template ExpectedType of object * * @param class-string<ExpectedType> $expected * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !ExpectedType $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotInstanceOf */ function assertNotInstanceOf(string $expected, mixed $actual, string $message = ''): void { Assert::assertNotInstanceOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsArray')) { /** * Asserts that a variable is of type array. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert array $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsArray */ function assertIsArray(mixed $actual, string $message = ''): void { Assert::assertIsArray(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsBool')) { /** * Asserts that a variable is of type bool. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert bool $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsBool */ function assertIsBool(mixed $actual, string $message = ''): void { Assert::assertIsBool(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsFloat')) { /** * Asserts that a variable is of type float. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert float $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsFloat */ function assertIsFloat(mixed $actual, string $message = ''): void { Assert::assertIsFloat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsInt')) { /** * Asserts that a variable is of type int. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert int $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsInt */ function assertIsInt(mixed $actual, string $message = ''): void { Assert::assertIsInt(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNumeric')) { /** * Asserts that a variable is of type numeric. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert numeric $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNumeric */ function assertIsNumeric(mixed $actual, string $message = ''): void { Assert::assertIsNumeric(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsObject')) { /** * Asserts that a variable is of type object. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert object $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsObject */ function assertIsObject(mixed $actual, string $message = ''): void { Assert::assertIsObject(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsResource')) { /** * Asserts that a variable is of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert resource $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsResource */ function assertIsResource(mixed $actual, string $message = ''): void { Assert::assertIsResource(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsClosedResource')) { /** * Asserts that a variable is of type resource and is closed. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert resource $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsClosedResource */ function assertIsClosedResource(mixed $actual, string $message = ''): void { Assert::assertIsClosedResource(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsString')) { /** * Asserts that a variable is of type string. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert string $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsString */ function assertIsString(mixed $actual, string $message = ''): void { Assert::assertIsString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsScalar')) { /** * Asserts that a variable is of type scalar. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert scalar $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsScalar */ function assertIsScalar(mixed $actual, string $message = ''): void { Assert::assertIsScalar(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsCallable')) { /** * Asserts that a variable is of type callable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert callable $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsCallable */ function assertIsCallable(mixed $actual, string $message = ''): void { Assert::assertIsCallable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsIterable')) { /** * Asserts that a variable is of type iterable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert iterable $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsIterable */ function assertIsIterable(mixed $actual, string $message = ''): void { Assert::assertIsIterable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotArray')) { /** * Asserts that a variable is not of type array. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !array $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotArray */ function assertIsNotArray(mixed $actual, string $message = ''): void { Assert::assertIsNotArray(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotBool')) { /** * Asserts that a variable is not of type bool. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !bool $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotBool */ function assertIsNotBool(mixed $actual, string $message = ''): void { Assert::assertIsNotBool(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotFloat')) { /** * Asserts that a variable is not of type float. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !float $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotFloat */ function assertIsNotFloat(mixed $actual, string $message = ''): void { Assert::assertIsNotFloat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotInt')) { /** * Asserts that a variable is not of type int. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !int $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotInt */ function assertIsNotInt(mixed $actual, string $message = ''): void { Assert::assertIsNotInt(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotNumeric')) { /** * Asserts that a variable is not of type numeric. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !numeric $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotNumeric */ function assertIsNotNumeric(mixed $actual, string $message = ''): void { Assert::assertIsNotNumeric(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotObject')) { /** * Asserts that a variable is not of type object. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !object $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotObject */ function assertIsNotObject(mixed $actual, string $message = ''): void { Assert::assertIsNotObject(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotResource')) { /** * Asserts that a variable is not of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !resource $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotResource */ function assertIsNotResource(mixed $actual, string $message = ''): void { Assert::assertIsNotResource(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotClosedResource')) { /** * Asserts that a variable is not of type resource. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !resource $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotClosedResource */ function assertIsNotClosedResource(mixed $actual, string $message = ''): void { Assert::assertIsNotClosedResource(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotString')) { /** * Asserts that a variable is not of type string. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !string $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotString */ function assertIsNotString(mixed $actual, string $message = ''): void { Assert::assertIsNotString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotScalar')) { /** * Asserts that a variable is not of type scalar. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !scalar $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotScalar */ function assertIsNotScalar(mixed $actual, string $message = ''): void { Assert::assertIsNotScalar(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotCallable')) { /** * Asserts that a variable is not of type callable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !callable $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotCallable */ function assertIsNotCallable(mixed $actual, string $message = ''): void { Assert::assertIsNotCallable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertIsNotIterable')) { /** * Asserts that a variable is not of type iterable. * * @throws Exception * @throws ExpectationFailedException * * @phpstan-assert !iterable $actual * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertIsNotIterable */ function assertIsNotIterable(mixed $actual, string $message = ''): void { Assert::assertIsNotIterable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertMatchesRegularExpression')) { /** * Asserts that a string matches a given regular expression. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertMatchesRegularExpression */ function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void { Assert::assertMatchesRegularExpression(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertDoesNotMatchRegularExpression')) { /** * Asserts that a string does not match a given regular expression. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertDoesNotMatchRegularExpression */ function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void { Assert::assertDoesNotMatchRegularExpression(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertSameSize')) { /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is the same. * * @param Countable|iterable<mixed> $expected * @param Countable|iterable<mixed> $actual * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertSameSize */ function assertSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { Assert::assertSameSize(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertNotSameSize')) { /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is not the same. * * @param Countable|iterable<mixed> $expected * @param Countable|iterable<mixed> $actual * * @throws Exception * @throws ExpectationFailedException * @throws GeneratorNotSupportedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertNotSameSize */ function assertNotSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { Assert::assertNotSameSize(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringLineEndings')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringContainsStringIgnoringLineEndings */ function assertStringContainsStringIgnoringLineEndings(string $needle, string $haystack, string $message = ''): void { Assert::assertStringContainsStringIgnoringLineEndings(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEqualsStringIgnoringLineEndings')) { /** * Asserts that two strings are equal except for line endings. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEqualsStringIgnoringLineEndings */ function assertStringEqualsStringIgnoringLineEndings(string $expected, string $actual, string $message = ''): void { Assert::assertStringEqualsStringIgnoringLineEndings(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileMatchesFormat')) { /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileMatchesFormat */ function assertFileMatchesFormat(string $format, string $actualFile, string $message = ''): void { Assert::assertFileMatchesFormat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertFileMatchesFormatFile')) { /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertFileMatchesFormatFile */ function assertFileMatchesFormatFile(string $formatFile, string $actualFile, string $message = ''): void { Assert::assertFileMatchesFormatFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringMatchesFormat')) { /** * Asserts that a string matches a given format string. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringMatchesFormat */ function assertStringMatchesFormat(string $format, string $string, string $message = ''): void { Assert::assertStringMatchesFormat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormat')) { /** * Asserts that a string does not match a given format string. * * @throws ExpectationFailedException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotMatchesFormat */ function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void { Assert::assertStringNotMatchesFormat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringMatchesFormatFile')) { /** * Asserts that a string matches a given format file. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringMatchesFormatFile */ function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void { Assert::assertStringMatchesFormatFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotMatchesFormatFile')) { /** * Asserts that a string does not match a given format string. * * @throws ExpectationFailedException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5472 * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotMatchesFormatFile */ function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void { Assert::assertStringNotMatchesFormatFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringStartsWith')) { /** * Asserts that a string starts with a given prefix. * * @param non-empty-string $prefix * * @throws ExpectationFailedException * @throws InvalidArgumentException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringStartsWith */ function assertStringStartsWith(string $prefix, string $string, string $message = ''): void { Assert::assertStringStartsWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringStartsNotWith')) { /** * Asserts that a string starts not with a given prefix. * * @param non-empty-string $prefix * * @throws ExpectationFailedException * @throws InvalidArgumentException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringStartsNotWith */ function assertStringStartsNotWith(string $prefix, string $string, string $message = ''): void { Assert::assertStringStartsNotWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringContainsString')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringContainsString */ function assertStringContainsString(string $needle, string $haystack, string $message = ''): void { Assert::assertStringContainsString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringContainsStringIgnoringCase')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringContainsStringIgnoringCase */ function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void { Assert::assertStringContainsStringIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotContainsString')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotContainsString */ function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void { Assert::assertStringNotContainsString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringNotContainsStringIgnoringCase')) { /** * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringNotContainsStringIgnoringCase */ function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void { Assert::assertStringNotContainsStringIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEndsWith')) { /** * Asserts that a string ends with a given suffix. * * @param non-empty-string $suffix * * @throws ExpectationFailedException * @throws InvalidArgumentException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEndsWith */ function assertStringEndsWith(string $suffix, string $string, string $message = ''): void { Assert::assertStringEndsWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertStringEndsNotWith')) { /** * Asserts that a string ends not with a given suffix. * * @param non-empty-string $suffix * * @throws ExpectationFailedException * @throws InvalidArgumentException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertStringEndsNotWith */ function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void { Assert::assertStringEndsNotWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlFileEqualsXmlFile')) { /** * Asserts that two XML files are equal. * * @throws Exception * @throws ExpectationFailedException * @throws XmlException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlFileEqualsXmlFile */ function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void { Assert::assertXmlFileEqualsXmlFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlFileNotEqualsXmlFile')) { /** * Asserts that two XML files are not equal. * * @throws \PHPUnit\Util\Exception * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlFileNotEqualsXmlFile */ function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void { Assert::assertXmlFileNotEqualsXmlFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlFile')) { /** * Asserts that two XML documents are equal. * * @throws ExpectationFailedException * @throws XmlException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlStringEqualsXmlFile */ function assertXmlStringEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void { Assert::assertXmlStringEqualsXmlFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlFile')) { /** * Asserts that two XML documents are not equal. * * @throws ExpectationFailedException * @throws XmlException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlStringNotEqualsXmlFile */ function assertXmlStringNotEqualsXmlFile(string $expectedFile, string $actualXml, string $message = ''): void { Assert::assertXmlStringNotEqualsXmlFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlStringEqualsXmlString')) { /** * Asserts that two XML documents are equal. * * @throws ExpectationFailedException * @throws XmlException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlStringEqualsXmlString */ function assertXmlStringEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void { Assert::assertXmlStringEqualsXmlString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertXmlStringNotEqualsXmlString')) { /** * Asserts that two XML documents are not equal. * * @throws ExpectationFailedException * @throws XmlException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertXmlStringNotEqualsXmlString */ function assertXmlStringNotEqualsXmlString(string $expectedXml, string $actualXml, string $message = ''): void { Assert::assertXmlStringNotEqualsXmlString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertThat')) { /** * Evaluates a PHPUnit\Framework\Constraint matcher object. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertThat */ function assertThat(mixed $value, Constraint $constraint, string $message = ''): void { Assert::assertThat(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJson')) { /** * Asserts that a string is a valid JSON string. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJson */ function assertJson(string $actual, string $message = ''): void { Assert::assertJson(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonString')) { /** * Asserts that two given JSON encoded objects or arrays are equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonStringEqualsJsonString */ function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void { Assert::assertJsonStringEqualsJsonString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonString')) { /** * Asserts that two given JSON encoded objects or arrays are not equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonStringNotEqualsJsonString */ function assertJsonStringNotEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void { Assert::assertJsonStringNotEqualsJsonString(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonStringEqualsJsonFile')) { /** * Asserts that the generated JSON encoded object and the content of the given file are equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonStringEqualsJsonFile */ function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void { Assert::assertJsonStringEqualsJsonFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonStringNotEqualsJsonFile')) { /** * Asserts that the generated JSON encoded object and the content of the given file are not equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonStringNotEqualsJsonFile */ function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void { Assert::assertJsonStringNotEqualsJsonFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonFileEqualsJsonFile')) { /** * Asserts that two JSON files are equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonFileEqualsJsonFile */ function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void { Assert::assertJsonFileEqualsJsonFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\assertJsonFileNotEqualsJsonFile')) { /** * Asserts that two JSON files are not equal. * * @throws ExpectationFailedException * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @see Assert::assertJsonFileNotEqualsJsonFile */ function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void { Assert::assertJsonFileNotEqualsJsonFile(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\logicalAnd')) { function logicalAnd(mixed ...$constraints): LogicalAnd { return Assert::logicalAnd(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\logicalOr')) { function logicalOr(mixed ...$constraints): LogicalOr { return Assert::logicalOr(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\logicalNot')) { function logicalNot(Constraint $constraint): LogicalNot { return Assert::logicalNot(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\logicalXor')) { function logicalXor(mixed ...$constraints): LogicalXor { return Assert::logicalXor(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\anything')) { function anything(): IsAnything { return Assert::anything(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isTrue')) { function isTrue(): IsTrue { return Assert::isTrue(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isFalse')) { function isFalse(): IsFalse { return Assert::isFalse(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isJson')) { function isJson(): IsJson { return Assert::isJson(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isNull')) { function isNull(): IsNull { return Assert::isNull(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isFinite')) { function isFinite(): IsFinite { return Assert::isFinite(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isInfinite')) { function isInfinite(): IsInfinite { return Assert::isInfinite(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isNan')) { function isNan(): IsNan { return Assert::isNan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\containsEqual')) { function containsEqual(mixed $value): TraversableContainsEqual { return Assert::containsEqual(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\containsIdentical')) { function containsIdentical(mixed $value): TraversableContainsIdentical { return Assert::containsIdentical(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\containsOnly')) { function containsOnly(string $type): TraversableContainsOnly { return Assert::containsOnly(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\containsOnlyInstancesOf')) { function containsOnlyInstancesOf(string $className): TraversableContainsOnly { return Assert::containsOnlyInstancesOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\arrayHasKey')) { function arrayHasKey(int|string $key): ArrayHasKey { return Assert::arrayHasKey(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isList')) { function isList(): IsList { return Assert::isList(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\equalTo')) { function equalTo(mixed $value): IsEqual { return Assert::equalTo(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\equalToCanonicalizing')) { function equalToCanonicalizing(mixed $value): IsEqualCanonicalizing { return Assert::equalToCanonicalizing(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\equalToIgnoringCase')) { function equalToIgnoringCase(mixed $value): IsEqualIgnoringCase { return Assert::equalToIgnoringCase(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\equalToWithDelta')) { function equalToWithDelta(mixed $value, float $delta): IsEqualWithDelta { return Assert::equalToWithDelta(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isEmpty')) { function isEmpty(): IsEmpty { return Assert::isEmpty(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isWritable')) { function isWritable(): IsWritable { return Assert::isWritable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isReadable')) { function isReadable(): IsReadable { return Assert::isReadable(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\directoryExists')) { function directoryExists(): DirectoryExists { return Assert::directoryExists(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\fileExists')) { function fileExists(): FileExists { return Assert::fileExists(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\greaterThan')) { function greaterThan(mixed $value): GreaterThan { return Assert::greaterThan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\greaterThanOrEqual')) { function greaterThanOrEqual(mixed $value): LogicalOr { return Assert::greaterThanOrEqual(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\identicalTo')) { function identicalTo(mixed $value): IsIdentical { return Assert::identicalTo(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isInstanceOf')) { function isInstanceOf(string $className): IsInstanceOf { return Assert::isInstanceOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\isType')) { function isType(string $type): IsType { return Assert::isType(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\lessThan')) { function lessThan(mixed $value): LessThan { return Assert::lessThan(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\lessThanOrEqual')) { function lessThanOrEqual(mixed $value): LogicalOr { return Assert::lessThanOrEqual(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\matchesRegularExpression')) { function matchesRegularExpression(string $pattern): RegularExpression { return Assert::matchesRegularExpression(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\matches')) { function matches(string $string): StringMatchesFormatDescription { return Assert::matches(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\stringStartsWith')) { function stringStartsWith(string $prefix): StringStartsWith { return Assert::stringStartsWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\stringContains')) { function stringContains(string $string, bool $case = true): StringContains { return Assert::stringContains(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\stringEndsWith')) { function stringEndsWith(string $suffix): StringEndsWith { return Assert::stringEndsWith(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\stringEqualsStringIgnoringLineEndings')) { function stringEqualsStringIgnoringLineEndings(string $string): StringEqualsStringIgnoringLineEndings { return Assert::stringEqualsStringIgnoringLineEndings(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\countOf')) { function countOf(int $count): Count { return Assert::countOf(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\objectEquals')) { function objectEquals(object $object, string $method = 'equals'): ObjectEquals { return Assert::objectEquals(...func_get_args()); } } if (!function_exists('PHPUnit\Framework\callback')) { /** * @template CallbackInput of mixed * * @param callable(CallbackInput $callback): bool $callback * * @return Callback<CallbackInput> */ function callback(callable $callback): Callback { return Assert::callback($callback); } } if (!function_exists('PHPUnit\Framework\any')) { /** * Returns a matcher that matches when the method is executed * zero or more times. */ function any(): AnyInvokedCountMatcher { return new AnyInvokedCountMatcher; } } if (!function_exists('PHPUnit\Framework\never')) { /** * Returns a matcher that matches when the method is never executed. */ function never(): InvokedCountMatcher { return new InvokedCountMatcher(0); } } if (!function_exists('PHPUnit\Framework\atLeast')) { /** * Returns a matcher that matches when the method is executed * at least N times. */ function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher { return new InvokedAtLeastCountMatcher( $requiredInvocations, ); } } if (!function_exists('PHPUnit\Framework\atLeastOnce')) { /** * Returns a matcher that matches when the method is executed at least once. */ function atLeastOnce(): InvokedAtLeastOnceMatcher { return new InvokedAtLeastOnceMatcher; } } if (!function_exists('PHPUnit\Framework\once')) { /** * Returns a matcher that matches when the method is executed exactly once. */ function once(): InvokedCountMatcher { return new InvokedCountMatcher(1); } } if (!function_exists('PHPUnit\Framework\exactly')) { /** * Returns a matcher that matches when the method is executed * exactly $count times. */ function exactly(int $count): InvokedCountMatcher { return new InvokedCountMatcher($count); } } if (!function_exists('PHPUnit\Framework\atMost')) { /** * Returns a matcher that matches when the method is executed * at most N times. */ function atMost(int $allowedInvocations): InvokedAtMostCountMatcher { return new InvokedAtMostCountMatcher($allowedInvocations); } } if (!function_exists('PHPUnit\Framework\returnValue')) { function returnValue(mixed $value): ReturnStub { return new ReturnStub($value); } } if (!function_exists('PHPUnit\Framework\returnValueMap')) { /** * @param array<mixed> $valueMap */ function returnValueMap(array $valueMap): ReturnValueMapStub { return new ReturnValueMapStub($valueMap); } } if (!function_exists('PHPUnit\Framework\returnArgument')) { function returnArgument(int $argumentIndex): ReturnArgumentStub { return new ReturnArgumentStub($argumentIndex); } } if (!function_exists('PHPUnit\Framework\returnCallback')) { function returnCallback(callable $callback): ReturnCallbackStub { return new ReturnCallbackStub($callback); } } if (!function_exists('PHPUnit\Framework\returnSelf')) { /** * Returns the current object. * * This method is useful when mocking a fluent interface. */ function returnSelf(): ReturnSelfStub { return new ReturnSelfStub; } } if (!function_exists('PHPUnit\Framework\throwException')) { function throwException(Throwable $exception): ExceptionStub { return new ExceptionStub($exception); } } if (!function_exists('PHPUnit\Framework\onConsecutiveCalls')) { function onConsecutiveCalls(): ConsecutiveCallsStub { $arguments = func_get_args(); return new ConsecutiveCallsStub($arguments); } } phpunit/src/Framework/Constraint/Filesystem/IsReadable.php 0000644 00000002372 15253321353 0017741 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_readable; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsReadable extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is readable'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_readable($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( '"%s" is readable', $other, ); } } phpunit/src/Framework/Constraint/Filesystem/DirectoryExists.php 0000644 00000002377 15253321353 0021117 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_dir; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class DirectoryExists extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'directory exists'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_dir($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( 'directory "%s" exists', $other, ); } } phpunit/src/Framework/Constraint/Filesystem/IsWritable.php 0000644 00000002372 15253321353 0020013 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_writable; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsWritable extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is writable'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_writable($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( '"%s" is writable', $other, ); } } phpunit/src/Framework/Constraint/Filesystem/FileExists.php 0000644 00000002372 15253321353 0020025 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function file_exists; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class FileExists extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'file exists'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return file_exists($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( 'file "%s" exists', $other, ); } } phpunit/src/Framework/Constraint/Math/IsNan.php 0000644 00000001520 15253321353 0015515 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_nan; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsNan extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is nan'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_nan($other); } } phpunit/src/Framework/Constraint/Math/IsInfinite.php 0000644 00000001544 15253321353 0016554 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_infinite; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsInfinite extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is infinite'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_infinite($other); } } phpunit/src/Framework/Constraint/Math/IsFinite.php 0000644 00000001534 15253321353 0016224 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_finite; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsFinite extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is finite'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return is_finite($other); } } phpunit/src/Framework/Constraint/JsonMatches.php 0000644 00000005143 15253321353 0016037 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function json_decode; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\InvalidJsonException; use PHPUnit\Util\Json; use SebastianBergmann\Comparator\ComparisonFailure; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class JsonMatches extends Constraint { private readonly string $value; public function __construct(string $value) { $this->value = $value; } /** * Returns a string representation of the object. */ public function toString(): string { return sprintf( 'matches JSON string "%s"', $this->value, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * This method can be overridden to implement the evaluation algorithm. */ protected function matches(mixed $other): bool { [$error, $recodedOther] = Json::canonicalize($other); if ($error) { return false; } [$error, $recodedValue] = Json::canonicalize($this->value); if ($error) { return false; } return $recodedOther == $recodedValue; } /** * Throws an exception for the given compared value and test description. * * @throws ExpectationFailedException * @throws InvalidJsonException */ protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never { if ($comparisonFailure === null) { [$error, $recodedOther] = Json::canonicalize($other); if ($error) { parent::fail($other, $description); } [$error, $recodedValue] = Json::canonicalize($this->value); if ($error) { parent::fail($other, $description); } $comparisonFailure = new ComparisonFailure( json_decode($this->value), json_decode($other), Json::prettify($recodedValue), Json::prettify($recodedOther), 'Failed asserting that two json values are equal.', ); } parent::fail($other, $description, $comparisonFailure); } } phpunit/src/Framework/Constraint/Traversable/TraversableContainsEqual.php 0000644 00000002011 15253321353 0023023 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use SplObjectStorage; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class TraversableContainsEqual extends TraversableContains { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if ($other instanceof SplObjectStorage) { return $other->contains($this->value()); } foreach ($other as $element) { /* @noinspection TypeUnsafeComparisonInspection */ if ($this->value() == $element) { return true; } } return false; } } phpunit/src/Framework/Constraint/Traversable/IsList.php 0000644 00000002465 15253321353 0017306 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function array_is_list; use function is_array; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsList extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is a list'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if (!is_array($other)) { return false; } return array_is_list($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return $this->valueToTypeStringFragment($other) . $this->toString(); } } phpunit/src/Framework/Constraint/Traversable/TraversableContainsIdentical.php 0000644 00000001717 15253321353 0023664 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use SplObjectStorage; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class TraversableContainsIdentical extends TraversableContains { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if ($other instanceof SplObjectStorage) { return $other->contains($this->value()); } foreach ($other as $element) { if ($this->value() === $element) { return true; } } return false; } } phpunit/src/Framework/Constraint/Traversable/ArrayHasKey.php 0000644 00000003151 15253321353 0020253 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function array_key_exists; use function is_array; use ArrayAccess; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class ArrayHasKey extends Constraint { private readonly int|string $key; public function __construct(int|string $key) { $this->key = $key; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'has the key ' . Exporter::export($this->key); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if (is_array($other)) { return array_key_exists($this->key, $other); } if ($other instanceof ArrayAccess) { return $other->offsetExists($this->key); } return false; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return 'an array ' . $this->toString(); } } phpunit/src/Framework/Constraint/Traversable/TraversableContains.php 0000644 00000002537 15253321353 0022050 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_array; use function sprintf; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class TraversableContains extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'contains ' . Exporter::export($this->value); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( '%s %s', is_array($other) ? 'an array' : 'a traversable', $this->toString(), ); } protected function value(): mixed { return $this->value; } } phpunit/src/Framework/Constraint/Traversable/TraversableContainsOnly.php 0000644 00000004275 15253321353 0022713 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Framework\Exception; use PHPUnit\Framework\ExpectationFailedException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class TraversableContainsOnly extends Constraint { private readonly Constraint $constraint; private readonly string $type; /** * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string'|class-string $type * * @throws Exception */ public function __construct(string $type, bool $isNativeType = true) { if ($isNativeType) { $this->constraint = new IsType($type); } else { $this->constraint = new IsInstanceOf($type); } $this->type = $type; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): bool { $success = true; foreach ($other as $item) { if (!$this->constraint->evaluate($item, '', true)) { $success = false; break; } } if (!$success && !$returnResult) { $this->fail($other, $description); } return $success; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'contains only values of type "' . $this->type . '"'; } } phpunit/src/Framework/Constraint/IsAnything.php 0000644 00000002552 15253321353 0015677 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Framework\ExpectationFailedException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsAnything extends Constraint { /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { return $returnResult ? true : null; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is anything'; } /** * Counts the number of constraint elements. */ public function count(): int { return 0; } } phpunit/src/Framework/Constraint/Equality/IsEqualWithDelta.php 0000644 00000005122 15253321353 0020564 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function sprintf; use function trim; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\Exporter; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory as ComparatorFactory; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsEqualWithDelta extends Constraint { private readonly mixed $value; private readonly float $delta; public function __construct(mixed $value, float $delta) { $this->value = $value; $this->delta = $delta; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { // If $this->value and $other are identical, they are also equal. // This is the most common path and will allow us to skip // initialization of all the comparators. if ($this->value === $other) { return true; } $comparatorFactory = ComparatorFactory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( $this->value, $other, ); $comparator->assertEquals( $this->value, $other, $this->delta, ); } catch (ComparisonFailure $f) { if ($returnResult) { return false; } throw new ExpectationFailedException( trim($description . "\n" . $f->getMessage()), $f, ); } return true; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'is equal to %s with delta <%F>', Exporter::export($this->value), $this->delta, ); } } phpunit/src/Framework/Constraint/Equality/IsEqual.php 0000644 00000005437 15253321353 0016767 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_string; use function sprintf; use function str_contains; use function trim; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\Exporter; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory as ComparatorFactory; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsEqual extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { // If $this->value and $other are identical, they are also equal. // This is the most common path and will allow us to skip // initialization of all the comparators. if ($this->value === $other) { return true; } $comparatorFactory = ComparatorFactory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( $this->value, $other, ); $comparator->assertEquals( $this->value, $other, ); } catch (ComparisonFailure $f) { if ($returnResult) { return false; } throw new ExpectationFailedException( trim($description . "\n" . $f->getMessage()), $f, ); } return true; } /** * Returns a string representation of the constraint. */ public function toString(): string { $delta = ''; if (is_string($this->value)) { if (str_contains($this->value, "\n")) { return 'is equal to <text>'; } return sprintf( "is equal to '%s'", $this->value, ); } return sprintf( 'is equal to %s%s', Exporter::export($this->value), $delta, ); } } phpunit/src/Framework/Constraint/Equality/IsEqualCanonicalizing.php 0000644 00000005454 15253321353 0021637 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_string; use function sprintf; use function str_contains; use function trim; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\Exporter; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory as ComparatorFactory; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsEqualCanonicalizing extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { // If $this->value and $other are identical, they are also equal. // This is the most common path and will allow us to skip // initialization of all the comparators. if ($this->value === $other) { return true; } $comparatorFactory = ComparatorFactory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( $this->value, $other, ); $comparator->assertEquals( $this->value, $other, 0.0, true, ); } catch (ComparisonFailure $f) { if ($returnResult) { return false; } throw new ExpectationFailedException( trim($description . "\n" . $f->getMessage()), $f, ); } return true; } /** * Returns a string representation of the constraint. */ public function toString(): string { if (is_string($this->value)) { if (str_contains($this->value, "\n")) { return 'is equal to <text>'; } return sprintf( "is equal to '%s'", $this->value, ); } return sprintf( 'is equal to %s', Exporter::export($this->value), ); } } phpunit/src/Framework/Constraint/Equality/IsEqualIgnoringCase.php 0000644 00000005501 15253321353 0021250 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_string; use function sprintf; use function str_contains; use function trim; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\Exporter; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Comparator\Factory as ComparatorFactory; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsEqualIgnoringCase extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { // If $this->value and $other are identical, they are also equal. // This is the most common path and will allow us to skip // initialization of all the comparators. if ($this->value === $other) { return true; } $comparatorFactory = ComparatorFactory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( $this->value, $other, ); $comparator->assertEquals( $this->value, $other, 0.0, false, true, ); } catch (ComparisonFailure $f) { if ($returnResult) { return false; } throw new ExpectationFailedException( trim($description . "\n" . $f->getMessage()), $f, ); } return true; } /** * Returns a string representation of the constraint. */ public function toString(): string { if (is_string($this->value)) { if (str_contains($this->value, "\n")) { return 'is equal to <text>'; } return sprintf( "is equal to '%s'", $this->value, ); } return sprintf( 'is equal to %s', Exporter::export($this->value), ); } } phpunit/src/Framework/Constraint/Callback.php 0000644 00000002310 15253321353 0015306 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @template CallbackInput of mixed * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class Callback extends Constraint { /** * @var callable(CallbackInput): bool */ private readonly mixed $callback; /** * @param callable(CallbackInput $input): bool $callback */ public function __construct(callable $callback) { $this->callback = $callback; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is accepted by specified callback'; } /** * Evaluates the constraint for parameter $value. Returns true if the * constraint is met, false otherwise. * * @param CallbackInput $other */ protected function matches(mixed $other): bool { return ($this->callback)($other); } } phpunit/src/Framework/Constraint/Boolean/IsTrue.php 0000644 00000001475 15253321353 0016417 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsTrue extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is true'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $other === true; } } phpunit/src/Framework/Constraint/Boolean/IsFalse.php 0000644 00000001500 15253321353 0016517 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsFalse extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is false'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $other === false; } } phpunit/src/Framework/Constraint/Exception/ExceptionMessageIsOrContains.php 0000644 00000003552 15253321353 0023320 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function sprintf; use function str_contains; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExceptionMessageIsOrContains extends Constraint { private readonly string $expectedMessage; public function __construct(string $expectedMessage) { $this->expectedMessage = $expectedMessage; } public function toString(): string { if ($this->expectedMessage === '') { return 'exception message is empty'; } return 'exception message contains ' . Exporter::export($this->expectedMessage); } protected function matches(mixed $other): bool { if ($this->expectedMessage === '') { return $other === ''; } return str_contains((string) $other, $this->expectedMessage); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { if ($this->expectedMessage === '') { return sprintf( "exception message is empty but is '%s'", $other, ); } return sprintf( "exception message '%s' contains '%s'", $other, $this->expectedMessage, ); } } phpunit/src/Framework/Constraint/Exception/Exception.php 0000644 00000004144 15253321353 0017515 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function sprintf; use PHPUnit\Util\Filter; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Exception extends Constraint { private readonly string $className; public function __construct(string $className) { $this->className = $className; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'exception of type "%s"', $this->className, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $other instanceof $this->className; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @throws \PHPUnit\Framework\Exception */ protected function failureDescription(mixed $other): string { if ($other === null) { return sprintf( 'exception of type "%s" is thrown', $this->className, ); } $message = ''; if ($other instanceof Throwable) { $message = '. Message was: "' . $other->getMessage() . '" at' . "\n" . Filter::getFilteredStacktrace($other); } return sprintf( 'exception of type "%s" matches expected exception "%s"%s', $other::class, $this->className, $message, ); } } phpunit/src/Framework/Constraint/Exception/ExceptionMessageMatchesRegularExpression.php 0000644 00000004046 15253321353 0025732 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function preg_match; use function sprintf; use Exception; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExceptionMessageMatchesRegularExpression extends Constraint { private readonly string $regularExpression; public function __construct(string $regularExpression) { $this->regularExpression = $regularExpression; } public function toString(): string { return 'exception message matches ' . Exporter::export($this->regularExpression); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @throws \PHPUnit\Framework\Exception * @throws Exception */ protected function matches(mixed $other): bool { $match = @preg_match($this->regularExpression, (string) $other); if ($match === false) { throw new \PHPUnit\Framework\Exception( sprintf( 'Invalid expected exception message regular expression given: %s', $this->regularExpression, ), ); } return $match === 1; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( "exception message '%s' matches '%s'", $other, $this->regularExpression, ); } } phpunit/src/Framework/Constraint/Exception/ExceptionCode.php 0000644 00000003104 15253321353 0020303 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function sprintf; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExceptionCode extends Constraint { private readonly int|string $expectedCode; public function __construct(int|string $expected) { $this->expectedCode = $expected; } public function toString(): string { return 'exception code is ' . $this->expectedCode; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return (string) $other === (string) $this->expectedCode; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return sprintf( '%s is equal to expected exception code %s', Exporter::export($other), Exporter::export($this->expectedCode), ); } } phpunit/src/Framework/Constraint/Type/IsNull.php 0000644 00000001475 15253321353 0015754 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsNull extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is null'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $other === null; } } phpunit/src/Framework/Constraint/Type/IsInstanceOf.php 0000644 00000003740 15253321353 0017070 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function class_exists; use function interface_exists; use function sprintf; use PHPUnit\Framework\UnknownClassOrInterfaceException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsInstanceOf extends Constraint { /** * @var class-string */ private readonly string $name; /** * @var 'class'|'interface' */ private readonly string $type; /** * @throws UnknownClassOrInterfaceException */ public function __construct(string $name) { if (class_exists($name)) { $this->type = 'class'; } elseif (interface_exists($name)) { $this->type = 'interface'; } else { throw new UnknownClassOrInterfaceException($name); } $this->name = $name; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'is an instance of %s %s', $this->type, $this->name, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $other instanceof $this->name; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { return $this->valueToTypeStringFragment($other) . $this->toString(); } } phpunit/src/Framework/Constraint/Type/IsType.php 0000644 00000011356 15253321353 0015762 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function gettype; use function is_array; use function is_bool; use function is_callable; use function is_float; use function is_int; use function is_iterable; use function is_numeric; use function is_object; use function is_scalar; use function is_string; use function sprintf; use PHPUnit\Framework\UnknownTypeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsType extends Constraint { /** * @var string */ public const TYPE_ARRAY = 'array'; /** * @var string */ public const TYPE_BOOL = 'bool'; /** * @var string */ public const TYPE_FLOAT = 'float'; /** * @var string */ public const TYPE_INT = 'int'; /** * @var string */ public const TYPE_NULL = 'null'; /** * @var string */ public const TYPE_NUMERIC = 'numeric'; /** * @var string */ public const TYPE_OBJECT = 'object'; /** * @var string */ public const TYPE_RESOURCE = 'resource'; /** * @var string */ public const TYPE_CLOSED_RESOURCE = 'resource (closed)'; /** * @var string */ public const TYPE_STRING = 'string'; /** * @var string */ public const TYPE_SCALAR = 'scalar'; /** * @var string */ public const TYPE_CALLABLE = 'callable'; /** * @var string */ public const TYPE_ITERABLE = 'iterable'; /** * @var array<string,bool> */ private const KNOWN_TYPES = [ 'array' => true, 'boolean' => true, 'bool' => true, 'double' => true, 'float' => true, 'integer' => true, 'int' => true, 'null' => true, 'numeric' => true, 'object' => true, 'real' => true, 'resource' => true, 'resource (closed)' => true, 'string' => true, 'scalar' => true, 'callable' => true, 'iterable' => true, ]; /** * @var 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' */ private readonly string $type; /** * @param 'array'|'bool'|'boolean'|'callable'|'double'|'float'|'int'|'integer'|'iterable'|'null'|'numeric'|'object'|'real'|'resource (closed)'|'resource'|'scalar'|'string' $type * * @throws UnknownTypeException */ public function __construct(string $type) { /** @phpstan-ignore isset.offset */ if (!isset(self::KNOWN_TYPES[$type])) { throw new UnknownTypeException($type); } $this->type = $type; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'is of type %s', $this->type, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { switch ($this->type) { case 'numeric': return is_numeric($other); case 'integer': case 'int': return is_int($other); case 'double': case 'float': case 'real': return is_float($other); case 'string': return is_string($other); case 'boolean': case 'bool': return is_bool($other); case 'null': return null === $other; case 'array': return is_array($other); case 'object': return is_object($other); case 'resource': $type = gettype($other); return $type === 'resource' || $type === 'resource (closed)'; case 'resource (closed)': return gettype($other) === 'resource (closed)'; case 'scalar': return is_scalar($other); case 'callable': return is_callable($other); case 'iterable': return is_iterable($other); default: return false; } } } phpunit/src/Framework/Constraint/Cardinality/Count.php 0000644 00000006254 15253321353 0017160 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function count; use function is_countable; use function iterator_count; use function sprintf; use EmptyIterator; use Generator; use Iterator; use IteratorAggregate; use PHPUnit\Framework\Exception; use PHPUnit\Framework\GeneratorNotSupportedException; use Traversable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ class Count extends Constraint { private readonly int $expectedCount; public function __construct(int $expected) { $this->expectedCount = $expected; } public function toString(): string { return sprintf( 'count matches %d', $this->expectedCount, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @throws Exception */ protected function matches(mixed $other): bool { return $this->expectedCount === $this->getCountOf($other); } /** * @throws Exception */ protected function getCountOf(mixed $other): ?int { if (is_countable($other)) { return count($other); } if ($other instanceof EmptyIterator) { return 0; } if ($other instanceof Traversable) { while ($other instanceof IteratorAggregate) { try { $other = $other->getIterator(); } catch (\Exception $e) { throw new Exception( $e->getMessage(), $e->getCode(), $e, ); } } $iterator = $other; if ($iterator instanceof Generator) { throw new GeneratorNotSupportedException; } if (!$iterator instanceof Iterator) { return iterator_count($iterator); } $key = $iterator->key(); $count = iterator_count($iterator); // Manually rewind $iterator to previous key, since iterator_count // moves pointer. if ($key !== null) { $iterator->rewind(); while ($iterator->valid() && $key !== $iterator->key()) { $iterator->next(); } } return $count; } return null; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @throws Exception */ protected function failureDescription(mixed $other): string { return sprintf( 'actual size %d matches expected size %d', (int) $this->getCountOf($other), $this->expectedCount, ); } } phpunit/src/Framework/Constraint/Cardinality/LessThan.php 0000644 00000002006 15253321353 0017600 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class LessThan extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is less than ' . Exporter::export($this->value); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $this->value > $other; } } phpunit/src/Framework/Constraint/Cardinality/SameSize.php 0000644 00000001334 15253321353 0017602 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use Countable; use PHPUnit\Framework\Exception; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class SameSize extends Count { /** * @param Countable|iterable<mixed> $expected * * @throws Exception */ public function __construct(Countable|iterable $expected) { parent::__construct((int) $this->getCountOf($expected)); } } phpunit/src/Framework/Constraint/Cardinality/IsEmpty.php 0000644 00000003174 15253321353 0017460 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function count; use function gettype; use function sprintf; use function str_starts_with; use Countable; use EmptyIterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsEmpty extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is empty'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if ($other instanceof EmptyIterator) { return true; } if ($other instanceof Countable) { return count($other) === 0; } return empty($other); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { $type = gettype($other); return sprintf( '%s %s %s', str_starts_with($type, 'a') || str_starts_with($type, 'o') ? 'an' : 'a', $type, $this->toString(), ); } } phpunit/src/Framework/Constraint/Cardinality/GreaterThan.php 0000644 00000002014 15253321353 0020262 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class GreaterThan extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is greater than ' . Exporter::export($this->value); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $this->value < $other; } } phpunit/src/Framework/Constraint/Constraint.php 0000644 00000021050 15253321353 0015740 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function gettype; use function is_object; use function sprintf; use function str_replace; use function strpos; use function strtolower; use function substr; use Countable; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Util\Exporter; use ReflectionObject; use SebastianBergmann\Comparator\ComparisonFailure; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class Constraint implements Countable, SelfDescribing { /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { $success = false; if ($this->matches($other)) { $success = true; } if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } return null; } /** * Counts the number of constraint elements. */ public function count(): int { return 1; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * This method can be overridden to implement the evaluation algorithm. */ protected function matches(mixed $other): bool { return false; } /** * Throws an exception for the given compared value and test description. * * @throws ExpectationFailedException */ protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never { $failureDescription = sprintf( 'Failed asserting that %s.', $this->failureDescription($other), ); $additionalFailureDescription = $this->additionalFailureDescription($other); if ($additionalFailureDescription) { $failureDescription .= "\n" . $additionalFailureDescription; } if (!empty($description)) { $failureDescription = $description . "\n" . $failureDescription; } throw new ExpectationFailedException( $failureDescription, $comparisonFailure, ); } /** * Return additional failure description where needed. * * The function can be overridden to provide additional failure * information like a diff */ protected function additionalFailureDescription(mixed $other): string { return ''; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * To provide additional failure information additionalFailureDescription * can be used. */ protected function failureDescription(mixed $other): string { return Exporter::export($other) . ' ' . $this->toString(); } /** * Returns a custom string representation of the constraint object when it * appears in context of an $operator expression. * * The purpose of this method is to provide meaningful descriptive string * in context of operators such as LogicalNot. Native PHPUnit constraints * are supported out of the box by LogicalNot, but externally developed * ones had no way to provide correct strings in this context. * * The method shall return empty string, when it does not handle * customization by itself. */ protected function toStringInContext(Operator $operator, mixed $role): string { return ''; } /** * Returns the description of the failure when this constraint appears in * context of an $operator expression. * * The purpose of this method is to provide meaningful failure description * in context of operators such as LogicalNot. Native PHPUnit constraints * are supported out of the box by LogicalNot, but externally developed * ones had no way to provide correct messages in this context. * * The method shall return empty string, when it does not handle * customization by itself. */ protected function failureDescriptionInContext(Operator $operator, mixed $role, mixed $other): string { $string = $this->toStringInContext($operator, $role); if ($string === '') { return ''; } return Exporter::export($other) . ' ' . $string; } /** * Reduces the sub-expression starting at $this by skipping degenerate * sub-expression and returns first descendant constraint that starts * a non-reducible sub-expression. * * Returns $this for terminal constraints and for operators that start * non-reducible sub-expression, or the nearest descendant of $this that * starts a non-reducible sub-expression. * * A constraint expression may be modelled as a tree with non-terminal * nodes (operators) and terminal nodes. For example: * * LogicalOr (operator, non-terminal) * + LogicalAnd (operator, non-terminal) * | + IsType('int') (terminal) * | + GreaterThan(10) (terminal) * + LogicalNot (operator, non-terminal) * + IsType('array') (terminal) * * A degenerate sub-expression is a part of the tree, that effectively does * not contribute to the evaluation of the expression it appears in. An example * of degenerate sub-expression is a BinaryOperator constructed with single * operand or nested BinaryOperators, each with single operand. An * expression involving a degenerate sub-expression is equivalent to a * reduced expression with the degenerate sub-expression removed, for example * * LogicalAnd (operator) * + LogicalOr (degenerate operator) * | + LogicalAnd (degenerate operator) * | + IsType('int') (terminal) * + GreaterThan(10) (terminal) * * is equivalent to * * LogicalAnd (operator) * + IsType('int') (terminal) * + GreaterThan(10) (terminal) * * because the subexpression * * + LogicalOr * + LogicalAnd * + - * * is degenerate. Calling reduce() on the LogicalOr object above, as well * as on LogicalAnd, shall return the IsType('int') instance. * * Other specific reductions can be implemented, for example cascade of * LogicalNot operators * * + LogicalNot * + LogicalNot * +LogicalNot * + IsTrue * * can be reduced to * * LogicalNot * + IsTrue */ protected function reduce(): self { return $this; } /** * @return non-empty-string */ protected function valueToTypeStringFragment(mixed $value): string { if (is_object($value)) { $reflector = new ReflectionObject($value); if ($reflector->isAnonymous()) { $name = str_replace('class@anonymous', '', $reflector->getName()); $name = substr($name, 0, strpos($name, '$')); return 'an instance of anonymous class created at ' . $name . ' '; } return 'an instance of class ' . $reflector->getName() . ' '; } $type = strtolower(gettype($value)); if ($type === 'double') { $type = 'float'; } if ($type === 'resource (closed)') { $type = 'closed resource'; } return match ($type) { 'array', 'integer' => 'an ' . $type . ' ', 'boolean', 'closed resource', 'float', 'resource', 'string' => 'a ' . $type . ' ', 'null' => 'null ', default => 'a value of ' . $type . ' ', }; } } phpunit/src/Framework/Constraint/Operator/Operator.php 0000644 00000002662 15253321353 0017212 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class Operator extends Constraint { /** * Returns the name of this operator. */ abstract public function operator(): string; /** * Returns this operator's precedence. * * @see https://www.php.net/manual/en/language.operators.precedence.php */ abstract public function precedence(): int; /** * Returns the number of operands. */ abstract public function arity(): int; /** * Validates $constraint argument. */ protected function checkConstraint(mixed $constraint): Constraint { if (!$constraint instanceof Constraint) { return new IsEqual($constraint); } return $constraint; } /** * Returns true if the $constraint needs to be wrapped with braces. */ protected function constraintNeedsParentheses(Constraint $constraint): bool { return $constraint instanceof self && $constraint->arity() > 1 && $this->precedence() <= $constraint->precedence(); } } phpunit/src/Framework/Constraint/Operator/BinaryOperator.php 0000644 00000006320 15253321353 0020352 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function array_map; use function count; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class BinaryOperator extends Operator { /** * @var list<Constraint> */ private readonly array $constraints; protected function __construct(mixed ...$constraints) { $this->constraints = array_map( fn ($constraint): Constraint => $this->checkConstraint($constraint), $constraints, ); } /** * Returns the number of operands (constraints). */ final public function arity(): int { return count($this->constraints); } /** * Returns a string representation of the constraint. */ public function toString(): string { $reduced = $this->reduce(); if ($reduced !== $this) { return $reduced->toString(); } $text = ''; foreach ($this->constraints as $key => $constraint) { $constraint = $constraint->reduce(); $text .= $this->constraintToString($constraint, $key); } return $text; } /** * Counts the number of constraint elements. */ public function count(): int { $count = 0; foreach ($this->constraints as $constraint) { $count += count($constraint); } return $count; } /** * @return list<Constraint> */ final protected function constraints(): array { return $this->constraints; } /** * Returns true if the $constraint needs to be wrapped with braces. */ final protected function constraintNeedsParentheses(Constraint $constraint): bool { return $this->arity() > 1 && parent::constraintNeedsParentheses($constraint); } /** * Reduces the sub-expression starting at $this by skipping degenerate * sub-expression and returns first descendant constraint that starts * a non-reducible sub-expression. * * See Constraint::reduce() for more. */ protected function reduce(): Constraint { if ($this->arity() === 1 && $this->constraints[0] instanceof Operator) { return $this->constraints[0]->reduce(); } return parent::reduce(); } /** * Returns string representation of given operand in context of this operator. */ private function constraintToString(Constraint $constraint, int $position): string { $prefix = ''; if ($position > 0) { $prefix = (' ' . $this->operator() . ' '); } if ($this->constraintNeedsParentheses($constraint)) { return $prefix . '( ' . $constraint->toString() . ' )'; } $string = $constraint->toStringInContext($this, $position); if ($string === '') { $string = $constraint->toString(); } return $prefix . $string; } } phpunit/src/Framework/Constraint/Operator/UnaryOperator.php 0000644 00000006653 15253321353 0020235 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function count; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class UnaryOperator extends Operator { private readonly Constraint $constraint; public function __construct(mixed $constraint) { $this->constraint = $this->checkConstraint($constraint); } /** * Returns the number of operands (constraints). */ public function arity(): int { return 1; } /** * Returns a string representation of the constraint. */ public function toString(): string { $reduced = $this->reduce(); if ($reduced !== $this) { return $reduced->toString(); } $constraint = $this->constraint->reduce(); if ($this->constraintNeedsParentheses($constraint)) { return $this->operator() . '( ' . $constraint->toString() . ' )'; } $string = $constraint->toStringInContext($this, 0); if ($string === '') { return $this->transformString($constraint->toString()); } return $string; } /** * Counts the number of constraint elements. */ public function count(): int { return count($this->constraint); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { $reduced = $this->reduce(); if ($reduced !== $this) { return $reduced->failureDescription($other); } $constraint = $this->constraint->reduce(); if ($this->constraintNeedsParentheses($constraint)) { return $this->operator() . '( ' . $constraint->failureDescription($other) . ' )'; } $string = $constraint->failureDescriptionInContext($this, 0, $other); if ($string === '') { return $this->transformString($constraint->failureDescription($other)); } return $string; } /** * Transforms string returned by the memeber constraint's toString() or * failureDescription() such that it reflects constraint's participation in * this expression. * * The method may be overwritten in a subclass to apply default * transformation in case the operand constraint does not provide its own * custom strings via toStringInContext() or failureDescriptionInContext(). */ protected function transformString(string $string): string { return $string; } /** * Provides access to $this->constraint for subclasses. */ final protected function constraint(): Constraint { return $this->constraint; } /** * Returns true if the $constraint needs to be wrapped with parentheses. */ protected function constraintNeedsParentheses(Constraint $constraint): bool { $constraint = $constraint->reduce(); return $constraint instanceof self || parent::constraintNeedsParentheses($constraint); } } phpunit/src/Framework/Constraint/Operator/LogicalXor.php 0000644 00000003217 15253321353 0017457 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function array_reduce; use function array_shift; use PHPUnit\Framework\ExpectationFailedException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class LogicalXor extends BinaryOperator { public static function fromConstraints(mixed ...$constraints): self { return new self(...$constraints); } /** * Returns the name of this operator. */ public function operator(): string { return 'xor'; } /** * Returns this operator's precedence. * * @see https://www.php.net/manual/en/language.operators.precedence.php. */ public function precedence(): int { return 23; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @throws ExpectationFailedException */ public function matches(mixed $other): bool { $constraints = $this->constraints(); $initial = array_shift($constraints); if ($initial === null) { return false; } return array_reduce( $constraints, static fn (bool $matches, Constraint $constraint): bool => $matches xor $constraint->evaluate($other, '', true), $initial->evaluate($other, '', true), ); } } phpunit/src/Framework/Constraint/Operator/LogicalAnd.php 0000644 00000002473 15253321353 0017414 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class LogicalAnd extends BinaryOperator { public static function fromConstraints(mixed ...$constraints): self { return new self(...$constraints); } /** * Returns the name of this operator. */ public function operator(): string { return 'and'; } /** * Returns this operator's precedence. * * @see https://www.php.net/manual/en/language.operators.precedence.php */ public function precedence(): int { return 22; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { foreach ($this->constraints() as $constraint) { if (!$constraint->evaluate($other, '', true)) { return false; } } return [] !== $this->constraints(); } } phpunit/src/Framework/Constraint/Operator/LogicalNot.php 0000644 00000007000 15253321353 0017441 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function array_map; use function count; use function preg_match; use function preg_quote; use function preg_replace; use PHPUnit\Framework\ExpectationFailedException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class LogicalNot extends UnaryOperator { public static function negate(string $string): string { $positives = [ 'contains ', 'exists', 'has ', 'is ', 'are ', 'matches ', 'starts with ', 'ends with ', 'reference ', 'not not ', ]; $negatives = [ 'does not contain ', 'does not exist', 'does not have ', 'is not ', 'are not ', 'does not match ', 'starts not with ', 'ends not with ', 'don\'t reference ', 'not ', ]; preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches); if (count($matches) === 0) { preg_match('/(\'[\w\W]*\')([\w\W]*)(\'[\w\W]*\')/i', $string, $matches); } $positives = array_map( static fn (string $s) => '/\\b' . preg_quote($s, '/') . '/', $positives, ); if (count($matches) > 0) { $nonInput = $matches[2]; $negatedString = preg_replace( '/' . preg_quote($nonInput, '/') . '/', preg_replace( $positives, $negatives, $nonInput, ), $string, ); } else { $negatedString = preg_replace( $positives, $negatives, $string, ); } return $negatedString; } /** * Returns the name of this operator. */ public function operator(): string { return 'not'; } /** * Returns this operator's precedence. * * @see https://www.php.net/manual/en/language.operators.precedence.php */ public function precedence(): int { return 5; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @throws ExpectationFailedException */ protected function matches(mixed $other): bool { return !$this->constraint()->evaluate($other, '', true); } /** * Applies additional transformation to strings returned by toString() or * failureDescription(). */ protected function transformString(string $string): string { return self::negate($string); } /** * Reduces the sub-expression starting at $this by skipping degenerate * sub-expression and returns first descendant constraint that starts * a non-reducible sub-expression. * * See Constraint::reduce() for more. */ protected function reduce(): Constraint { $constraint = $this->constraint(); if ($constraint instanceof self) { return $constraint->constraint()->reduce(); } return parent::reduce(); } } phpunit/src/Framework/Constraint/Operator/LogicalOr.php 0000644 00000002436 15253321353 0017271 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class LogicalOr extends BinaryOperator { public static function fromConstraints(mixed ...$constraints): self { return new self(...$constraints); } /** * Returns the name of this operator. */ public function operator(): string { return 'or'; } /** * Returns this operator's precedence. * * @see https://www.php.net/manual/en/language.operators.precedence.php */ public function precedence(): int { return 24; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ public function matches(mixed $other): bool { foreach ($this->constraints() as $constraint) { if ($constraint->evaluate($other, '', true)) { return true; } } return false; } } phpunit/src/Framework/Constraint/String/StringContains.php 0000644 00000010444 15253321353 0020034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_string; use function mb_detect_encoding; use function mb_stripos; use function mb_strtolower; use function sprintf; use function str_contains; use function strlen; use function strtr; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class StringContains extends Constraint { private readonly string $needle; private readonly bool $ignoreCase; private readonly bool $ignoreLineEndings; public function __construct(string $needle, bool $ignoreCase = false, bool $ignoreLineEndings = false) { if ($ignoreLineEndings) { $needle = $this->normalizeLineEndings($needle); } $this->needle = $needle; $this->ignoreCase = $ignoreCase; $this->ignoreLineEndings = $ignoreLineEndings; } /** * Returns a string representation of the constraint. */ public function toString(): string { $needle = $this->needle; if ($this->ignoreCase) { $needle = mb_strtolower($this->needle, 'UTF-8'); } return sprintf( 'contains "%s" [%s](length: %s)', $needle, $this->getDetectedEncoding($needle), strlen($needle), ); } public function failureDescription(mixed $other): string { $stringifiedHaystack = Exporter::export($other); $haystackEncoding = $this->getDetectedEncoding($other); $haystackLength = $this->getHaystackLength($other); $haystackInformation = sprintf( '%s [%s](length: %s) ', $stringifiedHaystack, $haystackEncoding, $haystackLength, ); $needleInformation = $this->toString(); return $haystackInformation . $needleInformation; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { $haystack = $other; if ('' === $this->needle) { return true; } if (!is_string($haystack)) { return false; } if ($this->ignoreLineEndings) { $haystack = $this->normalizeLineEndings($haystack); } if ($this->ignoreCase) { /* * We must use the multibyte-safe version, so we can accurately compare non-latin uppercase characters with * their lowercase equivalents. */ return mb_stripos($haystack, $this->needle, 0, 'UTF-8') !== false; } /* * Use the non-multibyte safe functions to see if the string is contained in $other. * * This function is very fast, and we don't care about the character position in the string. * * Additionally, we want this method to be binary safe, so we can check if some binary data is in other binary * data. */ return str_contains($haystack, $this->needle); } private function getDetectedEncoding(mixed $other): string { if ($this->ignoreCase) { return 'Encoding ignored'; } if (!is_string($other)) { return 'Encoding detection failed'; } $detectedEncoding = mb_detect_encoding($other, null, true); if ($detectedEncoding === false) { return 'Encoding detection failed'; } return $detectedEncoding; } private function getHaystackLength(mixed $haystack): int { if (!is_string($haystack)) { return 0; } if ($this->ignoreLineEndings) { $haystack = $this->normalizeLineEndings($haystack); } return strlen($haystack); } private function normalizeLineEndings(string $string): string { return strtr( $string, [ "\r\n" => "\n", "\r" => "\n", ], ); } } phpunit/src/Framework/Constraint/String/StringMatchesFormatDescription.php 0000644 00000006331 15253321353 0023217 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use const DIRECTORY_SEPARATOR; use const PHP_EOL; use function explode; use function implode; use function preg_match; use function preg_quote; use function preg_replace; use function strtr; use SebastianBergmann\Diff\Differ; use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class StringMatchesFormatDescription extends Constraint { private readonly string $formatDescription; public function __construct(string $formatDescription) { $this->formatDescription = $formatDescription; } public function toString(): string { return 'matches format description:' . PHP_EOL . $this->formatDescription; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { $other = $this->convertNewlines($other); $matches = preg_match( $this->regularExpressionForFormatDescription( $this->convertNewlines($this->formatDescription), ), $other, ); return $matches > 0; } protected function failureDescription(mixed $other): string { return 'string matches format description'; } protected function additionalFailureDescription(mixed $other): string { $from = explode("\n", $this->formatDescription); $to = explode("\n", $this->convertNewlines($other)); foreach ($from as $index => $line) { if (isset($to[$index]) && $line !== $to[$index]) { $line = $this->regularExpressionForFormatDescription($line); if (preg_match($line, $to[$index]) > 0) { $from[$index] = $to[$index]; } } } $from = implode("\n", $from); $to = implode("\n", $to); return $this->differ()->diff($from, $to); } private function regularExpressionForFormatDescription(string $string): string { $string = strtr( preg_quote($string, '/'), [ '%%' => '%', '%e' => '\\' . DIRECTORY_SEPARATOR, '%s' => '[^\r\n]+', '%S' => '[^\r\n]*', '%a' => '.+', '%A' => '.*', '%w' => '\s*', '%i' => '[+-]?\d+', '%d' => '\d+', '%x' => '[0-9a-fA-F]+', '%f' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', '%c' => '.', ], ); return '/^' . $string . '$/s'; } private function convertNewlines(string $text): string { return preg_replace('/\r\n/', "\n", $text); } private function differ(): Differ { return new Differ(new UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")); } } phpunit/src/Framework/Constraint/String/RegularExpression.php 0000644 00000002145 15253321353 0020547 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function preg_match; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class RegularExpression extends Constraint { private readonly string $pattern; public function __construct(string $pattern) { $this->pattern = $pattern; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'matches PCRE pattern "%s"', $this->pattern, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return preg_match($this->pattern, $other) > 0; } } phpunit/src/Framework/Constraint/String/StringEqualsStringIgnoringLineEndings.php 0000644 00000002623 15253321353 0024514 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function sprintf; use function strtr; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class StringEqualsStringIgnoringLineEndings extends Constraint { private readonly string $string; public function __construct(string $string) { $this->string = $this->normalizeLineEndings($string); } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'is equal to "%s" ignoring line endings', $this->string, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return $this->string === $this->normalizeLineEndings((string) $other); } private function normalizeLineEndings(string $string): string { return strtr( $string, [ "\r\n" => "\n", "\r" => "\n", ], ); } } phpunit/src/Framework/Constraint/String/IsJson.php 0000644 00000005044 15253321353 0016274 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use const JSON_ERROR_CTRL_CHAR; use const JSON_ERROR_DEPTH; use const JSON_ERROR_NONE; use const JSON_ERROR_STATE_MISMATCH; use const JSON_ERROR_SYNTAX; use const JSON_ERROR_UTF8; use function is_string; use function json_decode; use function json_last_error; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsJson extends Constraint { /** * Returns a string representation of the constraint. */ public function toString(): string { return 'is valid JSON'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { if (!is_string($other) || $other === '') { return false; } json_decode($other); if (json_last_error()) { return false; } return true; } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { if (!is_string($other)) { return $this->valueToTypeStringFragment($other) . 'is valid JSON'; } if ($other === '') { return 'an empty string is valid JSON'; } return sprintf( 'a string is valid JSON (%s)', $this->determineJsonError($other), ); } private function determineJsonError(string $json): string { json_decode($json); return match (json_last_error()) { JSON_ERROR_NONE => '', JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', JSON_ERROR_STATE_MISMATCH => 'Underflow or the modes mismatch', JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON', JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded', default => 'Unknown error', }; } } phpunit/src/Framework/Constraint/String/StringEndsWith.php 0000644 00000002323 15253321353 0020000 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function str_ends_with; use PHPUnit\Framework\EmptyStringException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class StringEndsWith extends Constraint { private readonly string $suffix; /** * @throws EmptyStringException */ public function __construct(string $suffix) { if ($suffix === '') { throw new EmptyStringException; } $this->suffix = $suffix; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'ends with "' . $this->suffix . '"'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return str_ends_with((string) $other, $this->suffix); } } phpunit/src/Framework/Constraint/String/StringStartsWith.php 0000644 00000002333 15253321353 0020370 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function str_starts_with; use PHPUnit\Framework\EmptyStringException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class StringStartsWith extends Constraint { private readonly string $prefix; /** * @throws EmptyStringException */ public function __construct(string $prefix) { if ($prefix === '') { throw new EmptyStringException; } $this->prefix = $prefix; } /** * Returns a string representation of the constraint. */ public function toString(): string { return 'starts with "' . $this->prefix . '"'; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. */ protected function matches(mixed $other): bool { return str_starts_with((string) $other, $this->prefix); } } phpunit/src/Framework/Constraint/IsIdentical.php 0000644 00000007243 15253321353 0016014 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function explode; use function gettype; use function is_array; use function is_object; use function is_string; use function sprintf; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Util\Exporter; use SebastianBergmann\Comparator\ComparisonFailure; use UnitEnum; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IsIdentical extends Constraint { private readonly mixed $value; public function __construct(mixed $value) { $this->value = $value; } /** * Evaluates the constraint for parameter $other. * * If $returnResult is set to false (the default), an exception is thrown * in case of a failure. null is returned otherwise. * * If $returnResult is true, the result of the evaluation is returned as * a boolean value instead: true in case of success, false in case of a * failure. * * @throws ExpectationFailedException */ public function evaluate(mixed $other, string $description = '', bool $returnResult = false): ?bool { $success = $this->value === $other; if ($returnResult) { return $success; } if (!$success) { $f = null; // if both values are strings, make sure a diff is generated if (is_string($this->value) && is_string($other)) { $f = new ComparisonFailure( $this->value, $other, sprintf("'%s'", $this->value), sprintf("'%s'", $other), ); } // if both values are array or enums, make sure a diff is generated if ((is_array($this->value) && is_array($other)) || ($this->value instanceof UnitEnum && $other instanceof UnitEnum)) { $f = new ComparisonFailure( $this->value, $other, Exporter::export($this->value), Exporter::export($other), ); } $this->fail($other, $description, $f); } return null; } /** * Returns a string representation of the constraint. */ public function toString(): string { if (is_object($this->value)) { return 'is identical to an object of class "' . $this->value::class . '"'; } return 'is identical to ' . Exporter::export($this->value); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. */ protected function failureDescription(mixed $other): string { if (is_object($this->value) && is_object($other)) { return 'two variables reference the same object'; } if (explode(' ', gettype($this->value), 2)[0] === 'resource' && explode(' ', gettype($other), 2)[0] === 'resource') { return 'two variables reference the same resource'; } if (is_string($this->value) && is_string($other)) { return 'two strings are identical'; } if (is_array($this->value) && is_array($other)) { return 'two arrays are identical'; } return parent::failureDescription($other); } } phpunit/src/Framework/Constraint/Object/ObjectHasProperty.php 0000644 00000003770 15253321353 0020442 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function gettype; use function is_object; use function sprintf; use ReflectionObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class ObjectHasProperty extends Constraint { private readonly string $propertyName; public function __construct(string $propertyName) { $this->propertyName = $propertyName; } /** * Returns a string representation of the constraint. */ public function toString(): string { return sprintf( 'has property "%s"', $this->propertyName, ); } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other value or object to evaluate */ protected function matches(mixed $other): bool { if (!is_object($other)) { return false; } return (new ReflectionObject($other))->hasProperty($this->propertyName); } /** * Returns the description of the failure. * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param mixed $other evaluated value or object */ protected function failureDescription(mixed $other): string { if (is_object($other)) { return sprintf( 'object of class "%s" %s', $other::class, $this->toString(), ); } return sprintf( '"%s" (%s) %s', $other, gettype($other), $this->toString(), ); } } phpunit/src/Framework/Constraint/Object/ObjectEquals.php 0000644 00000010431 15253321353 0017404 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use function is_object; use PHPUnit\Framework\ActualValueIsNotAnObjectException; use PHPUnit\Framework\ComparisonMethodDoesNotAcceptParameterTypeException; use PHPUnit\Framework\ComparisonMethodDoesNotDeclareBoolReturnTypeException; use PHPUnit\Framework\ComparisonMethodDoesNotDeclareExactlyOneParameterException; use PHPUnit\Framework\ComparisonMethodDoesNotDeclareParameterTypeException; use PHPUnit\Framework\ComparisonMethodDoesNotExistException; use ReflectionNamedType; use ReflectionObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class ObjectEquals extends Constraint { private readonly object $expected; private readonly string $method; public function __construct(object $object, string $method = 'equals') { $this->expected = $object; $this->method = $method; } public function toString(): string { return 'two objects are equal'; } /** * @throws ActualValueIsNotAnObjectException * @throws ComparisonMethodDoesNotAcceptParameterTypeException * @throws ComparisonMethodDoesNotDeclareBoolReturnTypeException * @throws ComparisonMethodDoesNotDeclareExactlyOneParameterException * @throws ComparisonMethodDoesNotDeclareParameterTypeException * @throws ComparisonMethodDoesNotExistException */ protected function matches(mixed $other): bool { if (!is_object($other)) { throw new ActualValueIsNotAnObjectException; } $object = new ReflectionObject($other); if (!$object->hasMethod($this->method)) { throw new ComparisonMethodDoesNotExistException( $other::class, $this->method, ); } $method = $object->getMethod($this->method); if (!$method->hasReturnType()) { throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( $other::class, $this->method, ); } $returnType = $method->getReturnType(); if (!$returnType instanceof ReflectionNamedType) { throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( $other::class, $this->method, ); } if ($returnType->allowsNull()) { throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( $other::class, $this->method, ); } if ($returnType->getName() !== 'bool') { throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException( $other::class, $this->method, ); } if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) { throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException( $other::class, $this->method, ); } $parameter = $method->getParameters()[0]; if (!$parameter->hasType()) { throw new ComparisonMethodDoesNotDeclareParameterTypeException( $other::class, $this->method, ); } $type = $parameter->getType(); if (!$type instanceof ReflectionNamedType) { throw new ComparisonMethodDoesNotDeclareParameterTypeException( $other::class, $this->method, ); } $typeName = $type->getName(); if ($typeName === 'self') { $typeName = $other::class; } if (!$this->expected instanceof $typeName) { throw new ComparisonMethodDoesNotAcceptParameterTypeException( $other::class, $this->method, $this->expected::class, ); } return $other->{$this->method}($this->expected); } protected function failureDescription(mixed $other): string { return $this->toString(); } } phpunit/src/Framework/TestStatus/TestStatus.php 0000644 00000007724 15253321353 0015752 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class TestStatus { private string $message; public static function from(int $status): self { return match ($status) { 0 => self::success(), 1 => self::skipped(), 2 => self::incomplete(), 3 => self::notice(), 4 => self::deprecation(), 5 => self::risky(), 6 => self::warning(), 7 => self::failure(), 8 => self::error(), default => self::unknown(), }; } public static function unknown(): self { return new Unknown; } public static function success(): self { return new Success; } public static function skipped(string $message = ''): self { return new Skipped($message); } public static function incomplete(string $message = ''): self { return new Incomplete($message); } public static function notice(string $message = ''): self { return new Notice($message); } public static function deprecation(string $message = ''): self { return new Deprecation($message); } public static function failure(string $message = ''): self { return new Failure($message); } public static function error(string $message = ''): self { return new Error($message); } public static function warning(string $message = ''): self { return new Warning($message); } public static function risky(string $message = ''): self { return new Risky($message); } private function __construct(string $message = '') { $this->message = $message; } /** * @phpstan-assert-if-true Known $this */ public function isKnown(): bool { return false; } /** * @phpstan-assert-if-true Unknown $this */ public function isUnknown(): bool { return false; } /** * @phpstan-assert-if-true Success $this */ public function isSuccess(): bool { return false; } /** * @phpstan-assert-if-true Skipped $this */ public function isSkipped(): bool { return false; } /** * @phpstan-assert-if-true Incomplete $this */ public function isIncomplete(): bool { return false; } /** * @phpstan-assert-if-true Notice $this */ public function isNotice(): bool { return false; } /** * @phpstan-assert-if-true Deprecation $this */ public function isDeprecation(): bool { return false; } /** * @phpstan-assert-if-true Failure $this */ public function isFailure(): bool { return false; } /** * @phpstan-assert-if-true Error $this */ public function isError(): bool { return false; } /** * @phpstan-assert-if-true Warning $this */ public function isWarning(): bool { return false; } /** * @phpstan-assert-if-true Risky $this */ public function isRisky(): bool { return false; } public function message(): string { return $this->message; } public function isMoreImportantThan(self $other): bool { return $this->asInt() > $other->asInt(); } abstract public function asInt(): int; abstract public function asString(): string; } phpunit/src/Framework/TestStatus/Warning.php 0000644 00000001410 15253321353 0015216 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Warning extends Known { public function isWarning(): true { return true; } public function asInt(): int { return 6; } public function asString(): string { return 'warning'; } } phpunit/src/Framework/TestStatus/Deprecation.php 0000644 00000001424 15253321353 0016053 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Deprecation extends Known { public function isDeprecation(): true { return true; } public function asInt(): int { return 4; } public function asString(): string { return 'deprecation'; } } phpunit/src/Framework/TestStatus/Skipped.php 0000644 00000001410 15253321353 0015210 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Skipped extends Known { public function isSkipped(): true { return true; } public function asInt(): int { return 1; } public function asString(): string { return 'skipped'; } } phpunit/src/Framework/TestStatus/Success.php 0000644 00000001410 15253321353 0015221 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Success extends Known { public function isSuccess(): true { return true; } public function asInt(): int { return 0; } public function asString(): string { return 'success'; } } phpunit/src/Framework/TestStatus/Known.php 0000644 00000001176 15253321353 0014716 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Known extends TestStatus { public function isKnown(): true { return true; } } phpunit/src/Framework/TestStatus/Risky.php 0000644 00000001402 15253321353 0014713 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Risky extends Known { public function isRisky(): true { return true; } public function asInt(): int { return 5; } public function asString(): string { return 'risky'; } } phpunit/src/Framework/TestStatus/Unknown.php 0000644 00000001416 15253321353 0015256 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Unknown extends TestStatus { public function isUnknown(): true { return true; } public function asInt(): int { return -1; } public function asString(): string { return 'unknown'; } } phpunit/src/Framework/TestStatus/Incomplete.php 0000644 00000001421 15253321353 0015712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Incomplete extends Known { public function isIncomplete(): true { return true; } public function asInt(): int { return 2; } public function asString(): string { return 'incomplete'; } } phpunit/src/Framework/TestStatus/Error.php 0000644 00000001402 15253321353 0014703 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Error extends Known { public function isError(): true { return true; } public function asInt(): int { return 8; } public function asString(): string { return 'error'; } } phpunit/src/Framework/TestStatus/Failure.php 0000644 00000001410 15253321353 0015200 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Failure extends Known { public function isFailure(): true { return true; } public function asInt(): int { return 7; } public function asString(): string { return 'failure'; } } phpunit/src/Framework/TestStatus/Notice.php 0000644 00000001405 15253321353 0015036 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Notice extends Known { public function isNotice(): true { return true; } public function asInt(): int { return 3; } public function asString(): string { return 'notice'; } } phpunit/src/Framework/TestRunner/SeparateProcessTestRunner.php 0000644 00000023332 15253321353 0020743 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function assert; use function defined; use function file_exists; use function file_get_contents; use function get_include_path; use function hrtime; use function restore_error_handler; use function serialize; use function set_error_handler; use function sys_get_temp_dir; use function tempnam; use function trim; use function unlink; use function unserialize; use function var_export; use ErrorException; use PHPUnit\Event\Code\TestMethodBuilder; use PHPUnit\Event\Code\ThrowableBuilder; use PHPUnit\Event\Facade; use PHPUnit\Event\NoPreviousThrowableException; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TestRunner\TestResult\PassedTests; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use PHPUnit\Util\GlobalState; use PHPUnit\Util\PHP\Job; use PHPUnit\Util\PHP\JobRunnerRegistry; use PHPUnit\Util\PHP\PhpProcessException; use ReflectionClass; use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; use SebastianBergmann\Template\InvalidArgumentException; use SebastianBergmann\Template\Template; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SeparateProcessTestRunner implements IsolatedTestRunner { /** * @throws \PHPUnit\Runner\Exception * @throws \PHPUnit\Util\Exception * @throws Exception * @throws InvalidArgumentException * @throws NoPreviousThrowableException * @throws ProcessIsolationException * @throws StaticAnalysisCacheNotConfiguredException */ public function run(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void { $class = new ReflectionClass($test); if ($runEntireClass) { $template = new Template( __DIR__ . '/templates/class.tpl', ); } else { $template = new Template( __DIR__ . '/templates/method.tpl', ); } $bootstrap = ''; $constants = ''; $globals = ''; $includedFiles = ''; $iniSettings = ''; if (ConfigurationRegistry::get()->hasBootstrap()) { $bootstrap = ConfigurationRegistry::get()->bootstrap(); } if ($preserveGlobalState) { $constants = GlobalState::getConstantsAsString(); $globals = GlobalState::getGlobalsAsString(); $includedFiles = GlobalState::getIncludedFilesAsString(); $iniSettings = GlobalState::getIniSettingsAsString(); } $coverage = CodeCoverage::instance()->isActive() ? 'true' : 'false'; $linesToBeIgnored = var_export(CodeCoverage::instance()->linesToBeIgnored(), true); if (defined('PHPUNIT_COMPOSER_INSTALL')) { $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); } else { $composerAutoload = '\'\''; } if (defined('__PHPUNIT_PHAR__')) { $phar = var_export(__PHPUNIT_PHAR__, true); } else { $phar = '\'\''; } $data = var_export(serialize($test->providedData()), true); $dataName = var_export($test->dataName(), true); $dependencyInput = var_export(serialize($test->dependencyInput()), true); $includePath = var_export(get_include_path(), true); // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences $data = "'." . $data . ".'"; $dataName = "'.(" . $dataName . ").'"; $dependencyInput = "'." . $dependencyInput . ".'"; $includePath = "'." . $includePath . ".'"; $offset = hrtime(); $serializedConfiguration = $this->saveConfigurationForChildProcess(); $processResultFile = tempnam(sys_get_temp_dir(), 'phpunit_'); $file = $class->getFileName(); assert($file !== false); $var = [ 'bootstrap' => $bootstrap, 'composerAutoload' => $composerAutoload, 'phar' => $phar, 'filename' => $file, 'className' => $class->getName(), 'collectCodeCoverageInformation' => $coverage, 'linesToBeIgnored' => $linesToBeIgnored, 'data' => $data, 'dataName' => $dataName, 'dependencyInput' => $dependencyInput, 'constants' => $constants, 'globals' => $globals, 'include_path' => $includePath, 'included_files' => $includedFiles, 'iniSettings' => $iniSettings, 'name' => $test->name(), 'offsetSeconds' => (string) $offset[0], 'offsetNanoseconds' => (string) $offset[1], 'serializedConfiguration' => $serializedConfiguration, 'processResultFile' => $processResultFile, ]; if (!$runEntireClass) { $var['methodName'] = $test->name(); } $template->setVar($var); $code = $template->render(); assert($code !== ''); $this->runTestJob($code, $test, $processResultFile); @unlink($serializedConfiguration); } /** * @param non-empty-string $code * * @throws Exception * @throws NoPreviousThrowableException * @throws PhpProcessException */ private function runTestJob(string $code, Test $test, string $processResultFile): void { $result = JobRunnerRegistry::run(new Job($code)); $processResult = ''; if (file_exists($processResultFile)) { $processResult = file_get_contents($processResultFile); assert($processResult !== false); @unlink($processResultFile); } $this->processChildResult( $test, $processResult, $result->stderr(), ); } /** * @throws Exception * @throws NoPreviousThrowableException */ private function processChildResult(Test $test, string $stdout, string $stderr): void { if (!empty($stderr)) { $exception = new Exception(trim($stderr)); assert($test instanceof TestCase); Facade::emitter()->testErrored( TestMethodBuilder::fromTestCase($test), ThrowableBuilder::from($exception), ); return; } set_error_handler( /** * @throws ErrorException */ static function (int $errno, string $errstr, string $errfile, int $errline): never { throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); }, ); try { $childResult = unserialize($stdout); restore_error_handler(); if ($childResult === false) { $exception = new AssertionFailedError('Test was run in child process and ended unexpectedly'); assert($test instanceof TestCase); Facade::emitter()->testErrored( TestMethodBuilder::fromTestCase($test), ThrowableBuilder::from($exception), ); Facade::emitter()->testFinished( TestMethodBuilder::fromTestCase($test), 0, ); } } catch (ErrorException $e) { restore_error_handler(); $childResult = false; $exception = new Exception(trim($stdout), 0, $e); assert($test instanceof TestCase); Facade::emitter()->testErrored( TestMethodBuilder::fromTestCase($test), ThrowableBuilder::from($exception), ); } if ($childResult !== false) { if (!empty($childResult['output'])) { $output = $childResult['output']; } Facade::instance()->forward($childResult['events']); PassedTests::instance()->import($childResult['passedTests']); assert($test instanceof TestCase); $test->setResult($childResult['testResult']); $test->addToAssertionCount($childResult['numAssertions']); if (CodeCoverage::instance()->isActive() && $childResult['codeCoverage'] instanceof \SebastianBergmann\CodeCoverage\CodeCoverage) { CodeCoverage::instance()->codeCoverage()->merge( $childResult['codeCoverage'], ); } } if (!empty($output)) { print $output; } } /** * @throws ProcessIsolationException */ private function saveConfigurationForChildProcess(): string { $path = tempnam(sys_get_temp_dir(), 'phpunit_'); if ($path === false) { throw new ProcessIsolationException; } if (!ConfigurationRegistry::saveTo($path)) { throw new ProcessIsolationException; } return $path; } } phpunit/src/Framework/TestRunner/templates/class.tpl 0000644 00000006167 15253321353 0016730 0 ustar 00 <?php declare(strict_types=1); use PHPUnit\Event\Facade; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\XmlConfiguration\Loader; use PHPUnit\TextUI\Configuration\PhpHandler; use PHPUnit\TestRunner\TestResult\PassedTests; // php://stdout does not obey output buffering. Any output would break // unserialization of child process results in the parent process. if (!defined('STDOUT')) { define('STDOUT', fopen('php://temp', 'w+b')); define('STDERR', fopen('php://stderr', 'wb')); } {iniSettings} ini_set('display_errors', 'stderr'); set_include_path('{include_path}'); $composerAutoload = {composerAutoload}; $phar = {phar}; ob_start(); if ($composerAutoload) { require_once $composerAutoload; define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload); } else if ($phar) { require $phar; } function __phpunit_run_isolated_test() { $dispatcher = Facade::instance()->initForIsolation( PHPUnit\Event\Telemetry\HRTime::fromSecondsAndNanoseconds( {offsetSeconds}, {offsetNanoseconds} ), ); require_once '{filename}'; if ({collectCodeCoverageInformation}) { CodeCoverage::instance()->init(ConfigurationRegistry::get(), CodeCoverageFilterRegistry::instance(), true); CodeCoverage::instance()->ignoreLines({linesToBeIgnored}); } $test = new {className}('{name}'); $test->setData('{dataName}', unserialize('{data}')); $test->setDependencyInput(unserialize('{dependencyInput}')); $test->setInIsolation(true); ob_end_clean(); $test->run(); $output = ''; if (!$test->expectsOutput()) { $output = $test->output(); } ini_set('xdebug.scream', '0'); // Not every STDOUT target stream is rewindable @rewind(STDOUT); if ($stdout = @stream_get_contents(STDOUT)) { $output = $stdout . $output; $streamMetaData = stream_get_meta_data(STDOUT); if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { @ftruncate(STDOUT, 0); @rewind(STDOUT); } } file_put_contents( '{processResultFile}', serialize( [ 'testResult' => $test->result(), 'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null, 'numAssertions' => $test->numberOfAssertionsPerformed(), 'output' => $output, 'events' => $dispatcher->flush(), 'passedTests' => PassedTests::instance() ] ) ); } function __phpunit_error_handler($errno, $errstr, $errfile, $errline) { return true; } set_error_handler('__phpunit_error_handler'); {constants} {included_files} {globals} restore_error_handler(); ConfigurationRegistry::loadFrom('{serializedConfiguration}'); (new PhpHandler)->handle(ConfigurationRegistry::get()->php()); if ('{bootstrap}' !== '') { require_once '{bootstrap}'; } __phpunit_run_isolated_test(); phpunit/src/Framework/TestRunner/templates/method.tpl 0000644 00000006175 15253321353 0017102 0 ustar 00 <?php declare(strict_types=1); use PHPUnit\Event\Facade; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\XmlConfiguration\Loader; use PHPUnit\TextUI\Configuration\PhpHandler; use PHPUnit\TestRunner\TestResult\PassedTests; // php://stdout does not obey output buffering. Any output would break // unserialization of child process results in the parent process. if (!defined('STDOUT')) { define('STDOUT', fopen('php://temp', 'w+b')); define('STDERR', fopen('php://stderr', 'wb')); } {iniSettings} ini_set('display_errors', 'stderr'); set_include_path('{include_path}'); $composerAutoload = {composerAutoload}; $phar = {phar}; ob_start(); if ($composerAutoload) { require_once $composerAutoload; define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload); } else if ($phar) { require $phar; } function __phpunit_run_isolated_test() { $dispatcher = Facade::instance()->initForIsolation( PHPUnit\Event\Telemetry\HRTime::fromSecondsAndNanoseconds( {offsetSeconds}, {offsetNanoseconds} ), ); require_once '{filename}'; if ({collectCodeCoverageInformation}) { CodeCoverage::instance()->init(ConfigurationRegistry::get(), CodeCoverageFilterRegistry::instance(), true); CodeCoverage::instance()->ignoreLines({linesToBeIgnored}); } $test = new {className}('{methodName}'); $test->setData('{dataName}', unserialize('{data}')); $test->setDependencyInput(unserialize('{dependencyInput}')); $test->setInIsolation(true); ob_end_clean(); $test->run(); $output = ''; if (!$test->expectsOutput()) { $output = $test->output(); } ini_set('xdebug.scream', '0'); // Not every STDOUT target stream is rewindable @rewind(STDOUT); if ($stdout = @stream_get_contents(STDOUT)) { $output = $stdout . $output; $streamMetaData = stream_get_meta_data(STDOUT); if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { @ftruncate(STDOUT, 0); @rewind(STDOUT); } } file_put_contents( '{processResultFile}', serialize( [ 'testResult' => $test->result(), 'codeCoverage' => {collectCodeCoverageInformation} ? CodeCoverage::instance()->codeCoverage() : null, 'numAssertions' => $test->numberOfAssertionsPerformed(), 'output' => $output, 'events' => $dispatcher->flush(), 'passedTests' => PassedTests::instance() ] ) ); } function __phpunit_error_handler($errno, $errstr, $errfile, $errline) { return true; } set_error_handler('__phpunit_error_handler'); {constants} {included_files} {globals} restore_error_handler(); ConfigurationRegistry::loadFrom('{serializedConfiguration}'); (new PhpHandler)->handle(ConfigurationRegistry::get()->php()); if ('{bootstrap}' !== '') { require_once '{bootstrap}'; } __phpunit_run_isolated_test(); phpunit/src/Framework/TestRunner/IsolatedTestRunnerRegistry.php 0000644 00000001742 15253321353 0021136 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IsolatedTestRunnerRegistry { private static ?IsolatedTestRunner $runner = null; public static function run(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void { if (self::$runner === null) { self::$runner = new SeparateProcessTestRunner; } self::$runner->run($test, $runEntireClass, $preserveGlobalState); } public static function set(IsolatedTestRunner $runner): void { self::$runner = $runner; } } phpunit/src/Framework/TestRunner/TestRunner.php 0000644 00000024354 15253321353 0015724 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use const PHP_EOL; use function assert; use function extension_loaded; use function sprintf; use AssertionError; use PHPUnit\Event\Facade; use PHPUnit\Metadata\Api\CodeCoverage as CodeCoverageMetadataApi; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Runner\CodeCoverage; use PHPUnit\Runner\ErrorHandler; use PHPUnit\Runner\Exception; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException; use SebastianBergmann\CodeCoverage\InvalidArgumentException; use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; use SebastianBergmann\Invoker\Invoker; use SebastianBergmann\Invoker\TimeoutException; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestRunner { private ?bool $timeLimitCanBeEnforced = null; private readonly Configuration $configuration; public function __construct() { $this->configuration = ConfigurationRegistry::get(); } /** * @throws CodeCoverageException * @throws Exception * @throws InvalidArgumentException * @throws UnintentionallyCoveredCodeException */ public function run(TestCase $test): void { Assert::resetCount(); $codeCoverageMetadataApi = new CodeCoverageMetadataApi; $shouldCodeCoverageBeCollected = $codeCoverageMetadataApi->shouldCodeCoverageBeCollectedFor( $test::class, $test->name(), ); $error = false; $failure = false; $incomplete = false; $risky = false; $skipped = false; if ($this->shouldErrorHandlerBeUsed($test)) { ErrorHandler::instance()->enable(); } $collectCodeCoverage = CodeCoverage::instance()->isActive() && $shouldCodeCoverageBeCollected; if ($collectCodeCoverage) { CodeCoverage::instance()->start($test); } try { if ($this->canTimeLimitBeEnforced() && $this->shouldTimeLimitBeEnforced($test)) { $risky = $this->runTestWithTimeout($test); } else { $test->runBare(); } } catch (AssertionFailedError $e) { $failure = true; if ($e instanceof IncompleteTestError) { $incomplete = true; } elseif ($e instanceof SkippedTest) { $skipped = true; } } catch (AssertionError $e) { $test->addToAssertionCount(1); $failure = true; $frame = $e->getTrace()[0]; assert(isset($frame['file'])); assert(isset($frame['line'])); $e = new AssertionFailedError( sprintf( '%s in %s:%s', $e->getMessage(), $frame['file'], $frame['line'], ), ); } catch (Throwable $e) { $error = true; } $test->addToAssertionCount(Assert::getCount()); if ($this->configuration->reportUselessTests() && !$test->doesNotPerformAssertions() && $test->numberOfAssertionsPerformed() === 0) { $risky = true; } if (!$error && !$failure && !$incomplete && !$skipped && !$risky && $this->configuration->requireCoverageMetadata() && !$this->hasCoverageMetadata($test::class, $test->name())) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), 'This test does not define a code coverage target but is expected to do so', ); $risky = true; } if ($collectCodeCoverage) { $append = !$risky && !$incomplete && !$skipped; $linesToBeCovered = []; $linesToBeUsed = []; if ($append) { try { $linesToBeCovered = $codeCoverageMetadataApi->linesToBeCovered( $test::class, $test->name(), ); $linesToBeUsed = $codeCoverageMetadataApi->linesToBeUsed( $test::class, $test->name(), ); } catch (InvalidCoversTargetException $cce) { Facade::emitter()->testTriggeredPhpunitWarning( $test->valueObjectForEvents(), $cce->getMessage(), ); $append = false; } } try { CodeCoverage::instance()->stop( $append, $linesToBeCovered, $linesToBeUsed, ); } catch (UnintentionallyCoveredCodeException $cce) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), 'This test executed code that is not listed as code to be covered or used:' . PHP_EOL . $cce->getMessage(), ); } catch (OriginalCodeCoverageException $cce) { $error = true; $e = $e ?? $cce; } } ErrorHandler::instance()->disable(); if (!$error && !$incomplete && !$skipped && $this->configuration->reportUselessTests() && !$test->doesNotPerformAssertions() && $test->numberOfAssertionsPerformed() === 0) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), 'This test did not perform any assertions', ); } if ($test->doesNotPerformAssertions() && $test->numberOfAssertionsPerformed() > 0) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), sprintf( 'This test is not expected to perform assertions but performed %d assertion%s', $test->numberOfAssertionsPerformed(), $test->numberOfAssertionsPerformed() > 1 ? 's' : '', ), ); } if ($test->hasUnexpectedOutput()) { Facade::emitter()->testPrintedUnexpectedOutput($test->output()); } if ($this->configuration->disallowTestOutput() && $test->hasUnexpectedOutput()) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), sprintf( 'This test printed output: %s', $test->output(), ), ); } if ($test->wasPrepared()) { Facade::emitter()->testFinished( $test->valueObjectForEvents(), $test->numberOfAssertionsPerformed(), ); } } /** * @param class-string $className * @param non-empty-string $methodName */ private function hasCoverageMetadata(string $className, string $methodName): bool { foreach (MetadataRegistry::parser()->forClassAndMethod($className, $methodName) as $metadata) { if ($metadata->isCovers()) { return true; } if ($metadata->isCoversClass()) { return true; } if ($metadata->isCoversTrait()) { return true; } if ($metadata->isCoversMethod()) { return true; } if ($metadata->isCoversFunction()) { return true; } if ($metadata->isCoversNothing()) { return true; } } return false; } private function canTimeLimitBeEnforced(): bool { if ($this->timeLimitCanBeEnforced !== null) { return $this->timeLimitCanBeEnforced; } $this->timeLimitCanBeEnforced = (new Invoker)->canInvokeWithTimeout(); return $this->timeLimitCanBeEnforced; } private function shouldTimeLimitBeEnforced(TestCase $test): bool { if (!$this->configuration->enforceTimeLimit()) { return false; } if (!(($this->configuration->defaultTimeLimit() || $test->size()->isKnown()))) { return false; } if (extension_loaded('xdebug') && xdebug_is_debugger_active()) { return false; } return true; } /** * @throws Throwable */ private function runTestWithTimeout(TestCase $test): bool { $_timeout = $this->configuration->defaultTimeLimit(); $testSize = $test->size(); if ($testSize->isSmall()) { $_timeout = $this->configuration->timeoutForSmallTests(); } elseif ($testSize->isMedium()) { $_timeout = $this->configuration->timeoutForMediumTests(); } elseif ($testSize->isLarge()) { $_timeout = $this->configuration->timeoutForLargeTests(); } try { (new Invoker)->invoke([$test, 'runBare'], [], $_timeout); } catch (TimeoutException) { Facade::emitter()->testConsideredRisky( $test->valueObjectForEvents(), sprintf( 'This test was aborted after %d second%s', $_timeout, $_timeout !== 1 ? 's' : '', ), ); return true; } return false; } private function shouldErrorHandlerBeUsed(TestCase $test): bool { if (MetadataRegistry::parser()->forMethod($test::class, $test->name())->isWithoutErrorHandler()->isNotEmpty()) { return false; } return true; } } phpunit/src/Framework/TestRunner/IsolatedTestRunner.php 0000644 00000001155 15253321353 0017403 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface IsolatedTestRunner { public function run(TestCase $test, bool $runEntireClass, bool $preserveGlobalState): void; } phpunit/src/Framework/Attributes/RequiresOperatingSystem.php 0000644 00000001725 15253321353 0020502 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class RequiresOperatingSystem { /** * @var non-empty-string */ private string $regularExpression; /** * @param non-empty-string $regularExpression */ public function __construct(string $regularExpression) { $this->regularExpression = $regularExpression; } /** * @return non-empty-string */ public function regularExpression(): string { return $this->regularExpression; } } phpunit/src/Framework/Attributes/WithoutErrorHandler.php 0000644 00000001014 15253321353 0017567 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class WithoutErrorHandler { } phpunit/src/Framework/Attributes/ExcludeStaticPropertyFromBackup.php 0000644 00000002407 15253321353 0022103 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class ExcludeStaticPropertyFromBackup { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $propertyName; /** * @param class-string $className * @param non-empty-string $propertyName */ public function __construct(string $className, string $propertyName) { $this->className = $className; $this->propertyName = $propertyName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function propertyName(): string { return $this->propertyName; } } phpunit/src/Framework/Attributes/ExcludeGlobalVariableFromBackup.php 0000644 00000001777 15253321353 0021766 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class ExcludeGlobalVariableFromBackup { /** * @var non-empty-string */ private string $globalVariableName; /** * @param non-empty-string $globalVariableName */ public function __construct(string $globalVariableName) { $this->globalVariableName = $globalVariableName; } /** * @return non-empty-string */ public function globalVariableName(): string { return $this->globalVariableName; } } phpunit/src/Framework/Attributes/RequiresMethod.php 0000644 00000002346 15253321353 0016565 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class RequiresMethod { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/RequiresPhp.php 0000644 00000001720 15253321353 0016067 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class RequiresPhp { /** * @var non-empty-string */ private string $versionRequirement; /** * @param non-empty-string $versionRequirement */ public function __construct(string $versionRequirement) { $this->versionRequirement = $versionRequirement; } /** * @return non-empty-string */ public function versionRequirement(): string { return $this->versionRequirement; } } phpunit/src/Framework/Attributes/DependsOnClass.php 0000644 00000001611 15253321353 0016464 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsOnClass { /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(string $className) { $this->className = $className; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Framework/Attributes/UsesMethod.php 0000644 00000002300 15253321353 0015673 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class UsesMethod { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/UsesFunction.php 0000644 00000001647 15253321353 0016255 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class UsesFunction { /** * @var non-empty-string */ private string $functionName; /** * @param non-empty-string $functionName */ public function __construct(string $functionName) { $this->functionName = $functionName; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } } phpunit/src/Framework/Attributes/Ticket.php 0000644 00000001604 15253321353 0015044 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class Ticket { /** * @var non-empty-string */ private string $text; /** * @param non-empty-string $text */ public function __construct(string $text) { $this->text = $text; } /** * @return non-empty-string */ public function text(): string { return $this->text; } } phpunit/src/Framework/Attributes/PreCondition.php 0000644 00000001554 15253321353 0016222 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class PreCondition { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/TestWith.php 0000644 00000002203 15253321353 0015370 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class TestWith { /** * @var array<mixed> */ private array $data; /** * @var ?non-empty-string */ private ?string $name; /** * @param array<mixed> $data * @param ?non-empty-string $name */ public function __construct(array $data, ?string $name = null) { $this->data = $data; $this->name = $name; } /** * @return array<mixed> */ public function data(): array { return $this->data; } /** * @return ?non-empty-string */ public function name(): ?string { return $this->name; } } phpunit/src/Framework/Attributes/DependsUsingDeepClone.php 0000644 00000001643 15253321353 0017773 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsUsingDeepClone { /** * @var non-empty-string */ private string $methodName; /** * @param non-empty-string $methodName */ public function __construct(string $methodName) { $this->methodName = $methodName; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/DataProvider.php 0000644 00000001632 15253321353 0016206 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DataProvider { /** * @var non-empty-string */ private string $methodName; /** * @param non-empty-string $methodName */ public function __construct(string $methodName) { $this->methodName = $methodName; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/UsesClass.php 0000644 00000001603 15253321353 0015525 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class UsesClass { /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(string $className) { $this->className = $className; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Framework/Attributes/IgnorePhpunitDeprecations.php 0000644 00000001210 15253321353 0020746 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class IgnorePhpunitDeprecations { } phpunit/src/Framework/Attributes/Large.php 0000644 00000000775 15253321353 0014663 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class Large { } phpunit/src/Framework/Attributes/CoversClass.php 0000644 00000001605 15253321353 0016051 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class CoversClass { /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(string $className) { $this->className = $className; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Framework/Attributes/Group.php 0000644 00000001603 15253321353 0014714 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class Group { /** * @var non-empty-string */ private string $name; /** * @param non-empty-string $name */ public function __construct(string $name) { $this->name = $name; } /** * @return non-empty-string */ public function name(): string { return $this->name; } } phpunit/src/Framework/Attributes/Small.php 0000644 00000000775 15253321353 0014701 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class Small { } phpunit/src/Framework/Attributes/CoversNothing.php 0000644 00000001040 15253321353 0016403 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class CoversNothing { } phpunit/src/Framework/Attributes/CoversTrait.php 0000644 00000001605 15253321353 0016067 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class CoversTrait { /** * @var trait-string */ private string $traitName; /** * @param trait-string $traitName */ public function __construct(string $traitName) { $this->traitName = $traitName; } /** * @return trait-string */ public function traitName(): string { return $this->traitName; } } phpunit/src/Framework/Attributes/RequiresPhpunit.php 0000644 00000001724 15253321353 0016773 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class RequiresPhpunit { /** * @var non-empty-string */ private string $versionRequirement; /** * @param non-empty-string $versionRequirement */ public function __construct(string $versionRequirement) { $this->versionRequirement = $versionRequirement; } /** * @return non-empty-string */ public function versionRequirement(): string { return $this->versionRequirement; } } phpunit/src/Framework/Attributes/TestDox.php 0000644 00000001552 15253321353 0015215 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class TestDox { /** * @var non-empty-string */ private string $text; /** * @param non-empty-string $text */ public function __construct(string $text) { $this->text = $text; } /** * @return non-empty-string */ public function text(): string { return $this->text; } } phpunit/src/Framework/Attributes/DependsExternal.php 0000644 00000002315 15253321353 0016706 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsExternal { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/PostCondition.php 0000644 00000001555 15253321353 0016422 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class PostCondition { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/Before.php 0000644 00000001546 15253321353 0015030 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class Before { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/TestWithJson.php 0000644 00000002222 15253321353 0016223 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class TestWithJson { /** * @var non-empty-string */ private string $json; /** * @var ?non-empty-string */ private ?string $name; /** * @param non-empty-string $json * @param ?non-empty-string $name */ public function __construct(string $json, ?string $name = null) { $this->json = $json; $this->name = $name; } /** * @return non-empty-string */ public function json(): string { return $this->json; } /** * @return ?non-empty-string */ public function name(): ?string { return $this->name; } } phpunit/src/Framework/Attributes/DataProviderExternal.php 0000644 00000002322 15253321353 0017706 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DataProviderExternal { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/DisableReturnValueGenerationForTestDoubles.php 0000644 00000001042 15253321353 0024216 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class DisableReturnValueGenerationForTestDoubles { } phpunit/src/Framework/Attributes/DependsOnClassUsingDeepClone.php 0000644 00000001627 15253321353 0021260 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsOnClassUsingDeepClone { /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(string $className) { $this->className = $className; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Framework/Attributes/CoversMethod.php 0000644 00000002302 15253321353 0016217 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class CoversMethod { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/RunClassInSeparateProcess.php 0000644 00000001021 15253321353 0020657 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class RunClassInSeparateProcess { } phpunit/src/Framework/Attributes/RequiresSetting.php 0000644 00000002277 15253321353 0016765 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class RequiresSetting { /** * @var non-empty-string */ private string $setting; /** * @var non-empty-string */ private string $value; /** * @param non-empty-string $setting * @param non-empty-string $value */ public function __construct(string $setting, string $value) { $this->setting = $setting; $this->value = $value; } /** * @return non-empty-string */ public function setting(): string { return $this->setting; } /** * @return non-empty-string */ public function value(): string { return $this->value; } } phpunit/src/Framework/Attributes/RequiresFunction.php 0000644 00000001706 15253321353 0017131 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class RequiresFunction { /** * @var non-empty-string */ private string $functionName; /** * @param non-empty-string $functionName */ public function __construct(string $functionName) { $this->functionName = $functionName; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } } phpunit/src/Framework/Attributes/CoversFunction.php 0000644 00000001651 15253321353 0016572 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class CoversFunction { /** * @var non-empty-string */ private string $functionName; /** * @param non-empty-string $functionName */ public function __construct(string $functionName) { $this->functionName = $functionName; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } } phpunit/src/Framework/Attributes/BackupGlobals.php 0000644 00000001352 15253321353 0016332 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class BackupGlobals { private bool $enabled; public function __construct(bool $enabled) { $this->enabled = $enabled; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Framework/Attributes/RequiresPhpExtension.php 0000644 00000002522 15253321353 0017765 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class RequiresPhpExtension { /** * @var non-empty-string */ private string $extension; /** * @var null|non-empty-string */ private ?string $versionRequirement; /** * @param non-empty-string $extension * @param null|non-empty-string $versionRequirement */ public function __construct(string $extension, ?string $versionRequirement = null) { $this->extension = $extension; $this->versionRequirement = $versionRequirement; } /** * @return non-empty-string */ public function extension(): string { return $this->extension; } /** * @return null|non-empty-string */ public function versionRequirement(): ?string { return $this->versionRequirement; } } phpunit/src/Framework/Attributes/BackupStaticProperties.php 0000644 00000001363 15253321353 0020255 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class BackupStaticProperties { private bool $enabled; public function __construct(bool $enabled) { $this->enabled = $enabled; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Framework/Attributes/BeforeClass.php 0000644 00000001553 15253321353 0016014 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class BeforeClass { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/RunInSeparateProcess.php 0000644 00000001015 15253321353 0017674 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class RunInSeparateProcess { } phpunit/src/Framework/Attributes/AfterClass.php 0000644 00000001552 15253321353 0015652 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class AfterClass { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/Depends.php 0000644 00000001625 15253321353 0015206 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class Depends { /** * @var non-empty-string */ private string $methodName; /** * @param non-empty-string $methodName */ public function __construct(string $methodName) { $this->methodName = $methodName; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/After.php 0000644 00000001545 15253321353 0014666 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class After { /** * @var non-negative-int */ private int $priority; /** * @param non-negative-int $priority */ public function __construct(int $priority = 0) { $this->priority = $priority; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Framework/Attributes/RequiresOperatingSystemFamily.php 0000644 00000001767 15253321353 0021652 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class RequiresOperatingSystemFamily { /** * @var non-empty-string */ private string $operatingSystemFamily; /** * @param non-empty-string $operatingSystemFamily */ public function __construct(string $operatingSystemFamily) { $this->operatingSystemFamily = $operatingSystemFamily; } /** * @return non-empty-string */ public function operatingSystemFamily(): string { return $this->operatingSystemFamily; } } phpunit/src/Framework/Attributes/DependsExternalUsingDeepClone.php 0000644 00000002333 15253321353 0021473 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsExternalUsingDeepClone { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/DependsExternalUsingShallowClone.php 0000644 00000002336 15253321353 0022232 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsExternalUsingShallowClone { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/IgnoreDeprecations.php 0000644 00000001045 15253321353 0017404 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class IgnoreDeprecations { } phpunit/src/Framework/Attributes/DependsOnClassUsingShallowClone.php 0000644 00000001632 15253321353 0022010 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsOnClassUsingShallowClone { /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(string $className) { $this->className = $className; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Framework/Attributes/RunTestsInSeparateProcesses.php 0000644 00000001023 15253321353 0021246 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class RunTestsInSeparateProcesses { } phpunit/src/Framework/Attributes/Medium.php 0000644 00000000776 15253321353 0015052 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS)] final readonly class Medium { } phpunit/src/Framework/Attributes/DependsUsingShallowClone.php 0000644 00000001646 15253321353 0020532 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)] final readonly class DependsUsingShallowClone { /** * @var non-empty-string */ private string $methodName; /** * @param non-empty-string $methodName */ public function __construct(string $methodName) { $this->methodName = $methodName; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Framework/Attributes/UsesTrait.php 0000644 00000001603 15253321353 0015543 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] final readonly class UsesTrait { /** * @var trait-string */ private string $traitName; /** * @param trait-string $traitName */ public function __construct(string $traitName) { $this->traitName = $traitName; } /** * @return trait-string */ public function traitName(): string { return $this->traitName; } } phpunit/src/Framework/Attributes/DoesNotPerformAssertions.php 0000644 00000001053 15253321353 0020600 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class DoesNotPerformAssertions { } phpunit/src/Framework/Attributes/PreserveGlobalState.php 0000644 00000001360 15253321353 0017535 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] final readonly class PreserveGlobalState { private bool $enabled; public function __construct(bool $enabled) { $this->enabled = $enabled; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Framework/Attributes/Test.php 0000644 00000000775 15253321353 0014550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Attributes; use Attribute; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ #[Attribute(Attribute::TARGET_METHOD)] final readonly class Test { } phpunit/src/Framework/TestCase.php 0000644 00000241412 15253321353 0013211 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use const LC_ALL; use const LC_COLLATE; use const LC_CTYPE; use const LC_MONETARY; use const LC_NUMERIC; use const LC_TIME; use const PATHINFO_FILENAME; use const PHP_EOL; use const PHP_URL_PATH; use function array_keys; use function array_merge; use function array_reverse; use function array_values; use function assert; use function basename; use function chdir; use function class_exists; use function clearstatcache; use function count; use function defined; use function error_clear_last; use function explode; use function getcwd; use function implode; use function in_array; use function ini_set; use function is_array; use function is_callable; use function is_int; use function is_object; use function is_string; use function libxml_clear_errors; use function method_exists; use function ob_end_clean; use function ob_get_clean; use function ob_get_contents; use function ob_get_level; use function ob_start; use function parse_url; use function pathinfo; use function preg_match; use function preg_replace; use function restore_error_handler; use function restore_exception_handler; use function set_error_handler; use function set_exception_handler; use function setlocale; use function sprintf; use function str_contains; use function trim; use AssertionError; use DeepCopy\DeepCopy; use PHPUnit\Event; use PHPUnit\Event\NoPreviousThrowableException; use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint; use PHPUnit\Framework\Constraint\ExceptionCode; use PHPUnit\Framework\Constraint\ExceptionMessageIsOrContains; use PHPUnit\Framework\Constraint\ExceptionMessageMatchesRegularExpression; use PHPUnit\Framework\MockObject\Exception as MockObjectException; use PHPUnit\Framework\MockObject\Generator\Generator as MockGenerator; use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\MockObjectInternal; use PHPUnit\Framework\MockObject\Rule\AnyInvokedCount as AnyInvokedCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastCount as InvokedAtLeastCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedAtMostCount as InvokedAtMostCountMatcher; use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher; use PHPUnit\Framework\MockObject\Stub; use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; use PHPUnit\Framework\MockObject\Stub\ReturnStub; use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; use PHPUnit\Framework\TestSize\TestSize; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\Metadata\Api\Groups; use PHPUnit\Metadata\Api\HookMethods; use PHPUnit\Metadata\Api\Requirements; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Runner\DeprecationCollector\Facade as DeprecationCollector; use PHPUnit\Runner\HookMethodCollection; use PHPUnit\TestRunner\TestResult\PassedTests; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use PHPUnit\Util\Exporter; use PHPUnit\Util\Test as TestUtil; use ReflectionClass; use ReflectionException; use ReflectionObject; use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Comparator\Factory as ComparatorFactory; use SebastianBergmann\Diff\Differ; use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder; use SebastianBergmann\GlobalState\ExcludeList as GlobalStateExcludeList; use SebastianBergmann\GlobalState\Restorer; use SebastianBergmann\GlobalState\Snapshot; use SebastianBergmann\Invoker\TimeoutException; use SebastianBergmann\ObjectEnumerator\Enumerator; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, Test { private const LOCALE_CATEGORIES = [LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME]; private ?bool $backupGlobals = null; /** * @var list<string> */ private array $backupGlobalsExcludeList = []; private ?bool $backupStaticProperties = null; /** * @var array<string,list<class-string>> */ private array $backupStaticPropertiesExcludeList = []; private ?Snapshot $snapshot = null; /** * @var list<callable> */ private ?array $backupGlobalErrorHandlers = null; /** * @var list<callable> */ private ?array $backupGlobalExceptionHandlers = null; private ?bool $runClassInSeparateProcess = null; private ?bool $runTestInSeparateProcess = null; private bool $preserveGlobalState = false; private bool $inIsolation = false; private ?string $expectedException = null; private ?string $expectedExceptionMessage = null; private ?string $expectedExceptionMessageRegExp = null; private null|int|string $expectedExceptionCode = null; /** * @var list<ExecutionOrderDependency> */ private array $providedTests = []; /** * @var array<mixed> */ private array $data = []; private int|string $dataName = ''; /** * @var non-empty-string */ private string $methodName; /** * @var list<string> */ private array $groups = []; /** * @var list<ExecutionOrderDependency> */ private array $dependencies = []; /** * @var array<non-empty-string, array<mixed>> */ private array $dependencyInput = []; /** * @var array<string,string> */ private array $iniSettings = []; /** * @var array<int, non-empty-string> */ private array $locale = []; /** * @var list<MockObjectInternal> */ private array $mockObjects = []; private TestStatus $status; private int $numberOfAssertionsPerformed = 0; private mixed $testResult = null; private string $output = ''; private ?string $outputExpectedRegex = null; private ?string $outputExpectedString = null; private bool $outputBufferingActive = false; private int $outputBufferingLevel; private bool $outputRetrievedForAssertion = false; private bool $doesNotPerformAssertions = false; /** * @var list<Comparator> */ private array $customComparators = []; private ?Event\Code\TestMethod $testValueObjectForEvents = null; private bool $wasPrepared = false; /** * @var array<class-string, true> */ private array $failureTypes = []; /** * @var list<non-empty-string> */ private array $expectedUserDeprecationMessage = []; /** * @var list<non-empty-string> */ private array $expectedUserDeprecationMessageRegularExpression = []; /** * @param non-empty-string $name * * @internal This method is not covered by the backward compatibility promise for PHPUnit * * @final */ public function __construct(string $name) { $this->methodName = $name; $this->status = TestStatus::unknown(); if (is_callable($this->sortId(), true)) { $this->providedTests = [new ExecutionOrderDependency($this->sortId())]; } } /** * This method is called before the first test of this test class is run. * * @codeCoverageIgnore */ public static function setUpBeforeClass(): void { } /** * This method is called after the last test of this test class is run. * * @codeCoverageIgnore */ public static function tearDownAfterClass(): void { } /** * This method is called before each test. * * @codeCoverageIgnore */ protected function setUp(): void { } /** * Performs assertions shared by all tests of a test case. * * This method is called between setUp() and test. * * @codeCoverageIgnore */ protected function assertPreConditions(): void { } /** * Performs assertions shared by all tests of a test case. * * This method is called between test and tearDown(). * * @codeCoverageIgnore */ protected function assertPostConditions(): void { } /** * This method is called after each test. * * @codeCoverageIgnore */ protected function tearDown(): void { } /** * Returns a string representation of the test case. * * @throws Exception * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function toString(): string { $buffer = sprintf( '%s::%s', (new ReflectionClass($this))->getName(), $this->methodName, ); return $buffer . $this->dataSetAsStringWithData(); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function count(): int { return 1; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function status(): TestStatus { return $this->status; } /** * @throws \PHPUnit\Runner\Exception * @throws \PHPUnit\Util\Exception * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException * @throws \SebastianBergmann\Template\InvalidArgumentException * @throws CodeCoverageException * @throws Exception * @throws NoPreviousThrowableException * @throws ProcessIsolationException * @throws StaticAnalysisCacheNotConfiguredException * @throws UnintentionallyCoveredCodeException * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function run(): void { if (!$this->handleDependencies()) { return; } if (!$this->shouldRunInSeparateProcess()) { (new TestRunner)->run($this); return; } IsolatedTestRunnerRegistry::run( $this, $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess, $this->preserveGlobalState, ); } /** * @return list<string> * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function groups(): array { return $this->groups; } /** * @param list<string> $groups * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setGroups(array $groups): void { $this->groups = $groups; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function nameWithDataSet(): string { return $this->methodName . $this->dataSetAsString(); } /** * @return non-empty-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function name(): string { return $this->methodName; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function size(): TestSize { return (new Groups)->size( static::class, $this->methodName, ); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function hasUnexpectedOutput(): bool { if ($this->output === '') { return false; } if ($this->expectsOutput()) { return false; } return true; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function output(): string { if (!$this->outputBufferingActive) { return $this->output; } return (string) ob_get_contents(); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function doesNotPerformAssertions(): bool { return $this->doesNotPerformAssertions; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function expectsOutput(): bool { return $this->hasExpectationOnOutput() || $this->outputRetrievedForAssertion; } /** * @throws Throwable * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function runBare(): void { $emitter = Event\Facade::emitter(); error_clear_last(); clearstatcache(); $emitter->testPreparationStarted( $this->valueObjectForEvents(), ); $this->snapshotGlobalState(); $this->snapshotGlobalErrorExceptionHandlers(); $this->startOutputBuffering(); $hookMethods = (new HookMethods)->hookMethods(static::class); $hasMetRequirements = false; $this->numberOfAssertionsPerformed = 0; $currentWorkingDirectory = getcwd(); try { $this->checkRequirements(); $hasMetRequirements = true; if ($this->inIsolation) { // @codeCoverageIgnoreStart $this->invokeBeforeClassHookMethods($hookMethods, $emitter); // @codeCoverageIgnoreEnd } if (method_exists(static::class, $this->methodName) && MetadataRegistry::parser()->forClassAndMethod(static::class, $this->methodName)->isDoesNotPerformAssertions()->isNotEmpty()) { $this->doesNotPerformAssertions = true; } $this->invokeBeforeTestHookMethods($hookMethods, $emitter); $this->invokePreConditionHookMethods($hookMethods, $emitter); $emitter->testPrepared( $this->valueObjectForEvents(), ); $this->wasPrepared = true; $this->testResult = $this->runTest(); $this->verifyDeprecationExpectations(); $this->verifyMockObjects(); $this->invokePostConditionHookMethods($hookMethods, $emitter); $this->status = TestStatus::success(); } catch (IncompleteTest $e) { $this->status = TestStatus::incomplete($e->getMessage()); $emitter->testMarkedAsIncomplete( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($e), ); } catch (SkippedTest $e) { $this->status = TestStatus::skipped($e->getMessage()); $emitter->testSkipped( $this->valueObjectForEvents(), $e->getMessage(), ); } catch (AssertionError|AssertionFailedError $e) { if (!$this->wasPrepared) { $this->wasPrepared = true; $emitter->testPreparationFailed( $this->valueObjectForEvents(), ); } $this->status = TestStatus::failure($e->getMessage()); $emitter->testFailed( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($e), Event\Code\ComparisonFailureBuilder::from($e), ); } catch (TimeoutException $e) { $this->status = TestStatus::risky($e->getMessage()); } catch (Throwable $_e) { if ($this->isRegisteredFailure($_e)) { $this->status = TestStatus::failure($_e->getMessage()); $emitter->testFailed( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($_e), null, ); } else { $e = $this->transformException($_e); $this->status = TestStatus::error($e->getMessage()); $emitter->testErrored( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($e), ); } } $outputBufferingStopped = false; if (!isset($e) && $this->hasExpectationOnOutput() && $this->stopOutputBuffering()) { $outputBufferingStopped = true; $this->performAssertionsOnOutput(); } if ($this->status->isSuccess()) { $emitter->testPassed( $this->valueObjectForEvents(), ); if (!$this->usesDataProvider()) { PassedTests::instance()->testMethodPassed( $this->valueObjectForEvents(), $this->testResult, ); } } try { $this->mockObjects = []; /** @phpstan-ignore catch.neverThrown */ } catch (Throwable $t) { Event\Facade::emitter()->testErrored( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($t), ); } // Tear down the fixture. An exception raised in tearDown() will be // caught and passed on when no exception was raised before. try { if ($hasMetRequirements) { $this->invokeAfterTestHookMethods($hookMethods, $emitter); if ($this->inIsolation) { // @codeCoverageIgnoreStart $this->invokeAfterClassHookMethods($hookMethods, $emitter); // @codeCoverageIgnoreEnd } } } catch (AssertionError|AssertionFailedError $e) { $this->status = TestStatus::failure($e->getMessage()); $emitter->testFailed( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($e), Event\Code\ComparisonFailureBuilder::from($e), ); } catch (Throwable $exceptionRaisedDuringTearDown) { if (!isset($e)) { $this->status = TestStatus::error($exceptionRaisedDuringTearDown->getMessage()); $e = $exceptionRaisedDuringTearDown; $emitter->testErrored( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($exceptionRaisedDuringTearDown), ); } } if (!$outputBufferingStopped) { $this->stopOutputBuffering(); } clearstatcache(); if ($currentWorkingDirectory !== getcwd()) { chdir($currentWorkingDirectory); } $this->restoreGlobalErrorExceptionHandlers(); $this->restoreGlobalState(); $this->unregisterCustomComparators(); $this->cleanupIniSettings(); $this->cleanupLocaleSettings(); libxml_clear_errors(); $this->testValueObjectForEvents = null; if (isset($e)) { $this->onNotSuccessfulTest($e); } } /** * @param list<ExecutionOrderDependency> $dependencies * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setDependencies(array $dependencies): void { $this->dependencies = $dependencies; } /** * @param array<non-empty-string, array<mixed>> $dependencyInput * * @internal This method is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final public function setDependencyInput(array $dependencyInput): void { $this->dependencyInput = $dependencyInput; } /** * @return array<non-empty-string, array<mixed>> * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function dependencyInput(): array { return $this->dependencyInput; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function hasDependencyInput(): bool { return !empty($this->dependencyInput); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setBackupGlobals(bool $backupGlobals): void { $this->backupGlobals = $backupGlobals; } /** * @param list<string> $backupGlobalsExcludeList * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setBackupGlobalsExcludeList(array $backupGlobalsExcludeList): void { $this->backupGlobalsExcludeList = $backupGlobalsExcludeList; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setBackupStaticProperties(bool $backupStaticProperties): void { $this->backupStaticProperties = $backupStaticProperties; } /** * @param array<string,list<class-string>> $backupStaticPropertiesExcludeList * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setBackupStaticPropertiesExcludeList(array $backupStaticPropertiesExcludeList): void { $this->backupStaticPropertiesExcludeList = $backupStaticPropertiesExcludeList; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void { if ($this->runTestInSeparateProcess === null) { $this->runTestInSeparateProcess = $runTestInSeparateProcess; } } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void { $this->runClassInSeparateProcess = $runClassInSeparateProcess; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setPreserveGlobalState(bool $preserveGlobalState): void { $this->preserveGlobalState = $preserveGlobalState; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final public function setInIsolation(bool $inIsolation): void { $this->inIsolation = $inIsolation; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final public function result(): mixed { return $this->testResult; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setResult(mixed $result): void { $this->testResult = $result; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function registerMockObject(MockObject $mockObject): void { assert($mockObject instanceof MockObjectInternal); $this->mockObjects[] = $mockObject; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function addToAssertionCount(int $count): void { $this->numberOfAssertionsPerformed += $count; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function numberOfAssertionsPerformed(): int { return $this->numberOfAssertionsPerformed; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function usesDataProvider(): bool { return !empty($this->data); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function dataName(): int|string { return $this->dataName; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function dataSetAsString(): string { $buffer = ''; if (!empty($this->data)) { if (is_int($this->dataName)) { $buffer .= sprintf(' with data set #%d', $this->dataName); } else { $buffer .= sprintf(' with data set "%s"', $this->dataName); } } return $buffer; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function dataSetAsStringWithData(): string { if (empty($this->data)) { return ''; } return $this->dataSetAsString() . sprintf( ' (%s)', Exporter::shortenedRecursiveExport($this->data), ); } /** * @return array<mixed> * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function providedData(): array { return $this->data; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function sortId(): string { $id = $this->methodName; if (!str_contains($id, '::')) { $id = static::class . '::' . $id; } if ($this->usesDataProvider()) { $id .= $this->dataSetAsString(); } return $id; } /** * @return list<ExecutionOrderDependency> * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function provides(): array { return $this->providedTests; } /** * @return list<ExecutionOrderDependency> * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function requires(): array { return $this->dependencies; } /** * @param array<mixed> $data * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function setData(int|string $dataName, array $data): void { $this->dataName = $dataName; $this->data = $data; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function valueObjectForEvents(): Event\Code\TestMethod { if ($this->testValueObjectForEvents !== null) { return $this->testValueObjectForEvents; } $this->testValueObjectForEvents = Event\Code\TestMethodBuilder::fromTestCase($this); return $this->testValueObjectForEvents; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final public function wasPrepared(): bool { return $this->wasPrepared; } /** * Returns a matcher that matches when the method is executed * zero or more times. */ final protected function any(): AnyInvokedCountMatcher { return new AnyInvokedCountMatcher; } /** * Returns a matcher that matches when the method is never executed. */ final protected function never(): InvokedCountMatcher { return new InvokedCountMatcher(0); } /** * Returns a matcher that matches when the method is executed * at least N times. */ final protected function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher { return new InvokedAtLeastCountMatcher( $requiredInvocations, ); } /** * Returns a matcher that matches when the method is executed at least once. */ final protected function atLeastOnce(): InvokedAtLeastOnceMatcher { return new InvokedAtLeastOnceMatcher; } /** * Returns a matcher that matches when the method is executed exactly once. */ final protected function once(): InvokedCountMatcher { return new InvokedCountMatcher(1); } /** * Returns a matcher that matches when the method is executed * exactly $count times. */ final protected function exactly(int $count): InvokedCountMatcher { return new InvokedCountMatcher($count); } /** * Returns a matcher that matches when the method is executed * at most N times. */ final protected function atMost(int $allowedInvocations): InvokedAtMostCountMatcher { return new InvokedAtMostCountMatcher($allowedInvocations); } /** * @deprecated Use <code>$double->willReturn()</code> instead of <code>$double->will($this->returnValue())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * * @codeCoverageIgnore */ final protected function returnValue(mixed $value): ReturnStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'returnValue() is deprecated and will be removed in PHPUnit 12. Use $double->willReturn() instead of $double->will($this->returnValue())', ); return new ReturnStub($value); } /** * @param array<mixed> $valueMap * * @deprecated Use <code>$double->willReturnMap()</code> instead of <code>$double->will($this->returnValueMap())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * * @codeCoverageIgnore */ final protected function returnValueMap(array $valueMap): ReturnValueMapStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'returnValueMap() is deprecated and will be removed in PHPUnit 12. Use $double->willReturnMap() instead of $double->will($this->returnValueMap())', ); return new ReturnValueMapStub($valueMap); } /** * @deprecated Use <code>$double->willReturnArgument()</code> instead of <code>$double->will($this->returnArgument())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * * @codeCoverageIgnore */ final protected function returnArgument(int $argumentIndex): ReturnArgumentStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'returnArgument() is deprecated and will be removed in PHPUnit 12. Use $double->willReturnArgument() instead of $double->will($this->returnArgument())', ); return new ReturnArgumentStub($argumentIndex); } /** * @deprecated Use <code>$double->willReturnCallback()</code> instead of <code>$double->will($this->returnCallback())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * * @codeCoverageIgnore */ final protected function returnCallback(callable $callback): ReturnCallbackStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'returnCallback() is deprecated and will be removed in PHPUnit 12. Use $double->willReturnCallback() instead of $double->will($this->returnCallback())', ); return new ReturnCallbackStub($callback); } /** * @deprecated Use <code>$double->willReturnSelf()</code> instead of <code>$double->will($this->returnSelf())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * * @codeCoverageIgnore */ final protected function returnSelf(): ReturnSelfStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'returnSelf() is deprecated and will be removed in PHPUnit 12. Use $double->willReturnSelf() instead of $double->will($this->returnSelf())', ); return new ReturnSelfStub; } final protected function throwException(Throwable $exception): ExceptionStub { return new ExceptionStub($exception); } /** * @deprecated Use <code>$double->willReturn()</code> instead of <code>$double->will($this->onConsecutiveCalls())</code> * @see https://github.com/sebastianbergmann/phpunit/issues/5423 * @see https://github.com/sebastianbergmann/phpunit/issues/5425 * * @codeCoverageIgnore */ final protected function onConsecutiveCalls(mixed ...$arguments): ConsecutiveCallsStub { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'onConsecutiveCalls() is deprecated and will be removed in PHPUnit 12. Use $double->willReturn() instead of $double->will($this->onConsecutiveCalls())', ); return new ConsecutiveCallsStub($arguments); } final protected function getActualOutputForAssertion(): string { $this->outputRetrievedForAssertion = true; return $this->output(); } final protected function expectOutputRegex(string $expectedRegex): void { $this->outputExpectedRegex = $expectedRegex; } final protected function expectOutputString(string $expectedString): void { $this->outputExpectedString = $expectedString; } /** * @param class-string<Throwable> $exception */ final protected function expectException(string $exception): void { $this->expectedException = $exception; } final protected function expectExceptionCode(int|string $code): void { $this->expectedExceptionCode = $code; } final protected function expectExceptionMessage(string $message): void { $this->expectedExceptionMessage = $message; } final protected function expectExceptionMessageMatches(string $regularExpression): void { $this->expectedExceptionMessageRegExp = $regularExpression; } /** * Sets up an expectation for an exception to be raised by the code under test. * Information for expected exception class, expected exception message, and * expected exception code are retrieved from a given Exception object. */ final protected function expectExceptionObject(\Exception $exception): void { $this->expectException($exception::class); $this->expectExceptionMessage($exception->getMessage()); $this->expectExceptionCode($exception->getCode()); } final protected function expectNotToPerformAssertions(): void { $this->doesNotPerformAssertions = true; } /** * @param non-empty-string $expectedUserDeprecationMessage */ final protected function expectUserDeprecationMessage(string $expectedUserDeprecationMessage): void { $this->expectedUserDeprecationMessage[] = $expectedUserDeprecationMessage; } /** * @param non-empty-string $expectedUserDeprecationMessageRegularExpression */ final protected function expectUserDeprecationMessageMatches(string $expectedUserDeprecationMessageRegularExpression): void { $this->expectedUserDeprecationMessageRegularExpression[] = $expectedUserDeprecationMessageRegularExpression; } /** * Returns a builder object to create mock objects using a fluent interface. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $className * * @return MockBuilder<RealInstanceType> */ final protected function getMockBuilder(string $className): MockBuilder { return new MockBuilder($this, $className); } final protected function registerComparator(Comparator $comparator): void { ComparatorFactory::getInstance()->register($comparator); Event\Facade::emitter()->testRegisteredComparator($comparator::class); $this->customComparators[] = $comparator; } /** * @param class-string $classOrInterface */ final protected function registerFailureType(string $classOrInterface): void { $this->failureTypes[$classOrInterface] = true; } /** * @throws AssertionFailedError * @throws Exception * @throws ExpectationFailedException * @throws Throwable * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ final protected function runTest(): mixed { $testArguments = array_merge($this->data, array_values($this->dependencyInput)); try { $testResult = $this->{$this->methodName}(...$testArguments); } catch (Throwable $exception) { if (!$this->shouldExceptionExpectationsBeVerified($exception)) { throw $exception; } $this->verifyExceptionExpectations($exception); return null; } $this->expectedExceptionWasNotRaised(); return $testResult; } /** * This method is a wrapper for the ini_set() function that automatically * resets the modified php.ini setting to its original value after the * test is run. * * @throws Exception * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5214 * * @codeCoverageIgnore */ final protected function iniSet(string $varName, string $newValue): void { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'iniSet() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $currentValue = ini_set($varName, $newValue); if ($currentValue !== false) { $this->iniSettings[$varName] = $currentValue; } else { throw new Exception( sprintf( 'INI setting "%s" could not be set to "%s".', $varName, $newValue, ), ); } } /** * This method is a wrapper for the setlocale() function that automatically * resets the locale to its original value after the test is run. * * @throws Exception * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5216 * * @codeCoverageIgnore */ final protected function setLocale(mixed ...$arguments): void { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'setLocale() is deprecated and will be removed in PHPUnit 12 without replacement.', ); if (count($arguments) < 2) { throw new Exception; } [$category, $locale] = $arguments; if (!in_array($category, self::LOCALE_CATEGORIES, true)) { throw new Exception; } if (!is_array($locale) && !is_string($locale)) { throw new Exception; } $this->locale[$category] = setlocale($category, '0'); $result = setlocale(...$arguments); if ($result === false) { throw new Exception( 'The locale functionality is not implemented on your platform, ' . 'the specified locale does not exist or the category name is ' . 'invalid.', ); } } /** * Creates a mock object for the specified interface or class. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * * @throws InvalidArgumentException * @throws MockObjectException * @throws NoPreviousThrowableException * * @return MockObject&RealInstanceType */ final protected function createMock(string $originalClassName): MockObject { $mock = (new MockGenerator)->testDouble( $originalClassName, true, true, callOriginalConstructor: false, callOriginalClone: false, cloneArguments: false, allowMockingUnknownTypes: false, returnValueGeneration: self::generateReturnValuesForTestDoubles(), ); assert($mock instanceof $originalClassName); assert($mock instanceof MockObject); $this->registerMockObject($mock); Event\Facade::emitter()->testCreatedMockObject($originalClassName); return $mock; } /** * @param list<class-string> $interfaces * * @throws MockObjectException */ final protected function createMockForIntersectionOfInterfaces(array $interfaces): MockObject { $mock = (new MockGenerator)->testDoubleForInterfaceIntersection( $interfaces, true, returnValueGeneration: self::generateReturnValuesForTestDoubles(), ); assert($mock instanceof MockObject); $this->registerMockObject($mock); Event\Facade::emitter()->testCreatedMockObjectForIntersectionOfInterfaces($interfaces); return $mock; } /** * Creates (and configures) a mock object for the specified interface or class. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * @param array<non-empty-string, mixed> $configuration * * @throws InvalidArgumentException * @throws MockObjectException * @throws NoPreviousThrowableException * * @return MockObject&RealInstanceType */ final protected function createConfiguredMock(string $originalClassName, array $configuration): MockObject { $o = $this->createMock($originalClassName); foreach ($configuration as $method => $return) { $o->method($method)->willReturn($return); } return $o; } /** * Creates a partial mock object for the specified interface or class. * * @param class-string<RealInstanceType> $originalClassName * @param list<non-empty-string> $methods * * @template RealInstanceType of object * * @throws InvalidArgumentException * @throws MockObjectException * * @return MockObject&RealInstanceType */ final protected function createPartialMock(string $originalClassName, array $methods): MockObject { $mockBuilder = $this->getMockBuilder($originalClassName) ->disableOriginalConstructor() ->disableOriginalClone() ->disableArgumentCloning() ->disallowMockingUnknownTypes() ->onlyMethods($methods); if (!self::generateReturnValuesForTestDoubles()) { $mockBuilder->disableAutoReturnValueGeneration(); } $partialMock = $mockBuilder->getMock(); Event\Facade::emitter()->testCreatedPartialMockObject( $originalClassName, ...$methods, ); return $partialMock; } /** * Creates a test proxy for the specified class. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * @param array<mixed> $constructorArguments * * @throws InvalidArgumentException * @throws MockObjectException * * @return MockObject&RealInstanceType * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5240 */ final protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'createTestProxy() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $testProxy = $this->getMockBuilder($originalClassName) ->setConstructorArgs($constructorArguments) ->enableProxyingToOriginalMethods() ->getMock(); Event\Facade::emitter()->testCreatedTestProxy( $originalClassName, $constructorArguments, ); return $testProxy; } /** * Creates a mock object for the specified abstract class with all abstract * methods of the class mocked. Concrete methods are not mocked by default. * To mock concrete methods, use the 7th parameter ($mockedMethods). * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * @param array<mixed> $arguments * @param list<non-empty-string> $mockedMethods * * @throws InvalidArgumentException * @throws MockObjectException * * @return MockObject&RealInstanceType * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5241 */ final protected function getMockForAbstractClass(string $originalClassName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'getMockForAbstractClass() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $mockObject = (new MockGenerator)->mockObjectForAbstractClass( $originalClassName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments, ); $this->registerMockObject($mockObject); Event\Facade::emitter()->testCreatedMockObjectForAbstractClass($originalClassName); assert($mockObject instanceof $originalClassName); assert($mockObject instanceof MockObject); return $mockObject; } /** * Creates a mock object based on the given WSDL file. * * @param list<string> $methods * @param list<mixed> $options * * @throws MockObjectException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5242 */ final protected function getMockFromWsdl(string $wsdlFile, string $originalClassName = '', string $mockClassName = '', array $methods = [], bool $callOriginalConstructor = true, array $options = []): MockObject { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'getMockFromWsdl() is deprecated and will be removed in PHPUnit 12 without replacement.', ); if ($originalClassName === '') { $fileName = pathinfo(basename(parse_url($wsdlFile, PHP_URL_PATH)), PATHINFO_FILENAME); $originalClassName = preg_replace('/\W/', '', $fileName); } if (!class_exists($originalClassName)) { eval( (new MockGenerator)->generateClassFromWsdl( $wsdlFile, $originalClassName, $methods, $options, ) ); } $mockObject = (new MockGenerator)->testDouble( $originalClassName, true, true, $methods, ['', $options], $mockClassName, $callOriginalConstructor, false, false, ); Event\Facade::emitter()->testCreatedMockObjectFromWsdl( $wsdlFile, $originalClassName, $mockClassName, $methods, $callOriginalConstructor, $options, ); assert($mockObject instanceof MockObject); $this->registerMockObject($mockObject); return $mockObject; } /** * Creates a mock object for the specified trait with all abstract methods * of the trait mocked. Concrete methods to mock can be specified with the * `$mockedMethods` parameter. * * @param trait-string $traitName * @param array<mixed> $arguments * @param list<non-empty-string> $mockedMethods * * @throws InvalidArgumentException * @throws MockObjectException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5243 */ final protected function getMockForTrait(string $traitName, array $arguments = [], string $mockClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true, array $mockedMethods = [], bool $cloneArguments = false): MockObject { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'getMockForTrait() is deprecated and will be removed in PHPUnit 12 without replacement.', ); $mockObject = (new MockGenerator)->mockObjectForTrait( $traitName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments, ); $this->registerMockObject($mockObject); Event\Facade::emitter()->testCreatedMockObjectForTrait($traitName); return $mockObject; } /** * Creates an object that uses the specified trait. * * @param trait-string $traitName * @param array<mixed> $arguments * * @throws MockObjectException * * @deprecated https://github.com/sebastianbergmann/phpunit/issues/5244 */ final protected function getObjectForTrait(string $traitName, array $arguments = [], string $traitClassName = '', bool $callOriginalConstructor = true, bool $callOriginalClone = true, bool $callAutoload = true): object { Event\Facade::emitter()->testTriggeredPhpunitDeprecation( $this->valueObjectForEvents(), 'getObjectForTrait() is deprecated and will be removed in PHPUnit 12 without replacement.', ); return (new MockGenerator)->objectForTrait( $traitName, $traitClassName, $callAutoload, $callOriginalConstructor, $arguments, ); } protected function transformException(Throwable $t): Throwable { return $t; } /** * This method is called when a test method did not execute successfully. * * @throws Throwable */ protected function onNotSuccessfulTest(Throwable $t): never { throw $t; } /** * @throws ExpectationFailedException */ private function verifyDeprecationExpectations(): void { foreach ($this->expectedUserDeprecationMessage as $deprecationExpectation) { $this->numberOfAssertionsPerformed++; if (!in_array($deprecationExpectation, DeprecationCollector::deprecations(), true)) { throw new ExpectationFailedException( sprintf( 'Expected deprecation with message "%s" was not triggered', $deprecationExpectation, ), ); } } foreach ($this->expectedUserDeprecationMessageRegularExpression as $deprecationExpectation) { $this->numberOfAssertionsPerformed++; $expectedDeprecationTriggered = false; foreach (DeprecationCollector::deprecations() as $deprecation) { if (@preg_match($deprecationExpectation, $deprecation) > 0) { $expectedDeprecationTriggered = true; break; } } if (!$expectedDeprecationTriggered) { throw new ExpectationFailedException( sprintf( 'Expected deprecation with message matching regular expression "%s" was not triggered', $deprecationExpectation, ), ); } } } /** * @throws Throwable */ private function verifyMockObjects(): void { foreach ($this->mockObjects as $mockObject) { if ($mockObject->__phpunit_hasMatchers()) { $this->numberOfAssertionsPerformed++; } $mockObject->__phpunit_verify( $this->shouldInvocationMockerBeReset($mockObject), ); } } /** * @throws SkippedTest */ private function checkRequirements(): void { if (!$this->methodName || !method_exists($this, $this->methodName)) { return; } $missingRequirements = (new Requirements)->requirementsNotSatisfiedFor( static::class, $this->methodName, ); if (!empty($missingRequirements)) { $this->markTestSkipped(implode(PHP_EOL, $missingRequirements)); } } private function handleDependencies(): bool { if ([] === $this->dependencies || $this->inIsolation) { return true; } $passedTests = PassedTests::instance(); foreach ($this->dependencies as $dependency) { if (!$dependency->isValid()) { $this->markErrorForInvalidDependency(); return false; } if ($dependency->targetIsClass()) { $dependencyClassName = $dependency->getTargetClassName(); if (!class_exists($dependencyClassName)) { $this->markErrorForInvalidDependency($dependency); return false; } if (!$passedTests->hasTestClassPassed($dependencyClassName)) { $this->markSkippedForMissingDependency($dependency); return false; } continue; } $dependencyTarget = $dependency->getTarget(); if (!$passedTests->hasTestMethodPassed($dependencyTarget)) { if (!$this->isCallableTestMethod($dependencyTarget)) { $this->markErrorForInvalidDependency($dependency); } else { $this->markSkippedForMissingDependency($dependency); } return false; } if ($passedTests->isGreaterThan($dependencyTarget, $this->size())) { Event\Facade::emitter()->testConsideredRisky( $this->valueObjectForEvents(), 'This test depends on a test that is larger than itself', ); return false; } $returnValue = $passedTests->returnValue($dependencyTarget); if ($dependency->deepClone()) { $deepCopy = new DeepCopy; $deepCopy->skipUncloneable(false); $this->dependencyInput[$dependencyTarget] = $deepCopy->copy($returnValue); } elseif ($dependency->shallowClone()) { $this->dependencyInput[$dependencyTarget] = clone $returnValue; } else { $this->dependencyInput[$dependencyTarget] = $returnValue; } } $this->testValueObjectForEvents = null; return true; } /** * @throws Exception * @throws NoPreviousThrowableException */ private function markErrorForInvalidDependency(?ExecutionOrderDependency $dependency = null): void { $message = 'This test has an invalid dependency'; if ($dependency !== null) { $message = sprintf( 'This test depends on "%s" which does not exist', $dependency->targetIsClass() ? $dependency->getTargetClassName() : $dependency->getTarget(), ); } $exception = new InvalidDependencyException($message); Event\Facade::emitter()->testErrored( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($exception), ); $this->status = TestStatus::error($message); } private function markSkippedForMissingDependency(ExecutionOrderDependency $dependency): void { $message = sprintf( 'This test depends on "%s" to pass', $dependency->getTarget(), ); Event\Facade::emitter()->testSkipped( $this->valueObjectForEvents(), $message, ); $this->status = TestStatus::skipped($message); } private function startOutputBuffering(): void { ob_start(); $this->outputBufferingActive = true; $this->outputBufferingLevel = ob_get_level(); } private function stopOutputBuffering(): bool { $bufferingLevel = ob_get_level(); if ($bufferingLevel !== $this->outputBufferingLevel) { if ($bufferingLevel > $this->outputBufferingLevel) { $message = 'Test code or tested code did not close its own output buffers'; } else { $message = 'Test code or tested code closed output buffers other than its own'; } while (ob_get_level() >= $this->outputBufferingLevel) { ob_end_clean(); } Event\Facade::emitter()->testConsideredRisky( $this->valueObjectForEvents(), $message, ); $this->status = TestStatus::risky($message); return false; } $this->output = ob_get_clean(); $this->outputBufferingActive = false; $this->outputBufferingLevel = ob_get_level(); return true; } private function snapshotGlobalErrorExceptionHandlers(): void { $this->backupGlobalErrorHandlers = $this->getActiveErrorHandlers(); $this->backupGlobalExceptionHandlers = $this->getActiveExceptionHandlers(); } private function restoreGlobalErrorExceptionHandlers(): void { $activeErrorHandlers = $this->getActiveErrorHandlers(); $activeExceptionHandlers = $this->getActiveExceptionHandlers(); $message = null; if ($activeErrorHandlers !== $this->backupGlobalErrorHandlers) { if (count($activeErrorHandlers) > count($this->backupGlobalErrorHandlers)) { if (!$this->inIsolation) { $message = 'Test code or tested code did not remove its own error handlers'; } } else { $message = 'Test code or tested code removed error handlers other than its own'; } foreach ($activeErrorHandlers as $handler) { restore_error_handler(); } foreach ($this->backupGlobalErrorHandlers as $handler) { set_error_handler($handler); } } if ($message !== null) { Event\Facade::emitter()->testConsideredRisky( $this->valueObjectForEvents(), $message, ); $this->status = TestStatus::risky($message); } $message = null; if ($activeExceptionHandlers !== $this->backupGlobalExceptionHandlers) { if (count($activeExceptionHandlers) > count($this->backupGlobalExceptionHandlers)) { if (!$this->inIsolation) { $message = 'Test code or tested code did not remove its own exception handlers'; } } else { $message = 'Test code or tested code removed exception handlers other than its own'; } foreach ($activeExceptionHandlers as $handler) { restore_exception_handler(); } foreach ($this->backupGlobalExceptionHandlers as $handler) { set_exception_handler($handler); } } $this->backupGlobalErrorHandlers = null; $this->backupGlobalExceptionHandlers = null; if ($message !== null) { Event\Facade::emitter()->testConsideredRisky( $this->valueObjectForEvents(), $message, ); $this->status = TestStatus::risky($message); } } /** * @return list<callable> */ private function getActiveErrorHandlers(): array { $res = []; while (true) { $previousHandler = set_error_handler(static fn () => false); restore_error_handler(); if ($previousHandler === null) { break; } $res[] = $previousHandler; restore_error_handler(); } $res = array_reverse($res); foreach ($res as $handler) { set_error_handler($handler); } return $res; } /** * @return list<callable> */ private function getActiveExceptionHandlers(): array { $res = []; while (true) { $previousHandler = set_exception_handler(static fn () => null); restore_exception_handler(); if ($previousHandler === null) { break; } $res[] = $previousHandler; restore_exception_handler(); } $res = array_reverse($res); foreach ($res as $handler) { set_exception_handler($handler); } return $res; } private function snapshotGlobalState(): void { if ($this->runTestInSeparateProcess || $this->inIsolation || (!$this->backupGlobals && !$this->backupStaticProperties)) { return; } $snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true); $this->snapshot = $snapshot; } private function restoreGlobalState(): void { if (!$this->snapshot instanceof Snapshot) { return; } if (ConfigurationRegistry::get()->beStrictAboutChangesToGlobalState()) { $this->compareGlobalStateSnapshots( $this->snapshot, $this->createGlobalStateSnapshot($this->backupGlobals === true), ); } $restorer = new Restorer; if ($this->backupGlobals) { $restorer->restoreGlobalVariables($this->snapshot); } if ($this->backupStaticProperties) { $restorer->restoreStaticProperties($this->snapshot); } $this->snapshot = null; } private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot { $excludeList = new GlobalStateExcludeList; foreach ($this->backupGlobalsExcludeList as $globalVariable) { $excludeList->addGlobalVariable($globalVariable); } if (!defined('PHPUNIT_TESTSUITE')) { $excludeList->addClassNamePrefix('PHPUnit'); $excludeList->addClassNamePrefix('SebastianBergmann\CodeCoverage'); $excludeList->addClassNamePrefix('SebastianBergmann\FileIterator'); $excludeList->addClassNamePrefix('SebastianBergmann\Invoker'); $excludeList->addClassNamePrefix('SebastianBergmann\Template'); $excludeList->addClassNamePrefix('SebastianBergmann\Timer'); $excludeList->addStaticProperty(ComparatorFactory::class, 'instance'); foreach ($this->backupStaticPropertiesExcludeList as $class => $properties) { foreach ($properties as $property) { $excludeList->addStaticProperty($class, $property); } } } return new Snapshot( $excludeList, $backupGlobals, (bool) $this->backupStaticProperties, false, false, false, false, false, false, false, ); } private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after): void { $backupGlobals = $this->backupGlobals === null || $this->backupGlobals; if ($backupGlobals) { $this->compareGlobalStateSnapshotPart( $before->globalVariables(), $after->globalVariables(), "--- Global variables before the test\n+++ Global variables after the test\n", ); $this->compareGlobalStateSnapshotPart( $before->superGlobalVariables(), $after->superGlobalVariables(), "--- Super-global variables before the test\n+++ Super-global variables after the test\n", ); } if ($this->backupStaticProperties) { $this->compareGlobalStateSnapshotPart( $before->staticProperties(), $after->staticProperties(), "--- Static properties before the test\n+++ Static properties after the test\n", ); } } /** * @param array<mixed> $before * @param array<mixed> $after */ private function compareGlobalStateSnapshotPart(array $before, array $after, string $header): void { if ($before != $after) { $differ = new Differ(new UnifiedDiffOutputBuilder($header)); Event\Facade::emitter()->testConsideredRisky( $this->valueObjectForEvents(), 'This test modified global state but was not expected to do so' . PHP_EOL . trim( $differ->diff( Exporter::export($before), Exporter::export($after), ), ), ); } } private function shouldInvocationMockerBeReset(MockObject $mock): bool { $enumerator = new Enumerator; if (in_array($mock, $enumerator->enumerate($this->dependencyInput), true)) { return false; } if (!is_array($this->testResult) && !is_object($this->testResult)) { return true; } return !in_array($mock, $enumerator->enumerate($this->testResult), true); } private function unregisterCustomComparators(): void { $factory = ComparatorFactory::getInstance(); foreach ($this->customComparators as $comparator) { $factory->unregister($comparator); } $this->customComparators = []; } private function cleanupIniSettings(): void { foreach ($this->iniSettings as $varName => $oldValue) { ini_set($varName, $oldValue); } $this->iniSettings = []; } private function cleanupLocaleSettings(): void { foreach ($this->locale as $category => $locale) { setlocale($category, $locale); } $this->locale = []; } /** * @throws Exception */ private function shouldExceptionExpectationsBeVerified(Throwable $throwable): bool { $result = false; if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) { $result = true; } if ($throwable instanceof Exception) { $result = false; } if (is_string($this->expectedException)) { try { $reflector = new ReflectionClass($this->expectedException); // @codeCoverageIgnoreStart } catch (ReflectionException $e) { throw new Exception( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd if ($this->expectedException === 'PHPUnit\Framework\Exception' || $this->expectedException === '\PHPUnit\Framework\Exception' || $reflector->isSubclassOf(Exception::class)) { $result = true; } } return $result; } private function shouldRunInSeparateProcess(): bool { if ($this->inIsolation) { return false; } if ($this->runTestInSeparateProcess) { return true; } if ($this->runClassInSeparateProcess) { return true; } return ConfigurationRegistry::get()->processIsolation(); } private function isCallableTestMethod(string $dependency): bool { [$className, $methodName] = explode('::', $dependency); if (!class_exists($className)) { return false; } $class = new ReflectionClass($className); if (!$class->isSubclassOf(__CLASS__)) { return false; } if (!$class->hasMethod($methodName)) { return false; } return TestUtil::isTestMethod( $class->getMethod($methodName), ); } /** * @throws Exception * @throws ExpectationFailedException * @throws NoPreviousThrowableException */ private function performAssertionsOnOutput(): void { try { if ($this->outputExpectedRegex !== null) { $this->assertMatchesRegularExpression($this->outputExpectedRegex, $this->output); } elseif ($this->outputExpectedString !== null) { $this->assertSame($this->outputExpectedString, $this->output); } } catch (ExpectationFailedException $e) { $this->status = TestStatus::failure($e->getMessage()); Event\Facade::emitter()->testFailed( $this->valueObjectForEvents(), Event\Code\ThrowableBuilder::from($e), Event\Code\ComparisonFailureBuilder::from($e), ); throw $e; } } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable * * @codeCoverageIgnore */ private function invokeBeforeClassHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['beforeClass'], $emitter, 'testBeforeFirstTestMethodCalled', 'testBeforeFirstTestMethodFinished', ); } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable */ private function invokeBeforeTestHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['before'], $emitter, 'testBeforeTestMethodCalled', 'testBeforeTestMethodFinished', ); } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable */ private function invokePreConditionHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['preCondition'], $emitter, 'testPreConditionCalled', 'testPreConditionFinished', ); } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable */ private function invokePostConditionHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['postCondition'], $emitter, 'testPostConditionCalled', 'testPostConditionFinished', ); } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable */ private function invokeAfterTestHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['after'], $emitter, 'testAfterTestMethodCalled', 'testAfterTestMethodFinished', ); } /** * @param array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} $hookMethods * * @throws Throwable * * @codeCoverageIgnore */ private function invokeAfterClassHookMethods(array $hookMethods, Event\Emitter $emitter): void { $this->invokeHookMethods( $hookMethods['afterClass'], $emitter, 'testAfterLastTestMethodCalled', 'testAfterLastTestMethodFinished', ); } /** * @param 'testAfterLastTestMethodCalled'|'testAfterTestMethodCalled'|'testBeforeFirstTestMethodCalled'|'testBeforeTestMethodCalled'|'testPostConditionCalled'|'testPreConditionCalled' $calledMethod * @param 'testAfterLastTestMethodFinished'|'testAfterTestMethodFinished'|'testBeforeFirstTestMethodFinished'|'testBeforeTestMethodFinished'|'testPostConditionFinished'|'testPreConditionFinished' $finishedMethod * * @throws Throwable */ private function invokeHookMethods(HookMethodCollection $hookMethods, Event\Emitter $emitter, string $calledMethod, string $finishedMethod): void { $methodsInvoked = []; foreach ($hookMethods->methodNamesSortedByPriority() as $methodName) { if ($this->methodDoesNotExistOrIsDeclaredInTestCase($methodName)) { continue; } try { $this->{$methodName}(); } catch (Throwable $t) { } $methodInvoked = new Event\Code\ClassMethod( static::class, $methodName, ); $emitter->{$calledMethod}( static::class, $methodInvoked ); $methodsInvoked[] = $methodInvoked; if (isset($t)) { break; } } if (!empty($methodsInvoked)) { $emitter->{$finishedMethod}( static::class, ...$methodsInvoked ); } if (isset($t)) { throw $t; } } /** * @param non-empty-string $methodName */ private function methodDoesNotExistOrIsDeclaredInTestCase(string $methodName): bool { $reflector = new ReflectionObject($this); return !$reflector->hasMethod($methodName) || $reflector->getMethod($methodName)->getDeclaringClass()->getName() === self::class; } /** * @throws ExpectationFailedException */ private function verifyExceptionExpectations(\Exception|Throwable $exception): void { if ($this->expectedException !== null) { $this->assertThat( $exception, new ExceptionConstraint( $this->expectedException, ), ); } if ($this->expectedExceptionMessage !== null) { $this->assertThat( $exception->getMessage(), new ExceptionMessageIsOrContains( $this->expectedExceptionMessage, ), ); } if ($this->expectedExceptionMessageRegExp !== null) { $this->assertThat( $exception->getMessage(), new ExceptionMessageMatchesRegularExpression( $this->expectedExceptionMessageRegExp, ), ); } if ($this->expectedExceptionCode !== null) { $this->assertThat( $exception->getCode(), new ExceptionCode( $this->expectedExceptionCode, ), ); } } /** * @throws AssertionFailedError */ private function expectedExceptionWasNotRaised(): void { if ($this->expectedException !== null) { $this->assertThat( null, new ExceptionConstraint($this->expectedException), ); } elseif ($this->expectedExceptionMessage !== null) { $this->numberOfAssertionsPerformed++; throw new AssertionFailedError( sprintf( 'Failed asserting that exception with message "%s" is thrown', $this->expectedExceptionMessage, ), ); } elseif ($this->expectedExceptionMessageRegExp !== null) { $this->numberOfAssertionsPerformed++; throw new AssertionFailedError( sprintf( 'Failed asserting that exception with message matching "%s" is thrown', $this->expectedExceptionMessageRegExp, ), ); } elseif ($this->expectedExceptionCode !== null) { $this->numberOfAssertionsPerformed++; throw new AssertionFailedError( sprintf( 'Failed asserting that exception with code "%s" is thrown', $this->expectedExceptionCode, ), ); } } private function isRegisteredFailure(Throwable $t): bool { foreach (array_keys($this->failureTypes) as $failureType) { if ($t instanceof $failureType) { return true; } } return false; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ private function hasExpectationOnOutput(): bool { return is_string($this->outputExpectedString) || is_string($this->outputExpectedRegex); } /** * Creates a test stub for the specified interface or class. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * * @throws InvalidArgumentException * @throws MockObjectException * @throws NoPreviousThrowableException * * @return RealInstanceType&Stub */ final protected static function createStub(string $originalClassName): Stub { $stub = (new MockGenerator)->testDouble( $originalClassName, true, false, callOriginalConstructor: false, callOriginalClone: false, cloneArguments: false, allowMockingUnknownTypes: false, returnValueGeneration: self::generateReturnValuesForTestDoubles(), ); Event\Facade::emitter()->testCreatedStub($originalClassName); assert($stub instanceof $originalClassName); assert($stub instanceof Stub); return $stub; } /** * @param list<class-string> $interfaces * * @throws MockObjectException */ final protected static function createStubForIntersectionOfInterfaces(array $interfaces): Stub { $stub = (new MockGenerator)->testDoubleForInterfaceIntersection( $interfaces, false, returnValueGeneration: self::generateReturnValuesForTestDoubles(), ); Event\Facade::emitter()->testCreatedStubForIntersectionOfInterfaces($interfaces); return $stub; } /** * Creates (and configures) a test stub for the specified interface or class. * * @template RealInstanceType of object * * @param class-string<RealInstanceType> $originalClassName * @param array<non-empty-string, mixed> $configuration * * @throws InvalidArgumentException * @throws MockObjectException * @throws NoPreviousThrowableException * * @return RealInstanceType&Stub */ final protected static function createConfiguredStub(string $originalClassName, array $configuration): Stub { $o = self::createStub($originalClassName); foreach ($configuration as $method => $return) { $o->method($method)->willReturn($return); } return $o; } private static function generateReturnValuesForTestDoubles(): bool { return MetadataRegistry::parser()->forClass(static::class)->isDisableReturnValueGenerationForTestDoubles()->isEmpty(); } } phpunit/src/Framework/Reorderable.php 0000644 00000001364 15253321353 0013724 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Reorderable { public function sortId(): string; /** * @return list<ExecutionOrderDependency> */ public function provides(): array; /** * @return list<ExecutionOrderDependency> */ public function requires(): array; } phpunit/src/Framework/DataProviderTestSuite.php 0000644 00000004277 15253321353 0015742 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use function assert; use function class_exists; use function explode; use PHPUnit\Framework\TestSize\TestSize; use PHPUnit\Metadata\Api\Groups; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DataProviderTestSuite extends TestSuite { /** * @var list<ExecutionOrderDependency> */ private array $dependencies = []; /** * @var ?non-empty-list<ExecutionOrderDependency> */ private ?array $providedTests = null; /** * @param list<ExecutionOrderDependency> $dependencies */ public function setDependencies(array $dependencies): void { $this->dependencies = $dependencies; foreach ($this->tests() as $test) { if (!$test instanceof TestCase) { continue; } $test->setDependencies($dependencies); } } /** * @return non-empty-list<ExecutionOrderDependency> */ public function provides(): array { if ($this->providedTests === null) { $this->providedTests = [new ExecutionOrderDependency($this->name())]; } return $this->providedTests; } /** * @return list<ExecutionOrderDependency> */ public function requires(): array { // A DataProviderTestSuite does not have to traverse its child tests // as these are inherited and cannot reference dataProvider rows directly return $this->dependencies; } /** * Returns the size of each test created using the data provider(s). */ public function size(): TestSize { [$className, $methodName] = explode('::', $this->name()); assert(class_exists($className)); assert($methodName !== ''); return (new Groups)->size($className, $methodName); } } phpunit/src/Framework/Test.php 0000644 00000000742 15253321353 0012414 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Countable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Test extends Countable { public function run(): void; } phpunit/src/Exception.php 0000644 00000000513 15253321353 0011472 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit; use Throwable; interface Exception extends Throwable { } phpunit/src/Runner/CodeCoverage.php 0000644 00000033176 15253321353 0013346 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function file_put_contents; use function sprintf; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\TestCase; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Output\Printer; use SebastianBergmann\CodeCoverage\Driver\Driver; use SebastianBergmann\CodeCoverage\Driver\Selector; use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException; use SebastianBergmann\CodeCoverage\Filter; use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport; use SebastianBergmann\CodeCoverage\Report\Cobertura as CoberturaReport; use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport; use SebastianBergmann\CodeCoverage\Report\Html\Colors; use SebastianBergmann\CodeCoverage\Report\Html\CustomCssFile; use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport; use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport; use SebastianBergmann\CodeCoverage\Report\Text as TextReport; use SebastianBergmann\CodeCoverage\Report\Thresholds; use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport; use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize; use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus; use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Timer\NoActiveTimerException; use SebastianBergmann\Timer\Timer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final class CodeCoverage { private static ?self $instance = null; private ?\SebastianBergmann\CodeCoverage\CodeCoverage $codeCoverage = null; private ?Driver $driver = null; private bool $collecting = false; private ?TestCase $test = null; private ?Timer $timer = null; /** * @var array<string,list<int>> */ private array $linesToBeIgnored = []; public static function instance(): self { if (self::$instance === null) { self::$instance = new self; } return self::$instance; } public function init(Configuration $configuration, CodeCoverageFilterRegistry $codeCoverageFilterRegistry, bool $extensionRequiresCodeCoverageCollection): void { $codeCoverageFilterRegistry->init($configuration); if (!$configuration->hasCoverageReport() && !$extensionRequiresCodeCoverageCollection) { return; } $this->activate($codeCoverageFilterRegistry->get(), $configuration->pathCoverage()); if (!$this->isActive()) { return; } if ($configuration->hasCoverageCacheDirectory()) { $this->codeCoverage()->cacheStaticAnalysis($configuration->coverageCacheDirectory()); } $this->codeCoverage()->excludeSubclassesOfThisClassFromUnintentionallyCoveredCodeCheck(Comparator::class); if ($configuration->strictCoverage()) { $this->codeCoverage()->enableCheckForUnintentionallyCoveredCode(); } if ($configuration->ignoreDeprecatedCodeUnitsFromCodeCoverage()) { $this->codeCoverage()->ignoreDeprecatedCode(); } else { $this->codeCoverage()->doNotIgnoreDeprecatedCode(); } if ($configuration->disableCodeCoverageIgnore()) { $this->codeCoverage()->disableAnnotationsForIgnoringCode(); } else { $this->codeCoverage()->enableAnnotationsForIgnoringCode(); } if ($configuration->includeUncoveredFiles()) { $this->codeCoverage()->includeUncoveredFiles(); } else { $this->codeCoverage()->excludeUncoveredFiles(); } if ($codeCoverageFilterRegistry->get()->isEmpty()) { if (!$codeCoverageFilterRegistry->configured()) { EventFacade::emitter()->testRunnerTriggeredWarning( 'No filter is configured, code coverage will not be processed', ); } else { EventFacade::emitter()->testRunnerTriggeredWarning( 'Incorrect filter configuration, code coverage will not be processed', ); } $this->deactivate(); } } /** * @phpstan-assert-if-true !null $this->instance */ public function isActive(): bool { return $this->codeCoverage !== null; } public function codeCoverage(): \SebastianBergmann\CodeCoverage\CodeCoverage { return $this->codeCoverage; } public function driver(): Driver { return $this->driver; } public function start(TestCase $test): void { if ($this->collecting) { return; } $size = TestSize::unknown(); if ($test->size()->isSmall()) { $size = TestSize::small(); } elseif ($test->size()->isMedium()) { $size = TestSize::medium(); } elseif ($test->size()->isLarge()) { $size = TestSize::large(); } $this->test = $test; $this->codeCoverage->start( $test->valueObjectForEvents()->id(), $size, ); $this->collecting = true; } /** * @param array<string,list<int>>|false $linesToBeCovered * @param array<string,list<int>> $linesToBeUsed */ public function stop(bool $append = true, array|false $linesToBeCovered = [], array $linesToBeUsed = []): void { if (!$this->collecting) { return; } $status = TestStatus::unknown(); if ($this->test !== null) { if ($this->test->status()->isSuccess()) { $status = TestStatus::success(); } else { $status = TestStatus::failure(); } } /* @noinspection UnusedFunctionResultInspection */ $this->codeCoverage->stop($append, $status, $linesToBeCovered, $linesToBeUsed, $this->linesToBeIgnored); $this->test = null; $this->collecting = false; } public function deactivate(): void { $this->driver = null; $this->codeCoverage = null; $this->test = null; } public function generateReports(Printer $printer, Configuration $configuration): void { if (!$this->isActive()) { return; } if ($configuration->hasCoveragePhp()) { $this->codeCoverageGenerationStart($printer, 'PHP'); try { $writer = new PhpReport; $writer->process($this->codeCoverage(), $configuration->coveragePhp()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } if ($configuration->hasCoverageClover()) { $this->codeCoverageGenerationStart($printer, 'Clover XML'); try { $writer = new CloverReport; $writer->process($this->codeCoverage(), $configuration->coverageClover()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } if ($configuration->hasCoverageCobertura()) { $this->codeCoverageGenerationStart($printer, 'Cobertura XML'); try { $writer = new CoberturaReport; $writer->process($this->codeCoverage(), $configuration->coverageCobertura()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } if ($configuration->hasCoverageCrap4j()) { $this->codeCoverageGenerationStart($printer, 'Crap4J XML'); try { $writer = new Crap4jReport($configuration->coverageCrap4jThreshold()); $writer->process($this->codeCoverage(), $configuration->coverageCrap4j()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } if ($configuration->hasCoverageHtml()) { $this->codeCoverageGenerationStart($printer, 'HTML'); try { $customCssFile = CustomCssFile::default(); if ($configuration->hasCoverageHtmlCustomCssFile()) { $customCssFile = CustomCssFile::from($configuration->coverageHtmlCustomCssFile()); } $writer = new HtmlReport( sprintf( ' and <a href="https://phpunit.de/">PHPUnit %s</a>', Version::id(), ), Colors::from( $configuration->coverageHtmlColorSuccessLow(), $configuration->coverageHtmlColorSuccessMedium(), $configuration->coverageHtmlColorSuccessHigh(), $configuration->coverageHtmlColorWarning(), $configuration->coverageHtmlColorDanger(), ), Thresholds::from( $configuration->coverageHtmlLowUpperBound(), $configuration->coverageHtmlHighLowerBound(), ), $customCssFile, ); $writer->process($this->codeCoverage(), $configuration->coverageHtml()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } if ($configuration->hasCoverageText()) { $processor = new TextReport( Thresholds::default(), $configuration->coverageTextShowUncoveredFiles(), $configuration->coverageTextShowOnlySummary(), ); $textReport = $processor->process($this->codeCoverage(), $configuration->colors()); if ($configuration->coverageText() === 'php://stdout') { $printer->print($textReport); } else { file_put_contents($configuration->coverageText(), $textReport); } } if ($configuration->hasCoverageXml()) { $this->codeCoverageGenerationStart($printer, 'PHPUnit XML'); try { $writer = new XmlReport(Version::id()); $writer->process($this->codeCoverage(), $configuration->coverageXml()); $this->codeCoverageGenerationSucceeded($printer); unset($writer); } catch (CodeCoverageException $e) { $this->codeCoverageGenerationFailed($printer, $e); } } } /** * @param array<string,list<int>> $linesToBeIgnored */ public function ignoreLines(array $linesToBeIgnored): void { $this->linesToBeIgnored = $linesToBeIgnored; } /** * @return array<string,list<int>> */ public function linesToBeIgnored(): array { return $this->linesToBeIgnored; } private function activate(Filter $filter, bool $pathCoverage): void { try { if ($pathCoverage) { $this->driver = (new Selector)->forLineAndPathCoverage($filter); } else { $this->driver = (new Selector)->forLineCoverage($filter); } $this->codeCoverage = new \SebastianBergmann\CodeCoverage\CodeCoverage( $this->driver, $filter, ); } catch (CodeCoverageException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( $e->getMessage(), ); } } private function codeCoverageGenerationStart(Printer $printer, string $format): void { $printer->print( sprintf( "\nGenerating code coverage report in %s format ... ", $format, ), ); $this->timer()->start(); } /** * @throws NoActiveTimerException */ private function codeCoverageGenerationSucceeded(Printer $printer): void { $printer->print( sprintf( "done [%s]\n", $this->timer()->stop()->asString(), ), ); } /** * @throws NoActiveTimerException */ private function codeCoverageGenerationFailed(Printer $printer, CodeCoverageException $e): void { $printer->print( sprintf( "failed [%s]\n%s\n", $this->timer()->stop()->asString(), $e->getMessage(), ), ); } private function timer(): Timer { if ($this->timer === null) { $this->timer = new Timer; } return $this->timer; } } phpunit/src/Runner/TestSuiteLoader.php 0000644 00000007624 15253321353 0014077 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function array_diff; use function basename; use function get_declared_classes; use function realpath; use function str_ends_with; use function strpos; use function strtolower; use function substr; use PHPUnit\Framework\TestCase; use ReflectionClass; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestSuiteLoader { /** * @var list<class-string> */ private static array $declaredClasses = []; /** * @var array<non-empty-string, list<class-string>> */ private static array $fileToClassesMap = []; /** * @throws Exception * * @return ReflectionClass<TestCase> */ public function load(string $suiteClassFile): ReflectionClass { $suiteClassFile = realpath($suiteClassFile); $suiteClassName = $this->classNameFromFileName($suiteClassFile); $loadedClasses = $this->loadSuiteClassFile($suiteClassFile); foreach ($loadedClasses as $className) { /** @noinspection PhpUnhandledExceptionInspection */ $class = new ReflectionClass($className); if ($class->isAnonymous()) { continue; } if ($class->getFileName() !== $suiteClassFile) { continue; } if (!$class->isSubclassOf(TestCase::class)) { continue; } if (!str_ends_with(strtolower($class->getShortName()), strtolower($suiteClassName))) { continue; } if (!$class->isAbstract()) { return $class; } $e = new ClassIsAbstractException($class->getName(), $suiteClassFile); } if (isset($e)) { throw $e; } foreach ($loadedClasses as $className) { if (str_ends_with(strtolower($className), strtolower($suiteClassName))) { throw new ClassDoesNotExtendTestCaseException($className, $suiteClassFile); } } throw new ClassCannotBeFoundException($suiteClassName, $suiteClassFile); } private function classNameFromFileName(string $suiteClassFile): string { $className = basename($suiteClassFile, '.php'); $dotPos = strpos($className, '.'); if ($dotPos !== false) { $className = substr($className, 0, $dotPos); } return $className; } /** * @return array<class-string> */ private function loadSuiteClassFile(string $suiteClassFile): array { if (isset(self::$fileToClassesMap[$suiteClassFile])) { return self::$fileToClassesMap[$suiteClassFile]; } if (empty(self::$declaredClasses)) { self::$declaredClasses = get_declared_classes(); } require_once $suiteClassFile; $loadedClasses = array_diff( get_declared_classes(), self::$declaredClasses, ); foreach ($loadedClasses as $loadedClass) { /** @noinspection PhpUnhandledExceptionInspection */ $class = new ReflectionClass($loadedClass); if (!isset(self::$fileToClassesMap[$class->getFileName()])) { self::$fileToClassesMap[$class->getFileName()] = []; } self::$fileToClassesMap[$class->getFileName()][] = $class->getName(); } self::$declaredClasses = get_declared_classes(); if (empty($loadedClasses)) { return self::$declaredClasses; } return $loadedClasses; } } phpunit/src/Runner/ErrorHandler.php 0000644 00000023516 15253321353 0013404 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use const DEBUG_BACKTRACE_IGNORE_ARGS; use const E_COMPILE_ERROR; use const E_COMPILE_WARNING; use const E_CORE_ERROR; use const E_CORE_WARNING; use const E_DEPRECATED; use const E_ERROR; use const E_NOTICE; use const E_PARSE; use const E_RECOVERABLE_ERROR; use const E_STRICT; use const E_USER_DEPRECATED; use const E_USER_ERROR; use const E_USER_NOTICE; use const E_USER_WARNING; use const E_WARNING; use function array_keys; use function array_values; use function debug_backtrace; use function error_reporting; use function restore_error_handler; use function set_error_handler; use PHPUnit\Event; use PHPUnit\Event\Code\IssueTrigger\IssueTrigger; use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Runner\Baseline\Baseline; use PHPUnit\Runner\Baseline\Issue; use PHPUnit\TextUI\Configuration\Registry; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\SourceFilter; use PHPUnit\Util\ExcludeList; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ErrorHandler { private const UNHANDLEABLE_LEVELS = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING; private const INSUPPRESSIBLE_LEVELS = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR; private static ?self $instance = null; private ?Baseline $baseline = null; private bool $enabled = false; private ?int $originalErrorReportingLevel = null; private readonly Source $source; private readonly SourceFilter $sourceFilter; /** * @var array{functions: list<non-empty-string>, methods: list<array{className: class-string, methodName: non-empty-string}>} */ private ?array $deprecationTriggers = null; public static function instance(): self { return self::$instance ?? self::$instance = new self(Registry::get()->source()); } private function __construct(Source $source) { $this->source = $source; $this->sourceFilter = new SourceFilter; } /** * @throws NoTestCaseObjectOnCallStackException */ public function __invoke(int $errorNumber, string $errorString, string $errorFile, int $errorLine): bool { $suppressed = (error_reporting() & ~self::INSUPPRESSIBLE_LEVELS) === 0; if ($suppressed && (new ExcludeList)->isExcluded($errorFile)) { return false; } $test = Event\Code\TestMethodBuilder::fromCallStack(); $ignoredByBaseline = $this->ignoredByBaseline($errorFile, $errorLine, $errorString); $ignoredByTest = $test->metadata()->isIgnoreDeprecations()->isNotEmpty(); switch ($errorNumber) { case E_NOTICE: case E_STRICT: Event\Facade::emitter()->testTriggeredPhpNotice( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, ); break; case E_USER_NOTICE: Event\Facade::emitter()->testTriggeredNotice( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, ); break; case E_WARNING: Event\Facade::emitter()->testTriggeredPhpWarning( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, ); break; case E_USER_WARNING: Event\Facade::emitter()->testTriggeredWarning( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, ); break; case E_DEPRECATED: Event\Facade::emitter()->testTriggeredPhpDeprecation( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, $ignoredByTest, $this->trigger($test, false), ); break; case E_USER_DEPRECATED: Event\Facade::emitter()->testTriggeredDeprecation( $test, $errorString, $errorFile, $errorLine, $suppressed, $ignoredByBaseline, $ignoredByTest, $this->trigger($test, true), ); break; case E_USER_ERROR: Event\Facade::emitter()->testTriggeredError( $test, $errorString, $errorFile, $errorLine, $suppressed, ); throw new ErrorException('E_USER_ERROR was triggered'); default: return false; } return false; } public function enable(): void { if ($this->enabled) { return; } $oldErrorHandler = set_error_handler($this); if ($oldErrorHandler !== null) { restore_error_handler(); return; } $this->enabled = true; $this->originalErrorReportingLevel = error_reporting(); error_reporting($this->originalErrorReportingLevel & self::UNHANDLEABLE_LEVELS); } public function disable(): void { if (!$this->enabled) { return; } restore_error_handler(); error_reporting(error_reporting() | $this->originalErrorReportingLevel); $this->enabled = false; $this->originalErrorReportingLevel = null; } public function useBaseline(Baseline $baseline): void { $this->baseline = $baseline; } /** * @param array{functions: list<non-empty-string>, methods: list<array{className: class-string, methodName: non-empty-string}>} $deprecationTriggers */ public function useDeprecationTriggers(array $deprecationTriggers): void { $this->deprecationTriggers = $deprecationTriggers; } /** * @param non-empty-string $file * @param positive-int $line * @param non-empty-string $description */ private function ignoredByBaseline(string $file, int $line, string $description): bool { if ($this->baseline === null) { return false; } return $this->baseline->has(Issue::from($file, $line, null, $description)); } private function trigger(TestMethod $test, bool $filterTrigger): IssueTrigger { if (!$this->source->notEmpty()) { return IssueTrigger::unknown(); } $trace = $this->filteredStackTrace($filterTrigger); $triggeredInFirstPartyCode = false; $triggerCalledFromFirstPartyCode = false; if (isset($trace[0]['file']) && ($trace[0]['file'] === $test->file() || $this->sourceFilter->includes($this->source, $trace[0]['file']))) { $triggeredInFirstPartyCode = true; } if (isset($trace[1]['file']) && ($trace[1]['file'] === $test->file() || $this->sourceFilter->includes($this->source, $trace[1]['file']))) { $triggerCalledFromFirstPartyCode = true; } if ($triggerCalledFromFirstPartyCode) { if ($triggeredInFirstPartyCode) { return IssueTrigger::self(); } return IssueTrigger::direct(); } return IssueTrigger::indirect(); } /** * @return list<array{file: string, line: int, class: string, function: string, type: string}> */ private function filteredStackTrace(bool $filterDeprecationTriggers): array { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); // self::filteredStackTrace(), self::trigger(), self::__invoke() unset($trace[0], $trace[1], $trace[2]); if ($this->deprecationTriggers === null || !$filterDeprecationTriggers) { return array_values($trace); } foreach (array_keys($trace) as $frame) { foreach ($this->deprecationTriggers['functions'] as $function) { if (!isset($trace[$frame]['class']) && isset($trace[$frame]['function']) && $trace[$frame]['function'] === $function) { unset($trace[$frame]); continue 2; } } foreach ($this->deprecationTriggers['methods'] as $method) { if (isset($trace[$frame]['class']) && $trace[$frame]['class'] === $method['className'] && /** @phpstan-ignore isset.offset */ isset($trace[$frame]['function']) && $trace[$frame]['function'] === $method['methodName']) { unset($trace[$frame]); continue 2; } } } return array_values($trace); } } phpunit/src/Runner/Exception/ParameterDoesNotExistException.php 0000644 00000001475 15253321353 0021063 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ParameterDoesNotExistException extends RuntimeException implements Exception { public function __construct(string $name) { parent::__construct( sprintf( 'Parameter "%s" does not exist', $name, ), ); } } phpunit/src/Runner/Exception/Exception.php 0000644 00000001030 15253321353 0014674 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends \PHPUnit\Exception { } phpunit/src/Runner/Exception/ClassIsAbstractException.php 0000644 00000001554 15253321353 0017655 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ClassIsAbstractException extends RuntimeException implements Exception { public function __construct(string $className, string $file) { parent::__construct( sprintf( 'Class %s declared in %s is abstract', $className, $file, ), ); } } phpunit/src/Runner/Exception/InvalidOrderException.php 0000644 00000001120 15253321353 0017177 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidOrderException extends RuntimeException implements Exception { } phpunit/src/Runner/Exception/PhptExternalFileCannotBeLoadedException.php 0000644 00000001610 15253321353 0022562 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class PhptExternalFileCannotBeLoadedException extends RuntimeException implements Exception { public function __construct(string $section, string $file) { parent::__construct( sprintf( 'Could not load --%s-- %s for PHPT file', $section . '_EXTERNAL', $file, ), ); } } phpunit/src/Runner/Exception/InvalidPhptFileException.php 0000644 00000001123 15253321353 0017642 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidPhptFileException extends RuntimeException implements Exception { } phpunit/src/Runner/Exception/ClassDoesNotExtendTestCaseException.php 0000644 00000001626 15253321353 0021775 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ClassDoesNotExtendTestCaseException extends RuntimeException implements Exception { public function __construct(string $className, string $file) { parent::__construct( sprintf( 'Class %s declared in %s does not extend PHPUnit\Framework\TestCase', $className, $file, ), ); } } phpunit/src/Runner/Exception/ErrorException.php 0000644 00000001063 15253321353 0015714 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use Error; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ErrorException extends Error implements Exception { } phpunit/src/Runner/Exception/NoIgnoredEventException.php 0000644 00000001122 15253321353 0017505 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoIgnoredEventException extends RuntimeException implements Exception { } phpunit/src/Runner/Exception/FileDoesNotExistException.php 0000644 00000001463 15253321353 0020017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class FileDoesNotExistException extends RuntimeException implements Exception { public function __construct(string $file) { parent::__construct( sprintf( 'File "%s" does not exist', $file, ), ); } } phpunit/src/Runner/Exception/ClassCannotBeFoundException.php 0000644 00000001552 15253321353 0020301 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ClassCannotBeFoundException extends RuntimeException implements Exception { public function __construct(string $className, string $file) { parent::__construct( sprintf( 'Class %s cannot be found in %s', $className, $file, ), ); } } phpunit/src/Runner/Exception/ReflectionException.php 0000644 00000001116 15253321353 0016714 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReflectionException extends RuntimeException implements Exception { } phpunit/src/Runner/Exception/UnsupportedPhptSectionException.php 0000644 00000001520 15253321353 0021332 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class UnsupportedPhptSectionException extends RuntimeException implements Exception { public function __construct(string $section) { parent::__construct( sprintf( 'PHPUnit does not support PHPT %s sections', $section, ), ); } } phpunit/src/Runner/Exception/DirectoryDoesNotExistException.php 0000644 00000001540 15253321353 0021100 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DirectoryDoesNotExistException extends RuntimeException implements Exception { public function __construct(string $directory) { parent::__construct( sprintf( 'Directory "%s" does not exist and could not be created', $directory, ), ); } } phpunit/src/Runner/Extension/ParameterCollection.php 0000644 00000002520 15253321353 0016715 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Extension; use function array_key_exists; use PHPUnit\Runner\ParameterDoesNotExistException; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ParameterCollection { /** * @var array<string, string> */ private array $parameters; /** * @param array<string, string> $parameters */ public static function fromArray(array $parameters): self { return new self($parameters); } /** * @param array<string, string> $parameters */ private function __construct(array $parameters) { $this->parameters = $parameters; } public function has(string $name): bool { return array_key_exists($name, $this->parameters); } /** * @throws ParameterDoesNotExistException */ public function get(string $name): string { if (!$this->has($name)) { throw new ParameterDoesNotExistException($name); } return $this->parameters[$name]; } } phpunit/src/Runner/Extension/ExtensionBootstrapper.php 0000644 00000005377 15253321353 0017357 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Extension; use const PHP_EOL; use function assert; use function class_exists; use function class_implements; use function in_array; use function sprintf; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\TextUI\Configuration\Configuration; use ReflectionClass; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ExtensionBootstrapper { private Configuration $configuration; private Facade $facade; public function __construct(Configuration $configuration, Facade $facade) { $this->configuration = $configuration; $this->facade = $facade; } /** * @param non-empty-string $className * @param array<string, string> $parameters */ public function bootstrap(string $className, array $parameters): void { if (!class_exists($className)) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot bootstrap extension because class %s does not exist', $className, ), ); return; } if (!in_array(Extension::class, class_implements($className), true)) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot bootstrap extension because class %s does not implement interface %s', $className, Extension::class, ), ); return; } try { $instance = (new ReflectionClass($className))->newInstance(); assert($instance instanceof Extension); $instance->bootstrap( $this->configuration, $this->facade, ParameterCollection::fromArray($parameters), ); } catch (Throwable $t) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Bootstrapping of extension %s failed: %s%s%s', $className, $t->getMessage(), PHP_EOL, $t->getTraceAsString(), ), ); return; } EventFacade::emitter()->testRunnerBootstrappedExtension( $className, $parameters, ); } } phpunit/src/Runner/Extension/Extension.php 0000644 00000001120 15253321353 0014730 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Extension; use PHPUnit\TextUI\Configuration\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Extension { public function bootstrap(Configuration $configuration, Facade $facade, ParameterCollection $parameters): void; } phpunit/src/Runner/Extension/PharLoader.php 0000644 00000011030 15253321353 0014776 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Extension; use function count; use function explode; use function extension_loaded; use function implode; use function is_file; use function sprintf; use function str_contains; use PharIo\Manifest\ApplicationName; use PharIo\Manifest\Exception as ManifestException; use PharIo\Manifest\ManifestLoader; use PharIo\Version\Version as PharIoVersion; use PHPUnit\Event; use PHPUnit\Runner\Version; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class PharLoader { /** * @param non-empty-string $directory * * @return list<string> */ public function loadPharExtensionsInDirectory(string $directory): array { $pharExtensionLoaded = extension_loaded('phar'); $loadedExtensions = []; foreach ((new FileIteratorFacade)->getFilesAsArray($directory, '.phar') as $file) { if (!$pharExtensionLoaded) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot load extension from %s because the PHAR extension is not available', $file, ), ); continue; } if (!is_file('phar://' . $file . '/manifest.xml')) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( '%s is not an extension for PHPUnit', $file, ), ); continue; } try { $applicationName = new ApplicationName('phpunit/phpunit'); $version = new PharIoVersion($this->phpunitVersion()); $manifest = ManifestLoader::fromFile('phar://' . $file . '/manifest.xml'); if (!$manifest->isExtensionFor($applicationName)) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( '%s is not an extension for PHPUnit', $file, ), ); continue; } if (!$manifest->isExtensionFor($applicationName, $version)) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( '%s is not compatible with PHPUnit %s', $file, Version::series(), ), ); continue; } } catch (ManifestException $e) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot load extension from %s: %s', $file, $e->getMessage(), ), ); continue; } try { @require $file; } catch (Throwable $t) { Event\Facade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot load extension from %s: %s', $file, $t->getMessage(), ), ); continue; } $loadedExtensions[] = $manifest->getName()->asString() . ' ' . $manifest->getVersion()->getVersionString(); Event\Facade::emitter()->testRunnerLoadedExtensionFromPhar( $file, $manifest->getName()->asString(), $manifest->getVersion()->getVersionString(), ); } return $loadedExtensions; } private function phpunitVersion(): string { $version = Version::id(); if (!str_contains($version, '-')) { return $version; } $parts = explode('.', explode('-', $version)[0]); if (count($parts) === 2) { $parts[] = 0; } return implode('.', $parts); } } phpunit/src/Runner/Extension/Facade.php 0000644 00000004665 15253321353 0014140 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Extension; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\Subscriber; use PHPUnit\Event\Tracer\Tracer; use PHPUnit\Event\UnknownSubscriberTypeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class Facade { private bool $replacesOutput = false; private bool $replacesProgressOutput = false; private bool $replacesResultOutput = false; private bool $requiresCodeCoverageCollection = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function registerSubscribers(Subscriber ...$subscribers): void { EventFacade::instance()->registerSubscribers(...$subscribers); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function registerSubscriber(Subscriber $subscriber): void { EventFacade::instance()->registerSubscriber($subscriber); } /** * @throws EventFacadeIsSealedException */ public function registerTracer(Tracer $tracer): void { EventFacade::instance()->registerTracer($tracer); } public function replaceOutput(): void { $this->replacesOutput = true; } public function replacesOutput(): bool { return $this->replacesOutput; } public function replaceProgressOutput(): void { $this->replacesProgressOutput = true; } public function replacesProgressOutput(): bool { return $this->replacesOutput || $this->replacesProgressOutput; } public function replaceResultOutput(): void { $this->replacesResultOutput = true; } public function replacesResultOutput(): bool { return $this->replacesOutput || $this->replacesResultOutput; } public function requireCodeCoverageCollection(): void { $this->requiresCodeCoverageCollection = true; } public function requiresCodeCoverageCollection(): bool { return $this->requiresCodeCoverageCollection; } } phpunit/src/Runner/TestSuiteSorter.php 0000644 00000024631 15253321353 0014144 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function array_diff; use function array_merge; use function array_reverse; use function array_splice; use function count; use function in_array; use function max; use function shuffle; use function usort; use PHPUnit\Framework\DataProviderTestSuite; use PHPUnit\Framework\Reorderable; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\ResultCache\NullResultCache; use PHPUnit\Runner\ResultCache\ResultCache; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestSuiteSorter { /** * @var int */ public const ORDER_DEFAULT = 0; /** * @var int */ public const ORDER_RANDOMIZED = 1; /** * @var int */ public const ORDER_REVERSED = 2; /** * @var int */ public const ORDER_DEFECTS_FIRST = 3; /** * @var int */ public const ORDER_DURATION = 4; /** * @var int */ public const ORDER_SIZE = 5; private const SIZE_SORT_WEIGHT = [ 'small' => 1, 'medium' => 2, 'large' => 3, 'unknown' => 4, ]; /** * @var array<string, int> Associative array of (string => DEFECT_SORT_WEIGHT) elements */ private array $defectSortOrder = []; private readonly ResultCache $cache; /** * @var array<string> A list of normalized names of tests before reordering */ private array $originalExecutionOrder = []; /** * @var array<string> A list of normalized names of tests affected by reordering */ private array $executionOrder = []; public function __construct(?ResultCache $cache = null) { $this->cache = $cache ?? new NullResultCache; } /** * @throws Exception */ public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void { $allowedOrders = [ self::ORDER_DEFAULT, self::ORDER_REVERSED, self::ORDER_RANDOMIZED, self::ORDER_DURATION, self::ORDER_SIZE, ]; if (!in_array($order, $allowedOrders, true)) { throw new InvalidOrderException; } $allowedOrderDefects = [ self::ORDER_DEFAULT, self::ORDER_DEFECTS_FIRST, ]; if (!in_array($orderDefects, $allowedOrderDefects, true)) { throw new InvalidOrderException; } if ($isRootTestSuite) { $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite); } if ($suite instanceof TestSuite) { foreach ($suite as $_suite) { $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false); } if ($orderDefects === self::ORDER_DEFECTS_FIRST) { $this->addSuiteToDefectSortOrder($suite); } $this->sort($suite, $order, $resolveDependencies, $orderDefects); } if ($isRootTestSuite) { $this->executionOrder = $this->calculateTestExecutionOrder($suite); } } /** * @return array<string> */ public function getOriginalExecutionOrder(): array { return $this->originalExecutionOrder; } /** * @return array<string> */ public function getExecutionOrder(): array { return $this->executionOrder; } private function sort(TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects): void { if (empty($suite->tests())) { return; } if ($order === self::ORDER_REVERSED) { $suite->setTests($this->reverse($suite->tests())); } elseif ($order === self::ORDER_RANDOMIZED) { $suite->setTests($this->randomize($suite->tests())); } elseif ($order === self::ORDER_DURATION) { $suite->setTests($this->sortByDuration($suite->tests())); } elseif ($order === self::ORDER_SIZE) { $suite->setTests($this->sortBySize($suite->tests())); } if ($orderDefects === self::ORDER_DEFECTS_FIRST) { $suite->setTests($this->sortDefectsFirst($suite->tests())); } if ($resolveDependencies && !($suite instanceof DataProviderTestSuite)) { $tests = $suite->tests(); /** @noinspection PhpParamsInspection */ /** @phpstan-ignore argument.type */ $suite->setTests($this->resolveDependencies($tests)); } } private function addSuiteToDefectSortOrder(TestSuite $suite): void { $max = 0; foreach ($suite->tests() as $test) { if (!$test instanceof Reorderable) { continue; } if (!isset($this->defectSortOrder[$test->sortId()])) { $this->defectSortOrder[$test->sortId()] = $this->cache->status($test->sortId())->asInt(); $max = max($max, $this->defectSortOrder[$test->sortId()]); } } $this->defectSortOrder[$suite->sortId()] = $max; } /** * @param list<Test> $tests * * @return list<Test> */ private function reverse(array $tests): array { return array_reverse($tests); } /** * @param list<Test> $tests * * @return list<Test> */ private function randomize(array $tests): array { shuffle($tests); return $tests; } /** * @param list<Test> $tests * * @return list<Test> */ private function sortDefectsFirst(array $tests): array { usort( $tests, fn ($left, $right) => $this->cmpDefectPriorityAndTime($left, $right), ); return $tests; } /** * @param list<Test> $tests * * @return list<Test> */ private function sortByDuration(array $tests): array { usort( $tests, fn ($left, $right) => $this->cmpDuration($left, $right), ); return $tests; } /** * @param list<Test> $tests * * @return list<Test> */ private function sortBySize(array $tests): array { usort( $tests, fn ($left, $right) => $this->cmpSize($left, $right), ); return $tests; } /** * Comparator callback function to sort tests for "reach failure as fast as possible". * * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT * 2. when tests are equally defective, sort the fastest to the front * 3. do not reorder successful tests */ private function cmpDefectPriorityAndTime(Test $a, Test $b): int { if (!($a instanceof Reorderable && $b instanceof Reorderable)) { return 0; } $priorityA = $this->defectSortOrder[$a->sortId()] ?? 0; $priorityB = $this->defectSortOrder[$b->sortId()] ?? 0; if ($priorityB <=> $priorityA) { // Sort defect weight descending return $priorityB <=> $priorityA; } if ($priorityA || $priorityB) { return $this->cmpDuration($a, $b); } // do not change execution order return 0; } /** * Compares test duration for sorting tests by duration ascending. */ private function cmpDuration(Test $a, Test $b): int { if (!($a instanceof Reorderable && $b instanceof Reorderable)) { return 0; } return $this->cache->time($a->sortId()) <=> $this->cache->time($b->sortId()); } /** * Compares test size for sorting tests small->medium->large->unknown. */ private function cmpSize(Test $a, Test $b): int { $sizeA = ($a instanceof TestCase || $a instanceof DataProviderTestSuite) ? $a->size()->asString() : 'unknown'; $sizeB = ($b instanceof TestCase || $b instanceof DataProviderTestSuite) ? $b->size()->asString() : 'unknown'; return self::SIZE_SORT_WEIGHT[$sizeA] <=> self::SIZE_SORT_WEIGHT[$sizeB]; } /** * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible. * The algorithm will leave the tests in original running order when it can. * For more details see the documentation for test dependencies. * * Short description of algorithm: * 1. Pick the next Test from remaining tests to be checked for dependencies. * 2. If the test has no dependencies: mark done, start again from the top * 3. If the test has dependencies but none left to do: mark done, start again from the top * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution. * * @param array<DataProviderTestSuite|TestCase> $tests * * @return array<DataProviderTestSuite|TestCase> */ private function resolveDependencies(array $tests): array { $newTestOrder = []; $i = 0; $provided = []; do { if ([] === array_diff($tests[$i]->requires(), $provided)) { $provided = array_merge($provided, $tests[$i]->provides()); $newTestOrder = array_merge($newTestOrder, array_splice($tests, $i, 1)); $i = 0; } else { $i++; } } while (!empty($tests) && ($i < count($tests))); return array_merge($newTestOrder, $tests); } /** * @return array<string> */ private function calculateTestExecutionOrder(Test $suite): array { $tests = []; if ($suite instanceof TestSuite) { foreach ($suite->tests() as $test) { if (!$test instanceof TestSuite && $test instanceof Reorderable) { $tests[] = $test->sortId(); } else { $tests = array_merge($tests, $this->calculateTestExecutionOrder($test)); } } } return $tests; } } phpunit/src/Runner/PHPT/templates/phpt.tpl 0000644 00000002243 15253321353 0014543 0 ustar 00 <?php declare(strict_types=1); use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\Selector; use SebastianBergmann\CodeCoverage\Filter; $composerAutoload = {composerAutoload}; $phar = {phar}; ob_start(); $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'][] = '{job}'; if ($composerAutoload) { require_once $composerAutoload; define('PHPUNIT_COMPOSER_INSTALL', $composerAutoload); } else if ($phar) { require $phar; } $coverage = null; if ('{bootstrap}' !== '') { require_once '{bootstrap}'; } if (class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) { $filter = new Filter; $coverage = new CodeCoverage( (new Selector)->{driverMethod}($filter), $filter ); if ({codeCoverageCacheDirectory}) { $coverage->cacheStaticAnalysis({codeCoverageCacheDirectory}); } $coverage->start(__FILE__); } register_shutdown_function( function() use ($coverage) { $output = null; if ($coverage) { $output = $coverage->stop(); } file_put_contents('{coverageFile}', serialize($output)); } ); ob_end_clean(); require '{job}'; phpunit/src/Runner/PHPT/PhptTestCase.php 0000644 00000062161 15253321353 0014136 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use const DEBUG_BACKTRACE_IGNORE_ARGS; use const DIRECTORY_SEPARATOR; use function array_merge; use function assert; use function basename; use function debug_backtrace; use function defined; use function dirname; use function explode; use function extension_loaded; use function file; use function file_get_contents; use function file_put_contents; use function is_array; use function is_file; use function is_readable; use function is_string; use function ltrim; use function preg_match; use function preg_replace; use function preg_split; use function realpath; use function rtrim; use function str_contains; use function str_replace; use function str_starts_with; use function strncasecmp; use function substr; use function trim; use function unlink; use function unserialize; use function var_export; use PHPUnit\Event\Code\Phpt; use PHPUnit\Event\Code\ThrowableBuilder; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\NoPreviousThrowableException; use PHPUnit\Framework\Assert; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExecutionOrderDependency; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\IncompleteTestError; use PHPUnit\Framework\PhptAssertionFailedError; use PHPUnit\Framework\Reorderable; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Framework\Test; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use PHPUnit\Util\PHP\Job; use PHPUnit\Util\PHP\JobRunnerRegistry; use SebastianBergmann\CodeCoverage\Data\RawCodeCoverageData; use SebastianBergmann\CodeCoverage\InvalidArgumentException; use SebastianBergmann\CodeCoverage\ReflectionException; use SebastianBergmann\CodeCoverage\StaticAnalysisCacheNotConfiguredException; use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize; use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus; use SebastianBergmann\CodeCoverage\TestIdMissingException; use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; use SebastianBergmann\Template\Template; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class PhptTestCase implements Reorderable, SelfDescribing, Test { /** * @var non-empty-string */ private readonly string $filename; private string $output = ''; /** * Constructs a test case with the given filename. * * @param non-empty-string $filename * * @throws Exception */ public function __construct(string $filename) { if (!is_file($filename)) { throw new FileDoesNotExistException($filename); } $this->filename = $filename; } /** * Counts the number of test cases executed by run(TestResult result). */ public function count(): int { return 1; } /** * Runs a test and collects its result in a TestResult instance. * * @throws \PHPUnit\Framework\Exception * @throws \SebastianBergmann\Template\InvalidArgumentException * @throws Exception * @throws InvalidArgumentException * @throws NoPreviousThrowableException * @throws ReflectionException * @throws StaticAnalysisCacheNotConfiguredException * @throws TestIdMissingException * @throws UnintentionallyCoveredCodeException * * @noinspection RepetitiveMethodCallsInspection */ public function run(): void { $emitter = EventFacade::emitter(); $emitter->testPreparationStarted( $this->valueObjectForEvents(), ); try { $sections = $this->parse(); } catch (Exception $e) { $emitter->testPrepared($this->valueObjectForEvents()); $emitter->testErrored($this->valueObjectForEvents(), ThrowableBuilder::from($e)); $emitter->testFinished($this->valueObjectForEvents(), 0); return; } $code = $this->render($sections['FILE']); $xfail = false; $environmentVariables = []; $phpSettings = $this->parseIniSection($this->settings(CodeCoverage::instance()->isActive())); $input = null; $arguments = []; $emitter->testPrepared($this->valueObjectForEvents()); if (isset($sections['INI'])) { $phpSettings = $this->parseIniSection($sections['INI'], $phpSettings); } if (isset($sections['ENV'])) { $environmentVariables = $this->parseEnvSection($sections['ENV']); } if ($this->shouldTestBeSkipped($sections, $phpSettings)) { return; } if (isset($sections['XFAIL'])) { $xfail = trim($sections['XFAIL']); } if (isset($sections['STDIN'])) { $input = $sections['STDIN']; } if (isset($sections['ARGS'])) { $arguments = explode(' ', $sections['ARGS']); } if (CodeCoverage::instance()->isActive()) { $codeCoverageCacheDirectory = null; if (CodeCoverage::instance()->codeCoverage()->cachesStaticAnalysis()) { $codeCoverageCacheDirectory = CodeCoverage::instance()->codeCoverage()->cacheDirectory(); } $this->renderForCoverage( $code, CodeCoverage::instance()->codeCoverage()->collectsBranchAndPathCoverage(), $codeCoverageCacheDirectory, ); } $jobResult = JobRunnerRegistry::run( new Job( $code, $this->stringifyIni($phpSettings), $environmentVariables, $arguments, $input, true, ), ); $this->output = $jobResult->stdout(); if (CodeCoverage::instance()->isActive()) { $coverage = $this->cleanupForCoverage(); CodeCoverage::instance()->codeCoverage()->start($this->filename, TestSize::large()); CodeCoverage::instance()->codeCoverage()->append( $coverage, $this->filename, true, TestStatus::unknown(), ); } $passed = true; try { $this->assertPhptExpectation($sections, $this->output); } catch (AssertionFailedError $e) { $failure = $e; if ($xfail !== false) { $failure = new IncompleteTestError($xfail, 0, $e); } elseif ($e instanceof ExpectationFailedException) { $comparisonFailure = $e->getComparisonFailure(); if ($comparisonFailure) { $diff = $comparisonFailure->getDiff(); } else { $diff = $e->getMessage(); } $hint = $this->getLocationHintFromDiff($diff, $sections); $trace = array_merge($hint, debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)); $failure = new PhptAssertionFailedError( $e->getMessage(), 0, (string) $trace[0]['file'], (int) $trace[0]['line'], $trace, $comparisonFailure ? $diff : '', ); } if ($failure instanceof IncompleteTestError) { $emitter->testMarkedAsIncomplete($this->valueObjectForEvents(), ThrowableBuilder::from($failure)); } else { $emitter->testFailed($this->valueObjectForEvents(), ThrowableBuilder::from($failure), null); } $passed = false; } catch (Throwable $t) { $emitter->testErrored($this->valueObjectForEvents(), ThrowableBuilder::from($t)); $passed = false; } if ($passed) { $emitter->testPassed($this->valueObjectForEvents()); } $this->runClean($sections, CodeCoverage::instance()->isActive()); $emitter->testFinished($this->valueObjectForEvents(), 1); } /** * Returns the name of the test case. */ public function getName(): string { return $this->toString(); } /** * Returns a string representation of the test case. */ public function toString(): string { return $this->filename; } public function usesDataProvider(): bool { return false; } public function numberOfAssertionsPerformed(): int { return 1; } public function output(): string { return $this->output; } public function hasOutput(): bool { return !empty($this->output); } public function sortId(): string { return $this->filename; } /** * @return list<ExecutionOrderDependency> */ public function provides(): array { return []; } /** * @return list<ExecutionOrderDependency> */ public function requires(): array { return []; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function valueObjectForEvents(): Phpt { return new Phpt($this->filename); } /** * @param array<string>|string $content * @param array<non-empty-string, array<non-empty-string>|non-empty-string> $ini * * @return array<non-empty-string, array<non-empty-string>|non-empty-string> */ private function parseIniSection(array|string $content, array $ini = []): array { if (is_string($content)) { $content = explode("\n", trim($content)); } foreach ($content as $setting) { if (!str_contains($setting, '=')) { continue; } $setting = explode('=', $setting, 2); $name = trim($setting[0]); $value = trim($setting[1]); if ($name === 'extension' || $name === 'zend_extension') { if (!isset($ini[$name])) { $ini[$name] = []; } $ini[$name][] = $value; continue; } $ini[$name] = $value; } return $ini; } /** * @return array<non-empty-string, non-empty-string> */ private function parseEnvSection(string $content): array { $env = []; foreach (explode("\n", trim($content)) as $e) { $e = explode('=', trim($e), 2); if ($e[0] !== '' && isset($e[1])) { $env[$e[0]] = $e[1]; } } return $env; } /** * @param array<non-empty-string, non-empty-string> $sections * * @throws Exception * @throws ExpectationFailedException */ private function assertPhptExpectation(array $sections, string $output): void { $assertions = [ 'EXPECT' => 'assertEquals', 'EXPECTF' => 'assertStringMatchesFormat', 'EXPECTREGEX' => 'assertMatchesRegularExpression', ]; $actual = preg_replace('/\r\n/', "\n", trim($output)); foreach ($assertions as $sectionName => $sectionAssertion) { if (isset($sections[$sectionName])) { $sectionContent = preg_replace('/\r\n/', "\n", trim($sections[$sectionName])); $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent; Assert::$sectionAssertion($expected, $actual); return; } } throw new InvalidPhptFileException; } /** * @param array<non-empty-string, non-empty-string> $sections * @param array<non-empty-string, array<non-empty-string>|non-empty-string> $settings */ private function shouldTestBeSkipped(array $sections, array $settings): bool { if (!isset($sections['SKIPIF'])) { return false; } $jobResult = JobRunnerRegistry::run( new Job( $this->render($sections['SKIPIF']), $this->stringifyIni($settings), ), ); if (!strncasecmp('skip', ltrim($jobResult->stdout()), 4)) { $message = ''; if (preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult->stdout(), $skipMatch)) { $message = substr($skipMatch[1], 2); } EventFacade::emitter()->testSkipped( $this->valueObjectForEvents(), $message, ); EventFacade::emitter()->testFinished($this->valueObjectForEvents(), 0); return true; } return false; } /** * @param array<non-empty-string, non-empty-string> $sections */ private function runClean(array $sections, bool $collectCoverage): void { if (!isset($sections['CLEAN'])) { return; } JobRunnerRegistry::run( new Job( $this->render($sections['CLEAN']), $this->settings($collectCoverage), ), ); } /** * @throws Exception * * @return array<non-empty-string, non-empty-string> */ private function parse(): array { $sections = []; $section = ''; $unsupportedSections = [ 'CGI', 'COOKIE', 'DEFLATE_POST', 'EXPECTHEADERS', 'EXTENSIONS', 'GET', 'GZIP_POST', 'HEADERS', 'PHPDBG', 'POST', 'POST_RAW', 'PUT', 'REDIRECTTEST', 'REQUEST', ]; $lineNr = 0; foreach (file($this->filename) as $line) { $lineNr++; if (preg_match('/^--([_A-Z]+)--/', $line, $result)) { $section = $result[1]; $sections[$section] = ''; $sections[$section . '_offset'] = $lineNr; continue; } if (empty($section)) { throw new InvalidPhptFileException; } $sections[$section] .= $line; } if (isset($sections['FILEEOF'])) { $sections['FILE'] = rtrim($sections['FILEEOF'], "\r\n"); unset($sections['FILEEOF']); } $this->parseExternal($sections); if (!$this->validate($sections)) { throw new InvalidPhptFileException; } foreach ($unsupportedSections as $section) { if (isset($sections[$section])) { throw new UnsupportedPhptSectionException($section); } } return $sections; } /** * @param array<non-empty-string, non-empty-string> $sections * * @throws Exception */ private function parseExternal(array &$sections): void { $allowSections = [ 'FILE', 'EXPECT', 'EXPECTF', 'EXPECTREGEX', ]; $testDirectory = dirname($this->filename) . DIRECTORY_SEPARATOR; foreach ($allowSections as $section) { if (isset($sections[$section . '_EXTERNAL'])) { $externalFilename = trim($sections[$section . '_EXTERNAL']); if (!is_file($testDirectory . $externalFilename) || !is_readable($testDirectory . $externalFilename)) { throw new PhptExternalFileCannotBeLoadedException( $section, $testDirectory . $externalFilename, ); } $sections[$section] = file_get_contents($testDirectory . $externalFilename); } } } /** * @param array<non-empty-string, non-empty-string> $sections */ private function validate(array $sections): bool { $requiredSections = [ 'FILE', [ 'EXPECT', 'EXPECTF', 'EXPECTREGEX', ], ]; foreach ($requiredSections as $section) { if (is_array($section)) { $foundSection = false; foreach ($section as $anySection) { if (isset($sections[$anySection])) { $foundSection = true; break; } } if (!$foundSection) { return false; } continue; } if (!isset($sections[$section])) { return false; } } return true; } /** * @param non-empty-string $code * * @return non-empty-string */ private function render(string $code): string { return str_replace( [ '__DIR__', '__FILE__', ], [ "'" . dirname($this->filename) . "'", "'" . $this->filename . "'", ], $code, ); } /** * @return array{coverage: non-empty-string, job: non-empty-string} */ private function getCoverageFiles(): array { $baseDir = dirname(realpath($this->filename)) . DIRECTORY_SEPARATOR; $basename = basename($this->filename, 'phpt'); return [ 'coverage' => $baseDir . $basename . 'coverage', 'job' => $baseDir . $basename . 'php', ]; } /** * @param non-empty-string $job * * @param-out non-empty-string $job * * @throws \SebastianBergmann\Template\InvalidArgumentException */ private function renderForCoverage(string &$job, bool $pathCoverage, ?string $codeCoverageCacheDirectory): void { $files = $this->getCoverageFiles(); $template = new Template( __DIR__ . '/templates/phpt.tpl', ); $composerAutoload = '\'\''; if (defined('PHPUNIT_COMPOSER_INSTALL')) { $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); } $phar = '\'\''; if (defined('__PHPUNIT_PHAR__')) { $phar = var_export(__PHPUNIT_PHAR__, true); } if ($codeCoverageCacheDirectory === null) { $codeCoverageCacheDirectory = 'null'; } else { $codeCoverageCacheDirectory = "'" . $codeCoverageCacheDirectory . "'"; } $bootstrap = ''; if (ConfigurationRegistry::get()->hasBootstrap()) { $bootstrap = ConfigurationRegistry::get()->bootstrap(); } $template->setVar( [ 'bootstrap' => $bootstrap, 'composerAutoload' => $composerAutoload, 'phar' => $phar, 'job' => $files['job'], 'coverageFile' => $files['coverage'], 'driverMethod' => $pathCoverage ? 'forLineAndPathCoverage' : 'forLineCoverage', 'codeCoverageCacheDirectory' => $codeCoverageCacheDirectory, ], ); file_put_contents($files['job'], $job); $job = $template->render(); assert($job !== ''); } private function cleanupForCoverage(): RawCodeCoverageData { $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); $files = $this->getCoverageFiles(); $buffer = false; if (is_file($files['coverage'])) { $buffer = @file_get_contents($files['coverage']); } if ($buffer !== false) { $coverage = @unserialize($buffer); if ($coverage === false) { $coverage = RawCodeCoverageData::fromXdebugWithoutPathCoverage([]); } } foreach ($files as $file) { @unlink($file); } return $coverage; } /** * @param array<non-empty-string, array<non-empty-string>|non-empty-string> $ini * * @return list<non-empty-string> */ private function stringifyIni(array $ini): array { $settings = []; foreach ($ini as $key => $value) { if (is_array($value)) { foreach ($value as $val) { $settings[] = $key . '=' . $val; } continue; } $settings[] = $key . '=' . $value; } return $settings; } /** * @param array<non-empty-string, non-empty-string> $sections * * @return non-empty-list<array{file: non-empty-string, line: int}> */ private function getLocationHintFromDiff(string $message, array $sections): array { $needle = ''; $previousLine = ''; $block = 'message'; foreach (preg_split('/\r\n|\r|\n/', $message) as $line) { $line = trim($line); if ($block === 'message' && $line === '--- Expected') { $block = 'expected'; } if ($block === 'expected' && $line === '@@ @@') { $block = 'diff'; } if ($block === 'diff') { if (str_starts_with($line, '+')) { $needle = $this->getCleanDiffLine($previousLine); break; } if (str_starts_with($line, '-')) { $needle = $this->getCleanDiffLine($line); break; } } if (!empty($line)) { $previousLine = $line; } } return $this->getLocationHint($needle, $sections); } private function getCleanDiffLine(string $line): string { if (preg_match('/^[\-+]([\'\"]?)(.*)\1$/', $line, $matches)) { $line = $matches[2]; } return $line; } /** * @param array<non-empty-string, non-empty-string> $sections * * @return non-empty-list<array{file: non-empty-string, line: int}> */ private function getLocationHint(string $needle, array $sections): array { $needle = trim($needle); if (empty($needle)) { return [[ 'file' => realpath($this->filename), 'line' => 1, ]]; } $search = [ // 'FILE', 'EXPECT', 'EXPECTF', 'EXPECTREGEX', ]; foreach ($search as $section) { if (!isset($sections[$section])) { continue; } if (isset($sections[$section . '_EXTERNAL'])) { $externalFile = trim($sections[$section . '_EXTERNAL']); return [ [ 'file' => realpath(dirname($this->filename) . DIRECTORY_SEPARATOR . $externalFile), 'line' => 1, ], [ 'file' => realpath($this->filename), 'line' => ($sections[$section . '_EXTERNAL_offset'] ?? 0) + 1, ], ]; } $sectionOffset = $sections[$section . '_offset'] ?? 0; $offset = $sectionOffset + 1; foreach (preg_split('/\r\n|\r|\n/', $sections[$section]) as $line) { if (str_contains($line, $needle)) { return [ [ 'file' => realpath($this->filename), 'line' => $offset, ], ]; } $offset++; } } return [ [ 'file' => realpath($this->filename), 'line' => 1, ], ]; } /** * @return list<string> */ private function settings(bool $collectCoverage): array { $settings = [ 'allow_url_fopen=1', 'auto_append_file=', 'auto_prepend_file=', 'disable_functions=', 'display_errors=1', 'docref_ext=.html', 'docref_root=', 'error_append_string=', 'error_prepend_string=', 'error_reporting=-1', 'html_errors=0', 'log_errors=0', 'open_basedir=', 'output_buffering=Off', 'output_handler=', 'report_memleaks=0', 'report_zend_debug=0', ]; if (extension_loaded('pcov')) { if ($collectCoverage) { $settings[] = 'pcov.enabled=1'; } else { $settings[] = 'pcov.enabled=0'; } } if (extension_loaded('xdebug')) { if ($collectCoverage) { $settings[] = 'xdebug.mode=coverage'; } else { $settings[] = 'xdebug.mode=off'; } } return $settings; } } phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionStartedSubscriber.php 0000644 00000002022 15253321353 0023767 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\GarbageCollection; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\TestRunner\ExecutionStarted; use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber as TestRunnerExecutionStartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionStartedSubscriber extends Subscriber implements TestRunnerExecutionStartedSubscriber { /** * @throws \PHPUnit\Framework\InvalidArgumentException * @throws InvalidArgumentException */ public function notify(ExecutionStarted $event): void { $this->handler()->executionStarted(); } } phpunit/src/Runner/GarbageCollection/Subscriber/TestFinishedSubscriber.php 0000644 00000001654 15253321353 0023100 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\GarbageCollection; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { /** * @throws \PHPUnit\Framework\InvalidArgumentException * @throws InvalidArgumentException */ public function notify(Finished $event): void { $this->handler()->testFinished(); } } phpunit/src/Runner/GarbageCollection/Subscriber/Subscriber.php 0000644 00000001447 15253321353 0020566 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\GarbageCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private GarbageCollectionHandler $handler; public function __construct(GarbageCollectionHandler $handler) { $this->handler = $handler; } protected function handler(): GarbageCollectionHandler { return $this->handler; } } phpunit/src/Runner/GarbageCollection/Subscriber/ExecutionFinishedSubscriber.php 0000644 00000002031 15253321353 0024112 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\GarbageCollection; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\TestRunner\ExecutionFinished; use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber as TestRunnerExecutionFinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionFinishedSubscriber extends Subscriber implements TestRunnerExecutionFinishedSubscriber { /** * @throws \PHPUnit\Framework\InvalidArgumentException * @throws InvalidArgumentException */ public function notify(ExecutionFinished $event): void { $this->handler()->executionFinished(); } } phpunit/src/Runner/GarbageCollection/GarbageCollectionHandler.php 0000644 00000004420 15253321353 0021214 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\GarbageCollection; use function gc_collect_cycles; use function gc_disable; use function gc_enable; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\UnknownSubscriberTypeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class GarbageCollectionHandler { private readonly Facade $facade; private readonly int $threshold; private int $tests = 0; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade, int $threshold) { $this->facade = $facade; $this->threshold = $threshold; $this->registerSubscribers(); } public function executionStarted(): void { gc_disable(); $this->facade->emitter()->testRunnerDisabledGarbageCollection(); gc_collect_cycles(); $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); } public function executionFinished(): void { gc_collect_cycles(); $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); gc_enable(); $this->facade->emitter()->testRunnerEnabledGarbageCollection(); } public function testFinished(): void { $this->tests++; if ($this->tests === $this->threshold) { gc_collect_cycles(); $this->facade->emitter()->testRunnerTriggeredGarbageCollection(); $this->tests = 0; } } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(): void { $this->facade->registerSubscribers( new ExecutionStartedSubscriber($this), new ExecutionFinishedSubscriber($this), new TestFinishedSubscriber($this), ); } } phpunit/src/Runner/Baseline/Baseline.php 0000644 00000003052 15253321353 0014252 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Baseline { public const VERSION = 1; /** * @var array<non-empty-string, array<positive-int, list<Issue>>> */ private array $issues = []; public function add(Issue $issue): void { if (!isset($this->issues[$issue->file()])) { $this->issues[$issue->file()] = []; } if (!isset($this->issues[$issue->file()][$issue->line()])) { $this->issues[$issue->file()][$issue->line()] = []; } $this->issues[$issue->file()][$issue->line()][] = $issue; } public function has(Issue $issue): bool { if (!isset($this->issues[$issue->file()][$issue->line()])) { return false; } foreach ($this->issues[$issue->file()][$issue->line()] as $_issue) { if ($_issue->equals($issue)) { return true; } } return false; } /** * @return array<string, array<positive-int, list<Issue>>> */ public function groupedByFileAndLine(): array { return $this->issues; } } phpunit/src/Runner/Baseline/RelativePathCalculator.php 0000644 00000005354 15253321353 0017141 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use function array_fill; use function array_merge; use function array_slice; use function assert; use function count; use function explode; use function implode; use function str_replace; use function strpos; use function substr; use function trim; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @see Copied from https://github.com/phpstan/phpstan-src/blob/1.10.33/src/File/ParentDirectoryRelativePathHelper.php */ final readonly class RelativePathCalculator { /** * @var non-empty-string */ private string $baselineDirectory; /** * @param non-empty-string $baselineDirectory */ public function __construct(string $baselineDirectory) { $this->baselineDirectory = $baselineDirectory; } /** * @param non-empty-string $filename * * @return non-empty-string */ public function calculate(string $filename): string { $result = implode('/', $this->parts($filename)); assert($result !== ''); return $result; } /** * @param non-empty-string $filename * * @return list<non-empty-string> */ public function parts(string $filename): array { $schemePosition = strpos($filename, '://'); if ($schemePosition !== false) { $filename = substr($filename, $schemePosition + 3); assert($filename !== ''); } $parentParts = explode('/', trim(str_replace('\\', '/', $this->baselineDirectory), '/')); $parentPartsCount = count($parentParts); $filenameParts = explode('/', trim(str_replace('\\', '/', $filename), '/')); $filenamePartsCount = count($filenameParts); $i = 0; for (; $i < $filenamePartsCount; $i++) { if ($parentPartsCount < $i + 1) { break; } $parentPath = implode('/', array_slice($parentParts, 0, $i + 1)); $filenamePath = implode('/', array_slice($filenameParts, 0, $i + 1)); if ($parentPath !== $filenamePath) { break; } } if ($i === 0) { return [$filename]; } $dotsCount = $parentPartsCount - $i; assert($dotsCount >= 0); return array_merge(array_fill(0, $dotsCount, '..'), array_slice($filenameParts, $i)); } } phpunit/src/Runner/Baseline/Exception/FileDoesNotHaveLineException.php 0000644 00000001606 15253321353 0022137 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use function sprintf; use PHPUnit\Runner\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class FileDoesNotHaveLineException extends RuntimeException implements Exception { public function __construct(string $file, int $line) { parent::__construct( sprintf( 'File "%s" does not have line %d', $file, $line, ), ); } } phpunit/src/Runner/Baseline/Exception/CannotLoadBaselineException.php 0000644 00000001175 15253321353 0022036 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Runner\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CannotLoadBaselineException extends RuntimeException implements Exception { } phpunit/src/Runner/Baseline/Writer.php 0000644 00000003675 15253321353 0014017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use function assert; use function dirname; use function file_put_contents; use XMLWriter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Writer { /** * @param non-empty-string $baselineFile */ public function write(string $baselineFile, Baseline $baseline): void { $pathCalculator = new RelativePathCalculator(dirname($baselineFile)); $writer = new XMLWriter; $writer->openMemory(); $writer->setIndent(true); $writer->startDocument(); $writer->startElement('files'); $writer->writeAttribute('version', (string) Baseline::VERSION); foreach ($baseline->groupedByFileAndLine() as $file => $lines) { assert(!empty($file)); $writer->startElement('file'); $writer->writeAttribute('path', $pathCalculator->calculate($file)); foreach ($lines as $line => $issues) { $writer->startElement('line'); $writer->writeAttribute('number', (string) $line); $writer->writeAttribute('hash', $issues[0]->hash()); foreach ($issues as $issue) { $writer->startElement('issue'); $writer->writeCData($issue->description()); $writer->endElement(); } $writer->endElement(); } $writer->endElement(); } $writer->endElement(); file_put_contents($baselineFile, $writer->outputMemory()); } } phpunit/src/Runner/Baseline/Reader.php 0000644 00000006136 15253321353 0013740 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use const DIRECTORY_SEPARATOR; use function assert; use function dirname; use function file_exists; use function realpath; use function sprintf; use function str_replace; use function trim; use DOMElement; use DOMXPath; use PHPUnit\Util\Xml\Loader as XmlLoader; use PHPUnit\Util\Xml\XmlException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Reader { /** * @param non-empty-string $baselineFile * * @throws CannotLoadBaselineException */ public function read(string $baselineFile): Baseline { if (!file_exists($baselineFile)) { throw new CannotLoadBaselineException( sprintf( 'Cannot read baseline %s, file does not exist', $baselineFile, ), ); } try { $document = (new XmlLoader)->loadFile($baselineFile); } catch (XmlException $e) { throw new CannotLoadBaselineException( sprintf( 'Cannot read baseline: %s', trim($e->getMessage()), ), ); } $version = (int) $document->documentElement->getAttribute('version'); if ($version !== Baseline::VERSION) { throw new CannotLoadBaselineException( sprintf( 'Cannot read baseline %s, version %d is not supported', $baselineFile, $version, ), ); } $baseline = new Baseline; $baselineDirectory = dirname(realpath($baselineFile)); $xpath = new DOMXPath($document); foreach ($xpath->query('file') as $fileElement) { assert($fileElement instanceof DOMElement); $file = $baselineDirectory . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $fileElement->getAttribute('path')); foreach ($xpath->query('line', $fileElement) as $lineElement) { assert($lineElement instanceof DOMElement); $line = (int) $lineElement->getAttribute('number'); $hash = $lineElement->getAttribute('hash'); foreach ($xpath->query('issue', $lineElement) as $issueElement) { assert($issueElement instanceof DOMElement); $description = $issueElement->textContent; assert($line > 0); assert(!empty($hash)); assert(!empty($description)); $baseline->add(Issue::from($file, $line, $hash, $description)); } } } return $baseline; } } phpunit/src/Runner/Baseline/Generator.php 0000644 00000007662 15253321353 0014471 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Runner\FileDoesNotExistException; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\SourceFilter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Generator { private Baseline $baseline; private Source $source; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade, Source $source) { $facade->registerSubscribers( new TestTriggeredDeprecationSubscriber($this), new TestTriggeredNoticeSubscriber($this), new TestTriggeredPhpDeprecationSubscriber($this), new TestTriggeredPhpNoticeSubscriber($this), new TestTriggeredPhpWarningSubscriber($this), new TestTriggeredWarningSubscriber($this), ); $this->baseline = new Baseline; $this->source = $source; } public function baseline(): Baseline { return $this->baseline; } /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function testTriggeredIssue(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): void { if ($event->wasSuppressed() && !$this->isSuppressionIgnored($event)) { return; } if ($this->restrict($event) && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $this->baseline->add( Issue::from( $event->file(), $event->line(), null, $event->message(), ), ); } private function restrict(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): bool { if ($event instanceof WarningTriggered || $event instanceof PhpWarningTriggered) { return $this->source->restrictWarnings(); } if ($event instanceof NoticeTriggered || $event instanceof PhpNoticeTriggered) { return $this->source->restrictNotices(); } return $this->source->restrictDeprecations(); } private function isSuppressionIgnored(DeprecationTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): bool { if ($event instanceof WarningTriggered) { return $this->source->ignoreSuppressionOfWarnings(); } if ($event instanceof PhpWarningTriggered) { return $this->source->ignoreSuppressionOfPhpWarnings(); } if ($event instanceof PhpNoticeTriggered) { return $this->source->ignoreSuppressionOfPhpNotices(); } if ($event instanceof NoticeTriggered) { return $this->source->ignoreSuppressionOfNotices(); } if ($event instanceof PhpDeprecationTriggered) { return $this->source->ignoreSuppressionOfPhpDeprecations(); } return $this->source->ignoreSuppressionOfDeprecations(); } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredNoticeSubscriber.php 0000644 00000001710 15253321353 0022574 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\NoticeTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(NoticeTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpDeprecationSubscriber.php 0000644 00000001760 15253321353 0024265 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(PhpDeprecationTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredWarningSubscriber.php 0000644 00000001715 15253321353 0022765 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\Test\WarningTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(WarningTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Subscriber/Subscriber.php 0000644 00000001375 15253321353 0016744 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private Generator $generator; public function __construct(Generator $generator) { $this->generator = $generator; } protected function generator(): Generator { return $this->generator; } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpNoticeSubscriber.php 0000644 00000001727 15253321353 0023254 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(PhpNoticeTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredPhpWarningSubscriber.php 0000644 00000001734 15253321353 0023436 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(PhpWarningTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Subscriber/TestTriggeredDeprecationSubscriber.php 0000644 00000001741 15253321353 0023614 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { /** * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public function notify(DeprecationTriggered $event): void { $this->generator()->testTriggeredIssue($event); } } phpunit/src/Runner/Baseline/Issue.php 0000644 00000006542 15253321353 0013627 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Baseline; use const FILE_IGNORE_NEW_LINES; use function assert; use function file; use function is_file; use function sha1; use PHPUnit\Runner\FileDoesNotExistException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Issue { /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; /** * @var non-empty-string */ private string $hash; /** * @var non-empty-string */ private string $description; /** * @param non-empty-string $file * @param positive-int $line * @param ?non-empty-string $hash * @param non-empty-string $description * * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException */ public static function from(string $file, int $line, ?string $hash, string $description): self { if ($hash === null) { $hash = self::calculateHash($file, $line); } return new self($file, $line, $hash, $description); } /** * @param non-empty-string $file * @param positive-int $line * @param non-empty-string $hash * @param non-empty-string $description */ private function __construct(string $file, int $line, string $hash, string $description) { $this->file = $file; $this->line = $line; $this->hash = $hash; $this->description = $description; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } /** * @return non-empty-string */ public function hash(): string { return $this->hash; } /** * @return non-empty-string */ public function description(): string { return $this->description; } public function equals(self $other): bool { return $this->file() === $other->file() && $this->line() === $other->line() && $this->hash() === $other->hash() && $this->description() === $other->description(); } /** * @param non-empty-string $file * @param positive-int $line * * @throws FileDoesNotExistException * @throws FileDoesNotHaveLineException * * @return non-empty-string */ private static function calculateHash(string $file, int $line): string { $lines = @file($file, FILE_IGNORE_NEW_LINES); if ($lines === false && !is_file($file)) { throw new FileDoesNotExistException($file); } $key = $line - 1; if (!isset($lines[$key])) { throw new FileDoesNotHaveLineException($file, $line); } $hash = sha1($lines[$key]); assert($hash !== ''); return $hash; } } phpunit/src/Runner/DeprecationCollector/Collector.php 0000644 00000002722 15253321353 0017043 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\DeprecationCollector; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\UnknownSubscriberTypeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Collector { /** * @var list<non-empty-string> */ private array $deprecations = []; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade) { $facade->registerSubscribers( new TestPreparedSubscriber($this), new TestTriggeredDeprecationSubscriber($this), ); } /** * @return list<non-empty-string> */ public function deprecations(): array { return $this->deprecations; } public function testPrepared(): void { $this->deprecations = []; } public function testTriggeredDeprecation(DeprecationTriggered $event): void { $this->deprecations[] = $event->message(); } } phpunit/src/Runner/DeprecationCollector/Subscriber/Subscriber.php 0000644 00000001411 15253321353 0021315 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\DeprecationCollector; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract class Subscriber { private readonly Collector $collector; public function __construct(Collector $collector) { $this->collector = $collector; } protected function collector(): Collector { return $this->collector; } } phpunit/src/Runner/DeprecationCollector/Subscriber/TestPreparedSubscriber.php 0000644 00000001411 15253321353 0023640 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\DeprecationCollector; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->collector()->testPrepared(); } } phpunit/src/Runner/DeprecationCollector/Subscriber/TestTriggeredDeprecationSubscriber.php 0000644 00000001527 15253321353 0026200 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\DeprecationCollector; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { public function notify(DeprecationTriggered $event): void { $this->collector()->testTriggeredDeprecation($event); } } phpunit/src/Runner/DeprecationCollector/Facade.php 0000644 00000002725 15253321353 0016263 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\DeprecationCollector; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\UnknownSubscriberTypeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Facade { private static ?Collector $collector = null; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public static function init(): void { self::collector(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException * * @return list<non-empty-string> */ public static function deprecations(): array { return self::collector()->deprecations(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private static function collector(): Collector { if (self::$collector === null) { self::$collector = new Collector(EventFacade::instance()); } return self::$collector; } } phpunit/src/Runner/HookMethod/HookMethod.php 0000644 00000002254 15253321353 0015113 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class HookMethod { /** * @var non-empty-string */ private string $methodName; /** * @var non-negative-int */ private int $priority; /** * @param non-empty-string $methodName * @param non-negative-int $priority */ public function __construct(string $methodName, int $priority) { $this->methodName = $methodName; $this->priority = $priority; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Runner/HookMethod/HookMethodCollection.php 0000644 00000004502 15253321353 0017125 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function array_map; use function usort; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class HookMethodCollection { private readonly bool $shouldPrepend; /** * @var non-empty-list<HookMethod> */ private array $hookMethods; public static function defaultBeforeClass(): self { return new self(new HookMethod('setUpBeforeClass', 0), true); } public static function defaultBefore(): self { return new self(new HookMethod('setUp', 0), true); } public static function defaultPreCondition(): self { return new self(new HookMethod('assertPreConditions', 0), true); } public static function defaultPostCondition(): self { return new self(new HookMethod('assertPostConditions', 0), false); } public static function defaultAfter(): self { return new self(new HookMethod('tearDown', 0), false); } public static function defaultAfterClass(): self { return new self(new HookMethod('tearDownAfterClass', 0), false); } private function __construct(HookMethod $default, bool $shouldPrepend) { $this->hookMethods = [$default]; $this->shouldPrepend = $shouldPrepend; } public function add(HookMethod $hookMethod): self { if ($this->shouldPrepend) { $this->hookMethods = [$hookMethod, ...$this->hookMethods]; } else { $this->hookMethods[] = $hookMethod; } return $this; } /** * @return list<non-empty-string> */ public function methodNamesSortedByPriority(): array { $hookMethods = $this->hookMethods; usort($hookMethods, static fn (HookMethod $a, HookMethod $b) => $b->priority() <=> $a->priority()); return array_map( static fn (HookMethod $hookMethod) => $hookMethod->methodName(), $hookMethods, ); } } phpunit/src/Runner/Version.php 0000644 00000003307 15253321353 0012436 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use function array_slice; use function dirname; use function explode; use function implode; use function str_contains; use SebastianBergmann\Version as VersionId; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class Version { private static string $pharVersion = ''; private static string $version = ''; /** * @return non-empty-string */ public static function id(): string { if (self::$pharVersion !== '') { return self::$pharVersion; } if (self::$version === '') { self::$version = (new VersionId('11.3.1', dirname(__DIR__, 2)))->asString(); } return self::$version; } /** * @return non-empty-string */ public static function series(): string { if (str_contains(self::id(), '-')) { $version = explode('-', self::id(), 2)[0]; } else { $version = self::id(); } return implode('.', array_slice(explode('.', $version), 0, 2)); } /** * @return positive-int */ public static function majorVersionNumber(): int { return (int) explode('.', self::series())[0]; } /** * @return non-empty-string */ public static function getVersionString(): string { return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.'; } } phpunit/src/Runner/TestResult/Collector.php 0000644 00000046765 15253321353 0015074 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use function array_values; use function assert; use function implode; use function str_contains; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErrorTriggered; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\Skipped as TestSkipped; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\TestRunner\DeprecationTriggered as TestRunnerDeprecationTriggered; use PHPUnit\Event\TestRunner\ExecutionStarted; use PHPUnit\Event\TestRunner\WarningTriggered as TestRunnerWarningTriggered; use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; use PHPUnit\Event\TestSuite\TestSuiteForTestClass; use PHPUnit\Event\TestSuite\TestSuiteForTestMethodWithDataProvider; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\TestRunner\TestResult\Issues\Issue; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\SourceFilter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Collector { private readonly Source $source; private int $numberOfTests = 0; private int $numberOfTestsRun = 0; private int $numberOfAssertions = 0; private bool $prepared = false; private bool $currentTestSuiteForTestClassFailed = false; /** * @var non-negative-int */ private int $numberOfIssuesIgnoredByBaseline = 0; /** * @var list<BeforeFirstTestMethodErrored|Errored> */ private array $testErroredEvents = []; /** * @var list<Failed> */ private array $testFailedEvents = []; /** * @var list<MarkedIncomplete> */ private array $testMarkedIncompleteEvents = []; /** * @var list<TestSuiteSkipped> */ private array $testSuiteSkippedEvents = []; /** * @var list<TestSkipped> */ private array $testSkippedEvents = []; /** * @var array<string,list<ConsideredRisky>> */ private array $testConsideredRiskyEvents = []; /** * @var array<string,list<PhpunitDeprecationTriggered>> */ private array $testTriggeredPhpunitDeprecationEvents = []; /** * @var array<string,list<PhpunitErrorTriggered>> */ private array $testTriggeredPhpunitErrorEvents = []; /** * @var array<string,list<PhpunitWarningTriggered>> */ private array $testTriggeredPhpunitWarningEvents = []; /** * @var list<TestRunnerWarningTriggered> */ private array $testRunnerTriggeredWarningEvents = []; /** * @var list<TestRunnerDeprecationTriggered> */ private array $testRunnerTriggeredDeprecationEvents = []; /** * @var array<non-empty-string, Issue> */ private array $errors = []; /** * @var array<non-empty-string, Issue> */ private array $deprecations = []; /** * @var array<non-empty-string, Issue> */ private array $notices = []; /** * @var array<non-empty-string, Issue> */ private array $warnings = []; /** * @var array<non-empty-string, Issue> */ private array $phpDeprecations = []; /** * @var array<non-empty-string, Issue> */ private array $phpNotices = []; /** * @var array<non-empty-string, Issue> */ private array $phpWarnings = []; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade, Source $source) { $facade->registerSubscribers( new ExecutionStartedSubscriber($this), new TestSuiteSkippedSubscriber($this), new TestSuiteStartedSubscriber($this), new TestSuiteFinishedSubscriber($this), new TestPreparedSubscriber($this), new TestFinishedSubscriber($this), new BeforeTestClassMethodErroredSubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestSkippedSubscriber($this), new TestConsideredRiskySubscriber($this), new TestTriggeredDeprecationSubscriber($this), new TestTriggeredErrorSubscriber($this), new TestTriggeredNoticeSubscriber($this), new TestTriggeredPhpDeprecationSubscriber($this), new TestTriggeredPhpNoticeSubscriber($this), new TestTriggeredPhpunitDeprecationSubscriber($this), new TestTriggeredPhpunitErrorSubscriber($this), new TestTriggeredPhpunitWarningSubscriber($this), new TestTriggeredPhpWarningSubscriber($this), new TestTriggeredWarningSubscriber($this), new TestRunnerTriggeredDeprecationSubscriber($this), new TestRunnerTriggeredWarningSubscriber($this), ); $this->source = $source; } public function result(): TestResult { return new TestResult( $this->numberOfTests, $this->numberOfTestsRun, $this->numberOfAssertions, $this->testErroredEvents, $this->testFailedEvents, $this->testConsideredRiskyEvents, $this->testSuiteSkippedEvents, $this->testSkippedEvents, $this->testMarkedIncompleteEvents, $this->testTriggeredPhpunitDeprecationEvents, $this->testTriggeredPhpunitErrorEvents, $this->testTriggeredPhpunitWarningEvents, $this->testRunnerTriggeredDeprecationEvents, $this->testRunnerTriggeredWarningEvents, array_values($this->errors), array_values($this->deprecations), array_values($this->notices), array_values($this->warnings), array_values($this->phpDeprecations), array_values($this->phpNotices), array_values($this->phpWarnings), $this->numberOfIssuesIgnoredByBaseline, ); } public function executionStarted(ExecutionStarted $event): void { $this->numberOfTests = $event->testSuite()->count(); } public function testSuiteSkipped(TestSuiteSkipped $event): void { $testSuite = $event->testSuite(); if (!$testSuite->isForTestClass()) { return; } $this->testSuiteSkippedEvents[] = $event; } public function testSuiteStarted(TestSuiteStarted $event): void { $testSuite = $event->testSuite(); if (!$testSuite->isForTestClass()) { return; } $this->currentTestSuiteForTestClassFailed = false; } public function testSuiteFinished(TestSuiteFinished $event): void { if ($this->currentTestSuiteForTestClassFailed) { return; } $testSuite = $event->testSuite(); if ($testSuite->isWithName()) { return; } if ($testSuite->isForTestMethodWithDataProvider()) { assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); $test = $testSuite->tests()->asArray()[0]; assert($test instanceof TestMethod); PassedTests::instance()->testMethodPassed($test, null); return; } assert($testSuite instanceof TestSuiteForTestClass); PassedTests::instance()->testClassPassed($testSuite->className()); } public function testPrepared(): void { $this->prepared = true; } public function testFinished(Finished $event): void { $this->numberOfAssertions += $event->numberOfAssertionsPerformed(); $this->numberOfTestsRun++; $this->prepared = false; } public function beforeTestClassMethodErrored(BeforeFirstTestMethodErrored $event): void { $this->testErroredEvents[] = $event; $this->numberOfTestsRun++; } public function testErrored(Errored $event): void { $this->testErroredEvents[] = $event; $this->currentTestSuiteForTestClassFailed = true; /* * @todo Eliminate this special case */ if (str_contains($event->asString(), 'Test was run in child process and ended unexpectedly')) { return; } if (!$this->prepared) { $this->numberOfTestsRun++; } } public function testFailed(Failed $event): void { $this->testFailedEvents[] = $event; $this->currentTestSuiteForTestClassFailed = true; } public function testMarkedIncomplete(MarkedIncomplete $event): void { $this->testMarkedIncompleteEvents[] = $event; } public function testSkipped(TestSkipped $event): void { $this->testSkippedEvents[] = $event; if (!$this->prepared) { $this->numberOfTestsRun++; } } public function testConsideredRisky(ConsideredRisky $event): void { if (!isset($this->testConsideredRiskyEvents[$event->test()->id()])) { $this->testConsideredRiskyEvents[$event->test()->id()] = []; } $this->testConsideredRiskyEvents[$event->test()->id()][] = $event; } public function testTriggeredDeprecation(DeprecationTriggered $event): void { if ($event->ignoredByTest()) { return; } if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if ($this->source->ignoreSelfDeprecations() && $event->trigger()->isSelf()) { return; } if ($this->source->ignoreDirectDeprecations() && $event->trigger()->isDirect()) { return; } if ($this->source->ignoreIndirectDeprecations() && $event->trigger()->isIndirect()) { return; } if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->deprecations[$id])) { $this->deprecations[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->deprecations[$id]->triggeredBy($event->test()); } public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void { if ($event->ignoredByTest()) { return; } if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if ($this->source->ignoreSelfDeprecations() && $event->trigger()->isSelf()) { return; } if ($this->source->ignoreDirectDeprecations() && $event->trigger()->isDirect()) { return; } if ($this->source->ignoreIndirectDeprecations() && $event->trigger()->isIndirect()) { return; } if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->phpDeprecations[$id])) { $this->phpDeprecations[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->phpDeprecations[$id]->triggeredBy($event->test()); } public function testTriggeredPhpunitDeprecation(PhpunitDeprecationTriggered $event): void { if (!isset($this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()])) { $this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()] = []; } $this->testTriggeredPhpunitDeprecationEvents[$event->test()->id()][] = $event; } public function testTriggeredError(ErrorTriggered $event): void { if (!$this->source->ignoreSuppressionOfErrors() && $event->wasSuppressed()) { return; } $id = $this->issueId($event); if (!isset($this->errors[$id])) { $this->errors[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->errors[$id]->triggeredBy($event->test()); } public function testTriggeredNotice(NoticeTriggered $event): void { if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->notices[$id])) { $this->notices[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->notices[$id]->triggeredBy($event->test()); } public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void { if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->phpNotices[$id])) { $this->phpNotices[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->phpNotices[$id]->triggeredBy($event->test()); } public function testTriggeredWarning(WarningTriggered $event): void { if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->warnings[$id])) { $this->warnings[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->warnings[$id]->triggeredBy($event->test()); } public function testTriggeredPhpWarning(PhpWarningTriggered $event): void { if ($event->ignoredByBaseline()) { $this->numberOfIssuesIgnoredByBaseline++; return; } if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } $id = $this->issueId($event); if (!isset($this->phpWarnings[$id])) { $this->phpWarnings[$id] = Issue::from( $event->file(), $event->line(), $event->message(), $event->test(), ); return; } $this->phpWarnings[$id]->triggeredBy($event->test()); } public function testTriggeredPhpunitError(PhpunitErrorTriggered $event): void { if (!isset($this->testTriggeredPhpunitErrorEvents[$event->test()->id()])) { $this->testTriggeredPhpunitErrorEvents[$event->test()->id()] = []; } $this->testTriggeredPhpunitErrorEvents[$event->test()->id()][] = $event; } public function testTriggeredPhpunitWarning(PhpunitWarningTriggered $event): void { if (!isset($this->testTriggeredPhpunitWarningEvents[$event->test()->id()])) { $this->testTriggeredPhpunitWarningEvents[$event->test()->id()] = []; } $this->testTriggeredPhpunitWarningEvents[$event->test()->id()][] = $event; } public function testRunnerTriggeredDeprecation(TestRunnerDeprecationTriggered $event): void { $this->testRunnerTriggeredDeprecationEvents[] = $event; } public function testRunnerTriggeredWarning(TestRunnerWarningTriggered $event): void { $this->testRunnerTriggeredWarningEvents[] = $event; } public function hasErroredTests(): bool { return !empty($this->testErroredEvents); } public function hasFailedTests(): bool { return !empty($this->testFailedEvents); } public function hasRiskyTests(): bool { return !empty($this->testConsideredRiskyEvents); } public function hasSkippedTests(): bool { return !empty($this->testSkippedEvents); } public function hasIncompleteTests(): bool { return !empty($this->testMarkedIncompleteEvents); } public function hasDeprecations(): bool { return !empty($this->deprecations) || !empty($this->phpDeprecations) || !empty($this->testTriggeredPhpunitDeprecationEvents) || !empty($this->testRunnerTriggeredDeprecationEvents); } public function hasNotices(): bool { return !empty($this->notices) || !empty($this->phpNotices); } public function hasWarnings(): bool { return !empty($this->warnings) || !empty($this->phpWarnings) || !empty($this->testTriggeredPhpunitWarningEvents) || !empty($this->testRunnerTriggeredWarningEvents); } /** * @return non-empty-string */ private function issueId(DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpWarningTriggered|WarningTriggered $event): string { return implode(':', [$event->file(), $event->line(), $event->message()]); } } phpunit/src/Runner/TestResult/PassedTests.php 0000644 00000006017 15253321353 0015372 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use function array_merge; use function assert; use function in_array; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Framework\TestSize\Known; use PHPUnit\Framework\TestSize\TestSize; use PHPUnit\Metadata\Api\Groups; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class PassedTests { private static ?self $instance = null; /** * @var list<class-string> */ private array $passedTestClasses = []; /** * @var array<string,array{returnValue: mixed, size: TestSize}> */ private array $passedTestMethods = []; public static function instance(): self { if (self::$instance !== null) { return self::$instance; } self::$instance = new self; return self::$instance; } /** * @param class-string $className */ public function testClassPassed(string $className): void { $this->passedTestClasses[] = $className; } public function testMethodPassed(TestMethod $test, mixed $returnValue): void { $size = (new Groups)->size( $test->className(), $test->methodName(), ); $this->passedTestMethods[$test->className() . '::' . $test->methodName()] = [ 'returnValue' => $returnValue, 'size' => $size, ]; } public function import(self $other): void { $this->passedTestClasses = array_merge( $this->passedTestClasses, $other->passedTestClasses, ); $this->passedTestMethods = array_merge( $this->passedTestMethods, $other->passedTestMethods, ); } /** * @param class-string $className */ public function hasTestClassPassed(string $className): bool { return in_array($className, $this->passedTestClasses, true); } public function hasTestMethodPassed(string $method): bool { return isset($this->passedTestMethods[$method]); } public function isGreaterThan(string $method, TestSize $other): bool { if ($other->isUnknown()) { return false; } assert($other instanceof Known); $size = $this->passedTestMethods[$method]['size']; if ($size->isUnknown()) { return false; } assert($size instanceof Known); return $size->isGreaterThan($other); } public function returnValue(string $method): mixed { if (isset($this->passedTestMethods[$method])) { return $this->passedTestMethods[$method]['returnValue']; } return null; } } phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredDeprecationSubscriber.php 0000644 00000001562 15253321353 0025403 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestRunner\DeprecationTriggered; use PHPUnit\Event\TestRunner\DeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestRunnerTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { public function notify(DeprecationTriggered $event): void { $this->collector()->testRunnerTriggeredDeprecation($event); } } phpunit/src/Runner/TestResult/Subscriber/TestSuiteStartedSubscriber.php 0000644 00000001440 15253321353 0022532 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestSuite\Started; use PHPUnit\Event\TestSuite\StartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber { public function notify(Started $event): void { $this->collector()->testSuiteStarted($event); } } phpunit/src/Runner/TestResult/Subscriber/TestRunnerTriggeredWarningSubscriber.php 0000644 00000001532 15253321353 0024550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestRunner\WarningTriggered; use PHPUnit\Event\TestRunner\WarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestRunnerTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber { public function notify(WarningTriggered $event): void { $this->collector()->testRunnerTriggeredWarning($event); } } phpunit/src/Runner/TestResult/Subscriber/ExecutionStartedSubscriber.php 0000644 00000001570 15253321353 0022550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestRunner\ExecutionStarted; use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber as TestRunnerExecutionStartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionStartedSubscriber extends Subscriber implements TestRunnerExecutionStartedSubscriber { public function notify(ExecutionStarted $event): void { $this->collector()->executionStarted($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php 0000644 00000001540 15253321353 0024411 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitErrorSubscriber extends Subscriber implements PhpunitErrorTriggeredSubscriber { public function notify(PhpunitErrorTriggered $event): void { $this->collector()->testTriggeredPhpunitError($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php 0000644 00000001474 15253321353 0023177 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\NoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber { public function notify(NoticeTriggered $event): void { $this->collector()->testTriggeredNotice($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php 0000644 00000001554 15253321353 0024662 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber { public function notify(PhpDeprecationTriggered $event): void { $this->collector()->testTriggeredPhpDeprecation($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php 0000644 00000001604 15253321353 0025556 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber { public function notify(PhpunitDeprecationTriggered $event): void { $this->collector()->testTriggeredPhpunitDeprecation($event); } } phpunit/src/Runner/TestResult/Subscriber/TestErroredSubscriber.php 0000644 00000001414 15253321353 0021515 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { public function notify(Errored $event): void { $this->collector()->testErrored($event); } } phpunit/src/Runner/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001502 15253321353 0023334 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { public function notify(MarkedIncomplete $event): void { $this->collector()->testMarkedIncomplete($event); } } phpunit/src/Runner/TestResult/Subscriber/TestFinishedSubscriber.php 0000644 00000001422 15253321353 0021643 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->collector()->testFinished($event); } } phpunit/src/Runner/TestResult/Subscriber/BeforeTestClassMethodErroredSubscriber.php 0000644 00000001602 15253321353 0024766 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\BeforeFirstTestMethodErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeTestClassMethodErroredSubscriber extends Subscriber implements BeforeFirstTestMethodErroredSubscriber { public function notify(BeforeFirstTestMethodErrored $event): void { $this->collector()->beforeTestClassMethodErrored($event); } } phpunit/src/Runner/TestResult/Subscriber/TestSuiteSkippedSubscriber.php 0000644 00000001440 15253321353 0022523 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestSuite\Skipped; use PHPUnit\Event\TestSuite\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteSkippedSubscriber extends Subscriber implements SkippedSubscriber { public function notify(Skipped $event): void { $this->collector()->testSuiteSkipped($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredWarningSubscriber.php 0000644 00000001502 15253321353 0023353 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\Test\WarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber { public function notify(WarningTriggered $event): void { $this->collector()->testTriggeredWarning($event); } } phpunit/src/Runner/TestResult/Subscriber/Subscriber.php 0000644 00000001403 15253321353 0017330 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private Collector $collector; public function __construct(Collector $collector) { $this->collector = $collector; } protected function collector(): Collector { return $this->collector; } } phpunit/src/Runner/TestResult/Subscriber/TestFailedSubscriber.php 0000644 00000001406 15253321353 0021300 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { public function notify(Failed $event): void { $this->collector()->testFailed($event); } } phpunit/src/Runner/TestResult/Subscriber/TestPreparedSubscriber.php 0000644 00000001414 15253321353 0021655 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->collector()->testPrepared(); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php 0000644 00000001516 15253321353 0023644 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber { public function notify(PhpNoticeTriggered $event): void { $this->collector()->testTriggeredPhpNotice($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php 0000644 00000001554 15253321353 0024732 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber { public function notify(PhpunitWarningTriggered $event): void { $this->collector()->testTriggeredPhpunitWarning($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php 0000644 00000001524 15253321353 0024027 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber { public function notify(PhpWarningTriggered $event): void { $this->collector()->testTriggeredPhpWarning($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredErrorSubscriber.php 0000644 00000001466 15253321353 0023050 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\ErrorTriggered; use PHPUnit\Event\Test\ErrorTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredErrorSubscriber extends Subscriber implements ErrorTriggeredSubscriber { public function notify(ErrorTriggered $event): void { $this->collector()->testTriggeredError($event); } } phpunit/src/Runner/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php 0000644 00000001532 15253321353 0024206 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { public function notify(DeprecationTriggered $event): void { $this->collector()->testTriggeredDeprecation($event); } } phpunit/src/Runner/TestResult/Subscriber/TestSkippedSubscriber.php 0000644 00000001414 15253321353 0021512 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { public function notify(Skipped $event): void { $this->collector()->testSkipped($event); } } phpunit/src/Runner/TestResult/Subscriber/TestConsideredRiskySubscriber.php 0000644 00000001474 15253321353 0023222 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\ConsideredRiskySubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber { public function notify(ConsideredRisky $event): void { $this->collector()->testConsideredRisky($event); } } phpunit/src/Runner/TestResult/Subscriber/TestSuiteFinishedSubscriber.php 0000644 00000001446 15253321353 0022663 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\TestSuite\Finished; use PHPUnit\Event\TestSuite\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->collector()->testSuiteFinished($event); } } phpunit/src/Runner/TestResult/Issue.php 0000644 00000005204 15253321353 0014215 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult\Issues; use PHPUnit\Event\Code\Test; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Issue { /** * @var non-empty-string */ private readonly string $file; /** * @var positive-int */ private readonly int $line; /** * @var non-empty-string */ private readonly string $description; /** * @var non-empty-array<non-empty-string, array{test: Test, count: int}> */ private array $triggeringTests; /** * @param non-empty-string $file * @param positive-int $line * @param non-empty-string $description */ public static function from(string $file, int $line, string $description, Test $triggeringTest): self { return new self($file, $line, $description, $triggeringTest); } /** * @param non-empty-string $file * @param positive-int $line * @param non-empty-string $description */ private function __construct(string $file, int $line, string $description, Test $triggeringTest) { $this->file = $file; $this->line = $line; $this->description = $description; $this->triggeringTests = [ $triggeringTest->id() => [ 'test' => $triggeringTest, 'count' => 1, ], ]; } public function triggeredBy(Test $test): void { if (isset($this->triggeringTests[$test->id()])) { $this->triggeringTests[$test->id()]['count']++; return; } $this->triggeringTests[$test->id()] = [ 'test' => $test, 'count' => 1, ]; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } /** * @return non-empty-string */ public function description(): string { return $this->description; } /** * @return non-empty-array<non-empty-string, array{test: Test, count: int}> */ public function triggeringTests(): array { return $this->triggeringTests; } } phpunit/src/Runner/TestResult/Facade.php 0000644 00000005654 15253321353 0014301 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Facade { private static ?Collector $collector = null; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public static function init(): void { self::collector(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public static function result(): TestResult { return self::collector()->result(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public static function shouldStop(): bool { $configuration = ConfigurationRegistry::get(); $collector = self::collector(); if (($configuration->stopOnDefect() || $configuration->stopOnError()) && $collector->hasErroredTests()) { return true; } if (($configuration->stopOnDefect() || $configuration->stopOnFailure()) && $collector->hasFailedTests()) { return true; } if (($configuration->stopOnDefect() || $configuration->stopOnWarning()) && $collector->hasWarnings()) { return true; } if (($configuration->stopOnDefect() || $configuration->stopOnRisky()) && $collector->hasRiskyTests()) { return true; } if ($configuration->stopOnDeprecation() && $collector->hasDeprecations()) { return true; } if ($configuration->stopOnNotice() && $collector->hasNotices()) { return true; } if ($configuration->stopOnIncomplete() && $collector->hasIncompleteTests()) { return true; } if ($configuration->stopOnSkipped() && $collector->hasSkippedTests()) { return true; } return false; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private static function collector(): Collector { if (self::$collector === null) { $configuration = ConfigurationRegistry::get(); self::$collector = new Collector( EventFacade::instance(), $configuration->source(), ); } return self::$collector; } } phpunit/src/Runner/TestResult/TestResult.php 0000644 00000037606 15253321353 0015256 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TestRunner\TestResult; use function count; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\Skipped as TestSkipped; use PHPUnit\Event\TestRunner\DeprecationTriggered as TestRunnerDeprecationTriggered; use PHPUnit\Event\TestRunner\WarningTriggered as TestRunnerWarningTriggered; use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; use PHPUnit\TestRunner\TestResult\Issues\Issue; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestResult { private int $numberOfTests; private int $numberOfTestsRun; private int $numberOfAssertions; /** * @var list<BeforeFirstTestMethodErrored|Errored> */ private array $testErroredEvents; /** * @var list<Failed> */ private array $testFailedEvents; /** * @var list<MarkedIncomplete> */ private array $testMarkedIncompleteEvents; /** * @var list<TestSuiteSkipped> */ private array $testSuiteSkippedEvents; /** * @var list<TestSkipped> */ private array $testSkippedEvents; /** * @var array<string,list<ConsideredRisky>> */ private array $testConsideredRiskyEvents; /** * @var array<string,list<PhpunitDeprecationTriggered>> */ private array $testTriggeredPhpunitDeprecationEvents; /** * @var array<string,list<PhpunitErrorTriggered>> */ private array $testTriggeredPhpunitErrorEvents; /** * @var array<string,list<PhpunitWarningTriggered>> */ private array $testTriggeredPhpunitWarningEvents; /** * @var list<TestRunnerDeprecationTriggered> */ private array $testRunnerTriggeredDeprecationEvents; /** * @var list<TestRunnerWarningTriggered> */ private array $testRunnerTriggeredWarningEvents; /** * @var list<Issue> */ private array $errors; /** * @var list<Issue> */ private array $deprecations; /** * @var list<Issue> */ private array $notices; /** * @var list<Issue> */ private array $warnings; /** * @var list<Issue> */ private array $phpDeprecations; /** * @var list<Issue> */ private array $phpNotices; /** * @var list<Issue> */ private array $phpWarnings; /** * @var non-negative-int */ private int $numberOfIssuesIgnoredByBaseline; /** * @param list<BeforeFirstTestMethodErrored|Errored> $testErroredEvents * @param list<Failed> $testFailedEvents * @param array<string,list<ConsideredRisky>> $testConsideredRiskyEvents * @param list<TestSuiteSkipped> $testSuiteSkippedEvents * @param list<TestSkipped> $testSkippedEvents * @param list<MarkedIncomplete> $testMarkedIncompleteEvents * @param array<string,list<PhpunitDeprecationTriggered>> $testTriggeredPhpunitDeprecationEvents * @param array<string,list<PhpunitErrorTriggered>> $testTriggeredPhpunitErrorEvents * @param array<string,list<PhpunitWarningTriggered>> $testTriggeredPhpunitWarningEvents * @param list<TestRunnerDeprecationTriggered> $testRunnerTriggeredDeprecationEvents * @param list<TestRunnerWarningTriggered> $testRunnerTriggeredWarningEvents * @param list<Issue> $errors * @param list<Issue> $deprecations * @param list<Issue> $notices * @param list<Issue> $warnings * @param list<Issue> $phpDeprecations * @param list<Issue> $phpNotices * @param list<Issue> $phpWarnings * @param non-negative-int $numberOfIssuesIgnoredByBaseline */ public function __construct(int $numberOfTests, int $numberOfTestsRun, int $numberOfAssertions, array $testErroredEvents, array $testFailedEvents, array $testConsideredRiskyEvents, array $testSuiteSkippedEvents, array $testSkippedEvents, array $testMarkedIncompleteEvents, array $testTriggeredPhpunitDeprecationEvents, array $testTriggeredPhpunitErrorEvents, array $testTriggeredPhpunitWarningEvents, array $testRunnerTriggeredDeprecationEvents, array $testRunnerTriggeredWarningEvents, array $errors, array $deprecations, array $notices, array $warnings, array $phpDeprecations, array $phpNotices, array $phpWarnings, int $numberOfIssuesIgnoredByBaseline) { $this->numberOfTests = $numberOfTests; $this->numberOfTestsRun = $numberOfTestsRun; $this->numberOfAssertions = $numberOfAssertions; $this->testErroredEvents = $testErroredEvents; $this->testFailedEvents = $testFailedEvents; $this->testConsideredRiskyEvents = $testConsideredRiskyEvents; $this->testSuiteSkippedEvents = $testSuiteSkippedEvents; $this->testSkippedEvents = $testSkippedEvents; $this->testMarkedIncompleteEvents = $testMarkedIncompleteEvents; $this->testTriggeredPhpunitDeprecationEvents = $testTriggeredPhpunitDeprecationEvents; $this->testTriggeredPhpunitErrorEvents = $testTriggeredPhpunitErrorEvents; $this->testTriggeredPhpunitWarningEvents = $testTriggeredPhpunitWarningEvents; $this->testRunnerTriggeredDeprecationEvents = $testRunnerTriggeredDeprecationEvents; $this->testRunnerTriggeredWarningEvents = $testRunnerTriggeredWarningEvents; $this->errors = $errors; $this->deprecations = $deprecations; $this->notices = $notices; $this->warnings = $warnings; $this->phpDeprecations = $phpDeprecations; $this->phpNotices = $phpNotices; $this->phpWarnings = $phpWarnings; $this->numberOfIssuesIgnoredByBaseline = $numberOfIssuesIgnoredByBaseline; } public function numberOfTestsRun(): int { return $this->numberOfTestsRun; } public function numberOfAssertions(): int { return $this->numberOfAssertions; } /** * @return list<BeforeFirstTestMethodErrored|Errored> */ public function testErroredEvents(): array { return $this->testErroredEvents; } public function numberOfTestErroredEvents(): int { return count($this->testErroredEvents); } public function hasTestErroredEvents(): bool { return $this->numberOfTestErroredEvents() > 0; } /** * @return list<Failed> */ public function testFailedEvents(): array { return $this->testFailedEvents; } public function numberOfTestFailedEvents(): int { return count($this->testFailedEvents); } public function hasTestFailedEvents(): bool { return $this->numberOfTestFailedEvents() > 0; } /** * @return array<string,list<ConsideredRisky>> */ public function testConsideredRiskyEvents(): array { return $this->testConsideredRiskyEvents; } public function numberOfTestsWithTestConsideredRiskyEvents(): int { return count($this->testConsideredRiskyEvents); } public function hasTestConsideredRiskyEvents(): bool { return $this->numberOfTestsWithTestConsideredRiskyEvents() > 0; } /** * @return list<TestSuiteSkipped> */ public function testSuiteSkippedEvents(): array { return $this->testSuiteSkippedEvents; } public function numberOfTestSuiteSkippedEvents(): int { return count($this->testSuiteSkippedEvents); } public function hasTestSuiteSkippedEvents(): bool { return $this->numberOfTestSuiteSkippedEvents() > 0; } /** * @return list<TestSkipped> */ public function testSkippedEvents(): array { return $this->testSkippedEvents; } public function numberOfTestSkippedEvents(): int { return count($this->testSkippedEvents); } public function hasTestSkippedEvents(): bool { return $this->numberOfTestSkippedEvents() > 0; } /** * @return list<MarkedIncomplete> */ public function testMarkedIncompleteEvents(): array { return $this->testMarkedIncompleteEvents; } public function numberOfTestMarkedIncompleteEvents(): int { return count($this->testMarkedIncompleteEvents); } public function hasTestMarkedIncompleteEvents(): bool { return $this->numberOfTestMarkedIncompleteEvents() > 0; } /** * @return array<string,list<PhpunitDeprecationTriggered>> */ public function testTriggeredPhpunitDeprecationEvents(): array { return $this->testTriggeredPhpunitDeprecationEvents; } public function numberOfTestsWithTestTriggeredPhpunitDeprecationEvents(): int { return count($this->testTriggeredPhpunitDeprecationEvents); } public function hasTestTriggeredPhpunitDeprecationEvents(): bool { return $this->numberOfTestsWithTestTriggeredPhpunitDeprecationEvents() > 0; } /** * @return array<string,list<PhpunitErrorTriggered>> */ public function testTriggeredPhpunitErrorEvents(): array { return $this->testTriggeredPhpunitErrorEvents; } public function numberOfTestsWithTestTriggeredPhpunitErrorEvents(): int { return count($this->testTriggeredPhpunitErrorEvents); } public function hasTestTriggeredPhpunitErrorEvents(): bool { return $this->numberOfTestsWithTestTriggeredPhpunitErrorEvents() > 0; } /** * @return array<string,list<PhpunitWarningTriggered>> */ public function testTriggeredPhpunitWarningEvents(): array { return $this->testTriggeredPhpunitWarningEvents; } public function numberOfTestsWithTestTriggeredPhpunitWarningEvents(): int { return count($this->testTriggeredPhpunitWarningEvents); } public function hasTestTriggeredPhpunitWarningEvents(): bool { return $this->numberOfTestsWithTestTriggeredPhpunitWarningEvents() > 0; } /** * @return list<TestRunnerDeprecationTriggered> */ public function testRunnerTriggeredDeprecationEvents(): array { return $this->testRunnerTriggeredDeprecationEvents; } public function numberOfTestRunnerTriggeredDeprecationEvents(): int { return count($this->testRunnerTriggeredDeprecationEvents); } public function hasTestRunnerTriggeredDeprecationEvents(): bool { return $this->numberOfTestRunnerTriggeredDeprecationEvents() > 0; } /** * @return list<TestRunnerWarningTriggered> */ public function testRunnerTriggeredWarningEvents(): array { return $this->testRunnerTriggeredWarningEvents; } public function numberOfTestRunnerTriggeredWarningEvents(): int { return count($this->testRunnerTriggeredWarningEvents); } public function hasTestRunnerTriggeredWarningEvents(): bool { return $this->numberOfTestRunnerTriggeredWarningEvents() > 0; } public function wasSuccessful(): bool { return $this->wasSuccessfulIgnoringPhpunitWarnings() && !$this->hasTestTriggeredPhpunitErrorEvents() && !$this->hasTestRunnerTriggeredWarningEvents() && !$this->hasTestTriggeredPhpunitWarningEvents(); } public function wasSuccessfulIgnoringPhpunitWarnings(): bool { return !$this->hasTestErroredEvents() && !$this->hasTestFailedEvents(); } public function wasSuccessfulAndNoTestHasIssues(): bool { return $this->wasSuccessful() && !$this->hasTestsWithIssues(); } public function hasTestsWithIssues(): bool { return $this->hasRiskyTests() || $this->hasIncompleteTests() || $this->hasDeprecations() || !empty($this->errors) || $this->hasNotices() || $this->hasWarnings(); } /** * @return list<Issue> */ public function errors(): array { return $this->errors; } /** * @return list<Issue> */ public function deprecations(): array { return $this->deprecations; } /** * @return list<Issue> */ public function notices(): array { return $this->notices; } /** * @return list<Issue> */ public function warnings(): array { return $this->warnings; } /** * @return list<Issue> */ public function phpDeprecations(): array { return $this->phpDeprecations; } /** * @return list<Issue> */ public function phpNotices(): array { return $this->phpNotices; } /** * @return list<Issue> */ public function phpWarnings(): array { return $this->phpWarnings; } public function hasTests(): bool { return $this->numberOfTests > 0; } public function hasErrors(): bool { return $this->numberOfErrors() > 0; } public function numberOfErrors(): int { return $this->numberOfTestErroredEvents() + count($this->errors) + $this->numberOfTestsWithTestTriggeredPhpunitErrorEvents(); } public function hasDeprecations(): bool { return $this->numberOfDeprecations() > 0; } public function numberOfDeprecations(): int { return count($this->deprecations) + count($this->phpDeprecations) + count($this->testTriggeredPhpunitDeprecationEvents) + count($this->testRunnerTriggeredDeprecationEvents); } public function hasNotices(): bool { return $this->numberOfNotices() > 0; } public function numberOfNotices(): int { return count($this->notices) + count($this->phpNotices); } public function hasWarnings(): bool { return $this->numberOfWarnings() > 0; } public function numberOfWarnings(): int { return count($this->warnings) + count($this->phpWarnings) + count($this->testTriggeredPhpunitWarningEvents) + count($this->testRunnerTriggeredWarningEvents); } public function hasIncompleteTests(): bool { return !empty($this->testMarkedIncompleteEvents); } public function hasRiskyTests(): bool { return !empty($this->testConsideredRiskyEvents); } public function hasSkippedTests(): bool { return !empty($this->testSkippedEvents); } public function hasIssuesIgnoredByBaseline(): bool { return $this->numberOfIssuesIgnoredByBaseline > 0; } /** * @return non-negative-int */ public function numberOfIssuesIgnoredByBaseline(): int { return $this->numberOfIssuesIgnoredByBaseline; } } phpunit/src/Runner/ResultCache/Subscriber/TestSuiteStartedSubscriber.php 0000644 00000001425 15253321353 0022621 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\TestSuite\Started; use PHPUnit\Event\TestSuite\StartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber { public function notify(Started $event): void { $this->handler()->testSuiteStarted(); } } phpunit/src/Runner/ResultCache/Subscriber/TestErroredSubscriber.php 0000644 00000001407 15253321353 0021603 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { public function notify(Errored $event): void { $this->handler()->testErrored($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001475 15253321353 0023431 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { public function notify(MarkedIncomplete $event): void { $this->handler()->testMarkedIncomplete($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestFinishedSubscriber.php 0000644 00000001654 15253321353 0021736 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { /** * @throws \PHPUnit\Framework\InvalidArgumentException * @throws InvalidArgumentException */ public function notify(Finished $event): void { $this->handler()->testFinished($event); } } phpunit/src/Runner/ResultCache/Subscriber/Subscriber.php 0000644 00000001417 15253321353 0017421 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private ResultCacheHandler $handler; public function __construct(ResultCacheHandler $handler) { $this->handler = $handler; } protected function handler(): ResultCacheHandler { return $this->handler; } } phpunit/src/Runner/ResultCache/Subscriber/TestFailedSubscriber.php 0000644 00000001401 15253321353 0021357 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { public function notify(Failed $event): void { $this->handler()->testFailed($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestPreparedSubscriber.php 0000644 00000001415 15253321353 0021742 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->handler()->testPrepared($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestSkippedSubscriber.php 0000644 00000001646 15253321353 0021605 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { /** * @throws \PHPUnit\Framework\InvalidArgumentException * @throws InvalidArgumentException */ public function notify(Skipped $event): void { $this->handler()->testSkipped($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestConsideredRiskySubscriber.php 0000644 00000001467 15253321353 0023310 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\ConsideredRiskySubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber { public function notify(ConsideredRisky $event): void { $this->handler()->testConsideredRisky($event); } } phpunit/src/Runner/ResultCache/Subscriber/TestSuiteFinishedSubscriber.php 0000644 00000001433 15253321353 0022743 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Event\TestSuite\Finished; use PHPUnit\Event\TestSuite\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->handler()->testSuiteFinished(); } } phpunit/src/Runner/ResultCache/ResultCacheHandler.php 0000644 00000010424 15253321353 0016711 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use function round; use PHPUnit\Event\Event; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Telemetry\HRTime; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\InvalidArgumentException; use PHPUnit\Framework\TestStatus\TestStatus; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ResultCacheHandler { private readonly ResultCache $cache; private ?HRTime $time = null; private int $testSuite = 0; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(ResultCache $cache, Facade $facade) { $this->cache = $cache; $this->registerSubscribers($facade); } public function testSuiteStarted(): void { $this->testSuite++; } public function testSuiteFinished(): void { $this->testSuite--; if ($this->testSuite === 0) { $this->cache->persist(); } } public function testPrepared(Prepared $event): void { $this->time = $event->telemetryInfo()->time(); } public function testMarkedIncomplete(MarkedIncomplete $event): void { $this->cache->setStatus( $event->test()->id(), TestStatus::incomplete($event->throwable()->message()), ); } public function testConsideredRisky(ConsideredRisky $event): void { $this->cache->setStatus( $event->test()->id(), TestStatus::risky($event->message()), ); } public function testErrored(Errored $event): void { $this->cache->setStatus( $event->test()->id(), TestStatus::error($event->throwable()->message()), ); } public function testFailed(Failed $event): void { $this->cache->setStatus( $event->test()->id(), TestStatus::failure($event->throwable()->message()), ); } /** * @throws \PHPUnit\Event\InvalidArgumentException * @throws InvalidArgumentException */ public function testSkipped(Skipped $event): void { $this->cache->setStatus( $event->test()->id(), TestStatus::skipped($event->message()), ); $this->cache->setTime($event->test()->id(), $this->duration($event)); } /** * @throws \PHPUnit\Event\InvalidArgumentException * @throws InvalidArgumentException */ public function testFinished(Finished $event): void { $this->cache->setTime($event->test()->id(), $this->duration($event)); $this->time = null; } /** * @throws \PHPUnit\Event\InvalidArgumentException * @throws InvalidArgumentException */ private function duration(Event $event): float { if ($this->time === null) { return 0.0; } return round($event->telemetryInfo()->time()->duration($this->time)->asFloat(), 3); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new TestSuiteStartedSubscriber($this), new TestSuiteFinishedSubscriber($this), new TestPreparedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestConsideredRiskySubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestSkippedSubscriber($this), new TestFinishedSubscriber($this), ); } } phpunit/src/Runner/ResultCache/ResultCache.php 0000644 00000001547 15253321353 0015421 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Framework\TestStatus\TestStatus; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface ResultCache { public function setStatus(string $id, TestStatus $status): void; public function status(string $id): TestStatus; public function setTime(string $id, float $time): void; public function time(string $id): float; public function load(): void; public function persist(): void; } phpunit/src/Runner/ResultCache/NullResultCache.php 0000644 00000002007 15253321353 0016244 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use PHPUnit\Framework\TestStatus\TestStatus; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class NullResultCache implements ResultCache { public function setStatus(string $id, TestStatus $status): void { } public function status(string $id): TestStatus { return TestStatus::unknown(); } public function setTime(string $id, float $time): void { } public function time(string $id): float { return 0; } public function load(): void { } public function persist(): void { } } phpunit/src/Runner/ResultCache/DefaultResultCache.php 0000644 00000007347 15253321353 0016732 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\ResultCache; use const DIRECTORY_SEPARATOR; use const LOCK_EX; use function array_keys; use function assert; use function dirname; use function file_get_contents; use function file_put_contents; use function is_array; use function is_dir; use function is_file; use function json_decode; use function json_encode; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\Runner\DirectoryDoesNotExistException; use PHPUnit\Runner\Exception; use PHPUnit\Util\Filesystem; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DefaultResultCache implements ResultCache { /** * @var int */ private const VERSION = 1; /** * @var string */ private const DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache'; private readonly string $cacheFilename; /** * @var array<string, TestStatus> */ private array $defects = []; /** * @var array<string, float> */ private array $times = []; public function __construct(?string $filepath = null) { if ($filepath !== null && is_dir($filepath)) { $filepath .= DIRECTORY_SEPARATOR . self::DEFAULT_RESULT_CACHE_FILENAME; } $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME; } public function setStatus(string $id, TestStatus $status): void { if ($status->isSuccess()) { return; } $this->defects[$id] = $status; } public function status(string $id): TestStatus { return $this->defects[$id] ?? TestStatus::unknown(); } public function setTime(string $id, float $time): void { $this->times[$id] = $time; } public function time(string $id): float { return $this->times[$id] ?? 0.0; } public function load(): void { if (!is_file($this->cacheFilename)) { return; } $contents = file_get_contents($this->cacheFilename); if ($contents === false) { return; } $data = json_decode( $contents, true, ); if ($data === null) { return; } if (!isset($data['version'])) { return; } if ($data['version'] !== self::VERSION) { return; } assert(isset($data['defects']) && is_array($data['defects'])); assert(isset($data['times']) && is_array($data['times'])); foreach (array_keys($data['defects']) as $test) { $data['defects'][$test] = TestStatus::from($data['defects'][$test]); } $this->defects = $data['defects']; $this->times = $data['times']; } /** * @throws Exception */ public function persist(): void { if (!Filesystem::createDirectory(dirname($this->cacheFilename))) { throw new DirectoryDoesNotExistException(dirname($this->cacheFilename)); } $data = [ 'version' => self::VERSION, 'defects' => [], 'times' => $this->times, ]; foreach ($this->defects as $test => $status) { $data['defects'][$test] = $status->asInt(); } file_put_contents( $this->cacheFilename, json_encode($data), LOCK_EX, ); } } phpunit/src/Runner/Filter/IncludeNameFilterIterator.php 0000644 00000001211 15253321353 0017272 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IncludeNameFilterIterator extends NameFilterIterator { protected function doAccept(bool $result): bool { return $result; } } phpunit/src/Runner/Filter/GroupFilterIterator.php 0000644 00000004025 15253321353 0016210 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function array_merge; use function array_push; use function in_array; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\PhptTestCase; use RecursiveFilterIterator; use RecursiveIterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract class GroupFilterIterator extends RecursiveFilterIterator { /** * @var list<non-empty-string> */ private readonly array $groupTests; /** * @param RecursiveIterator<int, Test> $iterator * @param list<non-empty-string> $groups */ public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite) { parent::__construct($iterator); $groupTests = []; foreach ($suite->groupDetails() as $group => $tests) { if (in_array($group, $groups, true)) { $groupTests = array_merge($groupTests, $tests); array_push($groupTests, ...$groupTests); } } $this->groupTests = $groupTests; } public function accept(): bool { $test = $this->getInnerIterator()->current(); if ($test instanceof TestSuite) { return true; } if ($test instanceof TestCase || $test instanceof PhptTestCase) { return $this->doAccept($test->valueObjectForEvents()->id(), $this->groupTests); } return true; } /** * @param non-empty-string $id * @param list<non-empty-string> $groupTests */ abstract protected function doAccept(string $id, array $groupTests): bool; } phpunit/src/Runner/Filter/IncludeGroupFilterIterator.php 0000644 00000001467 15253321353 0017523 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function in_array; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IncludeGroupFilterIterator extends GroupFilterIterator { /** * @param non-empty-string $id * @param list<non-empty-string> $groupTests */ protected function doAccept(string $id, array $groupTests): bool { return in_array($id, $groupTests, true); } } phpunit/src/Runner/Filter/TestIdFilterIterator.php 0000644 00000003252 15253321353 0016311 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function in_array; use PHPUnit\Event\TestData\NoDataSetFromDataProviderException; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\PhptTestCase; use RecursiveFilterIterator; use RecursiveIterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestIdFilterIterator extends RecursiveFilterIterator { /** * @var non-empty-list<non-empty-string> */ private readonly array $testIds; /** * @param RecursiveIterator<int, Test> $iterator * @param non-empty-list<non-empty-string> $testIds */ public function __construct(RecursiveIterator $iterator, array $testIds) { parent::__construct($iterator); $this->testIds = $testIds; } public function accept(): bool { $test = $this->getInnerIterator()->current(); if ($test instanceof TestSuite) { return true; } if (!$test instanceof TestCase && !$test instanceof PhptTestCase) { return false; } try { return in_array($test->valueObjectForEvents()->id(), $this->testIds, true); } catch (NoDataSetFromDataProviderException) { return false; } } } phpunit/src/Runner/Filter/ExcludeNameFilterIterator.php 0000644 00000001212 15253321353 0017301 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExcludeNameFilterIterator extends NameFilterIterator { protected function doAccept(bool $result): bool { return !$result; } } phpunit/src/Runner/Filter/ExcludeGroupFilterIterator.php 0000644 00000001470 15253321353 0017523 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function in_array; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExcludeGroupFilterIterator extends GroupFilterIterator { /** * @param non-empty-string $id * @param list<non-empty-string> $groupTests */ protected function doAccept(string $id, array $groupTests): bool { return !in_array($id, $groupTests, true); } } phpunit/src/Runner/Filter/NameFilterIterator.php 0000644 00000010170 15253321353 0015772 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function end; use function preg_match; use function sprintf; use function str_replace; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\PhptTestCase; use RecursiveFilterIterator; use RecursiveIterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract class NameFilterIterator extends RecursiveFilterIterator { /** * @var non-empty-string */ private readonly string $regularExpression; private readonly ?int $dataSetMinimum; private readonly ?int $dataSetMaximum; /** * @param RecursiveIterator<int, Test> $iterator * @param non-empty-string $filter */ public function __construct(RecursiveIterator $iterator, string $filter) { parent::__construct($iterator); $preparedFilter = $this->prepareFilter($filter); $this->regularExpression = $preparedFilter['regularExpression']; $this->dataSetMinimum = $preparedFilter['dataSetMinimum']; $this->dataSetMaximum = $preparedFilter['dataSetMaximum']; } public function accept(): bool { $test = $this->getInnerIterator()->current(); if ($test instanceof TestSuite) { return true; } if ($test instanceof PhptTestCase) { return false; } $name = $test::class . '::' . $test->nameWithDataSet(); $accepted = @preg_match($this->regularExpression, $name, $matches) === 1; if ($accepted && isset($this->dataSetMaximum)) { $set = end($matches); $accepted = $set >= $this->dataSetMinimum && $set <= $this->dataSetMaximum; } return $this->doAccept($accepted); } abstract protected function doAccept(bool $result): bool; /** * @param non-empty-string $filter * * @return array{regularExpression: non-empty-string, dataSetMinimum: ?int, dataSetMaximum: ?int} */ private function prepareFilter(string $filter): array { $dataSetMinimum = null; $dataSetMaximum = null; if (@preg_match($filter, '') === false) { // Handles: // * testAssertEqualsSucceeds#4 // * testAssertEqualsSucceeds#4-8 if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { if (isset($matches[3]) && $matches[2] < $matches[3]) { $filter = sprintf( '%s.*with data set #(\d+)$', $matches[1], ); $dataSetMinimum = (int) $matches[2]; $dataSetMaximum = (int) $matches[3]; } else { $filter = sprintf( '%s.*with data set #%s$', $matches[1], $matches[2], ); } } // Handles: // * testDetermineJsonError@JSON_ERROR_NONE // * testDetermineJsonError@JSON.* elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { $filter = sprintf( '%s.*with data set "%s"$', $matches[1], $matches[2], ); } // Escape delimiters in regular expression. Do NOT use preg_quote, // to keep magic characters. $filter = sprintf( '/%s/i', str_replace( '/', '\\/', $filter, ), ); } return [ 'regularExpression' => $filter, 'dataSetMinimum' => $dataSetMinimum, 'dataSetMaximum' => $dataSetMaximum, ]; } } phpunit/src/Runner/Filter/Factory.php 0000644 00000004657 15253321353 0013656 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use function assert; use FilterIterator; use Iterator; use PHPUnit\Framework\TestSuite; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Factory { /** * @var list<array{className: class-string, argument: list<non-empty-string>|non-empty-string}> */ private array $filters = []; /** * @param list<non-empty-string> $testIds */ public function addTestIdFilter(array $testIds): void { $this->filters[] = [ 'className' => TestIdFilterIterator::class, 'argument' => $testIds, ]; } /** * @param list<non-empty-string> $groups */ public function addIncludeGroupFilter(array $groups): void { $this->filters[] = [ 'className' => IncludeGroupFilterIterator::class, 'argument' => $groups, ]; } /** * @param list<non-empty-string> $groups */ public function addExcludeGroupFilter(array $groups): void { $this->filters[] = [ 'className' => ExcludeGroupFilterIterator::class, 'argument' => $groups, ]; } /** * @param non-empty-string $name */ public function addIncludeNameFilter(string $name): void { $this->filters[] = [ 'className' => IncludeNameFilterIterator::class, 'argument' => $name, ]; } /** * @param non-empty-string $name */ public function addExcludeNameFilter(string $name): void { $this->filters[] = [ 'className' => ExcludeNameFilterIterator::class, 'argument' => $name, ]; } public function factory(Iterator $iterator, TestSuite $suite): FilterIterator { foreach ($this->filters as $filter) { $iterator = new $filter['className']( $iterator, $filter['argument'], $suite, ); } assert($iterator instanceof FilterIterator); return $iterator; } } phpunit/src/Event/Tracer.php 0000644 00000000755 15253321353 0012045 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Tracer; use PHPUnit\Event\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Tracer { public function trace(Event $event): void; } phpunit/src/Event/TypeMap.php 0000644 00000013017 15253321353 0012177 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use function array_key_exists; use function class_exists; use function class_implements; use function in_array; use function interface_exists; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TypeMap { /** * @var array<class-string, class-string> */ private array $mapping = []; /** * @param class-string $subscriberInterface * @param class-string $eventClass * * @throws EventAlreadyAssignedException * @throws InvalidEventException * @throws InvalidSubscriberException * @throws SubscriberTypeAlreadyRegisteredException * @throws UnknownEventException * @throws UnknownSubscriberException */ public function addMapping(string $subscriberInterface, string $eventClass): void { $this->ensureSubscriberInterfaceExists($subscriberInterface); $this->ensureSubscriberInterfaceExtendsInterface($subscriberInterface); $this->ensureEventClassExists($eventClass); $this->ensureEventClassImplementsEventInterface($eventClass); $this->ensureSubscriberWasNotAlreadyRegistered($subscriberInterface); $this->ensureEventWasNotAlreadyAssigned($eventClass); $this->mapping[$subscriberInterface] = $eventClass; } public function isKnownSubscriberType(Subscriber $subscriber): bool { foreach (class_implements($subscriber) as $interface) { if (array_key_exists($interface, $this->mapping)) { return true; } } return false; } public function isKnownEventType(Event $event): bool { return in_array($event::class, $this->mapping, true); } /** * @throws MapError * * @return class-string */ public function map(Subscriber $subscriber): string { foreach (class_implements($subscriber) as $interface) { if (array_key_exists($interface, $this->mapping)) { return $this->mapping[$interface]; } } throw new MapError( sprintf( 'Subscriber "%s" does not implement a known interface', $subscriber::class, ), ); } /** * @param class-string $subscriberInterface * * @throws UnknownSubscriberException */ private function ensureSubscriberInterfaceExists(string $subscriberInterface): void { if (!interface_exists($subscriberInterface)) { throw new UnknownSubscriberException( sprintf( 'Subscriber "%s" does not exist or is not an interface', $subscriberInterface, ), ); } } /** * @param class-string $eventClass * * @throws UnknownEventException */ private function ensureEventClassExists(string $eventClass): void { if (!class_exists($eventClass)) { throw new UnknownEventException( sprintf( 'Event class "%s" does not exist', $eventClass, ), ); } } /** * @param class-string $subscriberInterface * * @throws InvalidSubscriberException */ private function ensureSubscriberInterfaceExtendsInterface(string $subscriberInterface): void { if (!in_array(Subscriber::class, class_implements($subscriberInterface), true)) { throw new InvalidSubscriberException( sprintf( 'Subscriber "%s" does not extend Subscriber interface', $subscriberInterface, ), ); } } /** * @param class-string $eventClass * * @throws InvalidEventException */ private function ensureEventClassImplementsEventInterface(string $eventClass): void { if (!in_array(Event::class, class_implements($eventClass), true)) { throw new InvalidEventException( sprintf( 'Event "%s" does not implement Event interface', $eventClass, ), ); } } /** * @param class-string $subscriberInterface * * @throws SubscriberTypeAlreadyRegisteredException */ private function ensureSubscriberWasNotAlreadyRegistered(string $subscriberInterface): void { if (array_key_exists($subscriberInterface, $this->mapping)) { throw new SubscriberTypeAlreadyRegisteredException( sprintf( 'Subscriber type "%s" already registered', $subscriberInterface, ), ); } } /** * @param class-string $eventClass * * @throws EventAlreadyAssignedException */ private function ensureEventWasNotAlreadyAssigned(string $eventClass): void { if (in_array($eventClass, $this->mapping, true)) { throw new EventAlreadyAssignedException( sprintf( 'Event "%s" already assigned', $eventClass, ), ); } } } phpunit/src/Event/Exception/NoDataSetFromDataProviderException.php 0000644 00000001046 15253321353 0021407 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; use PHPUnit\Event\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class NoDataSetFromDataProviderException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/UnknownEventTypeException.php 0000644 00000000767 15253321353 0017750 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class UnknownEventTypeException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/Exception.php 0000644 00000000512 15253321353 0014510 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; interface Exception extends \PHPUnit\Exception { } phpunit/src/Event/Exception/MapError.php 0000644 00000000746 15253321353 0014312 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class MapError extends RuntimeException implements Exception { } phpunit/src/Event/Exception/UnknownSubscriberException.php 0000644 00000000770 15253321353 0020122 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class UnknownSubscriberException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/NoTestCaseObjectOnCallStackException.php 0000644 00000001370 15253321353 0021652 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use PHPUnit\Event\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoTestCaseObjectOnCallStackException extends RuntimeException implements Exception { public function __construct() { parent::__construct('Cannot find TestCase object on call stack'); } } phpunit/src/Event/Exception/InvalidEventException.php 0000644 00000000763 15253321353 0017031 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class InvalidEventException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/UnknownSubscriberTypeException.php 0000644 00000000774 15253321353 0020770 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class UnknownSubscriberTypeException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/EventFacadeIsSealedException.php 0000644 00000000772 15253321353 0020220 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class EventFacadeIsSealedException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/EventAlreadyAssignedException.php 0000644 00000000773 15253321353 0020503 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class EventAlreadyAssignedException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/NoComparisonFailureException.php 0000644 00000001034 15253321353 0020350 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class NoComparisonFailureException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/RuntimeException.php 0000644 00000000730 15253321353 0016056 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class RuntimeException extends \RuntimeException implements Exception { } phpunit/src/Event/Exception/InvalidArgumentException.php 0000644 00000000750 15253321353 0017526 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class InvalidArgumentException extends \InvalidArgumentException implements Exception { } phpunit/src/Event/Exception/InvalidSubscriberException.php 0000644 00000000770 15253321353 0020051 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class InvalidSubscriberException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/NoPreviousThrowableException.php 0000644 00000000772 15253321353 0020422 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class NoPreviousThrowableException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/UnknownEventException.php 0000644 00000000763 15253321353 0017102 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class UnknownEventException extends RuntimeException implements Exception { } phpunit/src/Event/Exception/SubscriberTypeAlreadyRegisteredException.php 0000644 00000001006 15253321353 0022715 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class SubscriberTypeAlreadyRegisteredException extends RuntimeException implements Exception { } phpunit/src/Event/Emitter/Emitter.php 0000644 00000023545 15253321353 0013651 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Event\Code\ComparisonFailure; use PHPUnit\Event\Code\IssueTrigger\IssueTrigger; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\TestSuite\TestSuite; use PHPUnit\TextUI\Configuration\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Emitter { public function applicationStarted(): void; public function testRunnerStarted(): void; public function testRunnerConfigured(Configuration $configuration): void; public function testRunnerBootstrapFinished(string $filename): void; public function testRunnerLoadedExtensionFromPhar(string $filename, string $name, string $version): void; /** * @param class-string $className * @param array<string, string> $parameters */ public function testRunnerBootstrappedExtension(string $className, array $parameters): void; public function dataProviderMethodCalled(ClassMethod $testMethod, ClassMethod $dataProviderMethod): void; public function dataProviderMethodFinished(ClassMethod $testMethod, ClassMethod ...$calledMethods): void; public function testSuiteLoaded(TestSuite $testSuite): void; public function testSuiteFiltered(TestSuite $testSuite): void; public function testSuiteSorted(int $executionOrder, int $executionOrderDefects, bool $resolveDependencies): void; public function testRunnerEventFacadeSealed(): void; public function testRunnerExecutionStarted(TestSuite $testSuite): void; public function testRunnerDisabledGarbageCollection(): void; public function testRunnerTriggeredGarbageCollection(): void; public function testSuiteSkipped(TestSuite $testSuite, string $message): void; public function testSuiteStarted(TestSuite $testSuite): void; public function testPreparationStarted(Code\Test $test): void; public function testPreparationFailed(Code\Test $test): void; /** * @param class-string $testClassName */ public function testBeforeFirstTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testBeforeFirstTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void; /** * @param class-string $testClassName */ public function testBeforeFirstTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; /** * @param class-string $testClassName */ public function testBeforeTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testBeforeTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; /** * @param class-string $testClassName */ public function testPreConditionCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testPreConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void; public function testPrepared(Code\Test $test): void; /** * @param class-string $className */ public function testRegisteredComparator(string $className): void; /** * @param class-string $className */ public function testCreatedMockObject(string $className): void; /** * @param list<class-string> $interfaces */ public function testCreatedMockObjectForIntersectionOfInterfaces(array $interfaces): void; /** * @param trait-string $traitName */ public function testCreatedMockObjectForTrait(string $traitName): void; /** * @param class-string $className */ public function testCreatedMockObjectForAbstractClass(string $className): void; /** * @param class-string $originalClassName * @param class-string $mockClassName * @param list<string> $methods * @param list<mixed> $options */ public function testCreatedMockObjectFromWsdl(string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options): void; /** * @param class-string $className */ public function testCreatedPartialMockObject(string $className, string ...$methodNames): void; /** * @param class-string $className * @param list<mixed> $constructorArguments */ public function testCreatedTestProxy(string $className, array $constructorArguments): void; /** * @param class-string $className */ public function testCreatedStub(string $className): void; /** * @param list<class-string> $interfaces */ public function testCreatedStubForIntersectionOfInterfaces(array $interfaces): void; public function testErrored(Code\Test $test, Throwable $throwable): void; public function testFailed(Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure): void; public function testPassed(Code\Test $test): void; /** * @param non-empty-string $message */ public function testConsideredRisky(Code\Test $test, string $message): void; public function testMarkedAsIncomplete(Code\Test $test, Throwable $throwable): void; /** * @param non-empty-string $message */ public function testSkipped(Code\Test $test, string $message): void; /** * @param non-empty-string $message */ public function testTriggeredPhpunitDeprecation(?Code\Test $test, string $message): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredPhpDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredError(Code\Test $test, string $message, string $file, int $line, bool $suppressed): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredPhpNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function testTriggeredPhpWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void; /** * @param non-empty-string $message */ public function testTriggeredPhpunitError(Code\Test $test, string $message): void; /** * @param non-empty-string $message */ public function testTriggeredPhpunitWarning(Code\Test $test, string $message): void; /** * @param non-empty-string $output */ public function testPrintedUnexpectedOutput(string $output): void; public function testFinished(Code\Test $test, int $numberOfAssertionsPerformed): void; /** * @param class-string $testClassName */ public function testPostConditionCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testPostConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void; /** * @param class-string $testClassName */ public function testAfterTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testAfterTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; /** * @param class-string $testClassName */ public function testAfterLastTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void; /** * @param class-string $testClassName */ public function testAfterLastTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void; public function testSuiteFinished(TestSuite $testSuite): void; public function testRunnerTriggeredDeprecation(string $message): void; public function testRunnerTriggeredWarning(string $message): void; public function testRunnerEnabledGarbageCollection(): void; public function testRunnerExecutionAborted(): void; public function testRunnerExecutionFinished(): void; public function testRunnerFinished(): void; public function applicationFinished(int $shellExitCode): void; } phpunit/src/Event/Emitter/DispatchingEmitter.php 0000644 00000100505 15253321353 0016017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use function assert; use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Event\Code\ComparisonFailure; use PHPUnit\Event\Code\IssueTrigger\IssueTrigger; use PHPUnit\Event\Code\NoTestCaseObjectOnCallStackException; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\TestMethodBuilder; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Test\DataProviderMethodCalled; use PHPUnit\Event\Test\DataProviderMethodFinished; use PHPUnit\Event\TestSuite\Filtered as TestSuiteFiltered; use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; use PHPUnit\Event\TestSuite\Loaded as TestSuiteLoaded; use PHPUnit\Event\TestSuite\Skipped as TestSuiteSkipped; use PHPUnit\Event\TestSuite\Sorted as TestSuiteSorted; use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; use PHPUnit\Event\TestSuite\TestSuite; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\Util\Exporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DispatchingEmitter implements Emitter { private readonly Dispatcher $dispatcher; private readonly Telemetry\System $system; private readonly Telemetry\Snapshot $startSnapshot; private Telemetry\Snapshot $previousSnapshot; public function __construct(Dispatcher $dispatcher, Telemetry\System $system) { $this->dispatcher = $dispatcher; $this->system = $system; $this->startSnapshot = $system->snapshot(); $this->previousSnapshot = $this->startSnapshot; } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function applicationStarted(): void { $this->dispatcher->dispatch( new Application\Started( $this->telemetryInfo(), new Runtime\Runtime, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerStarted(): void { $this->dispatcher->dispatch( new TestRunner\Started( $this->telemetryInfo(), ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerConfigured(Configuration $configuration): void { $this->dispatcher->dispatch( new TestRunner\Configured( $this->telemetryInfo(), $configuration, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerBootstrapFinished(string $filename): void { $this->dispatcher->dispatch( new TestRunner\BootstrapFinished( $this->telemetryInfo(), $filename, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerLoadedExtensionFromPhar(string $filename, string $name, string $version): void { $this->dispatcher->dispatch( new TestRunner\ExtensionLoadedFromPhar( $this->telemetryInfo(), $filename, $name, $version, ), ); } /** * @param class-string $className * @param array<string, string> $parameters * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerBootstrappedExtension(string $className, array $parameters): void { $this->dispatcher->dispatch( new TestRunner\ExtensionBootstrapped( $this->telemetryInfo(), $className, $parameters, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function dataProviderMethodCalled(ClassMethod $testMethod, ClassMethod $dataProviderMethod): void { $this->dispatcher->dispatch( new DataProviderMethodCalled( $this->telemetryInfo(), $testMethod, $dataProviderMethod, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function dataProviderMethodFinished(ClassMethod $testMethod, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new DataProviderMethodFinished( $this->telemetryInfo(), $testMethod, ...$calledMethods, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteLoaded(TestSuite $testSuite): void { $this->dispatcher->dispatch( new TestSuiteLoaded( $this->telemetryInfo(), $testSuite, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteFiltered(TestSuite $testSuite): void { $this->dispatcher->dispatch( new TestSuiteFiltered( $this->telemetryInfo(), $testSuite, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteSorted(int $executionOrder, int $executionOrderDefects, bool $resolveDependencies): void { $this->dispatcher->dispatch( new TestSuiteSorted( $this->telemetryInfo(), $executionOrder, $executionOrderDefects, $resolveDependencies, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerEventFacadeSealed(): void { $this->dispatcher->dispatch( new TestRunner\EventFacadeSealed( $this->telemetryInfo(), ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerExecutionStarted(TestSuite $testSuite): void { $this->dispatcher->dispatch( new TestRunner\ExecutionStarted( $this->telemetryInfo(), $testSuite, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerDisabledGarbageCollection(): void { $this->dispatcher->dispatch( new TestRunner\GarbageCollectionDisabled($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerTriggeredGarbageCollection(): void { $this->dispatcher->dispatch( new TestRunner\GarbageCollectionTriggered($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteSkipped(TestSuite $testSuite, string $message): void { $this->dispatcher->dispatch( new TestSuiteSkipped( $this->telemetryInfo(), $testSuite, $message, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteStarted(TestSuite $testSuite): void { $this->dispatcher->dispatch( new TestSuiteStarted( $this->telemetryInfo(), $testSuite, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPreparationStarted(Code\Test $test): void { $this->dispatcher->dispatch( new Test\PreparationStarted( $this->telemetryInfo(), $test, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPreparationFailed(Code\Test $test): void { $this->dispatcher->dispatch( new Test\PreparationFailed( $this->telemetryInfo(), $test, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testBeforeFirstTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\BeforeFirstTestMethodCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testBeforeFirstTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void { $this->dispatcher->dispatch( new Test\BeforeFirstTestMethodErrored( $this->telemetryInfo(), $testClassName, $calledMethod, $throwable, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testBeforeFirstTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\BeforeFirstTestMethodFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testBeforeTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\BeforeTestMethodCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testBeforeTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\BeforeTestMethodFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPreConditionCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\PreConditionCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPreConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\PreConditionFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPrepared(Code\Test $test): void { $this->dispatcher->dispatch( new Test\Prepared( $this->telemetryInfo(), $test, ), ); } /** * @param class-string $className * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRegisteredComparator(string $className): void { $this->dispatcher->dispatch( new Test\ComparatorRegistered( $this->telemetryInfo(), $className, ), ); } /** * @param class-string $className * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedMockObject(string $className): void { $this->dispatcher->dispatch( new Test\MockObjectCreated( $this->telemetryInfo(), $className, ), ); } /** * @param list<class-string> $interfaces * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedMockObjectForIntersectionOfInterfaces(array $interfaces): void { $this->dispatcher->dispatch( new Test\MockObjectForIntersectionOfInterfacesCreated( $this->telemetryInfo(), $interfaces, ), ); } /** * @param trait-string $traitName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedMockObjectForTrait(string $traitName): void { $this->dispatcher->dispatch( new Test\MockObjectForTraitCreated( $this->telemetryInfo(), $traitName, ), ); } /** * @param class-string $className * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedMockObjectForAbstractClass(string $className): void { $this->dispatcher->dispatch( new Test\MockObjectForAbstractClassCreated( $this->telemetryInfo(), $className, ), ); } /** * @param class-string $originalClassName * @param class-string $mockClassName * @param list<string> $methods * @param list<mixed> $options * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedMockObjectFromWsdl(string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options): void { $this->dispatcher->dispatch( new Test\MockObjectFromWsdlCreated( $this->telemetryInfo(), $wsdlFile, $originalClassName, $mockClassName, $methods, $callOriginalConstructor, $options, ), ); } /** * @param class-string $className * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedPartialMockObject(string $className, string ...$methodNames): void { $this->dispatcher->dispatch( new Test\PartialMockObjectCreated( $this->telemetryInfo(), $className, ...$methodNames, ), ); } /** * @param class-string $className * @param list<mixed> $constructorArguments * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedTestProxy(string $className, array $constructorArguments): void { $this->dispatcher->dispatch( new Test\TestProxyCreated( $this->telemetryInfo(), $className, Exporter::export($constructorArguments), ), ); } /** * @param class-string $className * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedStub(string $className): void { $this->dispatcher->dispatch( new Test\TestStubCreated( $this->telemetryInfo(), $className, ), ); } /** * @param list<class-string> $interfaces * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testCreatedStubForIntersectionOfInterfaces(array $interfaces): void { $this->dispatcher->dispatch( new Test\TestStubForIntersectionOfInterfacesCreated( $this->telemetryInfo(), $interfaces, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testErrored(Code\Test $test, Throwable $throwable): void { $this->dispatcher->dispatch( new Test\Errored( $this->telemetryInfo(), $test, $throwable, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testFailed(Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure): void { $this->dispatcher->dispatch( new Test\Failed( $this->telemetryInfo(), $test, $throwable, $comparisonFailure, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPassed(Code\Test $test): void { $this->dispatcher->dispatch( new Test\Passed( $this->telemetryInfo(), $test, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testConsideredRisky(Code\Test $test, string $message): void { $this->dispatcher->dispatch( new Test\ConsideredRisky( $this->telemetryInfo(), $test, $message, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testMarkedAsIncomplete(Code\Test $test, Throwable $throwable): void { $this->dispatcher->dispatch( new Test\MarkedIncomplete( $this->telemetryInfo(), $test, $throwable, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSkipped(Code\Test $test, string $message): void { $this->dispatcher->dispatch( new Test\Skipped( $this->telemetryInfo(), $test, $message, ), ); } /** * @param non-empty-string $message * * @throws InvalidArgumentException * @throws NoTestCaseObjectOnCallStackException * @throws UnknownEventTypeException */ public function testTriggeredPhpunitDeprecation(?Code\Test $test, string $message): void { if ($test === null) { $test = TestMethodBuilder::fromCallStack(); } if ($test->isTestMethod()) { assert($test instanceof TestMethod); if ($test->metadata()->isIgnorePhpunitDeprecations()->isNotEmpty()) { return; } } $this->dispatcher->dispatch( new Test\PhpunitDeprecationTriggered( $this->telemetryInfo(), $test, $message, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredPhpDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger): void { $this->dispatcher->dispatch( new Test\PhpDeprecationTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, $ignoredByTest, $trigger, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredDeprecation(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger): void { $this->dispatcher->dispatch( new Test\DeprecationTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, $ignoredByTest, $trigger, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredError(Code\Test $test, string $message, string $file, int $line, bool $suppressed): void { $this->dispatcher->dispatch( new Test\ErrorTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void { $this->dispatcher->dispatch( new Test\NoticeTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredPhpNotice(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void { $this->dispatcher->dispatch( new Test\PhpNoticeTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void { $this->dispatcher->dispatch( new Test\WarningTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, ), ); } /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredPhpWarning(Code\Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline): void { $this->dispatcher->dispatch( new Test\PhpWarningTriggered( $this->telemetryInfo(), $test, $message, $file, $line, $suppressed, $ignoredByBaseline, ), ); } /** * @param non-empty-string $message * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredPhpunitError(Code\Test $test, string $message): void { $this->dispatcher->dispatch( new Test\PhpunitErrorTriggered( $this->telemetryInfo(), $test, $message, ), ); } /** * @param non-empty-string $message * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testTriggeredPhpunitWarning(Code\Test $test, string $message): void { $this->dispatcher->dispatch( new Test\PhpunitWarningTriggered( $this->telemetryInfo(), $test, $message, ), ); } /** * @param non-empty-string $output * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPrintedUnexpectedOutput(string $output): void { $this->dispatcher->dispatch( new Test\PrintedUnexpectedOutput( $this->telemetryInfo(), $output, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testFinished(Code\Test $test, int $numberOfAssertionsPerformed): void { $this->dispatcher->dispatch( new Test\Finished( $this->telemetryInfo(), $test, $numberOfAssertionsPerformed, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPostConditionCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\PostConditionCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testPostConditionFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\PostConditionFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testAfterTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\AfterTestMethodCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testAfterTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\AfterTestMethodFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testAfterLastTestMethodCalled(string $testClassName, ClassMethod $calledMethod): void { $this->dispatcher->dispatch( new Test\AfterLastTestMethodCalled( $this->telemetryInfo(), $testClassName, $calledMethod, ), ); } /** * @param class-string $testClassName * * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testAfterLastTestMethodFinished(string $testClassName, ClassMethod ...$calledMethods): void { $this->dispatcher->dispatch( new Test\AfterLastTestMethodFinished( $this->telemetryInfo(), $testClassName, ...$calledMethods, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testSuiteFinished(TestSuite $testSuite): void { $this->dispatcher->dispatch( new TestSuiteFinished( $this->telemetryInfo(), $testSuite, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerTriggeredDeprecation(string $message): void { $this->dispatcher->dispatch( new TestRunner\DeprecationTriggered( $this->telemetryInfo(), $message, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerTriggeredWarning(string $message): void { $this->dispatcher->dispatch( new TestRunner\WarningTriggered( $this->telemetryInfo(), $message, ), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerEnabledGarbageCollection(): void { $this->dispatcher->dispatch( new TestRunner\GarbageCollectionEnabled($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerExecutionAborted(): void { $this->dispatcher->dispatch( new TestRunner\ExecutionAborted($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerExecutionFinished(): void { $this->dispatcher->dispatch( new TestRunner\ExecutionFinished($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function testRunnerFinished(): void { $this->dispatcher->dispatch( new TestRunner\Finished($this->telemetryInfo()), ); } /** * @throws InvalidArgumentException * @throws UnknownEventTypeException */ public function applicationFinished(int $shellExitCode): void { $this->dispatcher->dispatch( new Application\Finished( $this->telemetryInfo(), $shellExitCode, ), ); } /** * @throws InvalidArgumentException */ private function telemetryInfo(): Telemetry\Info { $current = $this->system->snapshot(); $info = new Telemetry\Info( $current, $current->time()->duration($this->startSnapshot->time()), $current->memoryUsage()->diff($this->startSnapshot->memoryUsage()), $current->time()->duration($this->previousSnapshot->time()), $current->memoryUsage()->diff($this->previousSnapshot->memoryUsage()), ); $this->previousSnapshot = $current; return $info; } } phpunit/src/Event/Subscriber.php 0000644 00000000641 15253321353 0012722 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Subscriber { } phpunit/src/Event/Value/ThrowableBuilder.php 0000644 00000002240 15253321353 0015126 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use PHPUnit\Event\NoPreviousThrowableException; use PHPUnit\Framework\Exception; use PHPUnit\Util\Filter; use PHPUnit\Util\ThrowableToStringMapper; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ThrowableBuilder { /** * @throws Exception * @throws NoPreviousThrowableException */ public static function from(\Throwable $t): Throwable { $previous = $t->getPrevious(); if ($previous !== null) { $previous = self::from($previous); } return new Throwable( $t::class, $t->getMessage(), ThrowableToStringMapper::map($t), Filter::getFilteredStacktrace($t, false), $previous, ); } } phpunit/src/Event/Value/ComparisonFailureBuilder.php 0000644 00000003545 15253321353 0016632 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use function is_bool; use function is_scalar; use function print_r; use PHPUnit\Framework\ExpectationFailedException; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ComparisonFailureBuilder { public static function from(Throwable $t): ?ComparisonFailure { if (!$t instanceof ExpectationFailedException) { return null; } if (!$t->getComparisonFailure()) { return null; } $expectedAsString = $t->getComparisonFailure()->getExpectedAsString(); if (empty($expectedAsString)) { $expectedAsString = self::mapScalarValueToString($t->getComparisonFailure()->getExpected()); } $actualAsString = $t->getComparisonFailure()->getActualAsString(); if (empty($actualAsString)) { $actualAsString = self::mapScalarValueToString($t->getComparisonFailure()->getActual()); } return new ComparisonFailure( $expectedAsString, $actualAsString, $t->getComparisonFailure()->getDiff(), ); } private static function mapScalarValueToString(mixed $value): string { if ($value === null) { return 'null'; } if (is_bool($value)) { return $value ? 'true' : 'false'; } if (is_scalar($value)) { return print_r($value, true); } return ''; } } phpunit/src/Event/Value/ComparisonFailure.php 0000644 00000001723 15253321353 0015317 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ComparisonFailure { private string $expected; private string $actual; private string $diff; public function __construct(string $expected, string $actual, string $diff) { $this->expected = $expected; $this->actual = $actual; $this->diff = $diff; } public function expected(): string { return $this->expected; } public function actual(): string { return $this->actual; } public function diff(): string { return $this->diff; } } phpunit/src/Event/Value/Throwable.php 0000644 00000004435 15253321353 0013627 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use const PHP_EOL; use PHPUnit\Event\NoPreviousThrowableException; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Throwable { /** * @var class-string */ private string $className; private string $message; private string $description; private string $stackTrace; private ?Throwable $previous; /** * @param class-string $className */ public function __construct(string $className, string $message, string $description, string $stackTrace, ?self $previous) { $this->className = $className; $this->message = $message; $this->description = $description; $this->stackTrace = $stackTrace; $this->previous = $previous; } /** * @throws NoPreviousThrowableException */ public function asString(): string { $buffer = $this->description(); if (!empty($this->stackTrace())) { $buffer .= PHP_EOL . $this->stackTrace(); } if ($this->hasPrevious()) { $buffer .= PHP_EOL . 'Caused by' . PHP_EOL . $this->previous()->asString(); } return $buffer; } /** * @return class-string */ public function className(): string { return $this->className; } public function message(): string { return $this->message; } public function description(): string { return $this->description; } public function stackTrace(): string { return $this->stackTrace; } /** * @phpstan-assert-if-true !null $this->previous */ public function hasPrevious(): bool { return $this->previous !== null; } /** * @throws NoPreviousThrowableException */ public function previous(): self { if ($this->previous === null) { throw new NoPreviousThrowableException; } return $this->previous; } } phpunit/src/Event/Value/TestSuite/TestSuite.php 0000644 00000003142 15253321353 0015554 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Code\TestCollection; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract readonly class TestSuite { /** * @var non-empty-string */ private string $name; private int $count; private TestCollection $tests; /** * @param non-empty-string $name */ public function __construct(string $name, int $size, TestCollection $tests) { $this->name = $name; $this->count = $size; $this->tests = $tests; } /** * @return non-empty-string */ public function name(): string { return $this->name; } public function count(): int { return $this->count; } public function tests(): TestCollection { return $this->tests; } /** * @phpstan-assert-if-true TestSuiteWithName $this */ public function isWithName(): bool { return false; } /** * @phpstan-assert-if-true TestSuiteForTestClass $this */ public function isForTestClass(): bool { return false; } /** * @phpstan-assert-if-true TestSuiteForTestMethodWithDataProvider $this */ public function isForTestMethodWithDataProvider(): bool { return false; } } phpunit/src/Event/Value/TestSuite/TestSuiteForTestMethodWithDataProvider.php 0000644 00000003323 15253321353 0023366 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Code\TestCollection; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteForTestMethodWithDataProvider extends TestSuite { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; private string $file; private int $line; /** * @param non-empty-string $name * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $name, int $size, TestCollection $tests, string $className, string $methodName, string $file, int $line) { parent::__construct($name, $size, $tests); $this->className = $className; $this->methodName = $methodName; $this->file = $file; $this->line = $line; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } public function file(): string { return $this->file; } public function line(): int { return $this->line; } public function isForTestMethodWithDataProvider(): true { return true; } } phpunit/src/Event/Value/TestSuite/TestSuiteWithName.php 0000644 00000001050 15253321353 0017205 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteWithName extends TestSuite { public function isWithName(): true { return true; } } phpunit/src/Event/Value/TestSuite/TestSuiteForTestClass.php 0000644 00000002452 15253321353 0020054 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Code\TestCollection; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteForTestClass extends TestSuite { /** * @var class-string */ private string $className; private string $file; private int $line; /** * @param class-string $name */ public function __construct(string $name, int $size, TestCollection $tests, string $file, int $line) { parent::__construct($name, $size, $tests); $this->className = $name; $this->file = $file; $this->line = $line; } /** * @return class-string */ public function className(): string { return $this->className; } public function file(): string { return $this->file; } public function line(): int { return $this->line; } public function isForTestClass(): true { return true; } } phpunit/src/Event/Value/TestSuite/TestSuiteBuilder.php 0000644 00000006270 15253321353 0017070 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function assert; use function class_exists; use function explode; use function method_exists; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Code\TestCollection; use PHPUnit\Event\RuntimeException; use PHPUnit\Framework\DataProviderTestSuite; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite as FrameworkTestSuite; use PHPUnit\Runner\PhptTestCase; use ReflectionClass; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteBuilder { /** * @throws RuntimeException */ public static function from(FrameworkTestSuite $testSuite): TestSuite { $tests = []; self::process($testSuite, $tests); if ($testSuite instanceof DataProviderTestSuite) { [$className, $methodName] = explode('::', $testSuite->name()); assert(class_exists($className)); assert($methodName !== '' && method_exists($className, $methodName)); $reflector = new ReflectionMethod($className, $methodName); $file = $reflector->getFileName(); $line = $reflector->getStartLine(); assert($file !== false); assert($line !== false); return new TestSuiteForTestMethodWithDataProvider( $testSuite->name(), $testSuite->count(), TestCollection::fromArray($tests), $className, $methodName, $file, $line, ); } if ($testSuite->isForTestClass()) { $testClassName = $testSuite->name(); assert(class_exists($testClassName)); $reflector = new ReflectionClass($testClassName); $file = $reflector->getFileName(); $line = $reflector->getStartLine(); assert($file !== false); assert($line !== false); return new TestSuiteForTestClass( $testClassName, $testSuite->count(), TestCollection::fromArray($tests), $file, $line, ); } return new TestSuiteWithName( $testSuite->name(), $testSuite->count(), TestCollection::fromArray($tests), ); } /** * @param list<Test> $tests */ private static function process(FrameworkTestSuite $testSuite, array &$tests): void { foreach ($testSuite->getIterator() as $test) { if ($test instanceof FrameworkTestSuite) { self::process($test, $tests); continue; } if ($test instanceof TestCase || $test instanceof PhptTestCase) { $tests[] = $test->valueObjectForEvents(); } } } } phpunit/src/Event/Value/Test/TestDoxBuilder.php 0000644 00000002673 15253321353 0015522 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use PHPUnit\Framework\TestCase; use PHPUnit\Logging\TestDox\NamePrettifier; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestDoxBuilder { public static function fromTestCase(TestCase $testCase): TestDox { $prettifier = new NamePrettifier; return new TestDox( $prettifier->prettifyTestClassName($testCase::class), $prettifier->prettifyTestCase($testCase, false), $prettifier->prettifyTestCase($testCase, true), ); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function fromClassNameAndMethodName(string $className, string $methodName): TestDox { $prettifier = new NamePrettifier; $prettifiedMethodName = $prettifier->prettifyTestMethodName($methodName); return new TestDox( $prettifier->prettifyTestClassName($className), $prettifiedMethodName, $prettifiedMethodName, ); } } phpunit/src/Event/Value/Test/TestCollection.php 0000644 00000002335 15253321353 0015547 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use function count; use Countable; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, Test> * * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestCollection implements Countable, IteratorAggregate { /** * @var list<Test> */ private array $tests; /** * @param list<Test> $tests */ public static function fromArray(array $tests): self { return new self(...$tests); } private function __construct(Test ...$tests) { $this->tests = $tests; } /** * @return list<Test> */ public function asArray(): array { return $this->tests; } public function count(): int { return count($this->tests); } public function getIterator(): TestCollectionIterator { return new TestCollectionIterator($this); } } phpunit/src/Event/Value/Test/TestMethodBuilder.php 0000644 00000005426 15253321353 0016207 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use const DEBUG_BACKTRACE_IGNORE_ARGS; use const DEBUG_BACKTRACE_PROVIDE_OBJECT; use function assert; use function debug_backtrace; use function is_numeric; use PHPUnit\Event\TestData\DataFromDataProvider; use PHPUnit\Event\TestData\DataFromTestDependency; use PHPUnit\Event\TestData\TestDataCollection; use PHPUnit\Framework\TestCase; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Util\Exporter; use PHPUnit\Util\Reflection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMethodBuilder { public static function fromTestCase(TestCase $testCase): TestMethod { $methodName = $testCase->name(); assert(!empty($methodName)); $location = Reflection::sourceLocationFor($testCase::class, $methodName); return new TestMethod( $testCase::class, $methodName, $location['file'], $location['line'], TestDoxBuilder::fromTestCase($testCase), MetadataRegistry::parser()->forClassAndMethod($testCase::class, $methodName), self::dataFor($testCase), ); } /** * @throws NoTestCaseObjectOnCallStackException */ public static function fromCallStack(): TestMethod { foreach (debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { if (isset($frame['object']) && $frame['object'] instanceof TestCase) { return $frame['object']->valueObjectForEvents(); } } throw new NoTestCaseObjectOnCallStackException; } private static function dataFor(TestCase $testCase): TestDataCollection { $testData = []; if ($testCase->usesDataProvider()) { $dataSetName = $testCase->dataName(); if (is_numeric($dataSetName)) { $dataSetName = (int) $dataSetName; } $testData[] = DataFromDataProvider::from( $dataSetName, Exporter::export($testCase->providedData()), $testCase->dataSetAsStringWithData(), ); } if ($testCase->hasDependencyInput()) { $testData[] = DataFromTestDependency::from( Exporter::export($testCase->dependencyInput()), ); } return TestDataCollection::fromArray($testData); } } phpunit/src/Event/Value/Test/TestCollectionIterator.php 0000644 00000002227 15253321353 0017261 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use function count; use Iterator; /** * @template-implements Iterator<int, Test> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class TestCollectionIterator implements Iterator { /** * @var list<Test> */ private readonly array $tests; private int $position = 0; public function __construct(TestCollection $tests) { $this->tests = $tests->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->tests); } public function key(): int { return $this->position; } public function current(): Test { return $this->tests[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/Event/Value/Test/TestDox.php 0000644 00000002414 15253321353 0014204 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestDox { private string $prettifiedClassName; private string $prettifiedMethodName; private string $prettifiedAndColorizedMethodName; public function __construct(string $prettifiedClassName, string $prettifiedMethodName, string $prettifiedAndColorizedMethodName) { $this->prettifiedClassName = $prettifiedClassName; $this->prettifiedMethodName = $prettifiedMethodName; $this->prettifiedAndColorizedMethodName = $prettifiedAndColorizedMethodName; } public function prettifiedClassName(): string { return $this->prettifiedClassName; } public function prettifiedMethodName(bool $colorize = false): string { if ($colorize) { return $this->prettifiedAndColorizedMethodName; } return $this->prettifiedMethodName; } } phpunit/src/Event/Value/Test/Issue/SelfTrigger.php 0000644 00000001361 15253321353 0016117 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code\IssueTrigger; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class SelfTrigger extends IssueTrigger { /** * Your own code triggers an issue in your own code. */ public function isSelf(): true { return true; } public function asString(): string { return 'issue triggered by first-party code calling into first-party code'; } } phpunit/src/Event/Value/Test/Issue/DirectTrigger.php 0000644 00000001370 15253321353 0016440 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code\IssueTrigger; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class DirectTrigger extends IssueTrigger { /** * Your own code triggers an issue in third-party code. */ public function isDirect(): true { return true; } public function asString(): string { return 'issue triggered by first-party code calling into third-party code'; } } phpunit/src/Event/Value/Test/Issue/UnknownTrigger.php 0000644 00000001263 15253321353 0016666 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code\IssueTrigger; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class UnknownTrigger extends IssueTrigger { public function isUnknown(): true { return true; } public function asString(): string { return 'unknown if issue was triggered in first-party code or third-party code'; } } phpunit/src/Event/Value/Test/Issue/IssueTrigger.php 0000644 00000003317 15253321353 0016321 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code\IssueTrigger; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract class IssueTrigger { public static function self(): SelfTrigger { return new SelfTrigger; } public static function direct(): DirectTrigger { return new DirectTrigger; } public static function indirect(): IndirectTrigger { return new IndirectTrigger; } public static function unknown(): UnknownTrigger { return new UnknownTrigger; } final private function __construct() { } /** * Your own code triggers an issue in your own code. * * @phpstan-assert-if-true SelfTrigger $this */ public function isSelf(): bool { return false; } /** * Your own code triggers an issue in third-party code. * * @phpstan-assert-if-true DirectTrigger $this */ public function isDirect(): bool { return false; } /** * Third-party code triggers an issue either in your own code or in third-party code. * * @phpstan-assert-if-true IndirectTrigger $this */ public function isIndirect(): bool { return false; } /** * @phpstan-assert-if-true UnknownTrigger $this */ public function isUnknown(): bool { return false; } abstract public function asString(): string; } phpunit/src/Event/Value/Test/Issue/IndirectTrigger.php 0000644 00000001374 15253321353 0016773 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code\IssueTrigger; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class IndirectTrigger extends IssueTrigger { /** * Third-party code triggers an issue either in your own code or in third-party code. */ public function isIndirect(): true { return true; } public function asString(): string { return 'issue triggered by third-party code'; } } phpunit/src/Event/Value/Test/TestMethod.php 0000644 00000006547 15253321353 0014705 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; use function is_int; use function sprintf; use PHPUnit\Event\TestData\TestDataCollection; use PHPUnit\Metadata\MetadataCollection; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMethod extends Test { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @var non-negative-int */ private int $line; private TestDox $testDox; private MetadataCollection $metadata; private TestDataCollection $testData; /** * @param class-string $className * @param non-empty-string $methodName * @param non-empty-string $file * @param non-negative-int $line */ public function __construct(string $className, string $methodName, string $file, int $line, TestDox $testDox, MetadataCollection $metadata, TestDataCollection $testData) { parent::__construct($file); $this->className = $className; $this->methodName = $methodName; $this->line = $line; $this->testDox = $testDox; $this->metadata = $metadata; $this->testData = $testData; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @return non-negative-int */ public function line(): int { return $this->line; } public function testDox(): TestDox { return $this->testDox; } public function metadata(): MetadataCollection { return $this->metadata; } public function testData(): TestDataCollection { return $this->testData; } public function isTestMethod(): true { return true; } /** * @return non-empty-string */ public function id(): string { $buffer = $this->className . '::' . $this->methodName; if ($this->testData()->hasDataFromDataProvider()) { $buffer .= '#' . $this->testData->dataFromDataProvider()->dataSetName(); } return $buffer; } /** * @return non-empty-string */ public function nameWithClass(): string { return $this->className . '::' . $this->name(); } /** * @return non-empty-string */ public function name(): string { if (!$this->testData->hasDataFromDataProvider()) { return $this->methodName; } $dataSetName = $this->testData->dataFromDataProvider()->dataSetName(); if (is_int($dataSetName)) { $dataSetName = sprintf( ' with data set #%d', $dataSetName, ); } else { $dataSetName = sprintf( ' with data set "%s"', $dataSetName, ); } return $this->methodName . $dataSetName; } } phpunit/src/Event/Value/Test/Phpt.php 0000644 00000001407 15253321353 0013526 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Phpt extends Test { public function isPhpt(): true { return true; } /** * @return non-empty-string */ public function id(): string { return $this->file(); } /** * @return non-empty-string */ public function name(): string { return $this->file(); } } phpunit/src/Event/Value/Test/TestData/TestData.php 0000644 00000001704 15253321353 0016035 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract readonly class TestData { private string $data; protected function __construct(string $data) { $this->data = $data; } public function data(): string { return $this->data; } /** * @phpstan-assert-if-true DataFromDataProvider $this */ public function isFromDataProvider(): bool { return false; } /** * @phpstan-assert-if-true DataFromTestDependency $this */ public function isFromTestDependency(): bool { return false; } } phpunit/src/Event/Value/Test/TestData/DataFromDataProvider.php 0000644 00000002700 15253321353 0020323 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DataFromDataProvider extends TestData { private int|string $dataSetName; private string $dataAsStringForResultOutput; public static function from(int|string $dataSetName, string $data, string $dataAsStringForResultOutput): self { return new self($dataSetName, $data, $dataAsStringForResultOutput); } protected function __construct(int|string $dataSetName, string $data, string $dataAsStringForResultOutput) { $this->dataSetName = $dataSetName; $this->dataAsStringForResultOutput = $dataAsStringForResultOutput; parent::__construct($data); } public function dataSetName(): int|string { return $this->dataSetName; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function dataAsStringForResultOutput(): string { return $this->dataAsStringForResultOutput; } public function isFromDataProvider(): true { return true; } } phpunit/src/Event/Value/Test/TestData/TestDataCollectionIterator.php 0000644 00000002251 15253321353 0021561 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; use function count; use Iterator; /** * @template-implements Iterator<int, TestData> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class TestDataCollectionIterator implements Iterator { /** * @var list<TestData> */ private readonly array $data; private int $position = 0; public function __construct(TestDataCollection $data) { $this->data = $data->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->data); } public function key(): int { return $this->position; } public function current(): TestData { return $this->data[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/Event/Value/Test/TestData/DataFromTestDependency.php 0000644 00000001226 15253321353 0020657 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DataFromTestDependency extends TestData { public static function from(string $data): self { return new self($data); } public function isFromTestDependency(): true { return true; } } phpunit/src/Event/Value/Test/TestData/TestDataCollection.php 0000644 00000004006 15253321353 0020047 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestData; use function count; use Countable; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, TestData> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestDataCollection implements Countable, IteratorAggregate { /** * @var list<TestData> */ private array $data; private ?DataFromDataProvider $fromDataProvider; /** * @param list<TestData> $data */ public static function fromArray(array $data): self { return new self(...$data); } private function __construct(TestData ...$data) { $fromDataProvider = null; foreach ($data as $_data) { if ($_data->isFromDataProvider()) { $fromDataProvider = $_data; } } $this->data = $data; $this->fromDataProvider = $fromDataProvider; } /** * @return list<TestData> */ public function asArray(): array { return $this->data; } public function count(): int { return count($this->data); } /** * @phpstan-assert-if-true !null $this->fromDataProvider */ public function hasDataFromDataProvider(): bool { return $this->fromDataProvider !== null; } /** * @throws NoDataSetFromDataProviderException */ public function dataFromDataProvider(): DataFromDataProvider { if (!$this->hasDataFromDataProvider()) { throw new NoDataSetFromDataProviderException; } return $this->fromDataProvider; } public function getIterator(): TestDataCollectionIterator { return new TestDataCollectionIterator($this); } } phpunit/src/Event/Value/Test/Test.php 0000644 00000002325 15253321353 0013532 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Test { /** * @var non-empty-string */ private string $file; /** * @param non-empty-string $file */ public function __construct(string $file) { $this->file = $file; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @phpstan-assert-if-true TestMethod $this */ public function isTestMethod(): bool { return false; } /** * @phpstan-assert-if-true Phpt $this */ public function isPhpt(): bool { return false; } /** * @return non-empty-string */ abstract public function id(): string; /** * @return non-empty-string */ abstract public function name(): string; } phpunit/src/Event/Value/ClassMethod.php 0000644 00000002155 15253321353 0014103 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Code; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ClassMethod { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param class-string $className * @param non-empty-string $methodName */ public function __construct(string $className, string $methodName) { $this->className = $className; $this->methodName = $methodName; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Event/Value/Telemetry/Snapshot.php 0000644 00000002600 15253321353 0015441 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Snapshot { private HRTime $time; private MemoryUsage $memoryUsage; private MemoryUsage $peakMemoryUsage; private GarbageCollectorStatus $garbageCollectorStatus; public function __construct(HRTime $time, MemoryUsage $memoryUsage, MemoryUsage $peakMemoryUsage, GarbageCollectorStatus $garbageCollectorStatus) { $this->time = $time; $this->memoryUsage = $memoryUsage; $this->peakMemoryUsage = $peakMemoryUsage; $this->garbageCollectorStatus = $garbageCollectorStatus; } public function time(): HRTime { return $this->time; } public function memoryUsage(): MemoryUsage { return $this->memoryUsage; } public function peakMemoryUsage(): MemoryUsage { return $this->peakMemoryUsage; } public function garbageCollectorStatus(): GarbageCollectorStatus { return $this->garbageCollectorStatus; } } phpunit/src/Event/Value/Telemetry/Duration.php 0000644 00000006710 15253321353 0015435 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function floor; use function sprintf; use PHPUnit\Event\InvalidArgumentException; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Duration { private int $seconds; private int $nanoseconds; /** * @throws InvalidArgumentException */ public static function fromSecondsAndNanoseconds(int $seconds, int $nanoseconds): self { return new self( $seconds, $nanoseconds, ); } /** * @throws InvalidArgumentException */ private function __construct(int $seconds, int $nanoseconds) { $this->ensureNotNegative($seconds, 'seconds'); $this->ensureNotNegative($nanoseconds, 'nanoseconds'); $this->ensureNanoSecondsInRange($nanoseconds); $this->seconds = $seconds; $this->nanoseconds = $nanoseconds; } public function seconds(): int { return $this->seconds; } public function nanoseconds(): int { return $this->nanoseconds; } public function asFloat(): float { return $this->seconds() + ($this->nanoseconds() / 1000000000); } public function asString(): string { $seconds = $this->seconds(); $minutes = 0; $hours = 0; if ($seconds > 60 * 60) { $hours = floor($seconds / 60 / 60); $seconds -= ($hours * 60 * 60); } if ($seconds > 60) { $minutes = floor($seconds / 60); $seconds -= ($minutes * 60); } return sprintf( '%02d:%02d:%02d.%09d', $hours, $minutes, $seconds, $this->nanoseconds(), ); } public function equals(self $other): bool { return $this->seconds === $other->seconds && $this->nanoseconds === $other->nanoseconds; } public function isLessThan(self $other): bool { if ($this->seconds < $other->seconds) { return true; } if ($this->seconds > $other->seconds) { return false; } return $this->nanoseconds < $other->nanoseconds; } public function isGreaterThan(self $other): bool { if ($this->seconds > $other->seconds) { return true; } if ($this->seconds < $other->seconds) { return false; } return $this->nanoseconds > $other->nanoseconds; } /** * @throws InvalidArgumentException */ private function ensureNotNegative(int $value, string $type): void { if ($value < 0) { throw new InvalidArgumentException( sprintf( 'Value for %s must not be negative.', $type, ), ); } } /** * @throws InvalidArgumentException */ private function ensureNanoSecondsInRange(int $nanoseconds): void { if ($nanoseconds > 999999999) { throw new InvalidArgumentException( 'Value for nanoseconds must not be greater than 999999999.', ); } } } phpunit/src/Event/Value/Telemetry/GarbageCollectorStatusProvider.php 0000644 00000001125 15253321353 0021761 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface GarbageCollectorStatusProvider { public function status(): GarbageCollectorStatus; } phpunit/src/Event/Value/Telemetry/MemoryMeter.php 0000644 00000001161 15253321353 0016110 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface MemoryMeter { public function memoryUsage(): MemoryUsage; public function peakMemoryUsage(): MemoryUsage; } phpunit/src/Event/Value/Telemetry/System.php 0000644 00000002460 15253321353 0015132 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class System { private StopWatch $stopWatch; private MemoryMeter $memoryMeter; private GarbageCollectorStatusProvider $garbageCollectorStatusProvider; public function __construct(StopWatch $stopWatch, MemoryMeter $memoryMeter, GarbageCollectorStatusProvider $garbageCollectorStatusProvider) { $this->stopWatch = $stopWatch; $this->memoryMeter = $memoryMeter; $this->garbageCollectorStatusProvider = $garbageCollectorStatusProvider; } public function snapshot(): Snapshot { return new Snapshot( $this->stopWatch->current(), $this->memoryMeter->memoryUsage(), $this->memoryMeter->peakMemoryUsage(), $this->garbageCollectorStatusProvider->status(), ); } } phpunit/src/Event/Value/Telemetry/Php81GarbageCollectorStatusProvider.php 0000644 00000002056 15253321353 0022606 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function gc_status; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final readonly class Php81GarbageCollectorStatusProvider implements GarbageCollectorStatusProvider { public function status(): GarbageCollectorStatus { $status = gc_status(); return new GarbageCollectorStatus( $status['runs'], $status['collected'], $status['threshold'], $status['roots'], null, null, null, null, null, null, null, null, ); } } phpunit/src/Event/Value/Telemetry/SystemMemoryMeter.php 0000644 00000001562 15253321353 0017322 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function memory_get_peak_usage; use function memory_get_usage; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class SystemMemoryMeter implements MemoryMeter { public function memoryUsage(): MemoryUsage { return MemoryUsage::fromBytes(memory_get_usage(true)); } public function peakMemoryUsage(): MemoryUsage { return MemoryUsage::fromBytes(memory_get_peak_usage(true)); } } phpunit/src/Event/Value/Telemetry/HRTime.php 0000644 00000005027 15253321353 0015000 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function sprintf; use PHPUnit\Event\InvalidArgumentException; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class HRTime { private int $seconds; private int $nanoseconds; /** * @throws InvalidArgumentException */ public static function fromSecondsAndNanoseconds(int $seconds, int $nanoseconds): self { return new self( $seconds, $nanoseconds, ); } /** * @throws InvalidArgumentException */ private function __construct(int $seconds, int $nanoseconds) { $this->ensureNotNegative($seconds, 'seconds'); $this->ensureNotNegative($nanoseconds, 'nanoseconds'); $this->ensureNanoSecondsInRange($nanoseconds); $this->seconds = $seconds; $this->nanoseconds = $nanoseconds; } public function seconds(): int { return $this->seconds; } public function nanoseconds(): int { return $this->nanoseconds; } public function duration(self $start): Duration { $seconds = $this->seconds - $start->seconds(); $nanoseconds = $this->nanoseconds - $start->nanoseconds(); if ($nanoseconds < 0) { $seconds--; $nanoseconds += 1000000000; } if ($seconds < 0) { return Duration::fromSecondsAndNanoseconds(0, 0); } return Duration::fromSecondsAndNanoseconds( $seconds, $nanoseconds, ); } /** * @throws InvalidArgumentException */ private function ensureNotNegative(int $value, string $type): void { if ($value < 0) { throw new InvalidArgumentException( sprintf( 'Value for %s must not be negative.', $type, ), ); } } /** * @throws InvalidArgumentException */ private function ensureNanoSecondsInRange(int $nanoseconds): void { if ($nanoseconds > 999999999) { throw new InvalidArgumentException( 'Value for nanoseconds must not be greater than 999999999.', ); } } } phpunit/src/Event/Value/Telemetry/MemoryUsage.php 0000644 00000001540 15253321353 0016101 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MemoryUsage { private int $bytes; public static function fromBytes(int $bytes): self { return new self($bytes); } private function __construct(int $bytes) { $this->bytes = $bytes; } public function bytes(): int { return $this->bytes; } public function diff(self $other): self { return self::fromBytes($this->bytes - $other->bytes); } } phpunit/src/Event/Value/Telemetry/GarbageCollectorStatus.php 0000644 00000011117 15253321353 0020250 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use PHPUnit\Event\RuntimeException; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class GarbageCollectorStatus { private int $runs; private int $collected; private int $threshold; private int $roots; private ?float $applicationTime; private ?float $collectorTime; private ?float $destructorTime; private ?float $freeTime; private ?bool $running; private ?bool $protected; private ?bool $full; private ?int $bufferSize; public function __construct(int $runs, int $collected, int $threshold, int $roots, ?float $applicationTime, ?float $collectorTime, ?float $destructorTime, ?float $freeTime, ?bool $running, ?bool $protected, ?bool $full, ?int $bufferSize) { $this->runs = $runs; $this->collected = $collected; $this->threshold = $threshold; $this->roots = $roots; $this->applicationTime = $applicationTime; $this->collectorTime = $collectorTime; $this->destructorTime = $destructorTime; $this->freeTime = $freeTime; $this->running = $running; $this->protected = $protected; $this->full = $full; $this->bufferSize = $bufferSize; } public function runs(): int { return $this->runs; } public function collected(): int { return $this->collected; } public function threshold(): int { return $this->threshold; } public function roots(): int { return $this->roots; } /** * @phpstan-assert-if-true !null $this->applicationTime * @phpstan-assert-if-true !null $this->collectorTime * @phpstan-assert-if-true !null $this->destructorTime * @phpstan-assert-if-true !null $this->freeTime * @phpstan-assert-if-true !null $this->running * @phpstan-assert-if-true !null $this->protected * @phpstan-assert-if-true !null $this->full * @phpstan-assert-if-true !null $this->bufferSize */ public function hasExtendedInformation(): bool { return $this->running !== null; } /** * @throws RuntimeException on PHP < 8.3 */ public function applicationTime(): float { if ($this->applicationTime === null) { throw new RuntimeException('Information not available'); } return $this->applicationTime; } /** * @throws RuntimeException on PHP < 8.3 */ public function collectorTime(): float { if ($this->collectorTime === null) { throw new RuntimeException('Information not available'); } return $this->collectorTime; } /** * @throws RuntimeException on PHP < 8.3 */ public function destructorTime(): float { if ($this->destructorTime === null) { throw new RuntimeException('Information not available'); } return $this->destructorTime; } /** * @throws RuntimeException on PHP < 8.3 */ public function freeTime(): float { if ($this->freeTime === null) { throw new RuntimeException('Information not available'); } return $this->freeTime; } /** * @throws RuntimeException on PHP < 8.3 */ public function isRunning(): bool { if ($this->running === null) { throw new RuntimeException('Information not available'); } return $this->running; } /** * @throws RuntimeException on PHP < 8.3 */ public function isProtected(): bool { if ($this->protected === null) { throw new RuntimeException('Information not available'); } return $this->protected; } /** * @throws RuntimeException on PHP < 8.3 */ public function isFull(): bool { if ($this->full === null) { throw new RuntimeException('Information not available'); } return $this->full; } /** * @throws RuntimeException on PHP < 8.3 */ public function bufferSize(): int { if ($this->bufferSize === null) { throw new RuntimeException('Information not available'); } return $this->bufferSize; } } phpunit/src/Event/Value/Telemetry/StopWatch.php 0000644 00000001061 15253321353 0015556 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface StopWatch { public function current(): HRTime; } phpunit/src/Event/Value/Telemetry/SystemStopWatchWithOffset.php 0000644 00000002104 15253321353 0020765 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function hrtime; use PHPUnit\Event\InvalidArgumentException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final class SystemStopWatchWithOffset implements StopWatch { private ?HRTime $offset; public function __construct(HRTime $offset) { $this->offset = $offset; } /** * @throws InvalidArgumentException */ public function current(): HRTime { if ($this->offset !== null) { $offset = $this->offset; $this->offset = null; return $offset; } return HRTime::fromSecondsAndNanoseconds(...hrtime()); } } phpunit/src/Event/Value/Telemetry/Info.php 0000644 00000004427 15253321353 0014546 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function sprintf; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Info { private Snapshot $current; private Duration $durationSinceStart; private MemoryUsage $memorySinceStart; private Duration $durationSincePrevious; private MemoryUsage $memorySincePrevious; public function __construct(Snapshot $current, Duration $durationSinceStart, MemoryUsage $memorySinceStart, Duration $durationSincePrevious, MemoryUsage $memorySincePrevious) { $this->current = $current; $this->durationSinceStart = $durationSinceStart; $this->memorySinceStart = $memorySinceStart; $this->durationSincePrevious = $durationSincePrevious; $this->memorySincePrevious = $memorySincePrevious; } public function time(): HRTime { return $this->current->time(); } public function memoryUsage(): MemoryUsage { return $this->current->memoryUsage(); } public function peakMemoryUsage(): MemoryUsage { return $this->current->peakMemoryUsage(); } public function durationSinceStart(): Duration { return $this->durationSinceStart; } public function memoryUsageSinceStart(): MemoryUsage { return $this->memorySinceStart; } public function durationSincePrevious(): Duration { return $this->durationSincePrevious; } public function memoryUsageSincePrevious(): MemoryUsage { return $this->memorySincePrevious; } public function garbageCollectorStatus(): GarbageCollectorStatus { return $this->current->garbageCollectorStatus(); } public function asString(): string { return sprintf( '[%s / %s] [%d bytes]', $this->durationSinceStart()->asString(), $this->durationSincePrevious()->asString(), $this->memoryUsage()->bytes(), ); } } phpunit/src/Event/Value/Telemetry/SystemStopWatch.php 0000644 00000001427 15253321353 0016771 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function hrtime; use PHPUnit\Event\InvalidArgumentException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class SystemStopWatch implements StopWatch { /** * @throws InvalidArgumentException */ public function current(): HRTime { return HRTime::fromSecondsAndNanoseconds(...hrtime()); } } phpunit/src/Event/Value/Telemetry/Php83GarbageCollectorStatusProvider.php 0000644 00000003151 15253321353 0022605 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Telemetry; use function gc_status; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Php83GarbageCollectorStatusProvider implements GarbageCollectorStatusProvider { public function status(): GarbageCollectorStatus { $status = gc_status(); return new GarbageCollectorStatus( $status['runs'], $status['collected'], $status['threshold'], $status['roots'], /** @phpstan-ignore offsetAccess.notFound */ $status['application_time'], /** @phpstan-ignore offsetAccess.notFound */ $status['collector_time'], /** @phpstan-ignore offsetAccess.notFound */ $status['destructor_time'], /** @phpstan-ignore offsetAccess.notFound */ $status['free_time'], /** @phpstan-ignore offsetAccess.notFound */ $status['running'], /** @phpstan-ignore offsetAccess.notFound */ $status['protected'], /** @phpstan-ignore offsetAccess.notFound */ $status['full'], /** @phpstan-ignore offsetAccess.notFound */ $status['buffer_size'], ); } } phpunit/src/Event/Value/Runtime/Runtime.php 0000644 00000002477 15253321353 0014752 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Runtime; use function sprintf; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Runtime { private OperatingSystem $operatingSystem; private PHP $php; private PHPUnit $phpunit; public function __construct() { $this->operatingSystem = new OperatingSystem; $this->php = new PHP; $this->phpunit = new PHPUnit; } public function asString(): string { $php = $this->php(); return sprintf( 'PHPUnit %s using PHP %s (%s) on %s', $this->phpunit()->versionId(), $php->version(), $php->sapi(), $this->operatingSystem()->operatingSystem(), ); } public function operatingSystem(): OperatingSystem { return $this->operatingSystem; } public function php(): PHP { return $this->php; } public function phpunit(): PHPUnit { return $this->phpunit; } } phpunit/src/Event/Value/Runtime/OperatingSystem.php 0000644 00000001652 15253321353 0016456 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Runtime; use const PHP_OS; use const PHP_OS_FAMILY; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class OperatingSystem { private string $operatingSystem; private string $operatingSystemFamily; public function __construct() { $this->operatingSystem = PHP_OS; $this->operatingSystemFamily = PHP_OS_FAMILY; } public function operatingSystem(): string { return $this->operatingSystem; } public function operatingSystemFamily(): string { return $this->operatingSystemFamily; } } phpunit/src/Event/Value/Runtime/PHPUnit.php 0000644 00000001544 15253321353 0014610 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Runtime; use PHPUnit\Runner\Version; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PHPUnit { private string $versionId; private string $releaseSeries; public function __construct() { $this->versionId = Version::id(); $this->releaseSeries = Version::series(); } public function versionId(): string { return $this->versionId; } public function releaseSeries(): string { return $this->releaseSeries; } } phpunit/src/Event/Value/Runtime/PHP.php 0000644 00000004416 15253321353 0013751 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Runtime; use const PHP_EXTRA_VERSION; use const PHP_MAJOR_VERSION; use const PHP_MINOR_VERSION; use const PHP_RELEASE_VERSION; use const PHP_SAPI; use const PHP_VERSION; use const PHP_VERSION_ID; use function array_merge; use function get_loaded_extensions; use function sort; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PHP { private string $version; private int $versionId; private int $majorVersion; private int $minorVersion; private int $releaseVersion; private string $extraVersion; private string $sapi; /** * @var list<string> */ private array $extensions; public function __construct() { $this->version = PHP_VERSION; $this->versionId = PHP_VERSION_ID; $this->majorVersion = PHP_MAJOR_VERSION; $this->minorVersion = PHP_MINOR_VERSION; $this->releaseVersion = PHP_RELEASE_VERSION; $this->extraVersion = PHP_EXTRA_VERSION; $this->sapi = PHP_SAPI; $extensions = array_merge( get_loaded_extensions(true), get_loaded_extensions(), ); sort($extensions); $this->extensions = $extensions; } public function version(): string { return $this->version; } public function sapi(): string { return $this->sapi; } public function majorVersion(): int { return $this->majorVersion; } public function minorVersion(): int { return $this->minorVersion; } public function releaseVersion(): int { return $this->releaseVersion; } public function extraVersion(): string { return $this->extraVersion; } public function versionId(): int { return $this->versionId; } /** * @return list<string> */ public function extensions(): array { return $this->extensions; } } phpunit/src/Event/Events/Application/Finished.php 0000644 00000002236 15253321353 0016061 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Application; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Finished implements Event { private Telemetry\Info $telemetryInfo; private int $shellExitCode; public function __construct(Telemetry\Info $telemetryInfo, int $shellExitCode) { $this->telemetryInfo = $telemetryInfo; $this->shellExitCode = $shellExitCode; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function shellExitCode(): int { return $this->shellExitCode; } public function asString(): string { return sprintf( 'PHPUnit Finished (Shell Exit Code: %d)', $this->shellExitCode, ); } } phpunit/src/Event/Events/Application/Started.php 0000644 00000002242 15253321353 0015733 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Application; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Runtime\Runtime; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Started implements Event { private Telemetry\Info $telemetryInfo; private Runtime $runtime; public function __construct(Telemetry\Info $telemetryInfo, Runtime $runtime) { $this->telemetryInfo = $telemetryInfo; $this->runtime = $runtime; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function runtime(): Runtime { return $this->runtime; } public function asString(): string { return sprintf( 'PHPUnit Started (%s)', $this->runtime->asString(), ); } } phpunit/src/Event/Events/Application/StartedSubscriber.php 0000644 00000001030 15253321353 0017751 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Application; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface StartedSubscriber extends Subscriber { public function notify(Started $event): void; } phpunit/src/Event/Events/Application/FinishedSubscriber.php 0000644 00000001032 15253321353 0020076 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Application; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FinishedSubscriber extends Subscriber { public function notify(Finished $event): void; } phpunit/src/Event/Events/Event.php 0000644 00000000772 15253321353 0013151 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface Event { public function telemetryInfo(): Telemetry\Info; public function asString(): string; } phpunit/src/Event/Events/EventCollectionIterator.php 0000644 00000002235 15253321353 0016673 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use function count; use Iterator; /** * @template-implements Iterator<int, Event> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class EventCollectionIterator implements Iterator { /** * @var list<Event> */ private readonly array $events; private int $position = 0; public function __construct(EventCollection $events) { $this->events = $events->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->events); } public function key(): int { return $this->position; } public function current(): Event { return $this->events[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/Event/Events/EventCollection.php 0000644 00000002425 15253321353 0015162 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use function count; use Countable; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, Event> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class EventCollection implements Countable, IteratorAggregate { /** * @var list<Event> */ private array $events = []; public function add(Event ...$events): void { foreach ($events as $event) { $this->events[] = $event; } } /** * @return list<Event> */ public function asArray(): array { return $this->events; } public function count(): int { return count($this->events); } public function isEmpty(): bool { return $this->count() === 0; } public function isNotEmpty(): bool { return $this->count() > 0; } public function getIterator(): EventCollectionIterator { return new EventCollectionIterator($this); } } phpunit/src/Event/Events/TestRunner/Finished.php 0000644 00000001565 15253321353 0015733 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Finished implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Finished'; } } phpunit/src/Event/Events/TestRunner/ExecutionAbortedSubscriber.php 0000644 00000001051 15253321353 0021460 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ExecutionAbortedSubscriber extends Subscriber { public function notify(ExecutionAborted $event): void; } phpunit/src/Event/Events/TestRunner/EventFacadeSealed.php 0000644 00000001575 15253321353 0017466 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class EventFacadeSealed implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Event Facade Sealed'; } } phpunit/src/Event/Events/TestRunner/ConfiguredSubscriber.php 0000644 00000001035 15253321353 0020303 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ConfiguredSubscriber extends Subscriber { public function notify(Configured $event): void; } phpunit/src/Event/Events/TestRunner/WarningTriggeredSubscriber.php 0000644 00000001051 15253321353 0021456 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface WarningTriggeredSubscriber extends Subscriber { public function notify(WarningTriggered $event): void; } phpunit/src/Event/Events/TestRunner/Started.php 0000644 00000001563 15253321353 0015606 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Started implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Started'; } } phpunit/src/Event/Events/TestRunner/ExtensionBootstrappedSubscriber.php 0000644 00000001063 15253321353 0022562 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ExtensionBootstrappedSubscriber extends Subscriber { public function notify(ExtensionBootstrapped $event): void; } phpunit/src/Event/Events/TestRunner/ExecutionStartedSubscriber.php 0000644 00000001051 15253321353 0021506 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ExecutionStartedSubscriber extends Subscriber { public function notify(ExecutionStarted $event): void; } phpunit/src/Event/Events/TestRunner/ExecutionFinished.php 0000644 00000001610 15253321353 0017606 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionFinished implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Execution Finished'; } } phpunit/src/Event/Events/TestRunner/WarningTriggered.php 0000644 00000002206 15253321353 0017435 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class WarningTriggered implements Event { private Telemetry\Info $telemetryInfo; private string $message; public function __construct(Telemetry\Info $telemetryInfo, string $message) { $this->telemetryInfo = $telemetryInfo; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function message(): string { return $this->message; } public function asString(): string { return sprintf( 'Test Runner Triggered Warning (%s)', $this->message, ); } } phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggered.php 0000644 00000001633 15253321353 0021377 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class GarbageCollectionTriggered implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Triggered Garbage Collection'; } } phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabled.php 0000644 00000001631 15253321353 0021170 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class GarbageCollectionDisabled implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Disabled Garbage Collection'; } } phpunit/src/Event/Events/TestRunner/BootstrapFinishedSubscriber.php 0000644 00000001053 15253321353 0021645 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BootstrapFinishedSubscriber extends Subscriber { public function notify(BootstrapFinished $event): void; } phpunit/src/Event/Events/TestRunner/Configured.php 0000644 00000002164 15253321353 0016263 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; use PHPUnit\TextUI\Configuration\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Configured implements Event { private Telemetry\Info $telemetryInfo; private Configuration $configuration; public function __construct(Telemetry\Info $telemetryInfo, Configuration $configuration) { $this->telemetryInfo = $telemetryInfo; $this->configuration = $configuration; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function configuration(): Configuration { return $this->configuration; } public function asString(): string { return 'Test Runner Configured'; } } phpunit/src/Event/Events/TestRunner/BootstrapFinished.php 0000644 00000002202 15253321353 0017616 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BootstrapFinished implements Event { private Telemetry\Info $telemetryInfo; private string $filename; public function __construct(Telemetry\Info $telemetryInfo, string $filename) { $this->telemetryInfo = $telemetryInfo; $this->filename = $filename; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function filename(): string { return $this->filename; } public function asString(): string { return sprintf( 'Bootstrap Finished (%s)', $this->filename, ); } } phpunit/src/Event/Events/TestRunner/EventFacadeSealedSubscriber.php 0000644 00000001053 15253321353 0021501 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface EventFacadeSealedSubscriber extends Subscriber { public function notify(EventFacadeSealed $event): void; } phpunit/src/Event/Events/TestRunner/StartedSubscriber.php 0000644 00000001027 15253321353 0017625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface StartedSubscriber extends Subscriber { public function notify(Started $event): void; } phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabled.php 0000644 00000001627 15253321353 0021020 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class GarbageCollectionEnabled implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Enabled Garbage Collection'; } } phpunit/src/Event/Events/TestRunner/GarbageCollectionDisabledSubscriber.php 0000644 00000001073 15253321353 0023214 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface GarbageCollectionDisabledSubscriber extends Subscriber { public function notify(GarbageCollectionDisabled $event): void; } phpunit/src/Event/Events/TestRunner/ExecutionAborted.php 0000644 00000001606 15253321353 0017442 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionAborted implements Event { private Telemetry\Info $telemetryInfo; public function __construct(Telemetry\Info $telemetryInfo) { $this->telemetryInfo = $telemetryInfo; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function asString(): string { return 'Test Runner Execution Aborted'; } } phpunit/src/Event/Events/TestRunner/DeprecationTriggeredSubscriber.php 0000644 00000001061 15253321353 0022307 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface DeprecationTriggeredSubscriber extends Subscriber { public function notify(DeprecationTriggered $event): void; } phpunit/src/Event/Events/TestRunner/ExtensionBootstrapped.php 0000644 00000003162 15253321353 0020540 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExtensionBootstrapped implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @var array<string, string> */ private array $parameters; /** * @param class-string $className * @param array<string, string> $parameters */ public function __construct(Telemetry\Info $telemetryInfo, string $className, array $parameters) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; $this->parameters = $parameters; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return array<string, string> */ public function parameters(): array { return $this->parameters; } public function asString(): string { return sprintf( 'Extension Bootstrapped (%s)', $this->className, ); } } phpunit/src/Event/Events/TestRunner/DeprecationTriggered.php 0000644 00000002216 15253321353 0020266 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DeprecationTriggered implements Event { private Telemetry\Info $telemetryInfo; private string $message; public function __construct(Telemetry\Info $telemetryInfo, string $message) { $this->telemetryInfo = $telemetryInfo; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function message(): string { return $this->message; } public function asString(): string { return sprintf( 'Test Runner Triggered Deprecation (%s)', $this->message, ); } } phpunit/src/Event/Events/TestRunner/FinishedSubscriber.php 0000644 00000001031 15253321353 0017743 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FinishedSubscriber extends Subscriber { public function notify(Finished $event): void; } phpunit/src/Event/Events/TestRunner/ExecutionFinishedSubscriber.php 0000644 00000001053 15253321353 0021633 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ExecutionFinishedSubscriber extends Subscriber { public function notify(ExecutionFinished $event): void; } phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPhar.php 0000644 00000002756 15253321353 0020731 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExtensionLoadedFromPhar implements Event { private Telemetry\Info $telemetryInfo; private string $filename; private string $name; private string $version; public function __construct(Telemetry\Info $telemetryInfo, string $filename, string $name, string $version) { $this->telemetryInfo = $telemetryInfo; $this->filename = $filename; $this->name = $name; $this->version = $version; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function filename(): string { return $this->filename; } public function name(): string { return $this->name; } public function version(): string { return $this->version; } public function asString(): string { return sprintf( 'Extension Loaded from PHAR (%s %s)', $this->name, $this->version, ); } } phpunit/src/Event/Events/TestRunner/ExecutionStarted.php 0000644 00000002412 15253321353 0017464 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; use PHPUnit\Event\TestSuite\TestSuite; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExecutionStarted implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function asString(): string { return sprintf( 'Test Runner Execution Started (%d test%s)', $this->testSuite->count(), $this->testSuite->count() !== 1 ? 's' : '', ); } } phpunit/src/Event/Events/TestRunner/ExtensionLoadedFromPharSubscriber.php 0000644 00000001067 15253321353 0022747 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ExtensionLoadedFromPharSubscriber extends Subscriber { public function notify(ExtensionLoadedFromPhar $event): void; } phpunit/src/Event/Events/TestRunner/GarbageCollectionEnabledSubscriber.php 0000644 00000001071 15253321353 0023035 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface GarbageCollectionEnabledSubscriber extends Subscriber { public function notify(GarbageCollectionEnabled $event): void; } phpunit/src/Event/Events/TestRunner/GarbageCollectionTriggeredSubscriber.php 0000644 00000001075 15253321353 0023423 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestRunner; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface GarbageCollectionTriggeredSubscriber extends Subscriber { public function notify(GarbageCollectionTriggered $event): void; } phpunit/src/Event/Events/TestSuite/Finished.php 0000644 00000002372 15253321353 0015550 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Finished implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function asString(): string { return sprintf( 'Test Suite Finished (%s, %d test%s)', $this->testSuite->name(), $this->testSuite->count(), $this->testSuite->count() !== 1 ? 's' : '', ); } } phpunit/src/Event/Events/TestSuite/FilteredSubscriber.php 0000644 00000001030 15253321353 0017567 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FilteredSubscriber extends Subscriber { public function notify(Filtered $event): void; } phpunit/src/Event/Events/TestSuite/Started.php 0000644 00000002370 15253321353 0015423 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Started implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function asString(): string { return sprintf( 'Test Suite Started (%s, %d test%s)', $this->testSuite->name(), $this->testSuite->count(), $this->testSuite->count() !== 1 ? 's' : '', ); } } phpunit/src/Event/Events/TestSuite/Sorted.php 0000644 00000003027 15253321353 0015255 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Sorted implements Event { private Telemetry\Info $telemetryInfo; private int $executionOrder; private int $executionOrderDefects; private bool $resolveDependencies; public function __construct(Telemetry\Info $telemetryInfo, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies) { $this->telemetryInfo = $telemetryInfo; $this->executionOrder = $executionOrder; $this->executionOrderDefects = $executionOrderDefects; $this->resolveDependencies = $resolveDependencies; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function executionOrder(): int { return $this->executionOrder; } public function executionOrderDefects(): int { return $this->executionOrderDefects; } public function resolveDependencies(): bool { return $this->resolveDependencies; } public function asString(): string { return 'Test Suite Sorted'; } } phpunit/src/Event/Events/TestSuite/Skipped.php 0000644 00000002527 15253321353 0015420 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Skipped implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; private string $message; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite, string $message) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function message(): string { return $this->message; } public function asString(): string { return sprintf( 'Test Suite Skipped (%s, %s)', $this->testSuite->name(), $this->message, ); } } phpunit/src/Event/Events/TestSuite/Loaded.php 0000644 00000002314 15253321353 0015203 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Loaded implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function asString(): string { return sprintf( 'Test Suite Loaded (%d test%s)', $this->testSuite->count(), $this->testSuite->count() !== 1 ? 's' : '', ); } } phpunit/src/Event/Events/TestSuite/StartedSubscriber.php 0000644 00000001026 15253321353 0017444 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface StartedSubscriber extends Subscriber { public function notify(Started $event): void; } phpunit/src/Event/Events/TestSuite/SortedSubscriber.php 0000644 00000001024 15253321353 0017274 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface SortedSubscriber extends Subscriber { public function notify(Sorted $event): void; } phpunit/src/Event/Events/TestSuite/SkippedSubscriber.php 0000644 00000001026 15253321353 0017435 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface SkippedSubscriber extends Subscriber { public function notify(Skipped $event): void; } phpunit/src/Event/Events/TestSuite/LoadedSubscriber.php 0000644 00000001024 15253321353 0017224 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface LoadedSubscriber extends Subscriber { public function notify(Loaded $event): void; } phpunit/src/Event/Events/TestSuite/FinishedSubscriber.php 0000644 00000001030 15253321353 0017562 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FinishedSubscriber extends Subscriber { public function notify(Finished $event): void; } phpunit/src/Event/Events/TestSuite/Filtered.php 0000644 00000002320 15253321353 0015546 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\TestSuite; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Filtered implements Event { private Telemetry\Info $telemetryInfo; private TestSuite $testSuite; public function __construct(Telemetry\Info $telemetryInfo, TestSuite $testSuite) { $this->telemetryInfo = $telemetryInfo; $this->testSuite = $testSuite; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testSuite(): TestSuite { return $this->testSuite; } public function asString(): string { return sprintf( 'Test Suite Filtered (%d test%s)', $this->testSuite->count(), $this->testSuite->count() !== 1 ? 's' : '', ); } } phpunit/src/Event/Events/Test/PrintedUnexpectedOutput.php 0000644 00000002476 15253321353 0017665 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PrintedUnexpectedOutput implements Event { private Telemetry\Info $telemetryInfo; /** * @var non-empty-string */ private string $output; /** * @param non-empty-string $output */ public function __construct(Telemetry\Info $telemetryInfo, string $output) { $this->telemetryInfo = $telemetryInfo; $this->output = $output; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return non-empty-string */ public function output(): string { return $this->output; } public function asString(): string { return sprintf( 'Test Printed Unexpected Output%s%s', PHP_EOL, $this->output, ); } } phpunit/src/Event/Events/Test/Lifecycle/Finished.php 0000644 00000002653 15253321353 0016437 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Finished implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; private int $numberOfAssertionsPerformed; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, int $numberOfAssertionsPerformed) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->numberOfAssertionsPerformed = $numberOfAssertionsPerformed; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function numberOfAssertionsPerformed(): int { return $this->numberOfAssertionsPerformed; } public function asString(): string { return sprintf( 'Test Finished (%s)', $this->test->id(), ); } } phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalledSubscriber.php 0000644 00000001063 15253321353 0023556 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface DataProviderMethodCalledSubscriber extends Subscriber { public function notify(DataProviderMethodCalled $event): void; } phpunit/src/Event/Events/Test/Lifecycle/PreparationFailedSubscriber.php 0000644 00000001045 15253321353 0022315 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PreparationFailedSubscriber extends Subscriber { public function notify(PreparationFailed $event): void; } phpunit/src/Event/Events/Test/Lifecycle/Prepared.php 0000644 00000002175 15253321353 0016447 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Prepared implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function asString(): string { return sprintf( 'Test Prepared (%s)', $this->test->id(), ); } } phpunit/src/Event/Events/Test/Lifecycle/PreparationStartedSubscriber.php 0000644 00000001047 15253321353 0022541 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PreparationStartedSubscriber extends Subscriber { public function notify(PreparationStarted $event): void; } phpunit/src/Event/Events/Test/Lifecycle/PreparedSubscriber.php 0000644 00000001023 15253321353 0020462 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PreparedSubscriber extends Subscriber { public function notify(Prepared $event): void; } phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinishedSubscriber.php 0000644 00000001067 15253321353 0024127 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface DataProviderMethodFinishedSubscriber extends Subscriber { public function notify(DataProviderMethodFinished $event): void; } phpunit/src/Event/Events/Test/Lifecycle/PreparationFailed.php 0000644 00000002220 15253321353 0020265 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreparationFailed implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function asString(): string { return sprintf( 'Test Preparation Failed (%s)', $this->test->id(), ); } } phpunit/src/Event/Events/Test/Lifecycle/FinishedSubscriber.php 0000644 00000001023 15253321353 0020451 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FinishedSubscriber extends Subscriber { public function notify(Finished $event): void; } phpunit/src/Event/Events/Test/Lifecycle/PreparationStarted.php 0000644 00000002222 15253321353 0020511 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreparationStarted implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function asString(): string { return sprintf( 'Test Preparation Started (%s)', $this->test->id(), ); } } phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodCalled.php 0000644 00000003156 15253321353 0021537 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry\Info; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DataProviderMethodCalled implements Event { private Info $telemetryInfo; private ClassMethod $testMethod; private ClassMethod $dataProviderMethod; public function __construct(Info $telemetryInfo, ClassMethod $testMethod, ClassMethod $dataProviderMethod) { $this->telemetryInfo = $telemetryInfo; $this->testMethod = $testMethod; $this->dataProviderMethod = $dataProviderMethod; } public function telemetryInfo(): Info { return $this->telemetryInfo; } public function testMethod(): ClassMethod { return $this->testMethod; } public function dataProviderMethod(): ClassMethod { return $this->dataProviderMethod; } public function asString(): string { return sprintf( 'Data Provider Method Called (%s::%s for test method %s::%s)', $this->dataProviderMethod->className(), $this->dataProviderMethod->methodName(), $this->testMethod->className(), $this->testMethod->methodName(), ); } } phpunit/src/Event/Events/Test/Lifecycle/DataProviderMethodFinished.php 0000644 00000003574 15253321353 0022110 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Code\ClassMethod; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DataProviderMethodFinished implements Event { private Telemetry\Info $telemetryInfo; private ClassMethod $testMethod; /** * @var list<ClassMethod> */ private array $calledMethods; public function __construct(Telemetry\Info $telemetryInfo, ClassMethod $testMethod, ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testMethod = $testMethod; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function testMethod(): ClassMethod { return $this->testMethod; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = sprintf( 'Data Provider Method Finished for %s::%s:', $this->testMethod->className(), $this->testMethod->methodName(), ); foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/ComparatorRegistered.php 0000644 00000002424 15253321353 0017130 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ComparatorRegistered implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } public function asString(): string { return sprintf( 'Comparator Registered (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/PrintedUnexpectedOutputSubscriber.php 0000644 00000001061 15253321353 0021676 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PrintedUnexpectedOutputSubscriber extends Subscriber { public function notify(PrintedUnexpectedOutput $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErroredSubscriber.php 0000644 00000001073 15253321353 0024625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BeforeFirstTestMethodErroredSubscriber extends Subscriber { public function notify(BeforeFirstTestMethodErrored $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinishedSubscriber.php 0000644 00000001075 15253321353 0024756 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BeforeFirstTestMethodFinishedSubscriber extends Subscriber { public function notify(BeforeFirstTestMethodFinished $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodFinished.php 0000644 00000003564 15253321353 0022737 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeFirstTestMethodFinished implements Event { private Telemetry\Info$telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'Before First Test Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinishedSubscriber.php 0000644 00000001071 15253321353 0024425 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface AfterLastTestMethodFinishedSubscriber extends Subscriber { public function notify(AfterLastTestMethodFinished $event): void; } phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodFinished.php 0000644 00000003561 15253321353 0022407 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class AfterLastTestMethodFinished implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'After Last Test Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/PostConditionFinishedSubscriber.php 0000644 00000001055 15253321353 0023335 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PostConditionFinishedSubscriber extends Subscriber { public function notify(PostConditionFinished $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodErrored.php 0000644 00000004012 15253321353 0022575 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeFirstTestMethodErrored implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; private Throwable $throwable; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod, Throwable $throwable) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; $this->throwable = $throwable; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function throwable(): Throwable { return $this->throwable; } public function asString(): string { $message = $this->throwable->message(); if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Before First Test Method Errored (%s::%s)%s', $this->calledMethod->className(), $this->calledMethod->methodName(), $message, ); } } phpunit/src/Event/Events/Test/HookMethod/PreConditionCalled.php 0000644 00000003152 15253321353 0020545 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreConditionCalled implements Event { private Telemetry\Info$telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'Pre Condition Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/PostConditionCalled.php 0000644 00000003155 15253321353 0020747 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PostConditionCalled implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'Post Condition Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalled.php 0000644 00000003170 15253321353 0022363 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeFirstTestMethodCalled implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'Before First Test Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinishedSubscriber.php 0000644 00000001061 15253321353 0023600 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface AfterTestMethodFinishedSubscriber extends Subscriber { public function notify(AfterTestMethodFinished $event): void; } phpunit/src/Event/Events/Test/HookMethod/PostConditionCalledSubscriber.php 0000644 00000001051 15253321353 0022764 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PostConditionCalledSubscriber extends Subscriber { public function notify(PostConditionCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalled.php 0000644 00000003164 15253321353 0022041 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class AfterLastTestMethodCalled implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'After Last Test Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/PreConditionFinished.php 0000644 00000003550 15253321353 0021114 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreConditionFinished implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'Pre Condition Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/BeforeFirstTestMethodCalledSubscriber.php 0000644 00000001071 15253321353 0024405 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BeforeFirstTestMethodCalledSubscriber extends Subscriber { public function notify(BeforeFirstTestMethodCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalled.php 0000644 00000003155 15253321353 0021356 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeTestMethodCalled implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'Before Test Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/PreConditionCalledSubscriber.php 0000644 00000001047 15253321353 0022572 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PreConditionCalledSubscriber extends Subscriber { public function notify(PreConditionCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/PreConditionFinishedSubscriber.php 0000644 00000001053 15253321353 0023134 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PreConditionFinishedSubscriber extends Subscriber { public function notify(PreConditionFinished $event): void; } phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodFinished.php 0000644 00000003550 15253321353 0021561 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class AfterTestMethodFinished implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'After Test Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/AfterLastTestMethodCalledSubscriber.php 0000644 00000001065 15253321353 0024063 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface AfterLastTestMethodCalledSubscriber extends Subscriber { public function notify(AfterLastTestMethodCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalledSubscriber.php 0000644 00000001055 15253321353 0023236 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface AfterTestMethodCalledSubscriber extends Subscriber { public function notify(AfterTestMethodCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodCalledSubscriber.php 0000644 00000001057 15253321353 0023401 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BeforeTestMethodCalledSubscriber extends Subscriber { public function notify(BeforeTestMethodCalled $event): void; } phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinished.php 0000644 00000003552 15253321353 0021724 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeTestMethodFinished implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'Before Test Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/PostConditionFinished.php 0000644 00000003552 15253321353 0021315 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PostConditionFinished implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; /** * @var list<Code\ClassMethod> */ private array $calledMethods; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod ...$calledMethods) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethods = $calledMethods; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } /** * @return list<Code\ClassMethod> */ public function calledMethods(): array { return $this->calledMethods; } public function asString(): string { $buffer = 'Post Condition Method Finished:'; foreach ($this->calledMethods as $calledMethod) { $buffer .= sprintf( PHP_EOL . '- %s::%s', $calledMethod->className(), $calledMethod->methodName(), ); } return $buffer; } } phpunit/src/Event/Events/Test/HookMethod/AfterTestMethodCalled.php 0000644 00000003153 15253321353 0021213 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class AfterTestMethodCalled implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $testClassName; private Code\ClassMethod $calledMethod; /** * @param class-string $testClassName */ public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod) { $this->telemetryInfo = $telemetryInfo; $this->testClassName = $testClassName; $this->calledMethod = $calledMethod; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function testClassName(): string { return $this->testClassName; } public function calledMethod(): Code\ClassMethod { return $this->calledMethod; } public function asString(): string { return sprintf( 'After Test Method Called (%s::%s)', $this->calledMethod->className(), $this->calledMethod->methodName(), ); } } phpunit/src/Event/Events/Test/HookMethod/BeforeTestMethodFinishedSubscriber.php 0000644 00000001063 15253321353 0023743 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface BeforeTestMethodFinishedSubscriber extends Subscriber { public function notify(BeforeTestMethodFinished $event): void; } phpunit/src/Event/Events/Test/Issue/ConsideredRiskySubscriber.php 0000644 00000001041 15253321353 0021212 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ConsideredRiskySubscriber extends Subscriber { public function notify(ConsideredRisky $event): void; } phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggeredSubscriber.php 0000644 00000001047 15253321353 0021645 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpNoticeTriggeredSubscriber extends Subscriber { public function notify(PhpNoticeTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/ErrorTriggered.php 0000644 00000004751 15253321353 0017026 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ErrorTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } return sprintf( 'Test Triggered Error (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/WarningTriggeredSubscriber.php 0000644 00000001043 15253321353 0021355 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface WarningTriggeredSubscriber extends Subscriber { public function notify(WarningTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/WarningTriggered.php 0000644 00000005501 15253321353 0017334 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class WarningTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered Warning (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggeredSubscriber.php 0000644 00000001071 15253321353 0023556 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpunitDeprecationTriggeredSubscriber extends Subscriber { public function notify(PhpunitDeprecationTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/PhpWarningTriggered.php 0000644 00000005510 15253321353 0020004 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpWarningTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered PHP Warning (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggered.php 0000644 00000006575 15253321353 0020650 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\IssueTrigger\IssueTrigger; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpDeprecationTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; private bool $ignoredByTest; private IssueTrigger $trigger; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; $this->ignoredByTest = $ignoredByTest; $this->trigger = $trigger; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function ignoredByTest(): bool { return $this->ignoredByTest; } public function trigger(): IssueTrigger { return $this->trigger; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id(), $this->trigger->asString()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByTest) { $details[] = 'ignored by test'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered PHP Deprecation (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/ConsideredRisky.php 0000644 00000003023 15253321353 0017170 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ConsideredRisky implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; /** * @var non-empty-string */ private string $message; /** * @param non-empty-string $message */ public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, string $message) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } public function asString(): string { return sprintf( 'Test Considered Risky (%s)%s%s', $this->test->id(), PHP_EOL, $this->message, ); } } phpunit/src/Event/Events/Test/Issue/PhpWarningTriggeredSubscriber.php 0000644 00000001051 15253321353 0022024 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpWarningTriggeredSubscriber extends Subscriber { public function notify(PhpWarningTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggeredSubscriber.php 0000644 00000001055 15253321353 0022414 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpunitErrorTriggeredSubscriber extends Subscriber { public function notify(PhpunitErrorTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/PhpunitErrorTriggered.php 0000644 00000003214 15253321353 0020367 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use function trim; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpunitErrorTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @param non-empty-string $message */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } public function asString(): string { $message = trim($this->message); if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Triggered PHPUnit Error (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggeredSubscriber.php 0000644 00000001061 15253321353 0022725 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpunitWarningTriggeredSubscriber extends Subscriber { public function notify(PhpunitWarningTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/NoticeTriggeredSubscriber.php 0000644 00000001041 15253321353 0021167 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface NoticeTriggeredSubscriber extends Subscriber { public function notify(NoticeTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/NoticeTriggered.php 0000644 00000005477 15253321353 0017164 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class NoticeTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered Notice (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/DeprecationTriggeredSubscriber.php 0000644 00000001053 15253321353 0022206 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface DeprecationTriggeredSubscriber extends Subscriber { public function notify(DeprecationTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/DeprecationTriggered.php 0000644 00000006566 15253321353 0020200 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\IssueTrigger\IssueTrigger; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DeprecationTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; private bool $ignoredByTest; private IssueTrigger $trigger; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline, bool $ignoredByTest, IssueTrigger $trigger) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; $this->ignoredByTest = $ignoredByTest; $this->trigger = $trigger; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function ignoredByTest(): bool { return $this->ignoredByTest; } public function trigger(): IssueTrigger { return $this->trigger; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id(), $this->trigger->asString()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByTest) { $details[] = 'ignored by test'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered Deprecation (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/Issue/PhpDeprecationTriggeredSubscriber.php 0000644 00000001061 15253321353 0022655 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PhpDeprecationTriggeredSubscriber extends Subscriber { public function notify(PhpDeprecationTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/PhpunitDeprecationTriggered.php 0000644 00000003177 15253321353 0021543 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpunitDeprecationTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @param non-empty-string $message */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Triggered PHPUnit Deprecation (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Issue/PhpunitWarningTriggered.php 0000644 00000003167 15253321353 0020712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpunitWarningTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @param non-empty-string $message */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Triggered PHPUnit Warning (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Issue/ErrorTriggeredSubscriber.php 0000644 00000001037 15253321353 0021044 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ErrorTriggeredSubscriber extends Subscriber { public function notify(ErrorTriggered $event): void; } phpunit/src/Event/Events/Test/Issue/PhpNoticeTriggered.php 0000644 00000005506 15253321353 0017625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function implode; use function sprintf; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpNoticeTriggered implements Event { private Telemetry\Info $telemetryInfo; private Test $test; /** * @var non-empty-string */ private string $message; /** * @var non-empty-string */ private string $file; /** * @var positive-int */ private int $line; private bool $suppressed; private bool $ignoredByBaseline; /** * @param non-empty-string $message * @param non-empty-string $file * @param positive-int $line */ public function __construct(Telemetry\Info $telemetryInfo, Test $test, string $message, string $file, int $line, bool $suppressed, bool $ignoredByBaseline) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; $this->file = $file; $this->line = $line; $this->suppressed = $suppressed; $this->ignoredByBaseline = $ignoredByBaseline; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Test { return $this->test; } /** * @return non-empty-string */ public function message(): string { return $this->message; } /** * @return non-empty-string */ public function file(): string { return $this->file; } /** * @return positive-int */ public function line(): int { return $this->line; } public function wasSuppressed(): bool { return $this->suppressed; } public function ignoredByBaseline(): bool { return $this->ignoredByBaseline; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } $details = [$this->test->id()]; if ($this->suppressed) { $details[] = 'suppressed using operator'; } if ($this->ignoredByBaseline) { $details[] = 'ignored by baseline'; } return sprintf( 'Test Triggered PHP Notice (%s)%s', implode(', ', $details), $message, ); } } phpunit/src/Event/Events/Test/ComparatorRegisteredSubscriber.php 0000644 00000001053 15253321353 0021151 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ComparatorRegisteredSubscriber extends Subscriber { public function notify(ComparatorRegistered $event): void; } phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreated.php 0000644 00000005262 15253321353 0022046 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MockObjectFromWsdlCreated implements Event { private Telemetry\Info $telemetryInfo; private string $wsdlFile; /** * @var class-string */ private string $originalClassName; /** * @var class-string */ private string $mockClassName; /** * @var list<string> */ private array $methods; private bool $callOriginalConstructor; /** * @var list<mixed> */ private array $options; /** * @param class-string $originalClassName * @param class-string $mockClassName * @param list<string> $methods * @param list<mixed> $options */ public function __construct(Telemetry\Info $telemetryInfo, string $wsdlFile, string $originalClassName, string $mockClassName, array $methods, bool $callOriginalConstructor, array $options) { $this->telemetryInfo = $telemetryInfo; $this->wsdlFile = $wsdlFile; $this->originalClassName = $originalClassName; $this->mockClassName = $mockClassName; $this->methods = $methods; $this->callOriginalConstructor = $callOriginalConstructor; $this->options = $options; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function wsdlFile(): string { return $this->wsdlFile; } /** * @return class-string */ public function originalClassName(): string { return $this->originalClassName; } /** * @return class-string */ public function mockClassName(): string { return $this->mockClassName; } /** * @return list<string> */ public function methods(): array { return $this->methods; } public function callOriginalConstructor(): bool { return $this->callOriginalConstructor; } /** * @return list<mixed> */ public function options(): array { return $this->options; } public function asString(): string { return sprintf( 'Mock Object Created (%s)', $this->wsdlFile, ); } } phpunit/src/Event/Events/Test/TestDouble/TestStubCreatedSubscriber.php 0000644 00000001041 15253321353 0022140 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface TestStubCreatedSubscriber extends Subscriber { public function notify(TestStubCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreatedSubscriber.php 0000644 00000001063 15253321353 0023724 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PartialMockObjectCreatedSubscriber extends Subscriber { public function notify(PartialMockObjectCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/TestProxyCreatedSubscriber.php 0000644 00000001043 15253321353 0022346 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface TestProxyCreatedSubscriber extends Subscriber { public function notify(TestProxyCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/TestProxyCreated.php 0000644 00000003014 15253321353 0020322 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestProxyCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; private string $constructorArguments; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className, string $constructorArguments) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; $this->constructorArguments = $constructorArguments; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } public function constructorArguments(): string { return $this->constructorArguments; } public function asString(): string { return sprintf( 'Test Proxy Created (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectCreated.php 0000644 00000002417 15253321353 0020367 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MockObjectCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } public function asString(): string { return sprintf( 'Mock Object Created (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreatedSubscriber.php 0000644 00000001133 15253321353 0027734 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObjectForIntersectionOfInterfacesCreatedSubscriber extends Subscriber { public function notify(MockObjectForIntersectionOfInterfacesCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreated.php 0000644 00000002437 15253321353 0023512 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MockObjectForAbstractClassCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } public function asString(): string { return sprintf( 'Mock Object Created (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectFromWsdlCreatedSubscriber.php 0000644 00000001065 15253321353 0024067 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObjectFromWsdlCreatedSubscriber extends Subscriber { public function notify(MockObjectFromWsdlCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/MockObjectForIntersectionOfInterfacesCreated.php 0000644 00000002544 15253321353 0025717 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function implode; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MockObjectForIntersectionOfInterfacesCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var list<class-string> */ private array $interfaces; /** * @param list<class-string> $interfaces */ public function __construct(Telemetry\Info $telemetryInfo, array $interfaces) { $this->telemetryInfo = $telemetryInfo; $this->interfaces = $interfaces; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return list<class-string> */ public function interfaces(): array { return $this->interfaces; } public function asString(): string { return sprintf( 'Mock Object Created (%s)', implode('&', $this->interfaces), ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreatedSubscriber.php 0000644 00000001065 15253321353 0024064 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObjectForTraitCreatedSubscriber extends Subscriber { public function notify(MockObjectForTraitCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreated.php 0000644 00000002540 15253321353 0025450 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function implode; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestStubForIntersectionOfInterfacesCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var list<class-string> */ private array $interfaces; /** * @param list<class-string> $interfaces */ public function __construct(Telemetry\Info $telemetryInfo, array $interfaces) { $this->telemetryInfo = $telemetryInfo; $this->interfaces = $interfaces; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return list<class-string> */ public function interfaces(): array { return $this->interfaces; } public function asString(): string { return sprintf( 'Test Stub Created (%s)', implode('&', $this->interfaces), ); } } phpunit/src/Event/Events/Test/TestDouble/TestStubCreated.php 0000644 00000002413 15253321353 0020120 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestStubCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } public function asString(): string { return sprintf( 'Test Stub Created (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectForTraitCreated.php 0000644 00000002427 15253321353 0022043 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MockObjectForTraitCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var trait-string */ private string $traitName; /** * @param trait-string $traitName */ public function __construct(Telemetry\Info $telemetryInfo, string $traitName) { $this->telemetryInfo = $telemetryInfo; $this->traitName = $traitName; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return trait-string */ public function traitName(): string { return $this->traitName; } public function asString(): string { return sprintf( 'Mock Object Created (%s)', $this->traitName, ); } } phpunit/src/Event/Events/Test/TestDouble/PartialMockObjectCreated.php 0000644 00000003062 15253321353 0021701 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PartialMockObjectCreated implements Event { private Telemetry\Info $telemetryInfo; /** * @var class-string */ private string $className; /** * @var list<string> */ private array $methodNames; /** * @param class-string $className */ public function __construct(Telemetry\Info $telemetryInfo, string $className, string ...$methodNames) { $this->telemetryInfo = $telemetryInfo; $this->className = $className; $this->methodNames = $methodNames; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return list<string> */ public function methodNames(): array { return $this->methodNames; } public function asString(): string { return sprintf( 'Partial Mock Object Created (%s)', $this->className, ); } } phpunit/src/Event/Events/Test/TestDouble/MockObjectCreatedSubscriber.php 0000644 00000001045 15253321353 0022407 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObjectCreatedSubscriber extends Subscriber { public function notify(MockObjectCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/TestStubForIntersectionOfInterfacesCreatedSubscriber.php 0000644 00000001127 15253321353 0027474 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface TestStubForIntersectionOfInterfacesCreatedSubscriber extends Subscriber { public function notify(TestStubForIntersectionOfInterfacesCreated $event): void; } phpunit/src/Event/Events/Test/TestDouble/MockObjectForAbstractClassCreatedSubscriber.php 0000644 00000001105 15253321353 0025525 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MockObjectForAbstractClassCreatedSubscriber extends Subscriber { public function notify(MockObjectForAbstractClassCreated $event): void; } phpunit/src/Event/Events/Test/Outcome/Failed.php 0000644 00000004304 15253321353 0015601 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use function trim; use PHPUnit\Event\Code; use PHPUnit\Event\Code\ComparisonFailure; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Failed implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; private Throwable $throwable; private ?ComparisonFailure $comparisonFailure; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable, ?ComparisonFailure $comparisonFailure) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->throwable = $throwable; $this->comparisonFailure = $comparisonFailure; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function throwable(): Throwable { return $this->throwable; } /** * @phpstan-assert-if-true !null $this->comparisonFailure */ public function hasComparisonFailure(): bool { return $this->comparisonFailure !== null; } /** * @throws NoComparisonFailureException */ public function comparisonFailure(): ComparisonFailure { if ($this->comparisonFailure === null) { throw new NoComparisonFailureException; } return $this->comparisonFailure; } public function asString(): string { $message = trim($this->throwable->message()); if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Failed (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Outcome/ErroredSubscriber.php 0000644 00000001021 15253321353 0020034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface ErroredSubscriber extends Subscriber { public function notify(Errored $event): void; } phpunit/src/Event/Events/Test/Outcome/Skipped.php 0000644 00000002711 15253321353 0016014 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Skipped implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; private string $message; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, string $message) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->message = $message; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function message(): string { return $this->message; } public function asString(): string { $message = $this->message; if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Skipped (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Outcome/MarkedIncompleteSubscriber.php 0000644 00000001043 15253321353 0021661 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface MarkedIncompleteSubscriber extends Subscriber { public function notify(MarkedIncomplete $event): void; } phpunit/src/Event/Events/Test/Outcome/MarkedIncomplete.php 0000644 00000003067 15253321353 0017645 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use function trim; use PHPUnit\Event\Code; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MarkedIncomplete implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; private Throwable $throwable; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->throwable = $throwable; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function throwable(): Throwable { return $this->throwable; } public function asString(): string { $message = trim($this->throwable->message()); if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Marked Incomplete (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Events/Test/Outcome/Passed.php 0000644 00000002171 15253321353 0015634 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use function sprintf; use PHPUnit\Event\Code; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Passed implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function asString(): string { return sprintf( 'Test Passed (%s)', $this->test->id(), ); } } phpunit/src/Event/Events/Test/Outcome/SkippedSubscriber.php 0000644 00000001021 15253321353 0020031 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface SkippedSubscriber extends Subscriber { public function notify(Skipped $event): void; } phpunit/src/Event/Events/Test/Outcome/FailedSubscriber.php 0000644 00000001017 15253321353 0017623 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface FailedSubscriber extends Subscriber { public function notify(Failed $event): void; } phpunit/src/Event/Events/Test/Outcome/PassedSubscriber.php 0000644 00000001017 15253321353 0017656 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use PHPUnit\Event\Subscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ interface PassedSubscriber extends Subscriber { public function notify(Passed $event): void; } phpunit/src/Event/Events/Test/Outcome/Errored.php 0000644 00000003044 15253321353 0016017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event\Test; use const PHP_EOL; use function sprintf; use function trim; use PHPUnit\Event\Code; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Event; use PHPUnit\Event\Telemetry; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Errored implements Event { private Telemetry\Info $telemetryInfo; private Code\Test $test; private Throwable $throwable; public function __construct(Telemetry\Info $telemetryInfo, Code\Test $test, Throwable $throwable) { $this->telemetryInfo = $telemetryInfo; $this->test = $test; $this->throwable = $throwable; } public function telemetryInfo(): Telemetry\Info { return $this->telemetryInfo; } public function test(): Code\Test { return $this->test; } public function throwable(): Throwable { return $this->throwable; } public function asString(): string { $message = trim($this->throwable->message()); if (!empty($message)) { $message = PHP_EOL . $message; } return sprintf( 'Test Errored (%s)%s', $this->test->id(), $message, ); } } phpunit/src/Event/Dispatcher/SubscribableDispatcher.php 0000644 00000001346 15253321353 0017317 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface SubscribableDispatcher extends Dispatcher { /** * @throws UnknownSubscriberTypeException */ public function registerSubscriber(Subscriber $subscriber): void; public function registerTracer(Tracer\Tracer $tracer): void; } phpunit/src/Event/Dispatcher/DeferringDispatcher.php 0000644 00000003040 15253321353 0016615 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DeferringDispatcher implements SubscribableDispatcher { private readonly SubscribableDispatcher $dispatcher; private EventCollection $events; private bool $recording = true; public function __construct(SubscribableDispatcher $dispatcher) { $this->dispatcher = $dispatcher; $this->events = new EventCollection; } public function registerTracer(Tracer\Tracer $tracer): void { $this->dispatcher->registerTracer($tracer); } public function registerSubscriber(Subscriber $subscriber): void { $this->dispatcher->registerSubscriber($subscriber); } public function dispatch(Event $event): void { if ($this->recording) { $this->events->add($event); return; } $this->dispatcher->dispatch($event); } public function flush(): void { $this->recording = false; foreach ($this->events as $event) { $this->dispatcher->dispatch($event); } $this->events = new EventCollection; } } phpunit/src/Event/Dispatcher/Dispatcher.php 0000644 00000001154 15253321353 0014773 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Dispatcher { /** * @throws UnknownEventTypeException */ public function dispatch(Event $event): void; } phpunit/src/Event/Dispatcher/DirectDispatcher.php 0000644 00000007274 15253321353 0016137 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use const PHP_EOL; use function array_key_exists; use function dirname; use function sprintf; use function str_starts_with; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DirectDispatcher implements SubscribableDispatcher { private readonly TypeMap $typeMap; /** * @var array<class-string, list<Subscriber>> */ private array $subscribers = []; /** * @var list<Tracer\Tracer> */ private array $tracers = []; public function __construct(TypeMap $map) { $this->typeMap = $map; } public function registerTracer(Tracer\Tracer $tracer): void { $this->tracers[] = $tracer; } /** * @throws MapError * @throws UnknownSubscriberTypeException */ public function registerSubscriber(Subscriber $subscriber): void { if (!$this->typeMap->isKnownSubscriberType($subscriber)) { throw new UnknownSubscriberTypeException( sprintf( 'Subscriber "%s" does not implement any known interface - did you forget to register it?', $subscriber::class, ), ); } $eventClassName = $this->typeMap->map($subscriber); if (!array_key_exists($eventClassName, $this->subscribers)) { $this->subscribers[$eventClassName] = []; } $this->subscribers[$eventClassName][] = $subscriber; } /** * @throws Throwable * @throws UnknownEventTypeException */ public function dispatch(Event $event): void { $eventClassName = $event::class; if (!$this->typeMap->isKnownEventType($event)) { throw new UnknownEventTypeException( sprintf( 'Unknown event type "%s"', $eventClassName, ), ); } foreach ($this->tracers as $tracer) { try { $tracer->trace($event); // @codeCoverageIgnoreStart } catch (Throwable $t) { $this->handleThrowable($t); } // @codeCoverageIgnoreEnd } if (!array_key_exists($eventClassName, $this->subscribers)) { return; } foreach ($this->subscribers[$eventClassName] as $subscriber) { try { /** @phpstan-ignore method.notFound */ $subscriber->notify($event); } catch (Throwable $t) { $this->handleThrowable($t); } } } /** * @throws Throwable */ public function handleThrowable(Throwable $t): void { if ($this->isThrowableFromThirdPartySubscriber($t)) { Facade::emitter()->testRunnerTriggeredWarning( sprintf( 'Exception in third-party event subscriber: %s%s%s', $t->getMessage(), PHP_EOL, $t->getTraceAsString(), ), ); return; } // @codeCoverageIgnoreStart throw $t; // @codeCoverageIgnoreEnd } private function isThrowableFromThirdPartySubscriber(Throwable $t): bool { return !str_starts_with($t->getFile(), dirname(__DIR__, 2)); } } phpunit/src/Event/Dispatcher/CollectingDispatcher.php 0000644 00000001644 15253321353 0017003 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CollectingDispatcher implements Dispatcher { private EventCollection $events; public function __construct() { $this->events = new EventCollection; } public function dispatch(Event $event): void { $this->events->add($event); } public function flush(): EventCollection { $events = $this->events; $this->events = new EventCollection; return $events; } } phpunit/src/Event/Facade.php 0000644 00000020225 15253321353 0011762 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Event; use const PHP_VERSION; use function assert; use function interface_exists; use function version_compare; use PHPUnit\Event\Telemetry\HRTime; use PHPUnit\Event\Telemetry\Php81GarbageCollectorStatusProvider; use PHPUnit\Event\Telemetry\Php83GarbageCollectorStatusProvider; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Facade { private static ?self $instance = null; private Emitter $emitter; private ?TypeMap $typeMap = null; private ?DeferringDispatcher $deferringDispatcher = null; private bool $sealed = false; public static function instance(): self { if (self::$instance === null) { self::$instance = new self; } return self::$instance; } public static function emitter(): Emitter { return self::instance()->emitter; } public function __construct() { $this->emitter = $this->createDispatchingEmitter(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function registerSubscribers(Subscriber ...$subscribers): void { foreach ($subscribers as $subscriber) { $this->registerSubscriber($subscriber); } } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function registerSubscriber(Subscriber $subscriber): void { if ($this->sealed) { throw new EventFacadeIsSealedException; } $this->deferredDispatcher()->registerSubscriber($subscriber); } /** * @throws EventFacadeIsSealedException */ public function registerTracer(Tracer\Tracer $tracer): void { if ($this->sealed) { throw new EventFacadeIsSealedException; } $this->deferredDispatcher()->registerTracer($tracer); } /** * @codeCoverageIgnore * * @noinspection PhpUnused */ public function initForIsolation(HRTime $offset): CollectingDispatcher { $dispatcher = new CollectingDispatcher; $this->emitter = new DispatchingEmitter( $dispatcher, new Telemetry\System( new Telemetry\SystemStopWatchWithOffset($offset), new Telemetry\SystemMemoryMeter, $this->garbageCollectorStatusProvider(), ), ); $this->sealed = true; return $dispatcher; } public function forward(EventCollection $events): void { $dispatcher = $this->deferredDispatcher(); foreach ($events as $event) { $dispatcher->dispatch($event); } } public function seal(): void { $this->deferredDispatcher()->flush(); $this->sealed = true; $this->emitter->testRunnerEventFacadeSealed(); } private function createDispatchingEmitter(): DispatchingEmitter { return new DispatchingEmitter( $this->deferredDispatcher(), $this->createTelemetrySystem(), ); } private function createTelemetrySystem(): Telemetry\System { return new Telemetry\System( new Telemetry\SystemStopWatch, new Telemetry\SystemMemoryMeter, $this->garbageCollectorStatusProvider(), ); } private function deferredDispatcher(): DeferringDispatcher { if ($this->deferringDispatcher === null) { $this->deferringDispatcher = new DeferringDispatcher( new DirectDispatcher($this->typeMap()), ); } return $this->deferringDispatcher; } private function typeMap(): TypeMap { if ($this->typeMap === null) { $typeMap = new TypeMap; $this->registerDefaultTypes($typeMap); $this->typeMap = $typeMap; } return $this->typeMap; } private function registerDefaultTypes(TypeMap $typeMap): void { $defaultEvents = [ Application\Started::class, Application\Finished::class, Test\DataProviderMethodCalled::class, Test\DataProviderMethodFinished::class, Test\MarkedIncomplete::class, Test\AfterLastTestMethodCalled::class, Test\AfterLastTestMethodFinished::class, Test\AfterTestMethodCalled::class, Test\AfterTestMethodFinished::class, Test\BeforeFirstTestMethodCalled::class, Test\BeforeFirstTestMethodErrored::class, Test\BeforeFirstTestMethodFinished::class, Test\BeforeTestMethodCalled::class, Test\BeforeTestMethodFinished::class, Test\ComparatorRegistered::class, Test\ConsideredRisky::class, Test\DeprecationTriggered::class, Test\Errored::class, Test\ErrorTriggered::class, Test\Failed::class, Test\Finished::class, Test\NoticeTriggered::class, Test\Passed::class, Test\PhpDeprecationTriggered::class, Test\PhpNoticeTriggered::class, Test\PhpunitDeprecationTriggered::class, Test\PhpunitErrorTriggered::class, Test\PhpunitWarningTriggered::class, Test\PhpWarningTriggered::class, Test\PostConditionCalled::class, Test\PostConditionFinished::class, Test\PreConditionCalled::class, Test\PreConditionFinished::class, Test\PreparationStarted::class, Test\Prepared::class, Test\PreparationFailed::class, Test\PrintedUnexpectedOutput::class, Test\Skipped::class, Test\WarningTriggered::class, Test\MockObjectCreated::class, Test\MockObjectForAbstractClassCreated::class, Test\MockObjectForIntersectionOfInterfacesCreated::class, Test\MockObjectForTraitCreated::class, Test\MockObjectFromWsdlCreated::class, Test\PartialMockObjectCreated::class, Test\TestProxyCreated::class, Test\TestStubCreated::class, Test\TestStubForIntersectionOfInterfacesCreated::class, TestRunner\BootstrapFinished::class, TestRunner\Configured::class, TestRunner\EventFacadeSealed::class, TestRunner\ExecutionAborted::class, TestRunner\ExecutionFinished::class, TestRunner\ExecutionStarted::class, TestRunner\ExtensionLoadedFromPhar::class, TestRunner\ExtensionBootstrapped::class, TestRunner\Finished::class, TestRunner\Started::class, TestRunner\DeprecationTriggered::class, TestRunner\WarningTriggered::class, TestRunner\GarbageCollectionDisabled::class, TestRunner\GarbageCollectionTriggered::class, TestRunner\GarbageCollectionEnabled::class, TestSuite\Filtered::class, TestSuite\Finished::class, TestSuite\Loaded::class, TestSuite\Skipped::class, TestSuite\Sorted::class, TestSuite\Started::class, ]; foreach ($defaultEvents as $eventClass) { $subscriberInterface = $eventClass . 'Subscriber'; assert(interface_exists($subscriberInterface)); $typeMap->addMapping($subscriberInterface, $eventClass); } } private function garbageCollectorStatusProvider(): Telemetry\GarbageCollectorStatusProvider { if (version_compare(PHP_VERSION, '8.3.0', '>=')) { return new Php83GarbageCollectorStatusProvider; } // @codeCoverageIgnoreStart return new Php81GarbageCollectorStatusProvider; // @codeCoverageIgnoreEnd } } phpunit/src/TextUI/Application.php 0000644 00000070033 15253321353 0013165 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use const PHP_EOL; use const PHP_VERSION; use function class_exists; use function explode; use function function_exists; use function is_file; use function is_readable; use function method_exists; use function printf; use function realpath; use function sprintf; use function str_contains; use function trim; use function unlink; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestSuite; use PHPUnit\Logging\EventLogger; use PHPUnit\Logging\JUnit\JunitXmlLogger; use PHPUnit\Logging\TeamCity\TeamCityLogger; use PHPUnit\Logging\TestDox\HtmlRenderer as TestDoxHtmlRenderer; use PHPUnit\Logging\TestDox\PlainTextRenderer as TestDoxTextRenderer; use PHPUnit\Logging\TestDox\TestResultCollector as TestDoxResultCollector; use PHPUnit\Runner\Baseline\CannotLoadBaselineException; use PHPUnit\Runner\Baseline\Generator as BaselineGenerator; use PHPUnit\Runner\Baseline\Reader; use PHPUnit\Runner\Baseline\Writer; use PHPUnit\Runner\CodeCoverage; use PHPUnit\Runner\DeprecationCollector\Facade as DeprecationCollector; use PHPUnit\Runner\DirectoryDoesNotExistException; use PHPUnit\Runner\ErrorHandler; use PHPUnit\Runner\Extension\ExtensionBootstrapper; use PHPUnit\Runner\Extension\Facade as ExtensionFacade; use PHPUnit\Runner\Extension\PharLoader; use PHPUnit\Runner\GarbageCollection\GarbageCollectionHandler; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Runner\ResultCache\DefaultResultCache; use PHPUnit\Runner\ResultCache\NullResultCache; use PHPUnit\Runner\ResultCache\ResultCache; use PHPUnit\Runner\ResultCache\ResultCacheHandler; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\Runner\Version; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\TextUI\CliArguments\Builder; use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; use PHPUnit\TextUI\CliArguments\Exception as ArgumentsException; use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder; use PHPUnit\TextUI\Command\AtLeastVersionCommand; use PHPUnit\TextUI\Command\GenerateConfigurationCommand; use PHPUnit\TextUI\Command\ListGroupsCommand; use PHPUnit\TextUI\Command\ListTestFilesCommand; use PHPUnit\TextUI\Command\ListTestsAsTextCommand; use PHPUnit\TextUI\Command\ListTestsAsXmlCommand; use PHPUnit\TextUI\Command\ListTestSuitesCommand; use PHPUnit\TextUI\Command\MigrateConfigurationCommand; use PHPUnit\TextUI\Command\Result; use PHPUnit\TextUI\Command\ShowHelpCommand; use PHPUnit\TextUI\Command\ShowVersionCommand; use PHPUnit\TextUI\Command\VersionCheckCommand; use PHPUnit\TextUI\Command\WarmCodeCoverageCacheCommand; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Configuration\PhpHandler; use PHPUnit\TextUI\Configuration\Registry; use PHPUnit\TextUI\Configuration\TestSuiteBuilder; use PHPUnit\TextUI\Output\DefaultPrinter; use PHPUnit\TextUI\Output\Facade as OutputFacade; use PHPUnit\TextUI\Output\Printer; use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; use PHPUnit\TextUI\XmlConfiguration\DefaultConfiguration; use PHPUnit\TextUI\XmlConfiguration\Loader; use SebastianBergmann\Timer\Timer; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Application { /** * @param list<string> $argv */ public function run(array $argv): int { try { EventFacade::emitter()->applicationStarted(); $cliConfiguration = $this->buildCliConfiguration($argv); $pathToXmlConfigurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration); $this->executeCommandsThatOnlyRequireCliConfiguration($cliConfiguration, $pathToXmlConfigurationFile); $xmlConfiguration = $this->loadXmlConfiguration($pathToXmlConfigurationFile); $configuration = Registry::init( $cliConfiguration, $xmlConfiguration, ); (new PhpHandler)->handle($configuration->php()); if ($configuration->hasBootstrap()) { $this->loadBootstrapScript($configuration->bootstrap()); } $this->executeCommandsThatDoNotRequireTheTestSuite($configuration, $cliConfiguration); $testSuite = $this->buildTestSuite($configuration); $this->executeCommandsThatRequireTheTestSuite($configuration, $cliConfiguration, $testSuite); if ($testSuite->isEmpty() && !$configuration->hasCliArguments() && $configuration->testSuite()->isEmpty()) { $this->execute(new ShowHelpCommand(Result::FAILURE)); } $pharExtensions = null; $extensionRequiresCodeCoverageCollection = false; $extensionReplacesOutput = false; $extensionReplacesProgressOutput = false; $extensionReplacesResultOutput = false; if (!$configuration->noExtensions()) { if ($configuration->hasPharExtensionDirectory()) { $pharExtensions = (new PharLoader)->loadPharExtensionsInDirectory( $configuration->pharExtensionDirectory(), ); } $bootstrappedExtensions = $this->bootstrapExtensions($configuration); $extensionRequiresCodeCoverageCollection = $bootstrappedExtensions['requiresCodeCoverageCollection']; $extensionReplacesOutput = $bootstrappedExtensions['replacesOutput']; $extensionReplacesProgressOutput = $bootstrappedExtensions['replacesProgressOutput']; $extensionReplacesResultOutput = $bootstrappedExtensions['replacesResultOutput']; } CodeCoverage::instance()->init( $configuration, CodeCoverageFilterRegistry::instance(), $extensionRequiresCodeCoverageCollection, ); $printer = OutputFacade::init( $configuration, $extensionReplacesProgressOutput, $extensionReplacesResultOutput, ); if (!$configuration->debug() && !$extensionReplacesOutput) { $this->writeRuntimeInformation($printer, $configuration); $this->writePharExtensionInformation($printer, $pharExtensions); $this->writeRandomSeedInformation($printer, $configuration); $printer->print(PHP_EOL); } if ($configuration->debug()) { EventFacade::instance()->registerTracer( new EventLogger( 'php://stdout', false, ), ); } $this->registerLogfileWriters($configuration); $testDoxResultCollector = $this->testDoxResultCollector($configuration); TestResultFacade::init(); DeprecationCollector::init(); $resultCache = $this->initializeTestResultCache($configuration); if ($configuration->controlGarbageCollector()) { new GarbageCollectionHandler( EventFacade::instance(), $configuration->numberOfTestsBeforeGarbageCollection(), ); } $baselineGenerator = $this->configureBaseline($configuration); $this->configureDeprecationTriggers($configuration); EventFacade::instance()->seal(); $timer = new Timer; $timer->start(); $runner = new TestRunner; $runner->run( $configuration, $resultCache, $testSuite, ); $duration = $timer->stop(); $testDoxResult = null; if (isset($testDoxResultCollector)) { $testDoxResult = $testDoxResultCollector->testMethodsGroupedByClass(); } if ($testDoxResult !== null && $configuration->hasLogfileTestdoxHtml()) { try { OutputFacade::printerFor($configuration->logfileTestdoxHtml())->print( (new TestDoxHtmlRenderer)->render($testDoxResult), ); } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot log test results in TestDox HTML format to "%s": %s', $configuration->logfileTestdoxHtml(), $e->getMessage(), ), ); } } if ($testDoxResult !== null && $configuration->hasLogfileTestdoxText()) { try { OutputFacade::printerFor($configuration->logfileTestdoxText())->print( (new TestDoxTextRenderer)->render($testDoxResult), ); } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot log test results in TestDox plain text format to "%s": %s', $configuration->logfileTestdoxText(), $e->getMessage(), ), ); } } $result = TestResultFacade::result(); if (!$extensionReplacesResultOutput && !$configuration->debug()) { OutputFacade::printResult($result, $testDoxResult, $duration); } CodeCoverage::instance()->generateReports($printer, $configuration); if (isset($baselineGenerator)) { (new Writer)->write( $configuration->generateBaseline(), $baselineGenerator->baseline(), ); $printer->print( sprintf( PHP_EOL . 'Baseline written to %s.' . PHP_EOL, realpath($configuration->generateBaseline()), ), ); } $shellExitCode = (new ShellExitCodeCalculator)->calculate( $configuration->failOnDeprecation(), $configuration->failOnEmptyTestSuite(), $configuration->failOnIncomplete(), $configuration->failOnNotice(), $configuration->failOnRisky(), $configuration->failOnSkipped(), $configuration->failOnWarning(), $result, ); EventFacade::emitter()->applicationFinished($shellExitCode); return $shellExitCode; // @codeCoverageIgnoreStart } catch (Throwable $t) { $this->exitWithCrashMessage($t); } // @codeCoverageIgnoreEnd } private function execute(Command\Command $command, bool $requiresResultCollectedFromEvents = false): never { if ($requiresResultCollectedFromEvents) { try { TestResultFacade::init(); EventFacade::instance()->seal(); $resultCollectedFromEvents = TestResultFacade::result(); } catch (EventFacadeIsSealedException|UnknownSubscriberTypeException) { } } print Version::getVersionString() . PHP_EOL . PHP_EOL; $result = $command->execute(); print $result->output(); $shellExitCode = $result->shellExitCode(); if (isset($resultCollectedFromEvents) && $resultCollectedFromEvents->hasTestTriggeredPhpunitErrorEvents()) { $shellExitCode = Result::EXCEPTION; print PHP_EOL . PHP_EOL . 'There were errors:' . PHP_EOL; foreach ($resultCollectedFromEvents->testTriggeredPhpunitErrorEvents() as $events) { foreach ($events as $event) { print PHP_EOL . trim($event->message()) . PHP_EOL; } } } exit($shellExitCode); } private function loadBootstrapScript(string $filename): void { if (!is_readable($filename)) { $this->exitWithErrorMessage( sprintf( 'Cannot open bootstrap script "%s"', $filename, ), ); } try { include_once $filename; } catch (Throwable $t) { $message = sprintf( 'Error in bootstrap script: %s:%s%s%s%s', $t::class, PHP_EOL, $t->getMessage(), PHP_EOL, $t->getTraceAsString(), ); while ($t = $t->getPrevious()) { $message .= sprintf( '%s%sPrevious error: %s:%s%s%s%s', PHP_EOL, PHP_EOL, $t::class, PHP_EOL, $t->getMessage(), PHP_EOL, $t->getTraceAsString(), ); } $this->exitWithErrorMessage($message); } EventFacade::emitter()->testRunnerBootstrapFinished($filename); } /** * @param list<string> $argv */ private function buildCliConfiguration(array $argv): CliConfiguration { try { $cliConfiguration = (new Builder)->fromParameters($argv); } catch (ArgumentsException $e) { $this->exitWithErrorMessage($e->getMessage()); } return $cliConfiguration; } private function loadXmlConfiguration(false|string $configurationFile): XmlConfiguration { if ($configurationFile === false) { return DefaultConfiguration::create(); } try { return (new Loader)->load($configurationFile); } catch (Throwable $e) { $this->exitWithErrorMessage($e->getMessage()); } } private function buildTestSuite(Configuration $configuration): TestSuite { try { return (new TestSuiteBuilder)->build($configuration); } catch (Exception $e) { $this->exitWithErrorMessage($e->getMessage()); } } /** * @return array{requiresCodeCoverageCollection: bool, replacesOutput: bool, replacesProgressOutput: bool, replacesResultOutput: bool} */ private function bootstrapExtensions(Configuration $configuration): array { $facade = new ExtensionFacade; $extensionBootstrapper = new ExtensionBootstrapper( $configuration, $facade, ); foreach ($configuration->extensionBootstrappers() as $bootstrapper) { $extensionBootstrapper->bootstrap( $bootstrapper['className'], $bootstrapper['parameters'], ); } return [ 'requiresCodeCoverageCollection' => $facade->requiresCodeCoverageCollection(), 'replacesOutput' => $facade->replacesOutput(), 'replacesProgressOutput' => $facade->replacesProgressOutput(), 'replacesResultOutput' => $facade->replacesResultOutput(), ]; } private function executeCommandsThatOnlyRequireCliConfiguration(CliConfiguration $cliConfiguration, false|string $configurationFile): void { if ($cliConfiguration->generateConfiguration()) { $this->execute(new GenerateConfigurationCommand); } if ($cliConfiguration->migrateConfiguration()) { if ($configurationFile === false) { $this->exitWithErrorMessage('No configuration file found to migrate'); } $this->execute(new MigrateConfigurationCommand(realpath($configurationFile))); } if ($cliConfiguration->hasAtLeastVersion()) { $this->execute(new AtLeastVersionCommand($cliConfiguration->atLeastVersion())); } if ($cliConfiguration->version()) { $this->execute(new ShowVersionCommand); } if ($cliConfiguration->checkVersion()) { $this->execute(new VersionCheckCommand); } if ($cliConfiguration->help()) { $this->execute(new ShowHelpCommand(Result::SUCCESS)); } } private function executeCommandsThatDoNotRequireTheTestSuite(Configuration $configuration, CliConfiguration $cliConfiguration): void { if ($cliConfiguration->listSuites()) { $this->execute(new ListTestSuitesCommand($configuration->testSuite())); } if ($cliConfiguration->warmCoverageCache()) { $this->execute(new WarmCodeCoverageCacheCommand($configuration, CodeCoverageFilterRegistry::instance())); } } private function executeCommandsThatRequireTheTestSuite(Configuration $configuration, CliConfiguration $cliConfiguration, TestSuite $testSuite): void { if ($cliConfiguration->listGroups()) { $this->execute( new ListGroupsCommand( $this->filteredTests( $configuration, $testSuite, ), ), true, ); } if ($cliConfiguration->listTests()) { $this->execute( new ListTestsAsTextCommand( $this->filteredTests( $configuration, $testSuite, ), ), true, ); } if ($cliConfiguration->hasListTestsXml()) { $this->execute( new ListTestsAsXmlCommand( $this->filteredTests( $configuration, $testSuite, ), $cliConfiguration->listTestsXml(), ), true, ); } if ($cliConfiguration->listTestFiles()) { $this->execute( new ListTestFilesCommand( $this->filteredTests( $configuration, $testSuite, ), ), true, ); } } private function writeRuntimeInformation(Printer $printer, Configuration $configuration): void { $printer->print(Version::getVersionString() . PHP_EOL . PHP_EOL); $runtime = 'PHP ' . PHP_VERSION; if (CodeCoverage::instance()->isActive()) { $runtime .= ' with ' . CodeCoverage::instance()->driver()->nameAndVersion(); } $this->writeMessage($printer, 'Runtime', $runtime); if ($configuration->hasConfigurationFile()) { $this->writeMessage( $printer, 'Configuration', $configuration->configurationFile(), ); } } /** * @param ?list<string> $pharExtensions */ private function writePharExtensionInformation(Printer $printer, ?array $pharExtensions): void { if ($pharExtensions === null) { return; } foreach ($pharExtensions as $extension) { $this->writeMessage( $printer, 'Extension', $extension, ); } } private function writeMessage(Printer $printer, string $type, string $message): void { $printer->print( sprintf( "%-15s%s\n", $type . ':', $message, ), ); } private function writeRandomSeedInformation(Printer $printer, Configuration $configuration): void { if ($configuration->executionOrder() === TestSuiteSorter::ORDER_RANDOMIZED) { $this->writeMessage( $printer, 'Random Seed', (string) $configuration->randomOrderSeed(), ); } } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerLogfileWriters(Configuration $configuration): void { if ($configuration->hasLogEventsText()) { if (is_file($configuration->logEventsText())) { unlink($configuration->logEventsText()); } EventFacade::instance()->registerTracer( new EventLogger( $configuration->logEventsText(), false, ), ); } if ($configuration->hasLogEventsVerboseText()) { if (is_file($configuration->logEventsVerboseText())) { unlink($configuration->logEventsVerboseText()); } EventFacade::instance()->registerTracer( new EventLogger( $configuration->logEventsVerboseText(), true, ), ); } if ($configuration->hasLogfileJunit()) { try { new JunitXmlLogger( OutputFacade::printerFor($configuration->logfileJunit()), EventFacade::instance(), ); } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot log test results in JUnit XML format to "%s": %s', $configuration->logfileJunit(), $e->getMessage(), ), ); } } if ($configuration->hasLogfileTeamcity()) { try { new TeamCityLogger( DefaultPrinter::from( $configuration->logfileTeamcity(), ), EventFacade::instance(), ); } catch (DirectoryDoesNotExistException|InvalidSocketException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot log test results in TeamCity format to "%s": %s', $configuration->logfileTeamcity(), $e->getMessage(), ), ); } } } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function testDoxResultCollector(Configuration $configuration): ?TestDoxResultCollector { if ($configuration->hasLogfileTestdoxHtml() || $configuration->hasLogfileTestdoxText() || $configuration->outputIsTestDox()) { return new TestDoxResultCollector(EventFacade::instance()); } return null; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function initializeTestResultCache(Configuration $configuration): ResultCache { if ($configuration->cacheResult()) { $cache = new DefaultResultCache($configuration->testResultCacheFile()); new ResultCacheHandler($cache, EventFacade::instance()); return $cache; } return new NullResultCache; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function configureBaseline(Configuration $configuration): ?BaselineGenerator { if ($configuration->hasGenerateBaseline()) { return new BaselineGenerator( EventFacade::instance(), $configuration->source(), ); } if ($configuration->source()->useBaseline()) { $baselineFile = $configuration->source()->baseline(); $baseline = null; try { $baseline = (new Reader)->read($baselineFile); } catch (CannotLoadBaselineException $e) { EventFacade::emitter()->testRunnerTriggeredWarning($e->getMessage()); } if ($baseline !== null) { ErrorHandler::instance()->useBaseline($baseline); } } return null; } /** * @codeCoverageIgnore */ private function exitWithCrashMessage(Throwable $t): never { $message = $t->getMessage(); if (empty(trim($message))) { $message = '(no message)'; } printf( '%s%sAn error occurred inside PHPUnit.%s%sMessage: %s', PHP_EOL, PHP_EOL, PHP_EOL, PHP_EOL, $message, ); $first = true; if ($t->getPrevious()) { $t = $t->getPrevious(); } do { printf( '%s%s: %s:%d%s%s%s%s', PHP_EOL, $first ? 'Location' : 'Caused by', $t->getFile(), $t->getLine(), PHP_EOL, PHP_EOL, $t->getTraceAsString(), PHP_EOL, ); $first = false; } while ($t = $t->getPrevious()); exit(Result::CRASH); } private function exitWithErrorMessage(string $message): never { print Version::getVersionString() . PHP_EOL . PHP_EOL . $message . PHP_EOL; exit(Result::EXCEPTION); } /** * @return list<PhptTestCase|TestCase> */ private function filteredTests(Configuration $configuration, TestSuite $suite): array { (new TestSuiteFilterProcessor)->process($configuration, $suite); return $suite->collect(); } private function configureDeprecationTriggers(Configuration $configuration): void { $deprecationTriggers = [ 'functions' => [], 'methods' => [], ]; foreach ($configuration->source()->deprecationTriggers()['functions'] as $function) { if (!function_exists($function)) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Function %s cannot be configured as a deprecation trigger because it is not declared', $function, ), ); continue; } $deprecationTriggers['functions'][] = $function; } foreach ($configuration->source()->deprecationTriggers()['methods'] as $method) { if (!str_contains($method, '::')) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( '%s cannot be configured as a deprecation trigger because it is not in ClassName::methodName format', $method, ), ); continue; } [$className, $methodName] = explode('::', $method); if (!class_exists($className) || !method_exists($className, $methodName)) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Method %s::%s cannot be configured as a deprecation trigger because it is not declared', $className, $methodName, ), ); continue; } $deprecationTriggers['methods'][] = [ 'className' => $className, 'methodName' => $methodName, ]; } ErrorHandler::instance()->useDeprecationTriggers($deprecationTriggers); } } phpunit/src/TextUI/Exception/Exception.php 0000644 00000001043 15253321353 0014611 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends Throwable { } phpunit/src/TextUI/Exception/CannotOpenSocketException.php 0000644 00000001535 15253321353 0017755 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CannotOpenSocketException extends RuntimeException implements Exception { public function __construct(string $hostname, int $port) { parent::__construct( sprintf( 'Cannot open socket %s:%d', $hostname, $port, ), ); } } phpunit/src/TextUI/Exception/TestDirectoryNotFoundException.php 0000644 00000001475 15253321353 0021024 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestDirectoryNotFoundException extends RuntimeException implements Exception { public function __construct(string $path) { parent::__construct( sprintf( 'Test directory "%s" not found', $path, ), ); } } phpunit/src/TextUI/Exception/ExtensionsNotConfiguredException.php 0000644 00000001133 15253321353 0021360 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ExtensionsNotConfiguredException extends RuntimeException implements Exception { } phpunit/src/TextUI/Exception/InvalidSocketException.php 0000644 00000001517 15253321353 0017277 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidSocketException extends RuntimeException implements Exception { public function __construct(string $socket) { parent::__construct( sprintf( '"%s" does not match "socket://hostname:port" format', $socket, ), ); } } phpunit/src/TextUI/Exception/RuntimeException.php 0000644 00000001065 15253321353 0016161 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class RuntimeException extends \RuntimeException implements Exception { } phpunit/src/TextUI/Exception/ReflectionException.php 0000644 00000001116 15253321353 0016625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReflectionException extends RuntimeException implements Exception { } phpunit/src/TextUI/Exception/TestFileNotFoundException.php 0000644 00000001463 15253321353 0017734 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestFileNotFoundException extends RuntimeException implements Exception { public function __construct(string $path) { parent::__construct( sprintf( 'Test file "%s" not found', $path, ), ); } } phpunit/src/TextUI/ShellExitCodeCalculator.php 0000644 00000004141 15253321353 0015425 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use PHPUnit\TestRunner\TestResult\TestResult; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ShellExitCodeCalculator { private const SUCCESS_EXIT = 0; private const FAILURE_EXIT = 1; private const EXCEPTION_EXIT = 2; public function calculate(bool $failOnDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, TestResult $result): int { $returnCode = self::FAILURE_EXIT; if ($result->wasSuccessful()) { $returnCode = self::SUCCESS_EXIT; } if ($failOnEmptyTestSuite && !$result->hasTests()) { $returnCode = self::FAILURE_EXIT; } if ($result->wasSuccessfulIgnoringPhpunitWarnings()) { if ($failOnDeprecation && $result->hasDeprecations()) { $returnCode = self::FAILURE_EXIT; } if ($failOnIncomplete && $result->hasIncompleteTests()) { $returnCode = self::FAILURE_EXIT; } if ($failOnNotice && $result->hasNotices()) { $returnCode = self::FAILURE_EXIT; } if ($failOnRisky && $result->hasRiskyTests()) { $returnCode = self::FAILURE_EXIT; } if ($failOnSkipped && $result->hasSkippedTests()) { $returnCode = self::FAILURE_EXIT; } if ($failOnWarning && $result->hasWarnings()) { $returnCode = self::FAILURE_EXIT; } } if ($result->hasErrors()) { $returnCode = self::EXCEPTION_EXIT; } return $returnCode; } } phpunit/src/TextUI/Command/Result.php 0000644 00000002316 15253321353 0013555 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Result { public const SUCCESS = 0; public const FAILURE = 1; public const EXCEPTION = 2; public const CRASH = 255; private string $output; private int $shellExitCode; public static function from(string $output = '', int $shellExitCode = self::SUCCESS): self { return new self($output, $shellExitCode); } private function __construct(string $output, int $shellExitCode) { $this->output = $output; $this->shellExitCode = $shellExitCode; } public function output(): string { return $this->output; } public function shellExitCode(): int { return $this->shellExitCode; } } phpunit/src/TextUI/Command/Command.php 0000644 00000001052 15253321353 0013651 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Command { public function execute(): Result; } phpunit/src/TextUI/Command/Commands/ListGroupsCommand.php 0000644 00000003305 15253321353 0017451 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function array_merge; use function array_unique; use function sort; use function sprintf; use function str_starts_with; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\PhptTestCase; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ListGroupsCommand implements Command { /** * @var list<PhptTestCase|TestCase> */ private array $tests; /** * @param list<PhptTestCase|TestCase> $tests */ public function __construct(array $tests) { $this->tests = $tests; } public function execute(): Result { $groups = []; foreach ($this->tests as $test) { if ($test instanceof PhptTestCase) { $groups[] = 'default'; continue; } $groups = array_merge($groups, $test->groups()); } $groups = array_unique($groups); sort($groups); $buffer = 'Available test group(s):' . PHP_EOL; foreach ($groups as $group) { if (str_starts_with($group, '__phpunit_')) { continue; } $buffer .= sprintf( ' - %s' . PHP_EOL, $group, ); } return Result::from($buffer); } } phpunit/src/TextUI/Command/Commands/GenerateConfigurationCommand.php 0000644 00000005572 15253321353 0021630 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use const STDIN; use function assert; use function fgets; use function file_put_contents; use function getcwd; use function sprintf; use function trim; use PHPUnit\Runner\Version; use PHPUnit\TextUI\XmlConfiguration\Generator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class GenerateConfigurationCommand implements Command { public function execute(): Result { print 'Generating phpunit.xml in ' . getcwd() . PHP_EOL . PHP_EOL; print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): '; $bootstrapScript = $this->read(); print 'Tests directory (relative to path shown above; default: tests): '; $testsDirectory = $this->read(); print 'Source directory (relative to path shown above; default: src): '; $src = $this->read(); print 'Cache directory (relative to path shown above; default: .phpunit.cache): '; $cacheDirectory = $this->read(); if ($bootstrapScript === '') { $bootstrapScript = 'vendor/autoload.php'; } if ($testsDirectory === '') { $testsDirectory = 'tests'; } if ($src === '') { $src = 'src'; } if ($cacheDirectory === '') { $cacheDirectory = '.phpunit.cache'; } $generator = new Generator; $result = @file_put_contents( 'phpunit.xml', $generator->generateDefaultConfiguration( Version::series(), $bootstrapScript, $testsDirectory, $src, $cacheDirectory, ), ); if ($result !== false) { return Result::from( sprintf( PHP_EOL . 'Generated phpunit.xml in %s.' . PHP_EOL . 'Make sure to exclude the %s directory from version control.' . PHP_EOL, getcwd(), $cacheDirectory, ), ); } // @codeCoverageIgnoreStart return Result::from( sprintf( PHP_EOL . 'Could not write phpunit.xml in %s.' . PHP_EOL, getcwd(), ), Result::EXCEPTION, ); // @codeCoverageIgnoreEnd } private function read(): string { $buffer = fgets(STDIN); assert($buffer !== false); return trim($buffer); } } phpunit/src/TextUI/Command/Commands/MigrateConfigurationCommand.php 0000644 00000003345 15253321353 0021462 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function copy; use function file_put_contents; use function sprintf; use PHPUnit\TextUI\XmlConfiguration\Migrator; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MigrateConfigurationCommand implements Command { private string $filename; public function __construct(string $filename) { $this->filename = $filename; } public function execute(): Result { try { $migrated = (new Migrator)->migrate($this->filename); copy($this->filename, $this->filename . '.bak'); file_put_contents($this->filename, $migrated); return Result::from( sprintf( 'Created backup: %s.bak%sMigrated configuration: %s%s', $this->filename, PHP_EOL, $this->filename, PHP_EOL, ), ); } catch (Throwable $t) { return Result::from( sprintf( 'Migration of %s failed:%s%s%s', $this->filename, PHP_EOL, $t->getMessage(), PHP_EOL, ), Result::FAILURE, ); } } } phpunit/src/TextUI/Command/Commands/VersionCheckCommand.php 0000644 00000004074 15253321353 0017725 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function assert; use function file_get_contents; use function sprintf; use function version_compare; use PHPUnit\Runner\Version; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final readonly class VersionCheckCommand implements Command { public function execute(): Result { $latestVersion = file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit'); assert($latestVersion !== false); $latestCompatibleVersion = @file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit-' . Version::majorVersionNumber()); $notLatest = version_compare($latestVersion, Version::id(), '>'); $notLatestCompatible = false; if ($latestCompatibleVersion !== false) { $notLatestCompatible = version_compare($latestCompatibleVersion, Version::id(), '>'); } if (!$notLatest && !$notLatestCompatible) { return Result::from( 'You are using the latest version of PHPUnit.' . PHP_EOL, ); } $buffer = 'You are not using the latest version of PHPUnit.' . PHP_EOL; if ($notLatestCompatible) { $buffer .= sprintf( 'The latest version compatible with PHPUnit %s is PHPUnit %s.' . PHP_EOL, Version::id(), $latestCompatibleVersion, ); } if ($notLatest) { $buffer .= sprintf( 'The latest version is PHPUnit %s.' . PHP_EOL, $latestVersion, ); } return Result::from($buffer, Result::FAILURE); } } phpunit/src/TextUI/Command/Commands/ListTestsAsTextCommand.php 0000644 00000003015 15253321353 0020423 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function sprintf; use function str_replace; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\PhptTestCase; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ListTestsAsTextCommand implements Command { /** * @var list<PhptTestCase|TestCase> */ private array $tests; /** * @param list<PhptTestCase|TestCase> $tests */ public function __construct(array $tests) { $this->tests = $tests; } public function execute(): Result { $buffer = 'Available test(s):' . PHP_EOL; foreach ($this->tests as $test) { if ($test instanceof TestCase) { $name = sprintf( '%s::%s', $test::class, str_replace(' with data set ', '', $test->nameWithDataSet()), ); } else { $name = $test->getName(); } $buffer .= sprintf( ' - %s' . PHP_EOL, $name, ); } return Result::from($buffer); } } phpunit/src/TextUI/Command/Commands/AtLeastVersionCommand.php 0000644 00000001677 15253321353 0020253 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use function version_compare; use PHPUnit\Runner\Version; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class AtLeastVersionCommand implements Command { private string $version; public function __construct(string $version) { $this->version = $version; } public function execute(): Result { if (version_compare(Version::id(), $this->version, '>=')) { return Result::from(); } return Result::from('', Result::FAILURE); } } phpunit/src/TextUI/Command/Commands/ListTestSuitesCommand.php 0000644 00000004175 15253321353 0020314 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function sprintf; use PHPUnit\TextUI\Configuration\Registry; use PHPUnit\TextUI\Configuration\TestSuiteCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ListTestSuitesCommand implements Command { private TestSuiteCollection $suites; public function __construct(TestSuiteCollection $suites) { $this->suites = $suites; } public function execute(): Result { $buffer = $this->warnAboutConflictingOptions(); $buffer .= 'Available test suite(s):' . PHP_EOL; foreach ($this->suites as $suite) { $buffer .= sprintf( ' - %s' . PHP_EOL, $suite->name(), ); } return Result::from($buffer); } private function warnAboutConflictingOptions(): string { $buffer = ''; $configuration = Registry::get(); if ($configuration->hasFilter()) { $buffer .= 'The --filter and --list-suites options cannot be combined, --filter is ignored' . PHP_EOL; } if ($configuration->hasGroups()) { $buffer .= 'The --group and --list-suites options cannot be combined, --group is ignored' . PHP_EOL; } if ($configuration->hasExcludeGroups()) { $buffer .= 'The --exclude-group and --list-suites options cannot be combined, --exclude-group is ignored' . PHP_EOL; } if ($configuration->includeTestSuite() !== '') { $buffer .= 'The --testsuite and --list-suites options cannot be combined, --exclude-group is ignored' . PHP_EOL; } if (!empty($buffer)) { $buffer .= PHP_EOL; } return $buffer; } } phpunit/src/TextUI/Command/Commands/ShowHelpCommand.php 0000644 00000001564 15253321353 0017074 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use PHPUnit\TextUI\Help; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ShowHelpCommand implements Command { private int $shellExitCode; public function __construct(int $shellExitCode) { $this->shellExitCode = $shellExitCode; } public function execute(): Result { return Result::from( (new Help)->generate(), $this->shellExitCode, ); } } phpunit/src/TextUI/Command/Commands/ListTestsAsXmlCommand.php 0000644 00000007355 15253321353 0020252 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function file_put_contents; use function ksort; use function sprintf; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\PhptTestCase; use XMLWriter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ListTestsAsXmlCommand implements Command { /** * @var list<PhptTestCase|TestCase> */ private array $tests; private string $filename; /** * @param list<PhptTestCase|TestCase> $tests */ public function __construct(array $tests, string $filename) { $this->tests = $tests; $this->filename = $filename; } public function execute(): Result { $writer = new XMLWriter; $writer->openMemory(); $writer->setIndent(true); $writer->startDocument(); $writer->startElement('testSuite'); $writer->writeAttribute('xmlns', 'https://xml.phpunit.de/testSuite'); $writer->startElement('tests'); $currentTestClass = null; $groups = []; foreach ($this->tests as $test) { if ($test instanceof TestCase) { foreach ($test->groups() as $group) { if (!isset($groups[$group])) { $groups[$group] = []; } $groups[$group][] = $test->valueObjectForEvents()->id(); } if ($test::class !== $currentTestClass) { if ($currentTestClass !== null) { $writer->endElement(); } $writer->startElement('testClass'); $writer->writeAttribute('name', $test::class); $writer->writeAttribute('file', $test->valueObjectForEvents()->file()); $currentTestClass = $test::class; } $writer->startElement('testMethod'); $writer->writeAttribute('id', $test->valueObjectForEvents()->id()); $writer->writeAttribute('name', $test->valueObjectForEvents()->methodName()); $writer->endElement(); continue; } if ($currentTestClass !== null) { $writer->endElement(); $currentTestClass = null; } $writer->startElement('phpt'); $writer->writeAttribute('file', $test->getName()); $writer->endElement(); } if ($currentTestClass !== null) { $writer->endElement(); } $writer->endElement(); ksort($groups); $writer->startElement('groups'); foreach ($groups as $groupName => $testIds) { $writer->startElement('group'); $writer->writeAttribute('name', $groupName); foreach ($testIds as $testId) { $writer->startElement('test'); $writer->writeAttribute('id', $testId); $writer->endElement(); } $writer->endElement(); } $writer->endElement(); $writer->endElement(); file_put_contents($this->filename, $writer->outputMemory()); return Result::from( sprintf( 'Wrote list of tests that would have been run to %s' . PHP_EOL, $this->filename, ), ); } } phpunit/src/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php 0000644 00000005045 15253321353 0021442 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function printf; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Configuration\NoCoverageCacheDirectoryException; use SebastianBergmann\CodeCoverage\StaticAnalysis\CacheWarmer; use SebastianBergmann\Timer\NoActiveTimerException; use SebastianBergmann\Timer\Timer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final readonly class WarmCodeCoverageCacheCommand implements Command { private Configuration $configuration; private CodeCoverageFilterRegistry $codeCoverageFilterRegistry; public function __construct(Configuration $configuration, CodeCoverageFilterRegistry $codeCoverageFilterRegistry) { $this->configuration = $configuration; $this->codeCoverageFilterRegistry = $codeCoverageFilterRegistry; } /** * @throws NoActiveTimerException * @throws NoCoverageCacheDirectoryException */ public function execute(): Result { if (!$this->configuration->hasCoverageCacheDirectory()) { return Result::from( 'Cache for static analysis has not been configured' . PHP_EOL, Result::FAILURE, ); } $this->codeCoverageFilterRegistry->init($this->configuration, true); if (!$this->codeCoverageFilterRegistry->configured()) { return Result::from( 'Filter for code coverage has not been configured' . PHP_EOL, Result::FAILURE, ); } $timer = new Timer; $timer->start(); print 'Warming cache for static analysis ... '; (new CacheWarmer)->warmCache( $this->configuration->coverageCacheDirectory(), !$this->configuration->disableCodeCoverageIgnore(), $this->configuration->ignoreDeprecatedCodeUnitsFromCodeCoverage(), $this->codeCoverageFilterRegistry->get(), ); printf( '[%s]%s', $timer->stop()->asString(), PHP_EOL, ); return Result::from(); } } phpunit/src/TextUI/Command/Commands/ShowVersionCommand.php 0000644 00000001175 15253321353 0017627 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ShowVersionCommand implements Command { public function execute(): Result { return Result::from(); } } phpunit/src/TextUI/Command/Commands/ListTestFilesCommand.php 0000644 00000003413 15253321353 0020074 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Command; use const PHP_EOL; use function array_unique; use function assert; use function sprintf; use PHPUnit\Framework\TestCase; use PHPUnit\Runner\PhptTestCase; use PHPUnit\TextUI\Configuration\Registry; use ReflectionClass; use ReflectionException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ListTestFilesCommand implements Command { /** * @var list<PhptTestCase|TestCase> */ private array $tests; /** * @param list<PhptTestCase|TestCase> $tests */ public function __construct(array $tests) { $this->tests = $tests; } /** * @throws ReflectionException */ public function execute(): Result { $configuration = Registry::get(); $buffer = 'Available test files:' . PHP_EOL; $results = []; foreach ($this->tests as $test) { if ($test instanceof TestCase) { $name = (new ReflectionClass($test))->getFileName(); assert($name !== false); $results[] = $name; continue; } $results[] = $test->getName(); } foreach (array_unique($results) as $result) { $buffer .= sprintf( ' - %s' . PHP_EOL, $result, ); } return Result::from($buffer); } } phpunit/src/TextUI/Configuration/Xml/Validator/Validator.php 0000644 00000002271 15253321353 0020142 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use function file_get_contents; use function libxml_clear_errors; use function libxml_get_errors; use function libxml_use_internal_errors; use DOMDocument; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Validator { public function validate(DOMDocument $document, string $xsdFilename): ValidationResult { $buffer = file_get_contents($xsdFilename); assert($buffer !== false); $originalErrorHandling = libxml_use_internal_errors(true); $document->schemaValidateSource($buffer); $errors = libxml_get_errors(); libxml_clear_errors(); libxml_use_internal_errors($originalErrorHandling); return ValidationResult::fromArray($errors); } } phpunit/src/TextUI/Configuration/Xml/Validator/ValidationResult.php 0000644 00000003571 15253321353 0021512 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use const PHP_EOL; use function sprintf; use function trim; use LibXMLError; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class ValidationResult { /** * @var array<int, list<string>> */ private array $validationErrors; /** * @param array<int, LibXMLError> $errors */ public static function fromArray(array $errors): self { $validationErrors = []; foreach ($errors as $error) { if (!isset($validationErrors[$error->line])) { $validationErrors[$error->line] = []; } $validationErrors[$error->line][] = trim($error->message); } return new self($validationErrors); } /** * @param array<int, list<string>> $validationErrors */ private function __construct(array $validationErrors) { $this->validationErrors = $validationErrors; } public function hasValidationErrors(): bool { return !empty($this->validationErrors); } public function asString(): string { $buffer = ''; foreach ($this->validationErrors as $line => $validationErrorsOnLine) { $buffer .= sprintf(PHP_EOL . ' Line %d:' . PHP_EOL, $line); foreach ($validationErrorsOnLine as $validationError) { $buffer .= sprintf(' - %s' . PHP_EOL, $validationError); } } return $buffer; } } phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilder.php 0000644 00000006360 15253321353 0021464 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function version_compare; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MigrationBuilder { private const AVAILABLE_MIGRATIONS = [ '8.5' => [ RemoveLogTypes::class, ], '9.2' => [ RemoveCacheTokensAttribute::class, IntroduceCoverageElement::class, MoveAttributesFromRootToCoverage::class, MoveAttributesFromFilterWhitelistToCoverage::class, MoveWhitelistIncludesToCoverage::class, MoveWhitelistExcludesToCoverage::class, RemoveEmptyFilter::class, CoverageCloverToReport::class, CoverageCrap4jToReport::class, CoverageHtmlToReport::class, CoveragePhpToReport::class, CoverageTextToReport::class, CoverageXmlToReport::class, ConvertLogTypes::class, ], '9.5' => [ RemoveListeners::class, RemoveTestSuiteLoaderAttributes::class, RemoveCacheResultFileAttribute::class, RemoveCoverageElementCacheDirectoryAttribute::class, RemoveCoverageElementProcessUncoveredFilesAttribute::class, IntroduceCacheDirectoryAttribute::class, RenameBackupStaticAttributesAttribute::class, RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute::class, RemoveBeStrictAboutTodoAnnotatedTestsAttribute::class, RemovePrinterAttributes::class, RemoveVerboseAttribute::class, RenameForceCoversAnnotationAttribute::class, RenameBeStrictAboutCoversAnnotationAttribute::class, RemoveConversionToExceptionsAttributes::class, RemoveNoInteractionAttribute::class, RemoveLoggingElements::class, RemoveTestDoxGroupsElement::class, ], '10.0' => [ MoveCoverageDirectoriesToSource::class, ], '10.5' => [ RemoveRegisterMockObjectsFromTestArgumentsRecursivelyAttribute::class, ], '11.0' => [ ReplaceRestrictDeprecationsWithIgnoreDeprecations::class, ], '11.1' => [ RemoveCacheResultFileAttribute::class, RemoveCoverageElementCacheDirectoryAttribute::class, ], ]; /** * @throws MigrationBuilderException * * @return non-empty-list<Migration> */ public function build(string $fromVersion): array { $stack = [new UpdateSchemaLocation]; foreach (self::AVAILABLE_MIGRATIONS as $version => $migrations) { if (version_compare($version, $fromVersion, '<')) { continue; } foreach ($migrations as $migration) { $stack[] = new $migration; } } return $stack; } } phpunit/src/TextUI/Configuration/Xml/Migration/MigrationException.php 0000644 00000001165 15253321353 0022032 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MigrationException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistExcludesToCoverage.php 0000644 00000004272 15253321353 0026617 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use function in_array; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MoveWhitelistExcludesToCoverage implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $whitelist = $document->getElementsByTagName('whitelist')->item(0); if ($whitelist === null) { return; } $excludeNodes = SnapshotNodeList::fromNodeList($whitelist->getElementsByTagName('exclude')); if ($excludeNodes->count() === 0) { return; } $coverage = $document->getElementsByTagName('coverage')->item(0); if (!$coverage instanceof DOMElement) { throw new MigrationException('Unexpected state - No coverage element'); } $targetExclude = $coverage->getElementsByTagName('exclude')->item(0); if ($targetExclude === null) { $targetExclude = $coverage->appendChild( $document->createElement('exclude'), ); } foreach ($excludeNodes as $excludeNode) { assert($excludeNode instanceof DOMElement); foreach (SnapshotNodeList::fromNodeList($excludeNode->childNodes) as $child) { if (!$child instanceof DOMElement || !in_array($child->nodeName, ['directory', 'file'], true)) { continue; } $targetExclude->appendChild($child); } if ($excludeNode->getElementsByTagName('*')->count() !== 0) { throw new MigrationException('Dangling child elements in exclude found.'); } $whitelist->removeChild($excludeNode); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageTextToReport.php 0000644 00000001776 15253321353 0024445 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoverageTextToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-text'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $text = $logNode->ownerDocument->createElement('text'); $text->setAttribute('outputFile', $logNode->getAttribute('target')); $this->migrateAttributes($logNode, $text, ['showUncoveredFiles', 'showOnlySummary']); return $text; } } src/TextUI/Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutTodoAnnotatedTestsAttribute.php0000644 00000001701 15253321353 0031536 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveBeStrictAboutTodoAnnotatedTestsAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('beStrictAboutTodoAnnotatedTests')) { $root->removeAttribute('beStrictAboutTodoAnnotatedTests'); } } } Configuration/Xml/Migration/Migrations/RemoveCoverageElementProcessUncoveredFilesAttribute.php 0000644 00000001762 15253321353 0032566 0 ustar 00 phpunit/src/TextUI <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveCoverageElementProcessUncoveredFilesAttribute implements Migration { public function migrate(DOMDocument $document): void { $node = $document->getElementsByTagName('coverage')->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } if ($node->hasAttribute('processUncoveredFiles')) { $node->removeAttribute('processUncoveredFiles'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveVerboseAttribute.php 0000644 00000001571 15253321353 0025006 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveVerboseAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('verbose')) { $root->removeAttribute('verbose'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveWhitelistIncludesToCoverage.php 0000644 00000003014 15253321353 0026602 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MoveWhitelistIncludesToCoverage implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $whitelist = $document->getElementsByTagName('whitelist')->item(0); if ($whitelist === null) { return; } $coverage = $document->getElementsByTagName('coverage')->item(0); if (!$coverage instanceof DOMElement) { throw new MigrationException('Unexpected state - No coverage element'); } $include = $document->createElement('include'); $coverage->appendChild($include); foreach (SnapshotNodeList::fromNodeList($whitelist->childNodes) as $child) { if (!$child instanceof DOMElement) { continue; } if (!($child->nodeName === 'directory' || $child->nodeName === 'file')) { continue; } $include->appendChild($child); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameBackupStaticAttributesAttribute.php 0000644 00000002172 15253321353 0027775 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RenameBackupStaticAttributesAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('backupStaticProperties')) { return; } if (!$root->hasAttribute('backupStaticAttributes')) { return; } $root->setAttribute('backupStaticProperties', $root->getAttribute('backupStaticAttributes')); $root->removeAttribute('backupStaticAttributes'); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLoggingElements.php 0000644 00000003016 15253321353 0024574 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; use DOMXPath; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveLoggingElements implements Migration { public function migrate(DOMDocument $document): void { $this->removeTestDoxElement($document); $this->removeTextElement($document); } private function removeTestDoxElement(DOMDocument $document): void { $nodes = (new DOMXPath($document))->query('logging/testdoxXml'); assert($nodes !== false); $node = $nodes->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } $node->parentNode->removeChild($node); } private function removeTextElement(DOMDocument $document): void { $nodes = (new DOMXPath($document))->query('logging/text'); assert($nodes !== false); $node = $nodes->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } $node->parentNode->removeChild($node); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/Migration.php 0000644 00000001132 15253321353 0022261 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Migration { public function migrate(DOMDocument $document): void; } TextUI/Configuration/Xml/Migration/Migrations/ReplaceRestrictDeprecationsWithIgnoreDeprecations.php 0000644 00000002572 15253321353 0032257 0 ustar 00 phpunit/src <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ReplaceRestrictDeprecationsWithIgnoreDeprecations implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $source = $document->getElementsByTagName('source')->item(0); if ($source === null) { return; } assert($source instanceof DOMElement); if (!$source->hasAttribute('restrictDeprecations')) { return; } $restrictDeprecations = $source->getAttribute('restrictDeprecations') === 'true'; $source->removeAttribute('restrictDeprecations'); if (!$restrictDeprecations || $source->hasAttribute('ignoreIndirectDeprecations')) { return; } $source->setAttribute('ignoreIndirectDeprecations', 'true'); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveNoInteractionAttribute.php 0000644 00000001613 15253321353 0026152 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveNoInteractionAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('noInteraction')) { $root->removeAttribute('noInteraction'); } } } src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCoverageElementCacheDirectoryAttribute.php 0000644 00000001735 15253321353 0031202 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveCoverageElementCacheDirectoryAttribute implements Migration { public function migrate(DOMDocument $document): void { $node = $document->getElementsByTagName('coverage')->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } if ($node->hasAttribute('cacheDirectory')) { $node->removeAttribute('cacheDirectory'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCloverToReport.php 0000644 00000001654 15253321353 0024746 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoverageCloverToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-clover'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $clover = $logNode->ownerDocument->createElement('clover'); $clover->setAttribute('outputFile', $logNode->getAttribute('target')); return $clover; } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveConversionToExceptionsAttributes.php0000644 00000002543 15253321353 0030256 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveConversionToExceptionsAttributes implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('convertDeprecationsToExceptions')) { $root->removeAttribute('convertDeprecationsToExceptions'); } if ($root->hasAttribute('convertErrorsToExceptions')) { $root->removeAttribute('convertErrorsToExceptions'); } if ($root->hasAttribute('convertNoticesToExceptions')) { $root->removeAttribute('convertNoticesToExceptions'); } if ($root->hasAttribute('convertWarningsToExceptions')) { $root->removeAttribute('convertWarningsToExceptions'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageXmlToReport.php 0000644 00000001636 15253321353 0024254 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoverageXmlToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-xml'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $xml = $logNode->ownerDocument->createElement('xml'); $xml->setAttribute('outputDirectory', $logNode->getAttribute('target')); return $xml; } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestSuiteLoaderAttributes.php 0000644 00000002034 15253321353 0026637 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveTestSuiteLoaderAttributes implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('testSuiteLoaderClass')) { $root->removeAttribute('testSuiteLoaderClass'); } if ($root->hasAttribute('testSuiteLoaderFile')) { $root->removeAttribute('testSuiteLoaderFile'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/UpdateSchemaLocation.php 0000644 00000002013 15253321353 0024363 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; use PHPUnit\Runner\Version; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class UpdateSchemaLocation implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); $root->setAttributeNS( 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation', 'https://schema.phpunit.de/' . Version::series() . '/phpunit.xsd', ); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RenameForceCoversAnnotationAttribute.php 0000644 00000002170 15253321353 0027622 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RenameForceCoversAnnotationAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('requireCoverageMetadata')) { return; } if (!$root->hasAttribute('forceCoversAnnotation')) { return; } $root->setAttribute('requireCoverageMetadata', $root->getAttribute('forceCoversAnnotation')); $root->removeAttribute('forceCoversAnnotation'); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveListeners.php 0000644 00000001573 15253321353 0023467 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveListeners implements Migration { public function migrate(DOMDocument $document): void { $node = $document->getElementsByTagName('listeners')->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } $node->parentNode->removeChild($node); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheResultFileAttribute.php 0000644 00000001621 15253321353 0026377 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveCacheResultFileAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('cacheResultFile')) { $root->removeAttribute('cacheResultFile'); } } } src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromFilterWhitelistToCoverage.php 0000644 00000003012 15253321353 0031073 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MoveAttributesFromFilterWhitelistToCoverage implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $whitelist = $document->getElementsByTagName('whitelist')->item(0); if (!$whitelist) { return; } $coverage = $document->getElementsByTagName('coverage')->item(0); if (!$coverage instanceof DOMElement) { throw new MigrationException('Unexpected state - No coverage element'); } $map = [ 'addUncoveredFilesFromWhitelist' => 'includeUncoveredFiles', 'processUncoveredFilesFromWhitelist' => 'processUncoveredFiles', ]; foreach ($map as $old => $new) { if (!$whitelist->hasAttribute($old)) { continue; } $coverage->setAttribute($new, $whitelist->getAttribute($old)); $whitelist->removeAttribute($old); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/LogToReportMigration.php 0000644 00000004677 15253321353 0024443 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use function sprintf; use DOMDocument; use DOMElement; use DOMXPath; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class LogToReportMigration implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $coverage = $document->getElementsByTagName('coverage')->item(0); if (!$coverage instanceof DOMElement) { throw new MigrationException('Unexpected state - No coverage element'); } $logNode = $this->findLogNode($document); if ($logNode === null) { return; } $reportChild = $this->toReportFormat($logNode); $report = $coverage->getElementsByTagName('report')->item(0); if ($report === null) { $report = $coverage->appendChild($document->createElement('report')); } $report->appendChild($reportChild); $logNode->parentNode->removeChild($logNode); } /** * @param list<non-empty-string> $attributes */ protected function migrateAttributes(DOMElement $src, DOMElement $dest, array $attributes): void { foreach ($attributes as $attr) { if (!$src->hasAttribute($attr)) { continue; } $dest->setAttribute($attr, $src->getAttribute($attr)); $src->removeAttribute($attr); } } abstract protected function forType(): string; abstract protected function toReportFormat(DOMElement $logNode): DOMElement; private function findLogNode(DOMDocument $document): ?DOMElement { $xpath = new DOMXPath($document); $logNode = $xpath->query( sprintf( '//logging/log[@type="%s"]', $this->forType(), ), ); assert($logNode !== false); $logNode = $logNode->item(0); if (!$logNode instanceof DOMElement) { return null; } return $logNode; } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveCoverageDirectoriesToSource.php 0000644 00000003330 15253321353 0026575 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; use DOMXPath; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MoveCoverageDirectoriesToSource implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $source = $document->getElementsByTagName('source')->item(0); if ($source !== null) { return; } $coverage = $document->getElementsByTagName('coverage')->item(0); if ($coverage === null) { return; } $root = $document->documentElement; assert($root instanceof DOMElement); $source = $document->createElement('source'); $root->appendChild($source); $xpath = new DOMXPath($document); foreach (['include', 'exclude'] as $element) { $nodes = $xpath->query('//coverage/' . $element); assert($nodes !== false); foreach (SnapshotNodeList::fromNodeList($nodes) as $node) { $source->appendChild($node); } } if ($coverage->childElementCount !== 0) { return; } assert($coverage->parentNode !== null); $coverage->parentNode->removeChild($coverage); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageCrap4jToReport.php 0000644 00000001760 15253321353 0024635 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoverageCrap4jToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-crap4j'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $crap4j = $logNode->ownerDocument->createElement('crap4j'); $crap4j->setAttribute('outputFile', $logNode->getAttribute('target')); $this->migrateAttributes($logNode, $crap4j, ['threshold']); return $crap4j; } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoverageHtmlToReport.php 0000644 00000001775 15253321353 0024424 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoverageHtmlToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-html'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $html = $logNode->ownerDocument->createElement('html'); $html->setAttribute('outputDirectory', $logNode->getAttribute('target')); $this->migrateAttributes($logNode, $html, ['lowUpperBound', 'highLowerBound']); return $html; } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemovePrinterAttributes.php 0000644 00000001764 15253321353 0025213 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemovePrinterAttributes implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('printerClass')) { $root->removeAttribute('printerClass'); } if ($root->hasAttribute('printerFile')) { $root->removeAttribute('printerFile'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/MoveAttributesFromRootToCoverage.php 0000644 00000002757 15253321353 0026772 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class MoveAttributesFromRootToCoverage implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $map = [ 'disableCodeCoverageIgnore' => 'disableCodeCoverageIgnore', 'ignoreDeprecatedCodeUnitsFromCodeCoverage' => 'ignoreDeprecatedCodeUnits', ]; $root = $document->documentElement; assert($root instanceof DOMElement); $coverage = $document->getElementsByTagName('coverage')->item(0); if (!$coverage instanceof DOMElement) { throw new MigrationException('Unexpected state - No coverage element'); } foreach ($map as $old => $new) { if (!$root->hasAttribute($old)) { continue; } $coverage->setAttribute($new, $root->getAttribute($old)); $root->removeAttribute($old); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveEmptyFilter.php 0000644 00000003217 15253321353 0023760 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function sprintf; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveEmptyFilter implements Migration { /** * @throws MigrationException */ public function migrate(DOMDocument $document): void { $whitelist = $document->getElementsByTagName('whitelist')->item(0); if ($whitelist instanceof DOMElement) { $this->ensureEmpty($whitelist); $whitelist->parentNode->removeChild($whitelist); } $filter = $document->getElementsByTagName('filter')->item(0); if ($filter instanceof DOMElement) { $this->ensureEmpty($filter); $filter->parentNode->removeChild($filter); } } /** * @throws MigrationException */ private function ensureEmpty(DOMElement $element): void { if ($element->attributes->length > 0) { throw new MigrationException(sprintf('%s element has unexpected attributes', $element->nodeName)); } if ($element->getElementsByTagName('*')->length > 0) { throw new MigrationException(sprintf('%s element has unexpected children', $element->nodeName)); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveCacheTokensAttribute.php 0000644 00000001605 15253321353 0025566 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveCacheTokensAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('cacheTokens')) { $root->removeAttribute('cacheTokens'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveLogTypes.php 0000644 00000002235 15253321353 0023261 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveLogTypes implements Migration { public function migrate(DOMDocument $document): void { $logging = $document->getElementsByTagName('logging')->item(0); if (!$logging instanceof DOMElement) { return; } foreach (SnapshotNodeList::fromNodeList($logging->getElementsByTagName('log')) as $logNode) { assert($logNode instanceof DOMElement); switch ($logNode->getAttribute('type')) { case 'json': case 'tap': $logging->removeChild($logNode); } } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCoverageElement.php 0000644 00000001527 15253321353 0025262 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class IntroduceCoverageElement implements Migration { public function migrate(DOMDocument $document): void { $coverage = $document->createElement('coverage'); $document->documentElement->insertBefore( $coverage, $document->documentElement->firstChild, ); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/CoveragePhpToReport.php 0000644 00000001631 15253321353 0024236 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class CoveragePhpToReport extends LogToReportMigration { protected function forType(): string { return 'coverage-php'; } protected function toReportFormat(DOMElement $logNode): DOMElement { $php = $logNode->ownerDocument->createElement('php'); $php->setAttribute('outputFile', $logNode->getAttribute('target')); return $php; } } Configuration/Xml/Migration/Migrations/RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute.php0000644 00000001742 15253321353 0033716 0 ustar 00 phpunit/src/TextUI <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveBeStrictAboutResourceUsageDuringSmallTestsAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('beStrictAboutResourceUsageDuringSmallTests')) { $root->removeAttribute('beStrictAboutResourceUsageDuringSmallTests'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/RemoveTestDoxGroupsElement.php 0000644 00000001612 15253321353 0025615 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveTestDoxGroupsElement implements Migration { public function migrate(DOMDocument $document): void { $node = $document->getElementsByTagName('testdoxGroups')->item(0); if (!$node instanceof DOMElement || $node->parentNode === null) { return; } $node->parentNode->removeChild($node); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/ConvertLogTypes.php 0000644 00000003151 15253321353 0023442 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ConvertLogTypes implements Migration { public function migrate(DOMDocument $document): void { $logging = $document->getElementsByTagName('logging')->item(0); if (!$logging instanceof DOMElement) { return; } $types = [ 'junit' => 'junit', 'teamcity' => 'teamcity', 'testdox-html' => 'testdoxHtml', 'testdox-text' => 'testdoxText', 'testdox-xml' => 'testdoxXml', 'plain' => 'text', ]; $logNodes = []; foreach ($logging->getElementsByTagName('log') as $logNode) { if (!isset($types[$logNode->getAttribute('type')])) { continue; } $logNodes[] = $logNode; } foreach ($logNodes as $oldNode) { $newLogNode = $document->createElement($types[$oldNode->getAttribute('type')]); $newLogNode->setAttribute('outputFile', $oldNode->getAttribute('target')); $logging->replaceChild($newLogNode, $oldNode); } } } src/TextUI/Configuration/Xml/Migration/Migrations/RenameBeStrictAboutCoversAnnotationAttribute.php 0000644 00000002244 15253321353 0031221 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RenameBeStrictAboutCoversAnnotationAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('beStrictAboutCoverageMetadata')) { return; } if (!$root->hasAttribute('beStrictAboutCoversAnnotation')) { return; } $root->setAttribute('beStrictAboutCoverageMetadata', $root->getAttribute('beStrictAboutCoversAnnotation')); $root->removeAttribute('beStrictAboutCoversAnnotation'); } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrations/IntroduceCacheDirectoryAttribute.php 0000644 00000001661 15253321353 0026770 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class IntroduceCacheDirectoryAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('cacheDirectory')) { return; } $root->setAttribute('cacheDirectory', '.phpunit.cache'); } } Xml/Migration/Migrations/RemoveRegisterMockObjectsFromTestArgumentsRecursivelyAttribute.php 0000644 00000001761 15253321353 0035042 0 ustar 00 phpunit/src/TextUI/Configuration <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use DOMDocument; use DOMElement; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class RemoveRegisterMockObjectsFromTestArgumentsRecursivelyAttribute implements Migration { public function migrate(DOMDocument $document): void { $root = $document->documentElement; assert($root instanceof DOMElement); if ($root->hasAttribute('registerMockObjectsFromTestArgumentsRecursively')) { $root->removeAttribute('registerMockObjectsFromTestArgumentsRecursively'); } } } phpunit/src/TextUI/Configuration/Xml/Migration/Migrator.php 0000644 00000003171 15253321353 0020005 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use PHPUnit\Runner\Version; use PHPUnit\Util\Xml\Loader as XmlLoader; use PHPUnit\Util\Xml\XmlException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Migrator { /** * @throws Exception * @throws MigrationBuilderException * @throws MigrationException * @throws XmlException */ public function migrate(string $filename): string { $origin = (new SchemaDetector)->detect($filename); if (!$origin->detected()) { throw new Exception('The file does not validate against any know schema'); } if ($origin->version() === Version::series()) { throw new Exception('The file does not need to be migrated'); } $configurationDocument = (new XmlLoader)->loadFile($filename); foreach ((new MigrationBuilder)->build($origin->version()) as $migration) { $migration->migrate($configurationDocument); } $configurationDocument->formatOutput = true; $configurationDocument->preserveWhiteSpace = false; $xml = $configurationDocument->saveXML(); assert($xml !== false); return $xml; } } phpunit/src/TextUI/Configuration/Xml/Migration/SnapshotNodeList.php 0000644 00000002500 15253321353 0021455 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function count; use ArrayIterator; use Countable; use DOMNode; use DOMNodeList; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @template-implements IteratorAggregate<int, DOMNode> */ final class SnapshotNodeList implements Countable, IteratorAggregate { /** * @var list<DOMNode> */ private array $nodes = []; /** * @param DOMNodeList<DOMNode> $list */ public static function fromNodeList(DOMNodeList $list): self { $snapshot = new self; foreach ($list as $node) { $snapshot->nodes[] = $node; } return $snapshot; } public function count(): int { return count($this->nodes); } /** * @return ArrayIterator<int, DOMNode> */ public function getIterator(): ArrayIterator { return new ArrayIterator($this->nodes); } } phpunit/src/TextUI/Configuration/Xml/Migration/MigrationBuilderException.php 0000644 00000001174 15253321353 0023341 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class MigrationBuilderException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Xml/Exception.php 0000644 00000001136 15253321353 0016225 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Exception extends RuntimeException implements \PHPUnit\Exception { } phpunit/src/TextUI/Configuration/Xml/Loader.php 0000644 00000117222 15253321353 0015501 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use const DIRECTORY_SEPARATOR; use const PHP_VERSION; use function assert; use function defined; use function dirname; use function explode; use function is_numeric; use function preg_match; use function realpath; use function str_contains; use function str_starts_with; use function strlen; use function strtolower; use function substr; use function trim; use DOMDocument; use DOMElement; use DOMNode; use DOMNodeList; use DOMXPath; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\Runner\Version; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Configuration\Constant; use PHPUnit\TextUI\Configuration\ConstantCollection; use PHPUnit\TextUI\Configuration\Directory; use PHPUnit\TextUI\Configuration\DirectoryCollection; use PHPUnit\TextUI\Configuration\ExtensionBootstrap; use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; use PHPUnit\TextUI\Configuration\File; use PHPUnit\TextUI\Configuration\FileCollection; use PHPUnit\TextUI\Configuration\FilterDirectory; use PHPUnit\TextUI\Configuration\FilterDirectoryCollection; use PHPUnit\TextUI\Configuration\Group; use PHPUnit\TextUI\Configuration\GroupCollection; use PHPUnit\TextUI\Configuration\IniSetting; use PHPUnit\TextUI\Configuration\IniSettingCollection; use PHPUnit\TextUI\Configuration\Php; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\TestDirectory; use PHPUnit\TextUI\Configuration\TestDirectoryCollection; use PHPUnit\TextUI\Configuration\TestFile; use PHPUnit\TextUI\Configuration\TestFileCollection; use PHPUnit\TextUI\Configuration\TestSuite as TestSuiteConfiguration; use PHPUnit\TextUI\Configuration\TestSuiteCollection; use PHPUnit\TextUI\Configuration\Variable; use PHPUnit\TextUI\Configuration\VariableCollection; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html as CodeCoverageHtml; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php as CodeCoveragePhp; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text as CodeCoverageText; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml as CodeCoverageXml; use PHPUnit\TextUI\XmlConfiguration\Logging\Junit; use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; use PHPUnit\TextUI\XmlConfiguration\Logging\TeamCity; use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; use PHPUnit\Util\VersionComparisonOperator; use PHPUnit\Util\Xml\Loader as XmlLoader; use PHPUnit\Util\Xml\XmlException; use SebastianBergmann\CodeCoverage\Report\Html\Colors; use SebastianBergmann\CodeCoverage\Report\Thresholds; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Loader { /** * @throws Exception */ public function load(string $filename): LoadedFromFileConfiguration { try { $document = (new XmlLoader)->loadFile($filename); } catch (XmlException $e) { throw new Exception( $e->getMessage(), $e->getCode(), $e, ); } $xpath = new DOMXPath($document); try { $xsdFilename = (new SchemaFinder)->find(Version::series()); } catch (CannotFindSchemaException $e) { throw new Exception( $e->getMessage(), $e->getCode(), $e, ); } $configurationFileRealpath = realpath($filename); assert($configurationFileRealpath !== false && $configurationFileRealpath !== ''); return new LoadedFromFileConfiguration( $configurationFileRealpath, (new Validator)->validate($document, $xsdFilename), $this->extensions($xpath), $this->source($configurationFileRealpath, $xpath), $this->codeCoverage($configurationFileRealpath, $xpath), $this->groups($xpath), $this->logging($configurationFileRealpath, $xpath), $this->php($configurationFileRealpath, $xpath), $this->phpunit($configurationFileRealpath, $document), $this->testSuite($configurationFileRealpath, $xpath), ); } private function logging(string $filename, DOMXPath $xpath): Logging { $junit = null; $element = $this->element($xpath, 'logging/junit'); if ($element) { $junit = new Junit( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $teamCity = null; $element = $this->element($xpath, 'logging/teamcity'); if ($element) { $teamCity = new TeamCity( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $testDoxHtml = null; $element = $this->element($xpath, 'logging/testdoxHtml'); if ($element) { $testDoxHtml = new TestDoxHtml( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $testDoxText = null; $element = $this->element($xpath, 'logging/testdoxText'); if ($element) { $testDoxText = new TestDoxText( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } return new Logging( $junit, $teamCity, $testDoxHtml, $testDoxText, ); } private function extensions(DOMXPath $xpath): ExtensionBootstrapCollection { $extensionBootstrappers = []; $bootstrapNodes = $xpath->query('extensions/bootstrap'); assert($bootstrapNodes instanceof DOMNodeList); foreach ($bootstrapNodes as $bootstrap) { assert($bootstrap instanceof DOMElement); $parameters = []; $parameterNodes = $xpath->query('parameter', $bootstrap); assert($parameterNodes instanceof DOMNodeList); foreach ($parameterNodes as $parameter) { assert($parameter instanceof DOMElement); $parameters[$parameter->getAttribute('name')] = $parameter->getAttribute('value'); } $className = $bootstrap->getAttribute('class'); assert($className !== ''); $extensionBootstrappers[] = new ExtensionBootstrap( $className, $parameters, ); } return ExtensionBootstrapCollection::fromArray($extensionBootstrappers); } /** * @return non-empty-string */ private function toAbsolutePath(string $filename, string $path): string { $path = trim($path); if (str_starts_with($path, '/')) { return $path; } // Matches the following on Windows: // - \\NetworkComputer\Path // - \\.\D: // - \\.\c: // - C:\Windows // - C:\windows // - C:/windows // - c:/windows if (defined('PHP_WINDOWS_VERSION_BUILD') && !empty($path) && ($path[0] === '\\' || (strlen($path) >= 3 && preg_match('#^[A-Z]:[/\\\]#i', substr($path, 0, 3))))) { return $path; } if (str_contains($path, '://')) { return $path; } return dirname($filename) . DIRECTORY_SEPARATOR . $path; } private function source(string $filename, DOMXPath $xpath): Source { $baseline = null; $restrictDeprecations = false; $restrictNotices = false; $restrictWarnings = false; $ignoreSuppressionOfDeprecations = false; $ignoreSuppressionOfPhpDeprecations = false; $ignoreSuppressionOfErrors = false; $ignoreSuppressionOfNotices = false; $ignoreSuppressionOfPhpNotices = false; $ignoreSuppressionOfWarnings = false; $ignoreSuppressionOfPhpWarnings = false; $ignoreSelfDeprecations = false; $ignoreDirectDeprecations = false; $ignoreIndirectDeprecations = false; $element = $this->element($xpath, 'source'); if ($element) { $baseline = $this->getStringAttribute($element, 'baseline'); if ($baseline !== null) { $baseline = $this->toAbsolutePath($filename, $baseline); } $restrictDeprecations = $this->getBooleanAttribute($element, 'restrictDeprecations', false); $restrictNotices = $this->getBooleanAttribute($element, 'restrictNotices', false); $restrictWarnings = $this->getBooleanAttribute($element, 'restrictWarnings', false); $ignoreSuppressionOfDeprecations = $this->getBooleanAttribute($element, 'ignoreSuppressionOfDeprecations', false); $ignoreSuppressionOfPhpDeprecations = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpDeprecations', false); $ignoreSuppressionOfErrors = $this->getBooleanAttribute($element, 'ignoreSuppressionOfErrors', false); $ignoreSuppressionOfNotices = $this->getBooleanAttribute($element, 'ignoreSuppressionOfNotices', false); $ignoreSuppressionOfPhpNotices = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpNotices', false); $ignoreSuppressionOfWarnings = $this->getBooleanAttribute($element, 'ignoreSuppressionOfWarnings', false); $ignoreSuppressionOfPhpWarnings = $this->getBooleanAttribute($element, 'ignoreSuppressionOfPhpWarnings', false); $ignoreSelfDeprecations = $this->getBooleanAttribute($element, 'ignoreSelfDeprecations', false); $ignoreDirectDeprecations = $this->getBooleanAttribute($element, 'ignoreDirectDeprecations', false); $ignoreIndirectDeprecations = $this->getBooleanAttribute($element, 'ignoreIndirectDeprecations', false); } $deprecationTriggers = [ 'functions' => [], 'methods' => [], ]; $functionNodes = $xpath->query('source/deprecationTrigger/function'); assert($functionNodes instanceof DOMNodeList); foreach ($functionNodes as $functionNode) { assert($functionNode instanceof DOMElement); $deprecationTriggers['functions'][] = $functionNode->textContent; } $methodNodes = $xpath->query('source/deprecationTrigger/method'); assert($methodNodes instanceof DOMNodeList); foreach ($methodNodes as $methodNode) { assert($methodNode instanceof DOMElement); $deprecationTriggers['methods'][] = $methodNode->textContent; } return new Source( $baseline, false, $this->readFilterDirectories($filename, $xpath, 'source/include/directory'), $this->readFilterFiles($filename, $xpath, 'source/include/file'), $this->readFilterDirectories($filename, $xpath, 'source/exclude/directory'), $this->readFilterFiles($filename, $xpath, 'source/exclude/file'), $restrictDeprecations, $restrictNotices, $restrictWarnings, $ignoreSuppressionOfDeprecations, $ignoreSuppressionOfPhpDeprecations, $ignoreSuppressionOfErrors, $ignoreSuppressionOfNotices, $ignoreSuppressionOfPhpNotices, $ignoreSuppressionOfWarnings, $ignoreSuppressionOfPhpWarnings, $deprecationTriggers, $ignoreSelfDeprecations, $ignoreDirectDeprecations, $ignoreIndirectDeprecations, ); } private function codeCoverage(string $filename, DOMXPath $xpath): CodeCoverage { $pathCoverage = false; $includeUncoveredFiles = true; $ignoreDeprecatedCodeUnits = false; $disableCodeCoverageIgnore = false; $element = $this->element($xpath, 'coverage'); if ($element) { $pathCoverage = $this->getBooleanAttribute( $element, 'pathCoverage', false, ); $includeUncoveredFiles = $this->getBooleanAttribute( $element, 'includeUncoveredFiles', true, ); $ignoreDeprecatedCodeUnits = $this->getBooleanAttribute( $element, 'ignoreDeprecatedCodeUnits', false, ); $disableCodeCoverageIgnore = $this->getBooleanAttribute( $element, 'disableCodeCoverageIgnore', false, ); } $clover = null; $element = $this->element($xpath, 'coverage/report/clover'); if ($element) { $clover = new Clover( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $cobertura = null; $element = $this->element($xpath, 'coverage/report/cobertura'); if ($element) { $cobertura = new Cobertura( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $crap4j = null; $element = $this->element($xpath, 'coverage/report/crap4j'); if ($element) { $crap4j = new Crap4j( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), $this->getIntegerAttribute($element, 'threshold', 30), ); } $html = null; $element = $this->element($xpath, 'coverage/report/html'); if ($element) { $defaultColors = Colors::default(); $defaultThresholds = Thresholds::default(); $html = new CodeCoverageHtml( new Directory( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputDirectory'), ), ), $this->getIntegerAttribute($element, 'lowUpperBound', $defaultThresholds->lowUpperBound()), $this->getIntegerAttribute($element, 'highLowerBound', $defaultThresholds->highLowerBound()), $this->getStringAttributeWithDefault($element, 'colorSuccessLow', $defaultColors->successLow()), $this->getStringAttributeWithDefault($element, 'colorSuccessMedium', $defaultColors->successMedium()), $this->getStringAttributeWithDefault($element, 'colorSuccessHigh', $defaultColors->successHigh()), $this->getStringAttributeWithDefault($element, 'colorWarning', $defaultColors->warning()), $this->getStringAttributeWithDefault($element, 'colorDanger', $defaultColors->danger()), $this->getStringAttribute($element, 'customCssFile'), ); } $php = null; $element = $this->element($xpath, 'coverage/report/php'); if ($element) { $php = new CodeCoveragePhp( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), ); } $text = null; $element = $this->element($xpath, 'coverage/report/text'); if ($element) { $text = new CodeCoverageText( new File( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputFile'), ), ), $this->getBooleanAttribute($element, 'showUncoveredFiles', false), $this->getBooleanAttribute($element, 'showOnlySummary', false), ); } $xml = null; $element = $this->element($xpath, 'coverage/report/xml'); if ($element) { $xml = new CodeCoverageXml( new Directory( $this->toAbsolutePath( $filename, (string) $this->getStringAttribute($element, 'outputDirectory'), ), ), ); } return new CodeCoverage( $pathCoverage, $includeUncoveredFiles, $ignoreDeprecatedCodeUnits, $disableCodeCoverageIgnore, $clover, $cobertura, $crap4j, $html, $php, $text, $xml, ); } private function getBoolean(string $value, bool $default): bool { if (strtolower($value) === 'false') { return false; } if (strtolower($value) === 'true') { return true; } return $default; } private function getValue(string $value): bool|string { if (strtolower($value) === 'false') { return false; } if (strtolower($value) === 'true') { return true; } return $value; } private function readFilterDirectories(string $filename, DOMXPath $xpath, string $query): FilterDirectoryCollection { $directories = []; $directoryNodes = $xpath->query($query); assert($directoryNodes instanceof DOMNodeList); foreach ($directoryNodes as $directoryNode) { assert($directoryNode instanceof DOMElement); $directoryPath = $directoryNode->textContent; if (!$directoryPath) { continue; } $directories[] = new FilterDirectory( $this->toAbsolutePath($filename, $directoryPath), $directoryNode->hasAttribute('prefix') ? $directoryNode->getAttribute('prefix') : '', $directoryNode->hasAttribute('suffix') ? $directoryNode->getAttribute('suffix') : '.php', ); } return FilterDirectoryCollection::fromArray($directories); } private function readFilterFiles(string $filename, DOMXPath $xpath, string $query): FileCollection { $files = []; $fileNodes = $xpath->query($query); assert($fileNodes instanceof DOMNodeList); foreach ($fileNodes as $fileNode) { assert($fileNode instanceof DOMNode); $filePath = $fileNode->textContent; if ($filePath) { $files[] = new File($this->toAbsolutePath($filename, $filePath)); } } return FileCollection::fromArray($files); } private function groups(DOMXPath $xpath): Groups { $include = []; $exclude = []; $groupNodes = $xpath->query('groups/include/group'); assert($groupNodes instanceof DOMNodeList); foreach ($groupNodes as $groupNode) { assert($groupNode instanceof DOMNode); $include[] = new Group($groupNode->textContent); } $groupNodes = $xpath->query('groups/exclude/group'); assert($groupNodes instanceof DOMNodeList); foreach ($groupNodes as $groupNode) { assert($groupNode instanceof DOMNode); $exclude[] = new Group($groupNode->textContent); } return new Groups( GroupCollection::fromArray($include), GroupCollection::fromArray($exclude), ); } private function getBooleanAttribute(DOMElement $element, string $attribute, bool $default): bool { if (!$element->hasAttribute($attribute)) { return $default; } return $this->getBoolean( $element->getAttribute($attribute), false, ); } private function getIntegerAttribute(DOMElement $element, string $attribute, int $default): int { if (!$element->hasAttribute($attribute)) { return $default; } return $this->getInteger( $element->getAttribute($attribute), $default, ); } private function getStringAttribute(DOMElement $element, string $attribute): ?string { if (!$element->hasAttribute($attribute)) { return null; } return $element->getAttribute($attribute); } private function getStringAttributeWithDefault(DOMElement $element, string $attribute, string $default): string { if (!$element->hasAttribute($attribute)) { return $default; } return $element->getAttribute($attribute); } private function getInteger(string $value, int $default): int { if (is_numeric($value)) { return (int) $value; } return $default; } private function php(string $filename, DOMXPath $xpath): Php { $includePaths = []; $includePathNodes = $xpath->query('php/includePath'); assert($includePathNodes instanceof DOMNodeList); foreach ($includePathNodes as $includePath) { assert($includePath instanceof DOMNode); $path = $includePath->textContent; if ($path) { $includePaths[] = new Directory($this->toAbsolutePath($filename, $path)); } } $iniSettings = []; $iniNodes = $xpath->query('php/ini'); assert($iniNodes instanceof DOMNodeList); foreach ($iniNodes as $ini) { assert($ini instanceof DOMElement); $iniSettings[] = new IniSetting( $ini->getAttribute('name'), $ini->getAttribute('value'), ); } $constants = []; $constNodes = $xpath->query('php/const'); assert($constNodes instanceof DOMNodeList); foreach ($constNodes as $constNode) { assert($constNode instanceof DOMElement); $value = $constNode->getAttribute('value'); $constants[] = new Constant( $constNode->getAttribute('name'), $this->getValue($value), ); } $variables = [ 'var' => [], 'env' => [], 'post' => [], 'get' => [], 'cookie' => [], 'server' => [], 'files' => [], 'request' => [], ]; foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) { $varNodes = $xpath->query('php/' . $array); assert($varNodes instanceof DOMNodeList); foreach ($varNodes as $var) { assert($var instanceof DOMElement); $name = $var->getAttribute('name'); $value = $var->getAttribute('value'); $force = false; $verbatim = false; if ($var->hasAttribute('force')) { $force = $this->getBoolean($var->getAttribute('force'), false); } if ($var->hasAttribute('verbatim')) { $verbatim = $this->getBoolean($var->getAttribute('verbatim'), false); } if (!$verbatim) { $value = $this->getValue($value); } $variables[$array][] = new Variable($name, $value, $force); } } return new Php( DirectoryCollection::fromArray($includePaths), IniSettingCollection::fromArray($iniSettings), ConstantCollection::fromArray($constants), VariableCollection::fromArray($variables['var']), VariableCollection::fromArray($variables['env']), VariableCollection::fromArray($variables['post']), VariableCollection::fromArray($variables['get']), VariableCollection::fromArray($variables['cookie']), VariableCollection::fromArray($variables['server']), VariableCollection::fromArray($variables['files']), VariableCollection::fromArray($variables['request']), ); } private function phpunit(string $filename, DOMDocument $document): PHPUnit { $executionOrder = TestSuiteSorter::ORDER_DEFAULT; $defectsFirst = false; $resolveDependencies = $this->getBooleanAttribute($document->documentElement, 'resolveDependencies', true); if ($document->documentElement->hasAttribute('executionOrder')) { foreach (explode(',', $document->documentElement->getAttribute('executionOrder')) as $order) { switch ($order) { case 'default': $executionOrder = TestSuiteSorter::ORDER_DEFAULT; $defectsFirst = false; $resolveDependencies = true; break; case 'depends': $resolveDependencies = true; break; case 'no-depends': $resolveDependencies = false; break; case 'defects': $defectsFirst = true; break; case 'duration': $executionOrder = TestSuiteSorter::ORDER_DURATION; break; case 'random': $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; break; case 'reverse': $executionOrder = TestSuiteSorter::ORDER_REVERSED; break; case 'size': $executionOrder = TestSuiteSorter::ORDER_SIZE; break; } } } $cacheDirectory = $this->getStringAttribute($document->documentElement, 'cacheDirectory'); if ($cacheDirectory !== null) { $cacheDirectory = $this->toAbsolutePath($filename, $cacheDirectory); } $bootstrap = $this->getStringAttribute($document->documentElement, 'bootstrap'); if ($bootstrap !== null) { $bootstrap = $this->toAbsolutePath($filename, $bootstrap); } $extensionsDirectory = $this->getStringAttribute($document->documentElement, 'extensionsDirectory'); if ($extensionsDirectory !== null) { $extensionsDirectory = $this->toAbsolutePath($filename, $extensionsDirectory); } $backupStaticProperties = false; if ($document->documentElement->hasAttribute('backupStaticProperties')) { $backupStaticProperties = $this->getBooleanAttribute($document->documentElement, 'backupStaticProperties', false); } $requireCoverageMetadata = false; if ($document->documentElement->hasAttribute('requireCoverageMetadata')) { $requireCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'requireCoverageMetadata', false); } $beStrictAboutCoverageMetadata = false; if ($document->documentElement->hasAttribute('beStrictAboutCoverageMetadata')) { $beStrictAboutCoverageMetadata = $this->getBooleanAttribute($document->documentElement, 'beStrictAboutCoverageMetadata', false); } $shortenArraysForExportThreshold = $this->getIntegerAttribute($document->documentElement, 'shortenArraysForExportThreshold', 0); if ($shortenArraysForExportThreshold < 0) { $shortenArraysForExportThreshold = 0; } return new PHPUnit( $cacheDirectory, $this->getBooleanAttribute($document->documentElement, 'cacheResult', true), $this->getColumns($document), $this->getColors($document), $this->getBooleanAttribute($document->documentElement, 'stderr', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnIncompleteTests', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnSkippedTests', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerDeprecations', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerErrors', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerNotices', false), $this->getBooleanAttribute($document->documentElement, 'displayDetailsOnTestsThatTriggerWarnings', false), $this->getBooleanAttribute($document->documentElement, 'reverseDefectList', false), $requireCoverageMetadata, $bootstrap, $this->getBooleanAttribute($document->documentElement, 'processIsolation', false), $this->getBooleanAttribute($document->documentElement, 'failOnDeprecation', false), $this->getBooleanAttribute($document->documentElement, 'failOnEmptyTestSuite', false), $this->getBooleanAttribute($document->documentElement, 'failOnIncomplete', false), $this->getBooleanAttribute($document->documentElement, 'failOnNotice', false), $this->getBooleanAttribute($document->documentElement, 'failOnRisky', false), $this->getBooleanAttribute($document->documentElement, 'failOnSkipped', false), $this->getBooleanAttribute($document->documentElement, 'failOnWarning', false), $this->getBooleanAttribute($document->documentElement, 'stopOnDefect', false), $this->getBooleanAttribute($document->documentElement, 'stopOnDeprecation', false), $this->getBooleanAttribute($document->documentElement, 'stopOnError', false), $this->getBooleanAttribute($document->documentElement, 'stopOnFailure', false), $this->getBooleanAttribute($document->documentElement, 'stopOnIncomplete', false), $this->getBooleanAttribute($document->documentElement, 'stopOnNotice', false), $this->getBooleanAttribute($document->documentElement, 'stopOnRisky', false), $this->getBooleanAttribute($document->documentElement, 'stopOnSkipped', false), $this->getBooleanAttribute($document->documentElement, 'stopOnWarning', false), $extensionsDirectory, $this->getBooleanAttribute($document->documentElement, 'beStrictAboutChangesToGlobalState', false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutOutputDuringTests', false), $this->getBooleanAttribute($document->documentElement, 'beStrictAboutTestsThatDoNotTestAnything', true), $beStrictAboutCoverageMetadata, $this->getBooleanAttribute($document->documentElement, 'enforceTimeLimit', false), $this->getIntegerAttribute($document->documentElement, 'defaultTimeLimit', 1), $this->getIntegerAttribute($document->documentElement, 'timeoutForSmallTests', 1), $this->getIntegerAttribute($document->documentElement, 'timeoutForMediumTests', 10), $this->getIntegerAttribute($document->documentElement, 'timeoutForLargeTests', 60), $this->getStringAttribute($document->documentElement, 'defaultTestSuite'), $executionOrder, $resolveDependencies, $defectsFirst, $this->getBooleanAttribute($document->documentElement, 'backupGlobals', false), $backupStaticProperties, $this->getBooleanAttribute($document->documentElement, 'testdox', false), $this->getBooleanAttribute($document->documentElement, 'testdoxSummary', false), $this->getBooleanAttribute($document->documentElement, 'controlGarbageCollector', false), $this->getIntegerAttribute($document->documentElement, 'numberOfTestsBeforeGarbageCollection', 100), $shortenArraysForExportThreshold, ); } private function getColors(DOMDocument $document): string { $colors = Configuration::COLOR_DEFAULT; if ($document->documentElement->hasAttribute('colors')) { /* only allow boolean for compatibility with previous versions 'always' only allowed from command line */ if ($this->getBoolean($document->documentElement->getAttribute('colors'), false)) { $colors = Configuration::COLOR_AUTO; } else { $colors = Configuration::COLOR_NEVER; } } return $colors; } private function getColumns(DOMDocument $document): int|string { $columns = 80; if ($document->documentElement->hasAttribute('columns')) { $columns = $document->documentElement->getAttribute('columns'); if ($columns !== 'max') { $columns = $this->getInteger($columns, 80); } } return $columns; } private function testSuite(string $filename, DOMXPath $xpath): TestSuiteCollection { $testSuites = []; foreach ($this->getTestSuiteElements($xpath) as $element) { $exclude = []; foreach ($element->getElementsByTagName('exclude') as $excludeNode) { $excludeFile = $excludeNode->textContent; if ($excludeFile) { $exclude[] = new File($this->toAbsolutePath($filename, $excludeFile)); } } $directories = []; foreach ($element->getElementsByTagName('directory') as $directoryNode) { assert($directoryNode instanceof DOMElement); $directory = $directoryNode->textContent; if (empty($directory)) { continue; } $prefix = ''; if ($directoryNode->hasAttribute('prefix')) { $prefix = $directoryNode->getAttribute('prefix'); } $suffix = 'Test.php'; if ($directoryNode->hasAttribute('suffix')) { $suffix = $directoryNode->getAttribute('suffix'); } $phpVersion = PHP_VERSION; if ($directoryNode->hasAttribute('phpVersion')) { $phpVersion = $directoryNode->getAttribute('phpVersion'); } $phpVersionOperator = new VersionComparisonOperator('>='); if ($directoryNode->hasAttribute('phpVersionOperator')) { $phpVersionOperator = new VersionComparisonOperator($directoryNode->getAttribute('phpVersionOperator')); } $groups = []; if ($directoryNode->hasAttribute('groups')) { foreach (explode(',', $directoryNode->getAttribute('groups')) as $group) { $group = trim($group); if (empty($group)) { continue; } $groups[] = $group; } } $directories[] = new TestDirectory( $this->toAbsolutePath($filename, $directory), $prefix, $suffix, $phpVersion, $phpVersionOperator, $groups, ); } $files = []; foreach ($element->getElementsByTagName('file') as $fileNode) { assert($fileNode instanceof DOMElement); $file = $fileNode->textContent; if (empty($file)) { continue; } $phpVersion = PHP_VERSION; if ($fileNode->hasAttribute('phpVersion')) { $phpVersion = $fileNode->getAttribute('phpVersion'); } $phpVersionOperator = new VersionComparisonOperator('>='); if ($fileNode->hasAttribute('phpVersionOperator')) { $phpVersionOperator = new VersionComparisonOperator($fileNode->getAttribute('phpVersionOperator')); } $groups = []; if ($fileNode->hasAttribute('groups')) { foreach (explode(',', $fileNode->getAttribute('groups')) as $group) { $group = trim($group); if (empty($group)) { continue; } $groups[] = $group; } } $files[] = new TestFile( $this->toAbsolutePath($filename, $file), $phpVersion, $phpVersionOperator, $groups, ); } $name = $element->getAttribute('name'); assert(!empty($name)); $testSuites[] = new TestSuiteConfiguration( $name, TestDirectoryCollection::fromArray($directories), TestFileCollection::fromArray($files), FileCollection::fromArray($exclude), ); } return TestSuiteCollection::fromArray($testSuites); } /** * @return list<DOMElement> */ private function getTestSuiteElements(DOMXPath $xpath): array { $elements = []; $testSuiteNodes = $xpath->query('testsuites/testsuite'); assert($testSuiteNodes instanceof DOMNodeList); if ($testSuiteNodes->length === 0) { $testSuiteNodes = $xpath->query('testsuite'); assert($testSuiteNodes instanceof DOMNodeList); } if ($testSuiteNodes->length === 1) { $element = $testSuiteNodes->item(0); assert($element instanceof DOMElement); $elements[] = $element; } else { foreach ($testSuiteNodes as $testSuiteNode) { assert($testSuiteNode instanceof DOMElement); $elements[] = $testSuiteNode; } } return $elements; } private function element(DOMXPath $xpath, string $element): ?DOMElement { $nodes = $xpath->query($element); assert($nodes instanceof DOMNodeList); if ($nodes->length === 1) { $node = $nodes->item(0); assert($node instanceof DOMElement); return $node; } return null; } } phpunit/src/TextUI/Configuration/Xml/Groups.php 0000644 00000002301 15253321353 0015541 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\TextUI\Configuration\GroupCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Groups { private GroupCollection $include; private GroupCollection $exclude; public function __construct(GroupCollection $include, GroupCollection $exclude) { $this->include = $include; $this->exclude = $exclude; } public function hasInclude(): bool { return !$this->include->isEmpty(); } public function include(): GroupCollection { return $this->include; } public function hasExclude(): bool { return !$this->exclude->isEmpty(); } public function exclude(): GroupCollection { return $this->exclude; } } phpunit/src/TextUI/Configuration/Xml/DefaultConfiguration.php 0000644 00000011263 15253321353 0020405 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\TextUI\Configuration\ConstantCollection; use PHPUnit\TextUI\Configuration\DirectoryCollection; use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; use PHPUnit\TextUI\Configuration\FileCollection; use PHPUnit\TextUI\Configuration\FilterDirectoryCollection as CodeCoverageFilterDirectoryCollection; use PHPUnit\TextUI\Configuration\GroupCollection; use PHPUnit\TextUI\Configuration\IniSettingCollection; use PHPUnit\TextUI\Configuration\Php; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\TestSuiteCollection; use PHPUnit\TextUI\Configuration\VariableCollection; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class DefaultConfiguration extends Configuration { public static function create(): self { return new self( ExtensionBootstrapCollection::fromArray([]), new Source( null, false, CodeCoverageFilterDirectoryCollection::fromArray([]), FileCollection::fromArray([]), CodeCoverageFilterDirectoryCollection::fromArray([]), FileCollection::fromArray([]), false, false, false, false, false, false, false, false, false, false, [ 'functions' => [], 'methods' => [], ], false, false, false, ), new CodeCoverage( false, true, false, false, null, null, null, null, null, null, null, ), new Groups( GroupCollection::fromArray([]), GroupCollection::fromArray([]), ), new Logging( null, null, null, null, ), new Php( DirectoryCollection::fromArray([]), IniSettingCollection::fromArray([]), ConstantCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), VariableCollection::fromArray([]), ), new PHPUnit( null, true, 80, \PHPUnit\TextUI\Configuration\Configuration::COLOR_DEFAULT, false, false, false, false, false, false, false, false, false, null, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, null, false, false, true, false, false, 1, 1, 10, 60, null, TestSuiteSorter::ORDER_DEFAULT, true, false, false, false, false, false, false, 100, 0, ), TestSuiteCollection::fromArray([]), ); } public function isDefault(): bool { return true; } } phpunit/src/TextUI/Configuration/Xml/Configuration.php 0000644 00000005230 15253321353 0017075 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; use PHPUnit\TextUI\Configuration\Php; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\TestSuiteCollection; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ abstract readonly class Configuration { private ExtensionBootstrapCollection $extensions; private Source $source; private CodeCoverage $codeCoverage; private Groups $groups; private Logging $logging; private Php $php; private PHPUnit $phpunit; private TestSuiteCollection $testSuite; public function __construct(ExtensionBootstrapCollection $extensions, Source $source, CodeCoverage $codeCoverage, Groups $groups, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite) { $this->extensions = $extensions; $this->source = $source; $this->codeCoverage = $codeCoverage; $this->groups = $groups; $this->logging = $logging; $this->php = $php; $this->phpunit = $phpunit; $this->testSuite = $testSuite; } public function extensions(): ExtensionBootstrapCollection { return $this->extensions; } public function source(): Source { return $this->source; } public function codeCoverage(): CodeCoverage { return $this->codeCoverage; } public function groups(): Groups { return $this->groups; } public function logging(): Logging { return $this->logging; } public function php(): Php { return $this->php; } public function phpunit(): PHPUnit { return $this->phpunit; } public function testSuite(): TestSuiteCollection { return $this->testSuite; } /** * @phpstan-assert-if-true DefaultConfiguration $this */ public function isDefault(): bool { return false; } /** * @phpstan-assert-if-true LoadedFromFileConfiguration $this */ public function wasLoadedFromFile(): bool { return false; } } phpunit/src/TextUI/Configuration/Xml/Generator.php 0000644 00000004254 15253321353 0016221 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function str_replace; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Generator { /** * @var string */ private const TEMPLATE = <<<'EOT' <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/{phpunit_version}/phpunit.xsd" bootstrap="{bootstrap_script}" cacheDirectory="{cache_directory}" executionOrder="depends,defects" shortenArraysForExportThreshold="10" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="true" beStrictAboutOutputDuringTests="true" failOnRisky="true" failOnWarning="true"> <testsuites> <testsuite name="default"> <directory>{tests_directory}</directory> </testsuite> </testsuites> <source ignoreIndirectDeprecations="true" restrictNotices="true" restrictWarnings="true"> <include> <directory>{src_directory}</directory> </include> </source> </phpunit> EOT; public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory, string $cacheDirectory): string { return str_replace( [ '{phpunit_version}', '{bootstrap_script}', '{tests_directory}', '{src_directory}', '{cache_directory}', ], [ $phpunitVersion, $bootstrapScript, $testsDirectory, $srcDirectory, $cacheDirectory, ], self::TEMPLATE, ); } } phpunit/src/TextUI/Configuration/Xml/SchemaDetector/FailedSchemaDetectionResult.php 0000644 00000001132 15253321353 0024520 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class FailedSchemaDetectionResult extends SchemaDetectionResult { } phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetector.php 0000644 00000002242 15253321353 0022052 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\Util\Xml\Loader; use PHPUnit\Util\Xml\XmlException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class SchemaDetector { /** * @throws XmlException */ public function detect(string $filename): SchemaDetectionResult { $document = (new Loader)->loadFile($filename); $schemaFinder = new SchemaFinder; foreach ($schemaFinder->available() as $candidate) { $schema = (new SchemaFinder)->find($candidate); if (!(new Validator)->validate($document, $schema)->hasValidationErrors()) { return new SuccessfulSchemaDetectionResult($candidate); } } return new FailedSchemaDetectionResult; } } phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SchemaDetectionResult.php 0000644 00000001634 15253321353 0023422 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\Util\Xml\XmlException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ abstract readonly class SchemaDetectionResult { /** * @phpstan-assert-if-true SuccessfulSchemaDetectionResult $this */ public function detected(): bool { return false; } /** * @throws XmlException */ public function version(): string { throw new XmlException('No supported schema was detected'); } } phpunit/src/TextUI/Configuration/Xml/SchemaDetector/SuccessfulSchemaDetectionResult.php 0000644 00000002012 15253321353 0025451 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class SuccessfulSchemaDetectionResult extends SchemaDetectionResult { /** * @var non-empty-string */ private string $version; /** * @param non-empty-string $version */ public function __construct(string $version) { $this->version = $version; } public function detected(): bool { return true; } /** * @return non-empty-string */ public function version(): string { return $this->version; } } phpunit/src/TextUI/Configuration/Xml/TestSuiteMapper.php 0000644 00000013341 15253321353 0017366 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use const PHP_VERSION; use function explode; use function in_array; use function is_dir; use function is_file; use function sprintf; use function str_contains; use function version_compare; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\Exception as FrameworkException; use PHPUnit\Framework\TestSuite as TestSuiteObject; use PHPUnit\TextUI\Configuration\TestSuiteCollection; use PHPUnit\TextUI\RuntimeException; use PHPUnit\TextUI\TestDirectoryNotFoundException; use PHPUnit\TextUI\TestFileNotFoundException; use SebastianBergmann\FileIterator\Facade; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteMapper { /** * @param non-empty-string $xmlConfigurationFile, * * @throws RuntimeException * @throws TestDirectoryNotFoundException * @throws TestFileNotFoundException */ public function map(string $xmlConfigurationFile, TestSuiteCollection $configuredTestSuites, string $namesOfIncludedTestSuites, string $namesOfExcludedTestSuites): TestSuiteObject { try { $namesOfIncludedTestSuitesAsArray = $namesOfIncludedTestSuites ? explode(',', $namesOfIncludedTestSuites) : []; $excludedTestSuitesAsArray = $namesOfExcludedTestSuites ? explode(',', $namesOfExcludedTestSuites) : []; $result = TestSuiteObject::empty($xmlConfigurationFile); $processed = []; foreach ($configuredTestSuites as $configuredTestSuite) { if (!empty($namesOfIncludedTestSuitesAsArray) && !in_array($configuredTestSuite->name(), $namesOfIncludedTestSuitesAsArray, true)) { continue; } if (!empty($excludedTestSuitesAsArray) && in_array($configuredTestSuite->name(), $excludedTestSuitesAsArray, true)) { continue; } $testSuiteName = $configuredTestSuite->name(); $exclude = []; foreach ($configuredTestSuite->exclude()->asArray() as $file) { $exclude[] = $file->path(); } $testSuite = TestSuiteObject::empty($configuredTestSuite->name()); $empty = true; foreach ($configuredTestSuite->directories() as $directory) { if (!str_contains($directory->path(), '*') && !is_dir($directory->path())) { throw new TestDirectoryNotFoundException($directory->path()); } if (!version_compare(PHP_VERSION, $directory->phpVersion(), $directory->phpVersionOperator()->asString())) { continue; } $files = (new Facade)->getFilesAsArray( $directory->path(), $directory->suffix(), $directory->prefix(), $exclude, ); $groups = $directory->groups(); foreach ($files as $file) { if (isset($processed[$file])) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot add file %s to test suite "%s" as it was already added to test suite "%s"', $file, $testSuiteName, $processed[$file], ), ); continue; } $processed[$file] = $testSuiteName; $empty = false; $testSuite->addTestFile($file, $groups); } } foreach ($configuredTestSuite->files() as $file) { if (!is_file($file->path())) { throw new TestFileNotFoundException($file->path()); } if (!version_compare(PHP_VERSION, $file->phpVersion(), $file->phpVersionOperator()->asString())) { continue; } if (isset($processed[$file->path()])) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Cannot add file %s to test suite "%s" as it was already added to test suite "%s"', $file->path(), $testSuiteName, $processed[$file->path()], ), ); continue; } $processed[$file->path()] = $testSuiteName; $empty = false; $testSuite->addTestFile($file->path(), $file->groups()); } if (!$empty) { $result->addTest($testSuite); } } return $result; } catch (FrameworkException $e) { throw new RuntimeException( $e->getMessage(), $e->getCode(), $e, ); } } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Text.php 0000644 00000002340 15253321353 0021012 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Text { private File $target; private bool $showUncoveredFiles; private bool $showOnlySummary; public function __construct(File $target, bool $showUncoveredFiles, bool $showOnlySummary) { $this->target = $target; $this->showUncoveredFiles = $showUncoveredFiles; $this->showOnlySummary = $showOnlySummary; } public function target(): File { return $this->target; } public function showUncoveredFiles(): bool { return $this->showUncoveredFiles; } public function showOnlySummary(): bool { return $this->showOnlySummary; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Cobertura.php 0000644 00000001452 15253321353 0022017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Cobertura { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Crap4j.php 0000644 00000001720 15253321353 0021212 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Crap4j { private File $target; private int $threshold; public function __construct(File $target, int $threshold) { $this->target = $target; $this->threshold = $threshold; } public function target(): File { return $this->target; } public function threshold(): int { return $this->threshold; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Xml.php 0000644 00000001470 15253321353 0020631 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\Directory; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Xml { private Directory $target; public function __construct(Directory $target) { $this->target = $target; } public function target(): Directory { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Clover.php 0000644 00000001447 15253321353 0021327 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Clover { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Php.php 0000644 00000001444 15253321353 0020621 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Php { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/Report/Html.php 0000644 00000005507 15253321353 0021002 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report; use PHPUnit\TextUI\Configuration\Directory; use PHPUnit\TextUI\Configuration\NoCustomCssFileException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Html { private Directory $target; private int $lowUpperBound; private int $highLowerBound; private string $colorSuccessLow; private string $colorSuccessMedium; private string $colorSuccessHigh; private string $colorWarning; private string $colorDanger; private ?string $customCssFile; public function __construct(Directory $target, int $lowUpperBound, int $highLowerBound, string $colorSuccessLow, string $colorSuccessMedium, string $colorSuccessHigh, string $colorWarning, string $colorDanger, ?string $customCssFile) { $this->target = $target; $this->lowUpperBound = $lowUpperBound; $this->highLowerBound = $highLowerBound; $this->colorSuccessLow = $colorSuccessLow; $this->colorSuccessMedium = $colorSuccessMedium; $this->colorSuccessHigh = $colorSuccessHigh; $this->colorWarning = $colorWarning; $this->colorDanger = $colorDanger; $this->customCssFile = $customCssFile; } public function target(): Directory { return $this->target; } public function lowUpperBound(): int { return $this->lowUpperBound; } public function highLowerBound(): int { return $this->highLowerBound; } public function colorSuccessLow(): string { return $this->colorSuccessLow; } public function colorSuccessMedium(): string { return $this->colorSuccessMedium; } public function colorSuccessHigh(): string { return $this->colorSuccessHigh; } public function colorWarning(): string { return $this->colorWarning; } public function colorDanger(): string { return $this->colorDanger; } /** * @phpstan-assert-if-true !null $this->customCssFile */ public function hasCustomCssFile(): bool { return $this->customCssFile !== null; } /** * @throws NoCustomCssFileException */ public function customCssFile(): string { if (!$this->hasCustomCssFile()) { throw new NoCustomCssFileException; } return $this->customCssFile; } } phpunit/src/TextUI/Configuration/Xml/CodeCoverage/CodeCoverage.php 0000644 00000013245 15253321353 0021147 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\CodeCoverage; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Clover; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Cobertura; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Crap4j; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Html; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Php; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Text; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\Report\Xml; use PHPUnit\TextUI\XmlConfiguration\Exception; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class CodeCoverage { private bool $pathCoverage; private bool $includeUncoveredFiles; private bool $ignoreDeprecatedCodeUnits; private bool $disableCodeCoverageIgnore; private ?Clover $clover; private ?Cobertura $cobertura; private ?Crap4j $crap4j; private ?Html $html; private ?Php $php; private ?Text $text; private ?Xml $xml; public function __construct(bool $pathCoverage, bool $includeUncoveredFiles, bool $ignoreDeprecatedCodeUnits, bool $disableCodeCoverageIgnore, ?Clover $clover, ?Cobertura $cobertura, ?Crap4j $crap4j, ?Html $html, ?Php $php, ?Text $text, ?Xml $xml) { $this->pathCoverage = $pathCoverage; $this->includeUncoveredFiles = $includeUncoveredFiles; $this->ignoreDeprecatedCodeUnits = $ignoreDeprecatedCodeUnits; $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; $this->clover = $clover; $this->cobertura = $cobertura; $this->crap4j = $crap4j; $this->html = $html; $this->php = $php; $this->text = $text; $this->xml = $xml; } public function pathCoverage(): bool { return $this->pathCoverage; } public function includeUncoveredFiles(): bool { return $this->includeUncoveredFiles; } public function ignoreDeprecatedCodeUnits(): bool { return $this->ignoreDeprecatedCodeUnits; } public function disableCodeCoverageIgnore(): bool { return $this->disableCodeCoverageIgnore; } /** * @phpstan-assert-if-true !null $this->clover */ public function hasClover(): bool { return $this->clover !== null; } /** * @throws Exception */ public function clover(): Clover { if (!$this->hasClover()) { throw new Exception( 'Code Coverage report "Clover XML" has not been configured', ); } return $this->clover; } /** * @phpstan-assert-if-true !null $this->cobertura */ public function hasCobertura(): bool { return $this->cobertura !== null; } /** * @throws Exception */ public function cobertura(): Cobertura { if (!$this->hasCobertura()) { throw new Exception( 'Code Coverage report "Cobertura XML" has not been configured', ); } return $this->cobertura; } /** * @phpstan-assert-if-true !null $this->crap4j */ public function hasCrap4j(): bool { return $this->crap4j !== null; } /** * @throws Exception */ public function crap4j(): Crap4j { if (!$this->hasCrap4j()) { throw new Exception( 'Code Coverage report "Crap4J" has not been configured', ); } return $this->crap4j; } /** * @phpstan-assert-if-true !null $this->html */ public function hasHtml(): bool { return $this->html !== null; } /** * @throws Exception */ public function html(): Html { if (!$this->hasHtml()) { throw new Exception( 'Code Coverage report "HTML" has not been configured', ); } return $this->html; } /** * @phpstan-assert-if-true !null $this->php */ public function hasPhp(): bool { return $this->php !== null; } /** * @throws Exception */ public function php(): Php { if (!$this->hasPhp()) { throw new Exception( 'Code Coverage report "PHP" has not been configured', ); } return $this->php; } /** * @phpstan-assert-if-true !null $this->text */ public function hasText(): bool { return $this->text !== null; } /** * @throws Exception */ public function text(): Text { if (!$this->hasText()) { throw new Exception( 'Code Coverage report "Text" has not been configured', ); } return $this->text; } /** * @phpstan-assert-if-true !null $this->xml */ public function hasXml(): bool { return $this->xml !== null; } /** * @throws Exception */ public function xml(): Xml { if (!$this->hasXml()) { throw new Exception( 'Code Coverage report "XML" has not been configured', ); } return $this->xml; } } phpunit/src/TextUI/Configuration/Xml/Logging/Logging.php 0000644 00000005042 15253321353 0017243 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\Logging; use PHPUnit\TextUI\XmlConfiguration\Exception; use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Html as TestDoxHtml; use PHPUnit\TextUI\XmlConfiguration\Logging\TestDox\Text as TestDoxText; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Logging { private ?Junit $junit; private ?TeamCity $teamCity; private ?TestDoxHtml $testDoxHtml; private ?TestDoxText $testDoxText; public function __construct(?Junit $junit, ?TeamCity $teamCity, ?TestDoxHtml $testDoxHtml, ?TestDoxText $testDoxText) { $this->junit = $junit; $this->teamCity = $teamCity; $this->testDoxHtml = $testDoxHtml; $this->testDoxText = $testDoxText; } public function hasJunit(): bool { return $this->junit !== null; } /** * @throws Exception */ public function junit(): Junit { if ($this->junit === null) { throw new Exception('Logger "JUnit XML" is not configured'); } return $this->junit; } public function hasTeamCity(): bool { return $this->teamCity !== null; } /** * @throws Exception */ public function teamCity(): TeamCity { if ($this->teamCity === null) { throw new Exception('Logger "Team City" is not configured'); } return $this->teamCity; } public function hasTestDoxHtml(): bool { return $this->testDoxHtml !== null; } /** * @throws Exception */ public function testDoxHtml(): TestDoxHtml { if ($this->testDoxHtml === null) { throw new Exception('Logger "TestDox HTML" is not configured'); } return $this->testDoxHtml; } public function hasTestDoxText(): bool { return $this->testDoxText !== null; } /** * @throws Exception */ public function testDoxText(): TestDoxText { if ($this->testDoxText === null) { throw new Exception('Logger "TestDox Text" is not configured'); } return $this->testDoxText; } } phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Text.php 0000644 00000001441 15253321353 0020172 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Text { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/Logging/TestDox/Html.php 0000644 00000001441 15253321353 0020152 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\Logging\TestDox; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Html { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/Logging/TeamCity.php 0000644 00000001435 15253321353 0017376 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\Logging; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class TeamCity { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/Logging/Junit.php 0000644 00000001432 15253321353 0016745 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration\Logging; use PHPUnit\TextUI\Configuration\File; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Junit { private File $target; public function __construct(File $target) { $this->target = $target; } public function target(): File { return $this->target; } } phpunit/src/TextUI/Configuration/Xml/LoadedFromFileConfiguration.php 0000644 00000004125 15253321353 0021634 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\TextUI\Configuration\ExtensionBootstrapCollection; use PHPUnit\TextUI\Configuration\Php; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\TestSuiteCollection; use PHPUnit\TextUI\XmlConfiguration\CodeCoverage\CodeCoverage; use PHPUnit\TextUI\XmlConfiguration\Logging\Logging; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class LoadedFromFileConfiguration extends Configuration { /** * @var non-empty-string */ private string $filename; private ValidationResult $validationResult; /** * @param non-empty-string $filename */ public function __construct(string $filename, ValidationResult $validationResult, ExtensionBootstrapCollection $extensions, Source $source, CodeCoverage $codeCoverage, Groups $groups, Logging $logging, Php $php, PHPUnit $phpunit, TestSuiteCollection $testSuite) { $this->filename = $filename; $this->validationResult = $validationResult; parent::__construct( $extensions, $source, $codeCoverage, $groups, $logging, $php, $phpunit, $testSuite, ); } /** * @return non-empty-string */ public function filename(): string { return $this->filename; } public function hasValidationErrors(): bool { return $this->validationResult->hasValidationErrors(); } public function validationErrors(): string { return $this->validationResult->asString(); } public function wasLoadedFromFile(): bool { return true; } } phpunit/src/TextUI/Configuration/Xml/PHPUnit.php 0000644 00000036500 15253321353 0015561 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class PHPUnit { private ?string $cacheDirectory; private bool $cacheResult; private int|string $columns; private string $colors; private bool $stderr; private bool $displayDetailsOnIncompleteTests; private bool $displayDetailsOnSkippedTests; private bool $displayDetailsOnTestsThatTriggerDeprecations; private bool $displayDetailsOnTestsThatTriggerErrors; private bool $displayDetailsOnTestsThatTriggerNotices; private bool $displayDetailsOnTestsThatTriggerWarnings; private bool $reverseDefectList; private bool $requireCoverageMetadata; private ?string $bootstrap; private bool $processIsolation; private bool $failOnDeprecation; private bool $failOnEmptyTestSuite; private bool $failOnIncomplete; private bool $failOnNotice; private bool $failOnRisky; private bool $failOnSkipped; private bool $failOnWarning; private bool $stopOnDefect; private bool $stopOnDeprecation; private bool $stopOnError; private bool $stopOnFailure; private bool $stopOnIncomplete; private bool $stopOnNotice; private bool $stopOnRisky; private bool $stopOnSkipped; private bool $stopOnWarning; /** * @var ?non-empty-string */ private ?string $extensionsDirectory; private bool $beStrictAboutChangesToGlobalState; private bool $beStrictAboutOutputDuringTests; private bool $beStrictAboutTestsThatDoNotTestAnything; private bool $beStrictAboutCoverageMetadata; private bool $enforceTimeLimit; private int $defaultTimeLimit; private int $timeoutForSmallTests; private int $timeoutForMediumTests; private int $timeoutForLargeTests; private ?string $defaultTestSuite; private int $executionOrder; private bool $resolveDependencies; private bool $defectsFirst; private bool $backupGlobals; private bool $backupStaticProperties; private bool $testdoxPrinter; private bool $testdoxPrinterSummary; private bool $controlGarbageCollector; private int $numberOfTestsBeforeGarbageCollection; /** * @var non-negative-int */ private int $shortenArraysForExportThreshold; /** * @param ?non-empty-string $extensionsDirectory * @param non-negative-int $shortenArraysForExportThreshold */ public function __construct(?string $cacheDirectory, bool $cacheResult, int|string $columns, string $colors, bool $stderr, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, ?string $bootstrap, bool $processIsolation, bool $failOnDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, ?string $extensionsDirectory, bool $beStrictAboutChangesToGlobalState, bool $beStrictAboutOutputDuringTests, bool $beStrictAboutTestsThatDoNotTestAnything, bool $beStrictAboutCoverageMetadata, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, ?string $defaultTestSuite, int $executionOrder, bool $resolveDependencies, bool $defectsFirst, bool $backupGlobals, bool $backupStaticProperties, bool $testdoxPrinter, bool $testdoxPrinterSummary, bool $controlGarbageCollector, int $numberOfTestsBeforeGarbageCollection, int $shortenArraysForExportThreshold) { $this->cacheDirectory = $cacheDirectory; $this->cacheResult = $cacheResult; $this->columns = $columns; $this->colors = $colors; $this->stderr = $stderr; $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; $this->reverseDefectList = $reverseDefectList; $this->requireCoverageMetadata = $requireCoverageMetadata; $this->bootstrap = $bootstrap; $this->processIsolation = $processIsolation; $this->failOnDeprecation = $failOnDeprecation; $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; $this->failOnIncomplete = $failOnIncomplete; $this->failOnNotice = $failOnNotice; $this->failOnRisky = $failOnRisky; $this->failOnSkipped = $failOnSkipped; $this->failOnWarning = $failOnWarning; $this->stopOnDefect = $stopOnDefect; $this->stopOnDeprecation = $stopOnDeprecation; $this->stopOnError = $stopOnError; $this->stopOnFailure = $stopOnFailure; $this->stopOnIncomplete = $stopOnIncomplete; $this->stopOnNotice = $stopOnNotice; $this->stopOnRisky = $stopOnRisky; $this->stopOnSkipped = $stopOnSkipped; $this->stopOnWarning = $stopOnWarning; $this->extensionsDirectory = $extensionsDirectory; $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; $this->beStrictAboutOutputDuringTests = $beStrictAboutOutputDuringTests; $this->beStrictAboutTestsThatDoNotTestAnything = $beStrictAboutTestsThatDoNotTestAnything; $this->beStrictAboutCoverageMetadata = $beStrictAboutCoverageMetadata; $this->enforceTimeLimit = $enforceTimeLimit; $this->defaultTimeLimit = $defaultTimeLimit; $this->timeoutForSmallTests = $timeoutForSmallTests; $this->timeoutForMediumTests = $timeoutForMediumTests; $this->timeoutForLargeTests = $timeoutForLargeTests; $this->defaultTestSuite = $defaultTestSuite; $this->executionOrder = $executionOrder; $this->resolveDependencies = $resolveDependencies; $this->defectsFirst = $defectsFirst; $this->backupGlobals = $backupGlobals; $this->backupStaticProperties = $backupStaticProperties; $this->testdoxPrinter = $testdoxPrinter; $this->testdoxPrinterSummary = $testdoxPrinterSummary; $this->controlGarbageCollector = $controlGarbageCollector; $this->numberOfTestsBeforeGarbageCollection = $numberOfTestsBeforeGarbageCollection; $this->shortenArraysForExportThreshold = $shortenArraysForExportThreshold; } /** * @phpstan-assert-if-true !null $this->cacheDirectory */ public function hasCacheDirectory(): bool { return $this->cacheDirectory !== null; } /** * @throws Exception */ public function cacheDirectory(): string { if (!$this->hasCacheDirectory()) { throw new Exception('Cache directory is not configured'); } return $this->cacheDirectory; } public function cacheResult(): bool { return $this->cacheResult; } public function columns(): int|string { return $this->columns; } public function colors(): string { return $this->colors; } public function stderr(): bool { return $this->stderr; } public function displayDetailsOnIncompleteTests(): bool { return $this->displayDetailsOnIncompleteTests; } public function displayDetailsOnSkippedTests(): bool { return $this->displayDetailsOnSkippedTests; } public function displayDetailsOnTestsThatTriggerDeprecations(): bool { return $this->displayDetailsOnTestsThatTriggerDeprecations; } public function displayDetailsOnTestsThatTriggerErrors(): bool { return $this->displayDetailsOnTestsThatTriggerErrors; } public function displayDetailsOnTestsThatTriggerNotices(): bool { return $this->displayDetailsOnTestsThatTriggerNotices; } public function displayDetailsOnTestsThatTriggerWarnings(): bool { return $this->displayDetailsOnTestsThatTriggerWarnings; } public function reverseDefectList(): bool { return $this->reverseDefectList; } public function requireCoverageMetadata(): bool { return $this->requireCoverageMetadata; } /** * @phpstan-assert-if-true !null $this->bootstrap */ public function hasBootstrap(): bool { return $this->bootstrap !== null; } /** * @throws Exception */ public function bootstrap(): string { if (!$this->hasBootstrap()) { throw new Exception('Bootstrap script is not configured'); } return $this->bootstrap; } public function processIsolation(): bool { return $this->processIsolation; } public function failOnDeprecation(): bool { return $this->failOnDeprecation; } public function failOnEmptyTestSuite(): bool { return $this->failOnEmptyTestSuite; } public function failOnIncomplete(): bool { return $this->failOnIncomplete; } public function failOnNotice(): bool { return $this->failOnNotice; } public function failOnRisky(): bool { return $this->failOnRisky; } public function failOnSkipped(): bool { return $this->failOnSkipped; } public function failOnWarning(): bool { return $this->failOnWarning; } public function stopOnDefect(): bool { return $this->stopOnDefect; } public function stopOnDeprecation(): bool { return $this->stopOnDeprecation; } public function stopOnError(): bool { return $this->stopOnError; } public function stopOnFailure(): bool { return $this->stopOnFailure; } public function stopOnIncomplete(): bool { return $this->stopOnIncomplete; } public function stopOnNotice(): bool { return $this->stopOnNotice; } public function stopOnRisky(): bool { return $this->stopOnRisky; } public function stopOnSkipped(): bool { return $this->stopOnSkipped; } public function stopOnWarning(): bool { return $this->stopOnWarning; } /** * @phpstan-assert-if-true !null $this->extensionsDirectory */ public function hasExtensionsDirectory(): bool { return $this->extensionsDirectory !== null; } /** * @throws Exception * * @return non-empty-string */ public function extensionsDirectory(): string { if (!$this->hasExtensionsDirectory()) { throw new Exception('Extensions directory is not configured'); } return $this->extensionsDirectory; } public function beStrictAboutChangesToGlobalState(): bool { return $this->beStrictAboutChangesToGlobalState; } public function beStrictAboutOutputDuringTests(): bool { return $this->beStrictAboutOutputDuringTests; } public function beStrictAboutTestsThatDoNotTestAnything(): bool { return $this->beStrictAboutTestsThatDoNotTestAnything; } public function beStrictAboutCoverageMetadata(): bool { return $this->beStrictAboutCoverageMetadata; } public function enforceTimeLimit(): bool { return $this->enforceTimeLimit; } public function defaultTimeLimit(): int { return $this->defaultTimeLimit; } public function timeoutForSmallTests(): int { return $this->timeoutForSmallTests; } public function timeoutForMediumTests(): int { return $this->timeoutForMediumTests; } public function timeoutForLargeTests(): int { return $this->timeoutForLargeTests; } /** * @phpstan-assert-if-true !null $this->defaultTestSuite */ public function hasDefaultTestSuite(): bool { return $this->defaultTestSuite !== null; } /** * @throws Exception */ public function defaultTestSuite(): string { if (!$this->hasDefaultTestSuite()) { throw new Exception('Default test suite is not configured'); } return $this->defaultTestSuite; } public function executionOrder(): int { return $this->executionOrder; } public function resolveDependencies(): bool { return $this->resolveDependencies; } public function defectsFirst(): bool { return $this->defectsFirst; } public function backupGlobals(): bool { return $this->backupGlobals; } public function backupStaticProperties(): bool { return $this->backupStaticProperties; } public function testdoxPrinter(): bool { return $this->testdoxPrinter; } public function testdoxPrinterSummary(): bool { return $this->testdoxPrinterSummary; } public function controlGarbageCollector(): bool { return $this->controlGarbageCollector; } public function numberOfTestsBeforeGarbageCollection(): int { return $this->numberOfTestsBeforeGarbageCollection; } /** * @return non-negative-int */ public function shortenArraysForExportThreshold(): int { return $this->shortenArraysForExportThreshold; } } phpunit/src/TextUI/Configuration/Xml/SchemaFinder.php 0000644 00000003677 15253321353 0016633 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use function assert; use function defined; use function is_file; use function rsort; use function sprintf; use DirectoryIterator; use PHPUnit\Runner\Version; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class SchemaFinder { /** * @return non-empty-list<non-empty-string> */ public function available(): array { $result = [Version::series()]; foreach ((new DirectoryIterator($this->path() . 'schema')) as $file) { if ($file->isDot()) { continue; } $version = $file->getBasename('.xsd'); assert(!empty($version)); $result[] = $version; } rsort($result); return $result; } /** * @throws CannotFindSchemaException */ public function find(string $version): string { if ($version === Version::series()) { $filename = $this->path() . 'phpunit.xsd'; } else { $filename = $this->path() . 'schema/' . $version . '.xsd'; } if (!is_file($filename)) { throw new CannotFindSchemaException( sprintf( 'Schema for PHPUnit %s is not available', $version, ), ); } return $filename; } private function path(): string { if (defined('__PHPUNIT_PHAR_ROOT__')) { return __PHPUNIT_PHAR_ROOT__ . '/'; } return __DIR__ . '/../../../../'; } } phpunit/src/TextUI/Configuration/SourceMapper.php 0000644 00000005054 15253321353 0016137 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function realpath; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; use SplObjectStorage; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SourceMapper { /** * @var ?SplObjectStorage<Source, array<non-empty-string, true>> */ private static ?SplObjectStorage $files = null; /** * @return array<non-empty-string, true> */ public function map(Source $source): array { if (self::$files === null) { /** @phpstan-ignore assign.propertyType */ self::$files = new SplObjectStorage; } if (isset(self::$files[$source])) { return self::$files[$source]; } $files = []; foreach ($source->includeDirectories() as $directory) { foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) { $file = realpath($file); if (!$file) { continue; } $files[$file] = true; } } foreach ($source->includeFiles() as $file) { $file = realpath($file->path()); if (!$file) { continue; } $files[$file] = true; } foreach ($source->excludeDirectories() as $directory) { foreach ((new FileIteratorFacade)->getFilesAsArray($directory->path(), $directory->suffix(), $directory->prefix()) as $file) { $file = realpath($file); if (!$file) { continue; } if (!isset($files[$file])) { continue; } unset($files[$file]); } } foreach ($source->excludeFiles() as $file) { $file = realpath($file->path()); if (!$file) { continue; } if (!isset($files[$file])) { continue; } unset($files[$file]); } self::$files[$source] = $files; return $files; } } phpunit/src/TextUI/Configuration/Builder.php 0000644 00000003364 15253321353 0015122 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use PHPUnit\TextUI\CliArguments\Builder as CliConfigurationBuilder; use PHPUnit\TextUI\CliArguments\Exception as CliConfigurationException; use PHPUnit\TextUI\CliArguments\XmlConfigurationFileFinder; use PHPUnit\TextUI\XmlConfiguration\DefaultConfiguration; use PHPUnit\TextUI\XmlConfiguration\Exception as XmlConfigurationException; use PHPUnit\TextUI\XmlConfiguration\Loader; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @codeCoverageIgnore */ final readonly class Builder { /** * @param list<string> $argv * * @throws ConfigurationCannotBeBuiltException */ public function build(array $argv): Configuration { try { $cliConfiguration = (new CliConfigurationBuilder)->fromParameters($argv); $configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration); $xmlConfiguration = DefaultConfiguration::create(); if ($configurationFile !== false) { $xmlConfiguration = (new Loader)->load($configurationFile); } return Registry::init( $cliConfiguration, $xmlConfiguration, ); } catch (CliConfigurationException|XmlConfigurationException $e) { throw new ConfigurationCannotBeBuiltException( $e->getMessage(), $e->getCode(), $e, ); } } } phpunit/src/TextUI/Configuration/Merger.php 0000644 00000106570 15253321353 0014760 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use const DIRECTORY_SEPARATOR; use const PATH_SEPARATOR; use function array_diff; use function assert; use function dirname; use function explode; use function is_int; use function realpath; use function time; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; use PHPUnit\TextUI\CliArguments\Exception; use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; use PHPUnit\TextUI\XmlConfiguration\LoadedFromFileConfiguration; use PHPUnit\TextUI\XmlConfiguration\SchemaDetector; use PHPUnit\Util\Filesystem; use SebastianBergmann\CodeCoverage\Report\Html\Colors; use SebastianBergmann\CodeCoverage\Report\Thresholds; use SebastianBergmann\Environment\Console; use SebastianBergmann\Invoker\Invoker; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Merger { /** * @throws \PHPUnit\TextUI\XmlConfiguration\Exception * @throws Exception * @throws NoCustomCssFileException */ public function merge(CliConfiguration $cliConfiguration, XmlConfiguration $xmlConfiguration): Configuration { $configurationFile = null; if ($xmlConfiguration->wasLoadedFromFile()) { assert($xmlConfiguration instanceof LoadedFromFileConfiguration); $configurationFile = $xmlConfiguration->filename(); } $bootstrap = null; if ($cliConfiguration->hasBootstrap()) { $bootstrap = $cliConfiguration->bootstrap(); } elseif ($xmlConfiguration->phpunit()->hasBootstrap()) { $bootstrap = $xmlConfiguration->phpunit()->bootstrap(); } if ($cliConfiguration->hasCacheResult()) { $cacheResult = $cliConfiguration->cacheResult(); } else { $cacheResult = $xmlConfiguration->phpunit()->cacheResult(); } $cacheDirectory = null; $coverageCacheDirectory = null; if ($cliConfiguration->hasCacheDirectory() && Filesystem::createDirectory($cliConfiguration->cacheDirectory())) { $cacheDirectory = realpath($cliConfiguration->cacheDirectory()); } elseif ($xmlConfiguration->phpunit()->hasCacheDirectory() && Filesystem::createDirectory($xmlConfiguration->phpunit()->cacheDirectory())) { $cacheDirectory = realpath($xmlConfiguration->phpunit()->cacheDirectory()); } if ($cacheDirectory !== null) { $coverageCacheDirectory = $cacheDirectory . DIRECTORY_SEPARATOR . 'code-coverage'; $testResultCacheFile = $cacheDirectory . DIRECTORY_SEPARATOR . 'test-results'; } if (!isset($testResultCacheFile)) { if ($xmlConfiguration->wasLoadedFromFile()) { $testResultCacheFile = dirname(realpath($xmlConfiguration->filename())) . DIRECTORY_SEPARATOR . '.phpunit.result.cache'; } else { $candidate = realpath($_SERVER['PHP_SELF']); if ($candidate) { $testResultCacheFile = dirname($candidate) . DIRECTORY_SEPARATOR . '.phpunit.result.cache'; } else { $testResultCacheFile = '.phpunit.result.cache'; } } } if ($cliConfiguration->hasDisableCodeCoverageIgnore()) { $disableCodeCoverageIgnore = $cliConfiguration->disableCodeCoverageIgnore(); } else { $disableCodeCoverageIgnore = $xmlConfiguration->codeCoverage()->disableCodeCoverageIgnore(); } if ($cliConfiguration->hasFailOnDeprecation()) { $failOnDeprecation = $cliConfiguration->failOnDeprecation(); } else { $failOnDeprecation = $xmlConfiguration->phpunit()->failOnDeprecation(); } if ($cliConfiguration->hasFailOnEmptyTestSuite()) { $failOnEmptyTestSuite = $cliConfiguration->failOnEmptyTestSuite(); } else { $failOnEmptyTestSuite = $xmlConfiguration->phpunit()->failOnEmptyTestSuite(); } if ($cliConfiguration->hasFailOnIncomplete()) { $failOnIncomplete = $cliConfiguration->failOnIncomplete(); } else { $failOnIncomplete = $xmlConfiguration->phpunit()->failOnIncomplete(); } if ($cliConfiguration->hasFailOnNotice()) { $failOnNotice = $cliConfiguration->failOnNotice(); } else { $failOnNotice = $xmlConfiguration->phpunit()->failOnNotice(); } if ($cliConfiguration->hasFailOnRisky()) { $failOnRisky = $cliConfiguration->failOnRisky(); } else { $failOnRisky = $xmlConfiguration->phpunit()->failOnRisky(); } if ($cliConfiguration->hasFailOnSkipped()) { $failOnSkipped = $cliConfiguration->failOnSkipped(); } else { $failOnSkipped = $xmlConfiguration->phpunit()->failOnSkipped(); } if ($cliConfiguration->hasFailOnWarning()) { $failOnWarning = $cliConfiguration->failOnWarning(); } else { $failOnWarning = $xmlConfiguration->phpunit()->failOnWarning(); } if ($cliConfiguration->hasStopOnDefect()) { $stopOnDefect = $cliConfiguration->stopOnDefect(); } else { $stopOnDefect = $xmlConfiguration->phpunit()->stopOnDefect(); } if ($cliConfiguration->hasStopOnDeprecation()) { $stopOnDeprecation = $cliConfiguration->stopOnDeprecation(); } else { $stopOnDeprecation = $xmlConfiguration->phpunit()->stopOnDeprecation(); } if ($cliConfiguration->hasStopOnError()) { $stopOnError = $cliConfiguration->stopOnError(); } else { $stopOnError = $xmlConfiguration->phpunit()->stopOnError(); } if ($cliConfiguration->hasStopOnFailure()) { $stopOnFailure = $cliConfiguration->stopOnFailure(); } else { $stopOnFailure = $xmlConfiguration->phpunit()->stopOnFailure(); } if ($cliConfiguration->hasStopOnIncomplete()) { $stopOnIncomplete = $cliConfiguration->stopOnIncomplete(); } else { $stopOnIncomplete = $xmlConfiguration->phpunit()->stopOnIncomplete(); } if ($cliConfiguration->hasStopOnNotice()) { $stopOnNotice = $cliConfiguration->stopOnNotice(); } else { $stopOnNotice = $xmlConfiguration->phpunit()->stopOnNotice(); } if ($cliConfiguration->hasStopOnRisky()) { $stopOnRisky = $cliConfiguration->stopOnRisky(); } else { $stopOnRisky = $xmlConfiguration->phpunit()->stopOnRisky(); } if ($cliConfiguration->hasStopOnSkipped()) { $stopOnSkipped = $cliConfiguration->stopOnSkipped(); } else { $stopOnSkipped = $xmlConfiguration->phpunit()->stopOnSkipped(); } if ($cliConfiguration->hasStopOnWarning()) { $stopOnWarning = $cliConfiguration->stopOnWarning(); } else { $stopOnWarning = $xmlConfiguration->phpunit()->stopOnWarning(); } if ($cliConfiguration->hasStderr() && $cliConfiguration->stderr()) { $outputToStandardErrorStream = true; } else { $outputToStandardErrorStream = $xmlConfiguration->phpunit()->stderr(); } if ($cliConfiguration->hasColumns()) { $columns = $cliConfiguration->columns(); } else { $columns = $xmlConfiguration->phpunit()->columns(); } if ($columns === 'max') { $columns = (new Console)->getNumberOfColumns(); } if ($columns < 16) { $columns = 16; EventFacade::emitter()->testRunnerTriggeredWarning( 'Less than 16 columns requested, number of columns set to 16', ); } assert(is_int($columns)); $noExtensions = false; if ($cliConfiguration->hasNoExtensions() && $cliConfiguration->noExtensions()) { $noExtensions = true; } $pharExtensionDirectory = null; if ($xmlConfiguration->phpunit()->hasExtensionsDirectory()) { $pharExtensionDirectory = $xmlConfiguration->phpunit()->extensionsDirectory(); } $extensionBootstrappers = []; if ($cliConfiguration->hasExtensions()) { foreach ($cliConfiguration->extensions() as $extension) { $extensionBootstrappers[] = [ 'className' => $extension, 'parameters' => [], ]; } } foreach ($xmlConfiguration->extensions() as $extension) { $extensionBootstrappers[] = [ 'className' => $extension->className(), 'parameters' => $extension->parameters(), ]; } if ($cliConfiguration->hasPathCoverage() && $cliConfiguration->pathCoverage()) { $pathCoverage = $cliConfiguration->pathCoverage(); } else { $pathCoverage = $xmlConfiguration->codeCoverage()->pathCoverage(); } $defaultColors = Colors::default(); $defaultThresholds = Thresholds::default(); $coverageClover = null; $coverageCobertura = null; $coverageCrap4j = null; $coverageCrap4jThreshold = 30; $coverageHtml = null; $coverageHtmlLowUpperBound = $defaultThresholds->lowUpperBound(); $coverageHtmlHighLowerBound = $defaultThresholds->highLowerBound(); $coverageHtmlColorSuccessLow = $defaultColors->successLow(); $coverageHtmlColorSuccessMedium = $defaultColors->successMedium(); $coverageHtmlColorSuccessHigh = $defaultColors->successHigh(); $coverageHtmlColorWarning = $defaultColors->warning(); $coverageHtmlColorDanger = $defaultColors->danger(); $coverageHtmlCustomCssFile = null; $coveragePhp = null; $coverageText = null; $coverageTextShowUncoveredFiles = false; $coverageTextShowOnlySummary = false; $coverageXml = null; $coverageFromXmlConfiguration = true; if ($cliConfiguration->hasNoCoverage() && $cliConfiguration->noCoverage()) { $coverageFromXmlConfiguration = false; } if ($cliConfiguration->hasCoverageClover()) { $coverageClover = $cliConfiguration->coverageClover(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasClover()) { $coverageClover = $xmlConfiguration->codeCoverage()->clover()->target()->path(); } if ($cliConfiguration->hasCoverageCobertura()) { $coverageCobertura = $cliConfiguration->coverageCobertura(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasCobertura()) { $coverageCobertura = $xmlConfiguration->codeCoverage()->cobertura()->target()->path(); } if ($xmlConfiguration->codeCoverage()->hasCrap4j()) { $coverageCrap4jThreshold = $xmlConfiguration->codeCoverage()->crap4j()->threshold(); } if ($cliConfiguration->hasCoverageCrap4J()) { $coverageCrap4j = $cliConfiguration->coverageCrap4J(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasCrap4j()) { $coverageCrap4j = $xmlConfiguration->codeCoverage()->crap4j()->target()->path(); } if ($xmlConfiguration->codeCoverage()->hasHtml()) { $coverageHtmlHighLowerBound = $xmlConfiguration->codeCoverage()->html()->highLowerBound(); $coverageHtmlLowUpperBound = $xmlConfiguration->codeCoverage()->html()->lowUpperBound(); if ($coverageHtmlLowUpperBound > $coverageHtmlHighLowerBound) { $coverageHtmlLowUpperBound = $defaultThresholds->lowUpperBound(); $coverageHtmlHighLowerBound = $defaultThresholds->highLowerBound(); } $coverageHtmlColorSuccessLow = $xmlConfiguration->codeCoverage()->html()->colorSuccessLow(); $coverageHtmlColorSuccessMedium = $xmlConfiguration->codeCoverage()->html()->colorSuccessMedium(); $coverageHtmlColorSuccessHigh = $xmlConfiguration->codeCoverage()->html()->colorSuccessHigh(); $coverageHtmlColorWarning = $xmlConfiguration->codeCoverage()->html()->colorWarning(); $coverageHtmlColorDanger = $xmlConfiguration->codeCoverage()->html()->colorDanger(); if ($xmlConfiguration->codeCoverage()->html()->hasCustomCssFile()) { $coverageHtmlCustomCssFile = $xmlConfiguration->codeCoverage()->html()->customCssFile(); } } if ($cliConfiguration->hasCoverageHtml()) { $coverageHtml = $cliConfiguration->coverageHtml(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasHtml()) { $coverageHtml = $xmlConfiguration->codeCoverage()->html()->target()->path(); } if ($cliConfiguration->hasCoveragePhp()) { $coveragePhp = $cliConfiguration->coveragePhp(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasPhp()) { $coveragePhp = $xmlConfiguration->codeCoverage()->php()->target()->path(); } if ($xmlConfiguration->codeCoverage()->hasText()) { $coverageTextShowUncoveredFiles = $xmlConfiguration->codeCoverage()->text()->showUncoveredFiles(); $coverageTextShowOnlySummary = $xmlConfiguration->codeCoverage()->text()->showOnlySummary(); } if ($cliConfiguration->hasCoverageTextShowUncoveredFiles()) { $coverageTextShowUncoveredFiles = $cliConfiguration->coverageTextShowUncoveredFiles(); } if ($cliConfiguration->hasCoverageTextShowOnlySummary()) { $coverageTextShowOnlySummary = $cliConfiguration->coverageTextShowOnlySummary(); } if ($cliConfiguration->hasCoverageText()) { $coverageText = $cliConfiguration->coverageText(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasText()) { $coverageText = $xmlConfiguration->codeCoverage()->text()->target()->path(); } if ($cliConfiguration->hasCoverageXml()) { $coverageXml = $cliConfiguration->coverageXml(); } elseif ($coverageFromXmlConfiguration && $xmlConfiguration->codeCoverage()->hasXml()) { $coverageXml = $xmlConfiguration->codeCoverage()->xml()->target()->path(); } if ($cliConfiguration->hasBackupGlobals()) { $backupGlobals = $cliConfiguration->backupGlobals(); } else { $backupGlobals = $xmlConfiguration->phpunit()->backupGlobals(); } if ($cliConfiguration->hasBackupStaticProperties()) { $backupStaticProperties = $cliConfiguration->backupStaticProperties(); } else { $backupStaticProperties = $xmlConfiguration->phpunit()->backupStaticProperties(); } if ($cliConfiguration->hasBeStrictAboutChangesToGlobalState()) { $beStrictAboutChangesToGlobalState = $cliConfiguration->beStrictAboutChangesToGlobalState(); } else { $beStrictAboutChangesToGlobalState = $xmlConfiguration->phpunit()->beStrictAboutChangesToGlobalState(); } if ($cliConfiguration->hasProcessIsolation()) { $processIsolation = $cliConfiguration->processIsolation(); } else { $processIsolation = $xmlConfiguration->phpunit()->processIsolation(); } if ($cliConfiguration->hasEnforceTimeLimit()) { $enforceTimeLimit = $cliConfiguration->enforceTimeLimit(); } else { $enforceTimeLimit = $xmlConfiguration->phpunit()->enforceTimeLimit(); } if ($enforceTimeLimit && !(new Invoker)->canInvokeWithTimeout()) { EventFacade::emitter()->testRunnerTriggeredWarning( 'The pcntl extension is required for enforcing time limits', ); } if ($cliConfiguration->hasDefaultTimeLimit()) { $defaultTimeLimit = $cliConfiguration->defaultTimeLimit(); } else { $defaultTimeLimit = $xmlConfiguration->phpunit()->defaultTimeLimit(); } $timeoutForSmallTests = $xmlConfiguration->phpunit()->timeoutForSmallTests(); $timeoutForMediumTests = $xmlConfiguration->phpunit()->timeoutForMediumTests(); $timeoutForLargeTests = $xmlConfiguration->phpunit()->timeoutForLargeTests(); if ($cliConfiguration->hasReportUselessTests()) { $reportUselessTests = $cliConfiguration->reportUselessTests(); } else { $reportUselessTests = $xmlConfiguration->phpunit()->beStrictAboutTestsThatDoNotTestAnything(); } if ($cliConfiguration->hasStrictCoverage()) { $strictCoverage = $cliConfiguration->strictCoverage(); } else { $strictCoverage = $xmlConfiguration->phpunit()->beStrictAboutCoverageMetadata(); } if ($cliConfiguration->hasDisallowTestOutput()) { $disallowTestOutput = $cliConfiguration->disallowTestOutput(); } else { $disallowTestOutput = $xmlConfiguration->phpunit()->beStrictAboutOutputDuringTests(); } if ($cliConfiguration->hasDisplayDetailsOnIncompleteTests()) { $displayDetailsOnIncompleteTests = $cliConfiguration->displayDetailsOnIncompleteTests(); } else { $displayDetailsOnIncompleteTests = $xmlConfiguration->phpunit()->displayDetailsOnIncompleteTests(); } if ($cliConfiguration->hasDisplayDetailsOnSkippedTests()) { $displayDetailsOnSkippedTests = $cliConfiguration->displayDetailsOnSkippedTests(); } else { $displayDetailsOnSkippedTests = $xmlConfiguration->phpunit()->displayDetailsOnSkippedTests(); } if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerDeprecations()) { $displayDetailsOnTestsThatTriggerDeprecations = $cliConfiguration->displayDetailsOnTestsThatTriggerDeprecations(); } else { $displayDetailsOnTestsThatTriggerDeprecations = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerDeprecations(); } if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerErrors()) { $displayDetailsOnTestsThatTriggerErrors = $cliConfiguration->displayDetailsOnTestsThatTriggerErrors(); } else { $displayDetailsOnTestsThatTriggerErrors = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerErrors(); } if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerNotices()) { $displayDetailsOnTestsThatTriggerNotices = $cliConfiguration->displayDetailsOnTestsThatTriggerNotices(); } else { $displayDetailsOnTestsThatTriggerNotices = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerNotices(); } if ($cliConfiguration->hasDisplayDetailsOnTestsThatTriggerWarnings()) { $displayDetailsOnTestsThatTriggerWarnings = $cliConfiguration->displayDetailsOnTestsThatTriggerWarnings(); } else { $displayDetailsOnTestsThatTriggerWarnings = $xmlConfiguration->phpunit()->displayDetailsOnTestsThatTriggerWarnings(); } if ($cliConfiguration->hasReverseList()) { $reverseDefectList = $cliConfiguration->reverseList(); } else { $reverseDefectList = $xmlConfiguration->phpunit()->reverseDefectList(); } $requireCoverageMetadata = $xmlConfiguration->phpunit()->requireCoverageMetadata(); if ($cliConfiguration->hasExecutionOrder()) { $executionOrder = $cliConfiguration->executionOrder(); } else { $executionOrder = $xmlConfiguration->phpunit()->executionOrder(); } $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT; if ($cliConfiguration->hasExecutionOrderDefects()) { $executionOrderDefects = $cliConfiguration->executionOrderDefects(); } elseif ($xmlConfiguration->phpunit()->defectsFirst()) { $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST; } if ($cliConfiguration->hasResolveDependencies()) { $resolveDependencies = $cliConfiguration->resolveDependencies(); } else { $resolveDependencies = $xmlConfiguration->phpunit()->resolveDependencies(); } $colors = false; $colorsSupported = (new Console)->hasColorSupport(); if ($cliConfiguration->hasColors()) { if ($cliConfiguration->colors() === Configuration::COLOR_ALWAYS) { $colors = true; } elseif ($colorsSupported && $cliConfiguration->colors() === Configuration::COLOR_AUTO) { $colors = true; } } elseif ($xmlConfiguration->phpunit()->colors() === Configuration::COLOR_ALWAYS) { $colors = true; } elseif ($colorsSupported && $xmlConfiguration->phpunit()->colors() === Configuration::COLOR_AUTO) { $colors = true; } $logfileTeamcity = null; $logfileJunit = null; $logfileTestdoxHtml = null; $logfileTestdoxText = null; $loggingFromXmlConfiguration = true; if ($cliConfiguration->hasNoLogging() && $cliConfiguration->noLogging()) { $loggingFromXmlConfiguration = false; } if ($cliConfiguration->hasTeamcityLogfile()) { $logfileTeamcity = $cliConfiguration->teamcityLogfile(); } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTeamCity()) { $logfileTeamcity = $xmlConfiguration->logging()->teamCity()->target()->path(); } if ($cliConfiguration->hasJunitLogfile()) { $logfileJunit = $cliConfiguration->junitLogfile(); } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasJunit()) { $logfileJunit = $xmlConfiguration->logging()->junit()->target()->path(); } if ($cliConfiguration->hasTestdoxHtmlFile()) { $logfileTestdoxHtml = $cliConfiguration->testdoxHtmlFile(); } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTestDoxHtml()) { $logfileTestdoxHtml = $xmlConfiguration->logging()->testDoxHtml()->target()->path(); } if ($cliConfiguration->hasTestdoxTextFile()) { $logfileTestdoxText = $cliConfiguration->testdoxTextFile(); } elseif ($loggingFromXmlConfiguration && $xmlConfiguration->logging()->hasTestDoxText()) { $logfileTestdoxText = $xmlConfiguration->logging()->testDoxText()->target()->path(); } $logEventsText = null; if ($cliConfiguration->hasLogEventsText()) { $logEventsText = $cliConfiguration->logEventsText(); } $logEventsVerboseText = null; if ($cliConfiguration->hasLogEventsVerboseText()) { $logEventsVerboseText = $cliConfiguration->logEventsVerboseText(); } $teamCityOutput = false; if ($cliConfiguration->hasTeamCityPrinter() && $cliConfiguration->teamCityPrinter()) { $teamCityOutput = true; } if ($cliConfiguration->hasTestDoxPrinter() && $cliConfiguration->testdoxPrinter()) { $testDoxOutput = true; } else { $testDoxOutput = $xmlConfiguration->phpunit()->testdoxPrinter(); } if ($cliConfiguration->hasTestDoxPrinterSummary() && $cliConfiguration->testdoxPrinterSummary()) { $testDoxOutputSummary = true; } else { $testDoxOutputSummary = $xmlConfiguration->phpunit()->testdoxPrinterSummary(); } $noProgress = false; if ($cliConfiguration->hasNoProgress() && $cliConfiguration->noProgress()) { $noProgress = true; } $noResults = false; if ($cliConfiguration->hasNoResults() && $cliConfiguration->noResults()) { $noResults = true; } $noOutput = false; if ($cliConfiguration->hasNoOutput() && $cliConfiguration->noOutput()) { $noOutput = true; } $testsCovering = null; if ($cliConfiguration->hasTestsCovering()) { $testsCovering = $cliConfiguration->testsCovering(); } $testsUsing = null; if ($cliConfiguration->hasTestsUsing()) { $testsUsing = $cliConfiguration->testsUsing(); } $filter = null; if ($cliConfiguration->hasFilter()) { $filter = $cliConfiguration->filter(); } $excludeFilter = null; if ($cliConfiguration->hasExcludeFilter()) { $excludeFilter = $cliConfiguration->excludeFilter(); } if ($cliConfiguration->hasGroups()) { $groups = $cliConfiguration->groups(); } else { $groups = $xmlConfiguration->groups()->include()->asArrayOfStrings(); } if ($cliConfiguration->hasExcludeGroups()) { $excludeGroups = $cliConfiguration->excludeGroups(); } else { $excludeGroups = $xmlConfiguration->groups()->exclude()->asArrayOfStrings(); } $excludeGroups = array_diff($excludeGroups, $groups); if ($cliConfiguration->hasRandomOrderSeed()) { $randomOrderSeed = $cliConfiguration->randomOrderSeed(); } else { $randomOrderSeed = time(); } if ($xmlConfiguration->wasLoadedFromFile() && $xmlConfiguration->hasValidationErrors()) { if ((new SchemaDetector)->detect($xmlConfiguration->filename())->detected()) { EventFacade::emitter()->testRunnerTriggeredDeprecation( 'Your XML configuration validates against a deprecated schema. Migrate your XML configuration using "--migrate-configuration"!', ); } else { EventFacade::emitter()->testRunnerTriggeredWarning( "Test results may not be as expected because the XML configuration file did not pass validation:\n" . $xmlConfiguration->validationErrors(), ); } } $includeUncoveredFiles = $xmlConfiguration->codeCoverage()->includeUncoveredFiles(); $includePaths = []; if ($cliConfiguration->hasIncludePath()) { foreach (explode(PATH_SEPARATOR, $cliConfiguration->includePath()) as $includePath) { $includePaths[] = new Directory($includePath); } } foreach ($xmlConfiguration->php()->includePaths() as $includePath) { $includePaths[] = $includePath; } $iniSettings = []; if ($cliConfiguration->hasIniSettings()) { foreach ($cliConfiguration->iniSettings() as $name => $value) { $iniSettings[] = new IniSetting($name, $value); } } foreach ($xmlConfiguration->php()->iniSettings() as $iniSetting) { $iniSettings[] = $iniSetting; } $includeTestSuite = ''; if ($cliConfiguration->hasTestSuite()) { $includeTestSuite = $cliConfiguration->testSuite(); } elseif ($xmlConfiguration->phpunit()->hasDefaultTestSuite()) { $includeTestSuite = $xmlConfiguration->phpunit()->defaultTestSuite(); } $excludeTestSuite = ''; if ($cliConfiguration->hasExcludedTestSuite()) { $excludeTestSuite = $cliConfiguration->excludedTestSuite(); } $testSuffixes = ['Test.php', '.phpt']; if ($cliConfiguration->hasTestSuffixes()) { $testSuffixes = $cliConfiguration->testSuffixes(); } $sourceIncludeDirectories = []; if ($cliConfiguration->hasCoverageFilter()) { foreach ($cliConfiguration->coverageFilter() as $directory) { $sourceIncludeDirectories[] = new FilterDirectory($directory, '', '.php'); } } foreach ($xmlConfiguration->source()->includeDirectories() as $directory) { $sourceIncludeDirectories[] = $directory; } $sourceIncludeFiles = $xmlConfiguration->source()->includeFiles(); $sourceExcludeDirectories = $xmlConfiguration->source()->excludeDirectories(); $sourceExcludeFiles = $xmlConfiguration->source()->excludeFiles(); $useBaseline = null; $generateBaseline = null; if (!$cliConfiguration->hasGenerateBaseline()) { if ($cliConfiguration->hasUseBaseline()) { $useBaseline = $cliConfiguration->useBaseline(); } elseif ($xmlConfiguration->source()->hasBaseline()) { $useBaseline = $xmlConfiguration->source()->baseline(); } } else { $generateBaseline = $cliConfiguration->generateBaseline(); } assert($useBaseline !== ''); assert($generateBaseline !== ''); if ($failOnDeprecation) { $displayDetailsOnTestsThatTriggerDeprecations = true; } if ($failOnNotice) { $displayDetailsOnTestsThatTriggerNotices = true; } if ($failOnWarning) { $displayDetailsOnTestsThatTriggerWarnings = true; } if ($failOnIncomplete) { $displayDetailsOnIncompleteTests = true; } if ($failOnSkipped) { $displayDetailsOnSkippedTests = true; } return new Configuration( $cliConfiguration->arguments(), $configurationFile, $bootstrap, $cacheResult, $cacheDirectory, $coverageCacheDirectory, new Source( $useBaseline, $cliConfiguration->ignoreBaseline(), FilterDirectoryCollection::fromArray($sourceIncludeDirectories), $sourceIncludeFiles, $sourceExcludeDirectories, $sourceExcludeFiles, $xmlConfiguration->source()->restrictDeprecations(), $xmlConfiguration->source()->restrictNotices(), $xmlConfiguration->source()->restrictWarnings(), $xmlConfiguration->source()->ignoreSuppressionOfDeprecations(), $xmlConfiguration->source()->ignoreSuppressionOfPhpDeprecations(), $xmlConfiguration->source()->ignoreSuppressionOfErrors(), $xmlConfiguration->source()->ignoreSuppressionOfNotices(), $xmlConfiguration->source()->ignoreSuppressionOfPhpNotices(), $xmlConfiguration->source()->ignoreSuppressionOfWarnings(), $xmlConfiguration->source()->ignoreSuppressionOfPhpWarnings(), $xmlConfiguration->source()->deprecationTriggers(), $xmlConfiguration->source()->ignoreSelfDeprecations(), $xmlConfiguration->source()->ignoreDirectDeprecations(), $xmlConfiguration->source()->ignoreIndirectDeprecations(), ), $testResultCacheFile, $coverageClover, $coverageCobertura, $coverageCrap4j, $coverageCrap4jThreshold, $coverageHtml, $coverageHtmlLowUpperBound, $coverageHtmlHighLowerBound, $coverageHtmlColorSuccessLow, $coverageHtmlColorSuccessMedium, $coverageHtmlColorSuccessHigh, $coverageHtmlColorWarning, $coverageHtmlColorDanger, $coverageHtmlCustomCssFile, $coveragePhp, $coverageText, $coverageTextShowUncoveredFiles, $coverageTextShowOnlySummary, $coverageXml, $pathCoverage, $xmlConfiguration->codeCoverage()->ignoreDeprecatedCodeUnits(), $disableCodeCoverageIgnore, $failOnDeprecation, $failOnEmptyTestSuite, $failOnIncomplete, $failOnNotice, $failOnRisky, $failOnSkipped, $failOnWarning, $stopOnDefect, $stopOnDeprecation, $stopOnError, $stopOnFailure, $stopOnIncomplete, $stopOnNotice, $stopOnRisky, $stopOnSkipped, $stopOnWarning, $outputToStandardErrorStream, $columns, $noExtensions, $pharExtensionDirectory, $extensionBootstrappers, $backupGlobals, $backupStaticProperties, $beStrictAboutChangesToGlobalState, $colors, $processIsolation, $enforceTimeLimit, $defaultTimeLimit, $timeoutForSmallTests, $timeoutForMediumTests, $timeoutForLargeTests, $reportUselessTests, $strictCoverage, $disallowTestOutput, $displayDetailsOnIncompleteTests, $displayDetailsOnSkippedTests, $displayDetailsOnTestsThatTriggerDeprecations, $displayDetailsOnTestsThatTriggerErrors, $displayDetailsOnTestsThatTriggerNotices, $displayDetailsOnTestsThatTriggerWarnings, $reverseDefectList, $requireCoverageMetadata, $noProgress, $noResults, $noOutput, $executionOrder, $executionOrderDefects, $resolveDependencies, $logfileTeamcity, $logfileJunit, $logfileTestdoxHtml, $logfileTestdoxText, $logEventsText, $logEventsVerboseText, $teamCityOutput, $testDoxOutput, $testDoxOutputSummary, $testsCovering, $testsUsing, $filter, $excludeFilter, $groups, $excludeGroups, $randomOrderSeed, $includeUncoveredFiles, $xmlConfiguration->testSuite(), $includeTestSuite, $excludeTestSuite, $xmlConfiguration->phpunit()->hasDefaultTestSuite() ? $xmlConfiguration->phpunit()->defaultTestSuite() : null, $testSuffixes, new Php( DirectoryCollection::fromArray($includePaths), IniSettingCollection::fromArray($iniSettings), $xmlConfiguration->php()->constants(), $xmlConfiguration->php()->globalVariables(), $xmlConfiguration->php()->envVariables(), $xmlConfiguration->php()->postVariables(), $xmlConfiguration->php()->getVariables(), $xmlConfiguration->php()->cookieVariables(), $xmlConfiguration->php()->serverVariables(), $xmlConfiguration->php()->filesVariables(), $xmlConfiguration->php()->requestVariables(), ), $xmlConfiguration->phpunit()->controlGarbageCollector(), $xmlConfiguration->phpunit()->numberOfTestsBeforeGarbageCollection(), $generateBaseline, $cliConfiguration->debug(), $xmlConfiguration->phpunit()->shortenArraysForExportThreshold(), ); } } phpunit/src/TextUI/Configuration/Exception/NoPharExtensionDirectoryException.php 0000644 00000001152 15253321353 0024313 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoPharExtensionDirectoryException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoCustomCssFileException.php 0000644 00000001141 15253321353 0022360 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoCustomCssFileException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/CodeCoverageReportNotConfiguredException.php 0000644 00000001161 15253321353 0025553 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CodeCoverageReportNotConfiguredException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/Exception.php 0000644 00000001061 15253321353 0017420 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends \PHPUnit\TextUI\Exception { } phpunit/src/TextUI/Configuration/Exception/NoCliArgumentException.php 0000644 00000001137 15253321353 0022054 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoCliArgumentException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoCacheDirectoryException.php 0000644 00000001142 15253321353 0022526 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoCacheDirectoryException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/ConfigurationCannotBeBuiltException.php 0000644 00000001154 15253321353 0024565 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ConfigurationCannotBeBuiltException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoCoverageCacheDirectoryException.php 0000644 00000001152 15253321353 0024203 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoCoverageCacheDirectoryException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/IncludePathNotConfiguredException.php 0000644 00000001152 15253321353 0024231 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class IncludePathNotConfiguredException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/FilterNotConfiguredException.php 0000644 00000001145 15253321353 0023260 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class FilterNotConfiguredException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/LoggingNotConfiguredException.php 0000644 00000001146 15253321353 0023422 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class LoggingNotConfiguredException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoBaselineException.php 0000644 00000001134 15253321353 0021361 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoBaselineException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoConfigurationFileException.php 0000644 00000001145 15253321353 0023250 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoConfigurationFileException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoDefaultTestSuiteException.php 0000644 00000001144 15253321353 0023076 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoDefaultTestSuiteException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/CannotFindSchemaException.php 0000644 00000001221 15253321353 0022503 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\XmlConfiguration; use PHPUnit\TextUI\Configuration\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CannotFindSchemaException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Exception/NoBootstrapException.php 0000644 00000001135 15253321353 0021615 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NoBootstrapException extends RuntimeException implements Exception { } phpunit/src/TextUI/Configuration/Configuration.php 0000644 00000114364 15253321353 0016346 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Configuration { public const COLOR_NEVER = 'never'; public const COLOR_AUTO = 'auto'; public const COLOR_ALWAYS = 'always'; public const COLOR_DEFAULT = self::COLOR_NEVER; /** * @var list<non-empty-string> */ private array $cliArguments; private ?string $configurationFile; private ?string $bootstrap; private bool $cacheResult; private ?string $cacheDirectory; private ?string $coverageCacheDirectory; private Source $source; private bool $pathCoverage; private ?string $coverageClover; private ?string $coverageCobertura; private ?string $coverageCrap4j; private int $coverageCrap4jThreshold; private ?string $coverageHtml; private int $coverageHtmlLowUpperBound; private int $coverageHtmlHighLowerBound; private string $coverageHtmlColorSuccessLow; private string $coverageHtmlColorSuccessMedium; private string $coverageHtmlColorSuccessHigh; private string $coverageHtmlColorWarning; private string $coverageHtmlColorDanger; private ?string $coverageHtmlCustomCssFile; private ?string $coveragePhp; private ?string $coverageText; private bool $coverageTextShowUncoveredFiles; private bool $coverageTextShowOnlySummary; private ?string $coverageXml; private string $testResultCacheFile; private bool $ignoreDeprecatedCodeUnitsFromCodeCoverage; private bool $disableCodeCoverageIgnore; private bool $failOnDeprecation; private bool $failOnEmptyTestSuite; private bool $failOnIncomplete; private bool $failOnNotice; private bool $failOnRisky; private bool $failOnSkipped; private bool $failOnWarning; private bool $stopOnDefect; private bool $stopOnDeprecation; private bool $stopOnError; private bool $stopOnFailure; private bool $stopOnIncomplete; private bool $stopOnNotice; private bool $stopOnRisky; private bool $stopOnSkipped; private bool $stopOnWarning; private bool $outputToStandardErrorStream; private int $columns; private bool $noExtensions; /** * @var ?non-empty-string */ private ?string $pharExtensionDirectory; /** * @var list<array{className: non-empty-string, parameters: array<string, string>}> */ private array $extensionBootstrappers; private bool $backupGlobals; private bool $backupStaticProperties; private bool $beStrictAboutChangesToGlobalState; private bool $colors; private bool $processIsolation; private bool $enforceTimeLimit; private int $defaultTimeLimit; private int $timeoutForSmallTests; private int $timeoutForMediumTests; private int $timeoutForLargeTests; private bool $reportUselessTests; private bool $strictCoverage; private bool $disallowTestOutput; private bool $displayDetailsOnIncompleteTests; private bool $displayDetailsOnSkippedTests; private bool $displayDetailsOnTestsThatTriggerDeprecations; private bool $displayDetailsOnTestsThatTriggerErrors; private bool $displayDetailsOnTestsThatTriggerNotices; private bool $displayDetailsOnTestsThatTriggerWarnings; private bool $reverseDefectList; private bool $requireCoverageMetadata; private bool $noProgress; private bool $noResults; private bool $noOutput; private int $executionOrder; private int $executionOrderDefects; private bool $resolveDependencies; private ?string $logfileTeamcity; private ?string $logfileJunit; private ?string $logfileTestdoxHtml; private ?string $logfileTestdoxText; private ?string $logEventsText; private ?string $logEventsVerboseText; /** * @var ?non-empty-list<non-empty-string> */ private ?array $testsCovering; /** * @var ?non-empty-list<non-empty-string> */ private ?array $testsUsing; private bool $teamCityOutput; private bool $testDoxOutput; private bool $testDoxOutputSummary; private ?string $filter; private ?string $excludeFilter; /** * @var list<non-empty-string> */ private ?array $groups; /** * @var list<non-empty-string> */ private ?array $excludeGroups; private int $randomOrderSeed; private bool $includeUncoveredFiles; private TestSuiteCollection $testSuite; private string $includeTestSuite; private string $excludeTestSuite; private ?string $defaultTestSuite; /** * @var non-empty-list<non-empty-string> */ private array $testSuffixes; private Php $php; private bool $controlGarbageCollector; private int $numberOfTestsBeforeGarbageCollection; private ?string $generateBaseline; private bool $debug; /** * @var non-negative-int */ private int $shortenArraysForExportThreshold; /** * @param list<non-empty-string> $cliArguments * @param ?non-empty-string $pharExtensionDirectory * @param list<array{className: non-empty-string, parameters: array<string, string>}> $extensionBootstrappers * @param ?non-empty-list<non-empty-string> $testsCovering * @param ?non-empty-list<non-empty-string> $testsUsing * @param list<non-empty-string> $groups * @param list<non-empty-string> $excludeGroups * @param non-empty-list<non-empty-string> $testSuffixes * @param non-negative-int $shortenArraysForExportThreshold */ public function __construct(array $cliArguments, ?string $configurationFile, ?string $bootstrap, bool $cacheResult, ?string $cacheDirectory, ?string $coverageCacheDirectory, Source $source, string $testResultCacheFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4j, int $coverageCrap4jThreshold, ?string $coverageHtml, int $coverageHtmlLowUpperBound, int $coverageHtmlHighLowerBound, string $coverageHtmlColorSuccessLow, string $coverageHtmlColorSuccessMedium, string $coverageHtmlColorSuccessHigh, string $coverageHtmlColorWarning, string $coverageHtmlColorDanger, ?string $coverageHtmlCustomCssFile, ?string $coveragePhp, ?string $coverageText, bool $coverageTextShowUncoveredFiles, bool $coverageTextShowOnlySummary, ?string $coverageXml, bool $pathCoverage, bool $ignoreDeprecatedCodeUnitsFromCodeCoverage, bool $disableCodeCoverageIgnore, bool $failOnDeprecation, bool $failOnEmptyTestSuite, bool $failOnIncomplete, bool $failOnNotice, bool $failOnRisky, bool $failOnSkipped, bool $failOnWarning, bool $stopOnDefect, bool $stopOnDeprecation, bool $stopOnError, bool $stopOnFailure, bool $stopOnIncomplete, bool $stopOnNotice, bool $stopOnRisky, bool $stopOnSkipped, bool $stopOnWarning, bool $outputToStandardErrorStream, int|string $columns, bool $noExtensions, ?string $pharExtensionDirectory, array $extensionBootstrappers, bool $backupGlobals, bool $backupStaticProperties, bool $beStrictAboutChangesToGlobalState, bool $colors, bool $processIsolation, bool $enforceTimeLimit, int $defaultTimeLimit, int $timeoutForSmallTests, int $timeoutForMediumTests, int $timeoutForLargeTests, bool $reportUselessTests, bool $strictCoverage, bool $disallowTestOutput, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $reverseDefectList, bool $requireCoverageMetadata, bool $noProgress, bool $noResults, bool $noOutput, int $executionOrder, int $executionOrderDefects, bool $resolveDependencies, ?string $logfileTeamcity, ?string $logfileJunit, ?string $logfileTestdoxHtml, ?string $logfileTestdoxText, ?string $logEventsText, ?string $logEventsVerboseText, bool $teamCityOutput, bool $testDoxOutput, bool $testDoxOutputSummary, ?array $testsCovering, ?array $testsUsing, ?string $filter, ?string $excludeFilter, array $groups, array $excludeGroups, int $randomOrderSeed, bool $includeUncoveredFiles, TestSuiteCollection $testSuite, string $includeTestSuite, string $excludeTestSuite, ?string $defaultTestSuite, array $testSuffixes, Php $php, bool $controlGarbageCollector, int $numberOfTestsBeforeGarbageCollection, ?string $generateBaseline, bool $debug, int $shortenArraysForExportThreshold) { $this->cliArguments = $cliArguments; $this->configurationFile = $configurationFile; $this->bootstrap = $bootstrap; $this->cacheResult = $cacheResult; $this->cacheDirectory = $cacheDirectory; $this->coverageCacheDirectory = $coverageCacheDirectory; $this->source = $source; $this->testResultCacheFile = $testResultCacheFile; $this->coverageClover = $coverageClover; $this->coverageCobertura = $coverageCobertura; $this->coverageCrap4j = $coverageCrap4j; $this->coverageCrap4jThreshold = $coverageCrap4jThreshold; $this->coverageHtml = $coverageHtml; $this->coverageHtmlLowUpperBound = $coverageHtmlLowUpperBound; $this->coverageHtmlHighLowerBound = $coverageHtmlHighLowerBound; $this->coverageHtmlColorSuccessLow = $coverageHtmlColorSuccessLow; $this->coverageHtmlColorSuccessMedium = $coverageHtmlColorSuccessMedium; $this->coverageHtmlColorSuccessHigh = $coverageHtmlColorSuccessHigh; $this->coverageHtmlColorWarning = $coverageHtmlColorWarning; $this->coverageHtmlColorDanger = $coverageHtmlColorDanger; $this->coverageHtmlCustomCssFile = $coverageHtmlCustomCssFile; $this->coveragePhp = $coveragePhp; $this->coverageText = $coverageText; $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles; $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary; $this->coverageXml = $coverageXml; $this->pathCoverage = $pathCoverage; $this->ignoreDeprecatedCodeUnitsFromCodeCoverage = $ignoreDeprecatedCodeUnitsFromCodeCoverage; $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; $this->failOnDeprecation = $failOnDeprecation; $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; $this->failOnIncomplete = $failOnIncomplete; $this->failOnNotice = $failOnNotice; $this->failOnRisky = $failOnRisky; $this->failOnSkipped = $failOnSkipped; $this->failOnWarning = $failOnWarning; $this->stopOnDefect = $stopOnDefect; $this->stopOnDeprecation = $stopOnDeprecation; $this->stopOnError = $stopOnError; $this->stopOnFailure = $stopOnFailure; $this->stopOnIncomplete = $stopOnIncomplete; $this->stopOnNotice = $stopOnNotice; $this->stopOnRisky = $stopOnRisky; $this->stopOnSkipped = $stopOnSkipped; $this->stopOnWarning = $stopOnWarning; $this->outputToStandardErrorStream = $outputToStandardErrorStream; $this->columns = $columns; $this->noExtensions = $noExtensions; $this->pharExtensionDirectory = $pharExtensionDirectory; $this->extensionBootstrappers = $extensionBootstrappers; $this->backupGlobals = $backupGlobals; $this->backupStaticProperties = $backupStaticProperties; $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; $this->colors = $colors; $this->processIsolation = $processIsolation; $this->enforceTimeLimit = $enforceTimeLimit; $this->defaultTimeLimit = $defaultTimeLimit; $this->timeoutForSmallTests = $timeoutForSmallTests; $this->timeoutForMediumTests = $timeoutForMediumTests; $this->timeoutForLargeTests = $timeoutForLargeTests; $this->reportUselessTests = $reportUselessTests; $this->strictCoverage = $strictCoverage; $this->disallowTestOutput = $disallowTestOutput; $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; $this->reverseDefectList = $reverseDefectList; $this->requireCoverageMetadata = $requireCoverageMetadata; $this->noProgress = $noProgress; $this->noResults = $noResults; $this->noOutput = $noOutput; $this->executionOrder = $executionOrder; $this->executionOrderDefects = $executionOrderDefects; $this->resolveDependencies = $resolveDependencies; $this->logfileTeamcity = $logfileTeamcity; $this->logfileJunit = $logfileJunit; $this->logfileTestdoxHtml = $logfileTestdoxHtml; $this->logfileTestdoxText = $logfileTestdoxText; $this->logEventsText = $logEventsText; $this->logEventsVerboseText = $logEventsVerboseText; $this->teamCityOutput = $teamCityOutput; $this->testDoxOutput = $testDoxOutput; $this->testDoxOutputSummary = $testDoxOutputSummary; $this->testsCovering = $testsCovering; $this->testsUsing = $testsUsing; $this->filter = $filter; $this->excludeFilter = $excludeFilter; $this->groups = $groups; $this->excludeGroups = $excludeGroups; $this->randomOrderSeed = $randomOrderSeed; $this->includeUncoveredFiles = $includeUncoveredFiles; $this->testSuite = $testSuite; $this->includeTestSuite = $includeTestSuite; $this->excludeTestSuite = $excludeTestSuite; $this->defaultTestSuite = $defaultTestSuite; $this->testSuffixes = $testSuffixes; $this->php = $php; $this->controlGarbageCollector = $controlGarbageCollector; $this->numberOfTestsBeforeGarbageCollection = $numberOfTestsBeforeGarbageCollection; $this->generateBaseline = $generateBaseline; $this->debug = $debug; $this->shortenArraysForExportThreshold = $shortenArraysForExportThreshold; } /** * @phpstan-assert-if-true !empty $this->cliArguments */ public function hasCliArguments(): bool { return !empty($this->cliArguments); } /** * @return list<non-empty-string> */ public function cliArguments(): array { return $this->cliArguments; } /** * @phpstan-assert-if-true !null $this->configurationFile */ public function hasConfigurationFile(): bool { return $this->configurationFile !== null; } /** * @throws NoConfigurationFileException */ public function configurationFile(): string { if (!$this->hasConfigurationFile()) { throw new NoConfigurationFileException; } return $this->configurationFile; } /** * @phpstan-assert-if-true !null $this->bootstrap */ public function hasBootstrap(): bool { return $this->bootstrap !== null; } /** * @throws NoBootstrapException */ public function bootstrap(): string { if (!$this->hasBootstrap()) { throw new NoBootstrapException; } return $this->bootstrap; } public function cacheResult(): bool { return $this->cacheResult; } /** * @phpstan-assert-if-true !null $this->cacheDirectory */ public function hasCacheDirectory(): bool { return $this->cacheDirectory !== null; } /** * @throws NoCacheDirectoryException */ public function cacheDirectory(): string { if (!$this->hasCacheDirectory()) { throw new NoCacheDirectoryException; } return $this->cacheDirectory; } /** * @phpstan-assert-if-true !null $this->coverageCacheDirectory */ public function hasCoverageCacheDirectory(): bool { return $this->coverageCacheDirectory !== null; } /** * @throws NoCoverageCacheDirectoryException */ public function coverageCacheDirectory(): string { if (!$this->hasCoverageCacheDirectory()) { throw new NoCoverageCacheDirectoryException; } return $this->coverageCacheDirectory; } public function source(): Source { return $this->source; } public function testResultCacheFile(): string { return $this->testResultCacheFile; } public function ignoreDeprecatedCodeUnitsFromCodeCoverage(): bool { return $this->ignoreDeprecatedCodeUnitsFromCodeCoverage; } public function disableCodeCoverageIgnore(): bool { return $this->disableCodeCoverageIgnore; } public function pathCoverage(): bool { return $this->pathCoverage; } public function hasCoverageReport(): bool { return $this->hasCoverageClover() || $this->hasCoverageCobertura() || $this->hasCoverageCrap4j() || $this->hasCoverageHtml() || $this->hasCoveragePhp() || $this->hasCoverageText() || $this->hasCoverageXml(); } /** * @phpstan-assert-if-true !null $this->coverageClover */ public function hasCoverageClover(): bool { return $this->coverageClover !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageClover(): string { if (!$this->hasCoverageClover()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageClover; } /** * @phpstan-assert-if-true !null $this->coverageCobertura */ public function hasCoverageCobertura(): bool { return $this->coverageCobertura !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageCobertura(): string { if (!$this->hasCoverageCobertura()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageCobertura; } /** * @phpstan-assert-if-true !null $this->coverageCrap4j */ public function hasCoverageCrap4j(): bool { return $this->coverageCrap4j !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageCrap4j(): string { if (!$this->hasCoverageCrap4j()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageCrap4j; } public function coverageCrap4jThreshold(): int { return $this->coverageCrap4jThreshold; } /** * @phpstan-assert-if-true !null $this->coverageHtml */ public function hasCoverageHtml(): bool { return $this->coverageHtml !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageHtml(): string { if (!$this->hasCoverageHtml()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageHtml; } public function coverageHtmlLowUpperBound(): int { return $this->coverageHtmlLowUpperBound; } public function coverageHtmlHighLowerBound(): int { return $this->coverageHtmlHighLowerBound; } public function coverageHtmlColorSuccessLow(): string { return $this->coverageHtmlColorSuccessLow; } public function coverageHtmlColorSuccessMedium(): string { return $this->coverageHtmlColorSuccessMedium; } public function coverageHtmlColorSuccessHigh(): string { return $this->coverageHtmlColorSuccessHigh; } public function coverageHtmlColorWarning(): string { return $this->coverageHtmlColorWarning; } public function coverageHtmlColorDanger(): string { return $this->coverageHtmlColorDanger; } /** * @phpstan-assert-if-true !null $this->coverageHtmlCustomCssFile */ public function hasCoverageHtmlCustomCssFile(): bool { return $this->coverageHtmlCustomCssFile !== null; } /** * @throws NoCustomCssFileException */ public function coverageHtmlCustomCssFile(): string { if (!$this->hasCoverageHtmlCustomCssFile()) { throw new NoCustomCssFileException; } return $this->coverageHtmlCustomCssFile; } /** * @phpstan-assert-if-true !null $this->coveragePhp */ public function hasCoveragePhp(): bool { return $this->coveragePhp !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coveragePhp(): string { if (!$this->hasCoveragePhp()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coveragePhp; } /** * @phpstan-assert-if-true !null $this->coverageText */ public function hasCoverageText(): bool { return $this->coverageText !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageText(): string { if (!$this->hasCoverageText()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageText; } public function coverageTextShowUncoveredFiles(): bool { return $this->coverageTextShowUncoveredFiles; } public function coverageTextShowOnlySummary(): bool { return $this->coverageTextShowOnlySummary; } /** * @phpstan-assert-if-true !null $this->coverageXml */ public function hasCoverageXml(): bool { return $this->coverageXml !== null; } /** * @throws CodeCoverageReportNotConfiguredException */ public function coverageXml(): string { if (!$this->hasCoverageXml()) { throw new CodeCoverageReportNotConfiguredException; } return $this->coverageXml; } public function failOnDeprecation(): bool { return $this->failOnDeprecation; } public function failOnEmptyTestSuite(): bool { return $this->failOnEmptyTestSuite; } public function failOnIncomplete(): bool { return $this->failOnIncomplete; } public function failOnNotice(): bool { return $this->failOnNotice; } public function failOnRisky(): bool { return $this->failOnRisky; } public function failOnSkipped(): bool { return $this->failOnSkipped; } public function failOnWarning(): bool { return $this->failOnWarning; } public function stopOnDefect(): bool { return $this->stopOnDefect; } public function stopOnDeprecation(): bool { return $this->stopOnDeprecation; } public function stopOnError(): bool { return $this->stopOnError; } public function stopOnFailure(): bool { return $this->stopOnFailure; } public function stopOnIncomplete(): bool { return $this->stopOnIncomplete; } public function stopOnNotice(): bool { return $this->stopOnNotice; } public function stopOnRisky(): bool { return $this->stopOnRisky; } public function stopOnSkipped(): bool { return $this->stopOnSkipped; } public function stopOnWarning(): bool { return $this->stopOnWarning; } public function outputToStandardErrorStream(): bool { return $this->outputToStandardErrorStream; } public function columns(): int { return $this->columns; } public function noExtensions(): bool { return $this->noExtensions; } /** * @phpstan-assert-if-true !null $this->pharExtensionDirectory */ public function hasPharExtensionDirectory(): bool { return $this->pharExtensionDirectory !== null; } /** * @throws NoPharExtensionDirectoryException * * @return non-empty-string */ public function pharExtensionDirectory(): string { if (!$this->hasPharExtensionDirectory()) { throw new NoPharExtensionDirectoryException; } return $this->pharExtensionDirectory; } /** * @return list<array{className: non-empty-string, parameters: array<string, string>}> */ public function extensionBootstrappers(): array { return $this->extensionBootstrappers; } public function backupGlobals(): bool { return $this->backupGlobals; } public function backupStaticProperties(): bool { return $this->backupStaticProperties; } public function beStrictAboutChangesToGlobalState(): bool { return $this->beStrictAboutChangesToGlobalState; } public function colors(): bool { return $this->colors; } public function processIsolation(): bool { return $this->processIsolation; } public function enforceTimeLimit(): bool { return $this->enforceTimeLimit; } public function defaultTimeLimit(): int { return $this->defaultTimeLimit; } public function timeoutForSmallTests(): int { return $this->timeoutForSmallTests; } public function timeoutForMediumTests(): int { return $this->timeoutForMediumTests; } public function timeoutForLargeTests(): int { return $this->timeoutForLargeTests; } public function reportUselessTests(): bool { return $this->reportUselessTests; } public function strictCoverage(): bool { return $this->strictCoverage; } public function disallowTestOutput(): bool { return $this->disallowTestOutput; } public function displayDetailsOnIncompleteTests(): bool { return $this->displayDetailsOnIncompleteTests; } public function displayDetailsOnSkippedTests(): bool { return $this->displayDetailsOnSkippedTests; } public function displayDetailsOnTestsThatTriggerDeprecations(): bool { return $this->displayDetailsOnTestsThatTriggerDeprecations; } public function displayDetailsOnTestsThatTriggerErrors(): bool { return $this->displayDetailsOnTestsThatTriggerErrors; } public function displayDetailsOnTestsThatTriggerNotices(): bool { return $this->displayDetailsOnTestsThatTriggerNotices; } public function displayDetailsOnTestsThatTriggerWarnings(): bool { return $this->displayDetailsOnTestsThatTriggerWarnings; } public function reverseDefectList(): bool { return $this->reverseDefectList; } public function requireCoverageMetadata(): bool { return $this->requireCoverageMetadata; } public function noProgress(): bool { return $this->noProgress; } public function noResults(): bool { return $this->noResults; } public function noOutput(): bool { return $this->noOutput; } public function executionOrder(): int { return $this->executionOrder; } public function executionOrderDefects(): int { return $this->executionOrderDefects; } public function resolveDependencies(): bool { return $this->resolveDependencies; } /** * @phpstan-assert-if-true !null $this->logfileTeamcity */ public function hasLogfileTeamcity(): bool { return $this->logfileTeamcity !== null; } /** * @throws LoggingNotConfiguredException */ public function logfileTeamcity(): string { if (!$this->hasLogfileTeamcity()) { throw new LoggingNotConfiguredException; } return $this->logfileTeamcity; } /** * @phpstan-assert-if-true !null $this->logfileJunit */ public function hasLogfileJunit(): bool { return $this->logfileJunit !== null; } /** * @throws LoggingNotConfiguredException */ public function logfileJunit(): string { if (!$this->hasLogfileJunit()) { throw new LoggingNotConfiguredException; } return $this->logfileJunit; } /** * @phpstan-assert-if-true !null $this->logfileTestdoxHtml */ public function hasLogfileTestdoxHtml(): bool { return $this->logfileTestdoxHtml !== null; } /** * @throws LoggingNotConfiguredException */ public function logfileTestdoxHtml(): string { if (!$this->hasLogfileTestdoxHtml()) { throw new LoggingNotConfiguredException; } return $this->logfileTestdoxHtml; } /** * @phpstan-assert-if-true !null $this->logfileTestdoxText */ public function hasLogfileTestdoxText(): bool { return $this->logfileTestdoxText !== null; } /** * @throws LoggingNotConfiguredException */ public function logfileTestdoxText(): string { if (!$this->hasLogfileTestdoxText()) { throw new LoggingNotConfiguredException; } return $this->logfileTestdoxText; } /** * @phpstan-assert-if-true !null $this->logEventsText */ public function hasLogEventsText(): bool { return $this->logEventsText !== null; } /** * @throws LoggingNotConfiguredException */ public function logEventsText(): string { if (!$this->hasLogEventsText()) { throw new LoggingNotConfiguredException; } return $this->logEventsText; } /** * @phpstan-assert-if-true !null $this->logEventsVerboseText */ public function hasLogEventsVerboseText(): bool { return $this->logEventsVerboseText !== null; } /** * @throws LoggingNotConfiguredException */ public function logEventsVerboseText(): string { if (!$this->hasLogEventsVerboseText()) { throw new LoggingNotConfiguredException; } return $this->logEventsVerboseText; } public function outputIsTeamCity(): bool { return $this->teamCityOutput; } public function outputIsTestDox(): bool { return $this->testDoxOutput; } public function testDoxOutputWithSummary(): bool { return $this->testDoxOutputSummary; } /** * @phpstan-assert-if-true !empty $this->testsCovering */ public function hasTestsCovering(): bool { return !empty($this->testsCovering); } /** * @throws FilterNotConfiguredException * * @return list<string> */ public function testsCovering(): array { if (!$this->hasTestsCovering()) { throw new FilterNotConfiguredException; } return $this->testsCovering; } /** * @phpstan-assert-if-true !empty $this->testsUsing */ public function hasTestsUsing(): bool { return !empty($this->testsUsing); } /** * @throws FilterNotConfiguredException * * @return list<string> */ public function testsUsing(): array { if (!$this->hasTestsUsing()) { throw new FilterNotConfiguredException; } return $this->testsUsing; } /** * @phpstan-assert-if-true !null $this->filter */ public function hasFilter(): bool { return $this->filter !== null; } /** * @throws FilterNotConfiguredException */ public function filter(): string { if (!$this->hasFilter()) { throw new FilterNotConfiguredException; } return $this->filter; } /** * @phpstan-assert-if-true !null $this->excludeFilter */ public function hasExcludeFilter(): bool { return $this->excludeFilter !== null; } /** * @throws FilterNotConfiguredException */ public function excludeFilter(): string { if (!$this->hasExcludeFilter()) { throw new FilterNotConfiguredException; } return $this->excludeFilter; } /** * @phpstan-assert-if-true !empty $this->groups */ public function hasGroups(): bool { return !empty($this->groups); } /** * @throws FilterNotConfiguredException * * @return non-empty-list<non-empty-string> */ public function groups(): array { if (!$this->hasGroups()) { throw new FilterNotConfiguredException; } return $this->groups; } /** * @phpstan-assert-if-true !empty $this->excludeGroups */ public function hasExcludeGroups(): bool { return !empty($this->excludeGroups); } /** * @throws FilterNotConfiguredException * * @return non-empty-list<non-empty-string> */ public function excludeGroups(): array { if (!$this->hasExcludeGroups()) { throw new FilterNotConfiguredException; } return $this->excludeGroups; } public function randomOrderSeed(): int { return $this->randomOrderSeed; } public function includeUncoveredFiles(): bool { return $this->includeUncoveredFiles; } public function testSuite(): TestSuiteCollection { return $this->testSuite; } public function includeTestSuite(): string { return $this->includeTestSuite; } public function excludeTestSuite(): string { return $this->excludeTestSuite; } /** * @phpstan-assert-if-true !null $this->defaultTestSuite */ public function hasDefaultTestSuite(): bool { return $this->defaultTestSuite !== null; } /** * @throws NoDefaultTestSuiteException */ public function defaultTestSuite(): string { if (!$this->hasDefaultTestSuite()) { throw new NoDefaultTestSuiteException; } return $this->defaultTestSuite; } /** * @return non-empty-list<non-empty-string> */ public function testSuffixes(): array { return $this->testSuffixes; } public function php(): Php { return $this->php; } public function controlGarbageCollector(): bool { return $this->controlGarbageCollector; } public function numberOfTestsBeforeGarbageCollection(): int { return $this->numberOfTestsBeforeGarbageCollection; } /** * @phpstan-assert-if-true !null $this->generateBaseline */ public function hasGenerateBaseline(): bool { return $this->generateBaseline !== null; } /** * @throws NoBaselineException */ public function generateBaseline(): string { if (!$this->hasGenerateBaseline()) { throw new NoBaselineException; } return $this->generateBaseline; } public function debug(): bool { return $this->debug; } /** * @return non-negative-int */ public function shortenArraysForExportThreshold(): int { return $this->shortenArraysForExportThreshold; } } phpunit/src/TextUI/Configuration/Registry.php 0000644 00000006621 15253321353 0015343 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function assert; use function file_get_contents; use function file_put_contents; use function serialize; use function unserialize; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\TextUI\CliArguments\Configuration as CliConfiguration; use PHPUnit\TextUI\CliArguments\Exception; use PHPUnit\TextUI\XmlConfiguration\Configuration as XmlConfiguration; use PHPUnit\Util\VersionComparisonOperator; /** * CLI options and XML configuration are static within a single PHPUnit process. * It is therefore okay to use a Singleton registry here. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Registry { private static ?Configuration $instance = null; public static function saveTo(string $path): bool { $result = file_put_contents( $path, serialize(self::get()), ); if ($result) { return true; } // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd } /** * This method is used by the "run test(s) in separate process" templates. * * @noinspection PhpUnused * * @codeCoverageIgnore */ public static function loadFrom(string $path): void { $buffer = file_get_contents($path); assert($buffer !== false); self::$instance = unserialize( $buffer, [ 'allowed_classes' => [ Configuration::class, Php::class, ConstantCollection::class, Constant::class, IniSettingCollection::class, IniSetting::class, VariableCollection::class, Variable::class, DirectoryCollection::class, Directory::class, FileCollection::class, File::class, FilterDirectoryCollection::class, FilterDirectory::class, TestDirectoryCollection::class, TestDirectory::class, TestFileCollection::class, TestFile::class, TestSuiteCollection::class, TestSuite::class, VersionComparisonOperator::class, Source::class, ], ], ); } public static function get(): Configuration { assert(self::$instance instanceof Configuration); return self::$instance; } /** * @throws \PHPUnit\TextUI\XmlConfiguration\Exception * @throws Exception * @throws NoCustomCssFileException */ public static function init(CliConfiguration $cliConfiguration, XmlConfiguration $xmlConfiguration): Configuration { self::$instance = (new Merger)->merge($cliConfiguration, $xmlConfiguration); EventFacade::emitter()->testRunnerConfigured(self::$instance); return self::$instance; } } phpunit/src/TextUI/Configuration/Value/FileCollection.php 0000644 00000002476 15253321353 0017506 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, File> */ final readonly class FileCollection implements Countable, IteratorAggregate { /** * @var list<File> */ private array $files; /** * @param list<File> $files */ public static function fromArray(array $files): self { return new self(...$files); } private function __construct(File ...$files) { $this->files = $files; } /** * @return list<File> */ public function asArray(): array { return $this->files; } public function count(): int { return count($this->files); } public function notEmpty(): bool { return !empty($this->files); } public function getIterator(): FileCollectionIterator { return new FileCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/Constant.php 0000644 00000001457 15253321353 0016402 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Constant { private string $name; private bool|string $value; public function __construct(string $name, bool|string $value) { $this->name = $name; $this->value = $value; } public function name(): string { return $this->name; } public function value(): bool|string { return $this->value; } } phpunit/src/TextUI/Configuration/Value/DirectoryCollection.php 0000644 00000002633 15253321353 0020566 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, Directory> */ final readonly class DirectoryCollection implements Countable, IteratorAggregate { /** * @var list<Directory> */ private array $directories; /** * @param list<Directory> $directories */ public static function fromArray(array $directories): self { return new self(...$directories); } private function __construct(Directory ...$directories) { $this->directories = $directories; } /** * @return list<Directory> */ public function asArray(): array { return $this->directories; } public function count(): int { return count($this->directories); } public function getIterator(): DirectoryCollectionIterator { return new DirectoryCollectionIterator($this); } public function isEmpty(): bool { return $this->count() === 0; } } phpunit/src/TextUI/Configuration/Value/ConstantCollectionIterator.php 0000644 00000002315 15253321353 0022122 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, Constant> */ final class ConstantCollectionIterator implements Iterator { /** * @var list<Constant> */ private readonly array $constants; private int $position = 0; public function __construct(ConstantCollection $constants) { $this->constants = $constants->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->constants); } public function key(): int { return $this->position; } public function current(): Constant { return $this->constants[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollectionIterator.php 0000644 00000002473 15253321353 0024210 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, ExtensionBootstrap> */ final class ExtensionBootstrapCollectionIterator implements Iterator { /** * @var list<ExtensionBootstrap> */ private readonly array $extensionBootstraps; private int $position = 0; public function __construct(ExtensionBootstrapCollection $extensionBootstraps) { $this->extensionBootstraps = $extensionBootstraps->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->extensionBootstraps); } public function key(): int { return $this->position; } public function current(): ExtensionBootstrap { return $this->extensionBootstraps[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/TestSuite.php 0000644 00000002620 15253321353 0016533 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class TestSuite { /** * @var non-empty-string */ private string $name; private TestDirectoryCollection $directories; private TestFileCollection $files; private FileCollection $exclude; /** * @param non-empty-string $name */ public function __construct(string $name, TestDirectoryCollection $directories, TestFileCollection $files, FileCollection $exclude) { $this->name = $name; $this->directories = $directories; $this->files = $files; $this->exclude = $exclude; } /** * @return non-empty-string */ public function name(): string { return $this->name; } public function directories(): TestDirectoryCollection { return $this->directories; } public function files(): TestFileCollection { return $this->files; } public function exclude(): FileCollection { return $this->exclude; } } phpunit/src/TextUI/Configuration/Value/IniSettingCollectionIterator.php 0000644 00000002343 15253321353 0022407 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, IniSetting> */ final class IniSettingCollectionIterator implements Iterator { /** * @var list<IniSetting> */ private readonly array $iniSettings; private int $position = 0; public function __construct(IniSettingCollection $iniSettings) { $this->iniSettings = $iniSettings->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->iniSettings); } public function key(): int { return $this->position; } public function current(): IniSetting { return $this->iniSettings[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/VariableCollectionIterator.php 0000644 00000002315 15253321353 0022056 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, Variable> */ final class VariableCollectionIterator implements Iterator { /** * @var list<Variable> */ private readonly array $variables; private int $position = 0; public function __construct(VariableCollection $variables) { $this->variables = $variables->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->variables); } public function key(): int { return $this->position; } public function current(): Variable { return $this->variables[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/ExtensionBootstrapCollection.php 0000644 00000002507 15253321353 0022474 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, ExtensionBootstrap> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class ExtensionBootstrapCollection implements IteratorAggregate { /** * @var list<ExtensionBootstrap> */ private array $extensionBootstraps; /** * @param list<ExtensionBootstrap> $extensionBootstraps */ public static function fromArray(array $extensionBootstraps): self { return new self(...$extensionBootstraps); } private function __construct(ExtensionBootstrap ...$extensionBootstraps) { $this->extensionBootstraps = $extensionBootstraps; } /** * @return list<ExtensionBootstrap> */ public function asArray(): array { return $this->extensionBootstraps; } public function getIterator(): ExtensionBootstrapCollectionIterator { return new ExtensionBootstrapCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/Group.php 0000644 00000001205 15253321353 0015674 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Group { private string $name; public function __construct(string $name) { $this->name = $name; } public function name(): string { return $this->name; } } phpunit/src/TextUI/Configuration/Value/GroupCollection.php 0000644 00000002702 15253321353 0017713 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, Group> */ final readonly class GroupCollection implements IteratorAggregate { /** * @var list<Group> */ private array $groups; /** * @param list<Group> $groups */ public static function fromArray(array $groups): self { return new self(...$groups); } private function __construct(Group ...$groups) { $this->groups = $groups; } /** * @return list<Group> */ public function asArray(): array { return $this->groups; } /** * @return list<string> */ public function asArrayOfStrings(): array { $result = []; foreach ($this->groups as $group) { $result[] = $group->name(); } return $result; } public function isEmpty(): bool { return empty($this->groups); } public function getIterator(): GroupCollectionIterator { return new GroupCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/DirectoryCollectionIterator.php 0000644 00000002336 15253321353 0022300 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, Directory> */ final class DirectoryCollectionIterator implements Iterator { /** * @var list<Directory> */ private readonly array $directories; private int $position = 0; public function __construct(DirectoryCollection $directories) { $this->directories = $directories->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->directories); } public function key(): int { return $this->position; } public function current(): Directory { return $this->directories[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/FileCollectionIterator.php 0000644 00000002241 15253321353 0021206 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, File> */ final class FileCollectionIterator implements Iterator { /** * @var list<File> */ private readonly array $files; private int $position = 0; public function __construct(FileCollection $files) { $this->files = $files->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->files); } public function key(): int { return $this->position; } public function current(): File { return $this->files[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/TestSuiteCollection.php 0000644 00000002622 15253321353 0020551 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, TestSuite> */ final readonly class TestSuiteCollection implements Countable, IteratorAggregate { /** * @var list<TestSuite> */ private array $testSuites; /** * @param list<TestSuite> $testSuites */ public static function fromArray(array $testSuites): self { return new self(...$testSuites); } private function __construct(TestSuite ...$testSuites) { $this->testSuites = $testSuites; } /** * @return list<TestSuite> */ public function asArray(): array { return $this->testSuites; } public function count(): int { return count($this->testSuites); } public function getIterator(): TestSuiteCollectionIterator { return new TestSuiteCollectionIterator($this); } public function isEmpty(): bool { return $this->count() === 0; } } phpunit/src/TextUI/Configuration/Value/TestDirectoryCollectionIterator.php 0000644 00000002362 15253321353 0023137 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, TestDirectory> */ final class TestDirectoryCollectionIterator implements Iterator { /** * @var list<TestDirectory> */ private readonly array $directories; private int $position = 0; public function __construct(TestDirectoryCollection $directories) { $this->directories = $directories->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->directories); } public function key(): int { return $this->position; } public function current(): TestDirectory { return $this->directories[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/File.php 0000644 00000001426 15253321353 0015464 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class File { /** * @var non-empty-string */ private string $path; /** * @param non-empty-string $path */ public function __construct(string $path) { $this->path = $path; } /** * @return non-empty-string */ public function path(): string { return $this->path; } } phpunit/src/TextUI/Configuration/Value/TestFileCollection.php 0000644 00000002535 15253321353 0020342 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, TestFile> */ final readonly class TestFileCollection implements Countable, IteratorAggregate { /** * @var list<TestFile> */ private array $files; /** * @param list<TestFile> $files */ public static function fromArray(array $files): self { return new self(...$files); } private function __construct(TestFile ...$files) { $this->files = $files; } /** * @return list<TestFile> */ public function asArray(): array { return $this->files; } public function count(): int { return count($this->files); } public function getIterator(): TestFileCollectionIterator { return new TestFileCollectionIterator($this); } public function isEmpty(): bool { return $this->count() === 0; } } phpunit/src/TextUI/Configuration/Value/TestFile.php 0000644 00000003163 15253321353 0016324 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use PHPUnit\Util\VersionComparisonOperator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class TestFile { /** * @var non-empty-string */ private string $path; private string $phpVersion; private VersionComparisonOperator $phpVersionOperator; /** * @var list<non-empty-string> */ private array $groups; /** * @param non-empty-string $path * @param list<non-empty-string> $groups */ public function __construct(string $path, string $phpVersion, VersionComparisonOperator $phpVersionOperator, array $groups) { $this->path = $path; $this->phpVersion = $phpVersion; $this->phpVersionOperator = $phpVersionOperator; $this->groups = $groups; } /** * @return non-empty-string */ public function path(): string { return $this->path; } public function phpVersion(): string { return $this->phpVersion; } public function phpVersionOperator(): VersionComparisonOperator { return $this->phpVersionOperator; } /** * @return list<non-empty-string> */ public function groups(): array { return $this->groups; } } phpunit/src/TextUI/Configuration/Value/Php.php 0000644 00000006072 15253321353 0015336 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Php { private DirectoryCollection $includePaths; private IniSettingCollection $iniSettings; private ConstantCollection $constants; private VariableCollection $globalVariables; private VariableCollection $envVariables; private VariableCollection $postVariables; private VariableCollection $getVariables; private VariableCollection $cookieVariables; private VariableCollection $serverVariables; private VariableCollection $filesVariables; private VariableCollection $requestVariables; public function __construct(DirectoryCollection $includePaths, IniSettingCollection $iniSettings, ConstantCollection $constants, VariableCollection $globalVariables, VariableCollection $envVariables, VariableCollection $postVariables, VariableCollection $getVariables, VariableCollection $cookieVariables, VariableCollection $serverVariables, VariableCollection $filesVariables, VariableCollection $requestVariables) { $this->includePaths = $includePaths; $this->iniSettings = $iniSettings; $this->constants = $constants; $this->globalVariables = $globalVariables; $this->envVariables = $envVariables; $this->postVariables = $postVariables; $this->getVariables = $getVariables; $this->cookieVariables = $cookieVariables; $this->serverVariables = $serverVariables; $this->filesVariables = $filesVariables; $this->requestVariables = $requestVariables; } public function includePaths(): DirectoryCollection { return $this->includePaths; } public function iniSettings(): IniSettingCollection { return $this->iniSettings; } public function constants(): ConstantCollection { return $this->constants; } public function globalVariables(): VariableCollection { return $this->globalVariables; } public function envVariables(): VariableCollection { return $this->envVariables; } public function postVariables(): VariableCollection { return $this->postVariables; } public function getVariables(): VariableCollection { return $this->getVariables; } public function cookieVariables(): VariableCollection { return $this->cookieVariables; } public function serverVariables(): VariableCollection { return $this->serverVariables; } public function filesVariables(): VariableCollection { return $this->filesVariables; } public function requestVariables(): VariableCollection { return $this->requestVariables; } } phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollectionIterator.php 0000644 00000002374 15253321353 0023450 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, FilterDirectory> */ final class FilterDirectoryCollectionIterator implements Iterator { /** * @var list<FilterDirectory> */ private readonly array $directories; private int $position = 0; public function __construct(FilterDirectoryCollection $directories) { $this->directories = $directories->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->directories); } public function key(): int { return $this->position; } public function current(): FilterDirectory { return $this->directories[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/TestSuiteCollectionIterator.php 0000644 00000002330 15253321353 0022257 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, TestSuite> */ final class TestSuiteCollectionIterator implements Iterator { /** * @var list<TestSuite> */ private readonly array $testSuites; private int $position = 0; public function __construct(TestSuiteCollection $testSuites) { $this->testSuites = $testSuites->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->testSuites); } public function key(): int { return $this->position; } public function current(): TestSuite { return $this->testSuites[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/IniSettingCollection.php 0000644 00000002515 15253321353 0020676 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, IniSetting> */ final readonly class IniSettingCollection implements Countable, IteratorAggregate { /** * @var list<IniSetting> */ private array $iniSettings; /** * @param list<IniSetting> $iniSettings */ public static function fromArray(array $iniSettings): self { return new self(...$iniSettings); } private function __construct(IniSetting ...$iniSettings) { $this->iniSettings = $iniSettings; } /** * @return list<IniSetting> */ public function asArray(): array { return $this->iniSettings; } public function count(): int { return count($this->iniSettings); } public function getIterator(): IniSettingCollectionIterator { return new IniSettingCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/Variable.php 0000644 00000001656 15253321353 0016337 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Variable { private string $name; private mixed $value; private bool $force; public function __construct(string $name, mixed $value, bool $force) { $this->name = $name; $this->value = $value; $this->force = $force; } public function name(): string { return $this->name; } public function value(): mixed { return $this->value; } public function force(): bool { return $this->force; } } phpunit/src/TextUI/Configuration/Value/VariableCollection.php 0000644 00000002453 15253321353 0020347 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, Variable> */ final readonly class VariableCollection implements Countable, IteratorAggregate { /** * @var list<Variable> */ private array $variables; /** * @param list<Variable> $variables */ public static function fromArray(array $variables): self { return new self(...$variables); } private function __construct(Variable ...$variables) { $this->variables = $variables; } /** * @return list<Variable> */ public function asArray(): array { return $this->variables; } public function count(): int { return count($this->variables); } public function getIterator(): VariableCollectionIterator { return new VariableCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/TestDirectory.php 0000644 00000003712 15253321353 0017411 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use PHPUnit\Util\VersionComparisonOperator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class TestDirectory { /** * @var non-empty-string */ private string $path; private string $prefix; private string $suffix; private string $phpVersion; private VersionComparisonOperator $phpVersionOperator; /** * @var list<non-empty-string> */ private array $groups; /** * @param non-empty-string $path * @param list<non-empty-string> $groups */ public function __construct(string $path, string $prefix, string $suffix, string $phpVersion, VersionComparisonOperator $phpVersionOperator, array $groups) { $this->path = $path; $this->prefix = $prefix; $this->suffix = $suffix; $this->phpVersion = $phpVersion; $this->phpVersionOperator = $phpVersionOperator; $this->groups = $groups; } /** * @return non-empty-string */ public function path(): string { return $this->path; } public function prefix(): string { return $this->prefix; } public function suffix(): string { return $this->suffix; } public function phpVersion(): string { return $this->phpVersion; } public function phpVersionOperator(): VersionComparisonOperator { return $this->phpVersionOperator; } /** * @return list<non-empty-string> */ public function groups(): array { return $this->groups; } } phpunit/src/TextUI/Configuration/Value/TestFileCollectionIterator.php 0000644 00000002265 15253321353 0022054 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, TestFile> */ final class TestFileCollectionIterator implements Iterator { /** * @var list<TestFile> */ private readonly array $files; private int $position = 0; public function __construct(TestFileCollection $files) { $this->files = $files->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->files); } public function key(): int { return $this->position; } public function current(): TestFile { return $this->files[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/Value/TestDirectoryCollection.php 0000644 00000002673 15253321353 0021432 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, TestDirectory> */ final readonly class TestDirectoryCollection implements Countable, IteratorAggregate { /** * @var list<TestDirectory> */ private array $directories; /** * @param list<TestDirectory> $directories */ public static function fromArray(array $directories): self { return new self(...$directories); } private function __construct(TestDirectory ...$directories) { $this->directories = $directories; } /** * @return list<TestDirectory> */ public function asArray(): array { return $this->directories; } public function count(): int { return count($this->directories); } public function getIterator(): TestDirectoryCollectionIterator { return new TestDirectoryCollectionIterator($this); } public function isEmpty(): bool { return $this->count() === 0; } } phpunit/src/TextUI/Configuration/Value/Source.php 0000644 00000015312 15253321353 0016044 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Source { /** * @var non-empty-string */ private ?string $baseline; private bool $ignoreBaseline; private FilterDirectoryCollection $includeDirectories; private FileCollection $includeFiles; private FilterDirectoryCollection $excludeDirectories; private FileCollection $excludeFiles; private bool $restrictDeprecations; private bool $restrictNotices; private bool $restrictWarnings; private bool $ignoreSuppressionOfDeprecations; private bool $ignoreSuppressionOfPhpDeprecations; private bool $ignoreSuppressionOfErrors; private bool $ignoreSuppressionOfNotices; private bool $ignoreSuppressionOfPhpNotices; private bool $ignoreSuppressionOfWarnings; private bool $ignoreSuppressionOfPhpWarnings; private bool $ignoreSelfDeprecations; private bool $ignoreDirectDeprecations; private bool $ignoreIndirectDeprecations; /** * @var array{functions: list<non-empty-string>, methods: list<non-empty-string>} */ private array $deprecationTriggers; /** * @param non-empty-string $baseline * @param array{functions: list<non-empty-string>, methods: list<non-empty-string>} $deprecationTriggers */ public function __construct(?string $baseline, bool $ignoreBaseline, FilterDirectoryCollection $includeDirectories, FileCollection $includeFiles, FilterDirectoryCollection $excludeDirectories, FileCollection $excludeFiles, bool $restrictDeprecations, bool $restrictNotices, bool $restrictWarnings, bool $ignoreSuppressionOfDeprecations, bool $ignoreSuppressionOfPhpDeprecations, bool $ignoreSuppressionOfErrors, bool $ignoreSuppressionOfNotices, bool $ignoreSuppressionOfPhpNotices, bool $ignoreSuppressionOfWarnings, bool $ignoreSuppressionOfPhpWarnings, array $deprecationTriggers, bool $ignoreSelfDeprecations, bool $ignoreDirectDeprecations, bool $ignoreIndirectDeprecations) { $this->baseline = $baseline; $this->ignoreBaseline = $ignoreBaseline; $this->includeDirectories = $includeDirectories; $this->includeFiles = $includeFiles; $this->excludeDirectories = $excludeDirectories; $this->excludeFiles = $excludeFiles; $this->restrictDeprecations = $restrictDeprecations; $this->restrictNotices = $restrictNotices; $this->restrictWarnings = $restrictWarnings; $this->ignoreSuppressionOfDeprecations = $ignoreSuppressionOfDeprecations; $this->ignoreSuppressionOfPhpDeprecations = $ignoreSuppressionOfPhpDeprecations; $this->ignoreSuppressionOfErrors = $ignoreSuppressionOfErrors; $this->ignoreSuppressionOfNotices = $ignoreSuppressionOfNotices; $this->ignoreSuppressionOfPhpNotices = $ignoreSuppressionOfPhpNotices; $this->ignoreSuppressionOfWarnings = $ignoreSuppressionOfWarnings; $this->ignoreSuppressionOfPhpWarnings = $ignoreSuppressionOfPhpWarnings; $this->deprecationTriggers = $deprecationTriggers; $this->ignoreSelfDeprecations = $ignoreSelfDeprecations; $this->ignoreDirectDeprecations = $ignoreDirectDeprecations; $this->ignoreIndirectDeprecations = $ignoreIndirectDeprecations; } /** * @phpstan-assert-if-true !null $this->baseline */ public function useBaseline(): bool { return $this->hasBaseline() && !$this->ignoreBaseline; } /** * @phpstan-assert-if-true !null $this->baseline */ public function hasBaseline(): bool { return $this->baseline !== null; } /** * @throws NoBaselineException * * @return non-empty-string */ public function baseline(): string { if (!$this->hasBaseline()) { throw new NoBaselineException; } return $this->baseline; } public function includeDirectories(): FilterDirectoryCollection { return $this->includeDirectories; } public function includeFiles(): FileCollection { return $this->includeFiles; } public function excludeDirectories(): FilterDirectoryCollection { return $this->excludeDirectories; } public function excludeFiles(): FileCollection { return $this->excludeFiles; } public function notEmpty(): bool { return $this->includeDirectories->notEmpty() || $this->includeFiles->notEmpty(); } public function restrictDeprecations(): bool { return $this->restrictDeprecations; } public function restrictNotices(): bool { return $this->restrictNotices; } public function restrictWarnings(): bool { return $this->restrictWarnings; } public function ignoreSuppressionOfDeprecations(): bool { return $this->ignoreSuppressionOfDeprecations; } public function ignoreSuppressionOfPhpDeprecations(): bool { return $this->ignoreSuppressionOfPhpDeprecations; } public function ignoreSuppressionOfErrors(): bool { return $this->ignoreSuppressionOfErrors; } public function ignoreSuppressionOfNotices(): bool { return $this->ignoreSuppressionOfNotices; } public function ignoreSuppressionOfPhpNotices(): bool { return $this->ignoreSuppressionOfPhpNotices; } public function ignoreSuppressionOfWarnings(): bool { return $this->ignoreSuppressionOfWarnings; } public function ignoreSuppressionOfPhpWarnings(): bool { return $this->ignoreSuppressionOfPhpWarnings; } /** * @return array{functions: list<non-empty-string>, methods: list<non-empty-string>} */ public function deprecationTriggers(): array { return $this->deprecationTriggers; } public function ignoreSelfDeprecations(): bool { return $this->ignoreSelfDeprecations; } public function ignoreDirectDeprecations(): bool { return $this->ignoreDirectDeprecations; } public function ignoreIndirectDeprecations(): bool { return $this->ignoreIndirectDeprecations; } } phpunit/src/TextUI/Configuration/Value/Directory.php 0000644 00000001211 15253321353 0016541 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Directory { private string $path; public function __construct(string $path) { $this->path = $path; } public function path(): string { return $this->path; } } phpunit/src/TextUI/Configuration/Value/FilterDirectory.php 0000644 00000002135 15253321353 0017715 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class FilterDirectory { /** * @var non-empty-string */ private string $path; private string $prefix; private string $suffix; /** * @param non-empty-string $path */ public function __construct(string $path, string $prefix, string $suffix) { $this->path = $path; $this->prefix = $prefix; $this->suffix = $suffix; } /** * @return non-empty-string */ public function path(): string { return $this->path; } public function prefix(): string { return $this->prefix; } public function suffix(): string { return $this->suffix; } } phpunit/src/TextUI/Configuration/Value/IniSetting.php 0000644 00000001442 15253321353 0016660 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class IniSetting { private string $name; private string $value; public function __construct(string $name, string $value) { $this->name = $name; $this->value = $value; } public function name(): string { return $this->name; } public function value(): string { return $this->value; } } phpunit/src/TextUI/Configuration/Value/FilterDirectoryCollection.php 0000644 00000002722 15253321353 0021733 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, FilterDirectory> */ final readonly class FilterDirectoryCollection implements Countable, IteratorAggregate { /** * @var list<FilterDirectory> */ private array $directories; /** * @param list<FilterDirectory> $directories */ public static function fromArray(array $directories): self { return new self(...$directories); } private function __construct(FilterDirectory ...$directories) { $this->directories = $directories; } /** * @return list<FilterDirectory> */ public function asArray(): array { return $this->directories; } public function count(): int { return count($this->directories); } public function notEmpty(): bool { return !empty($this->directories); } public function getIterator(): FilterDirectoryCollectionIterator { return new FilterDirectoryCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/ExtensionBootstrap.php 0000644 00000002223 15253321353 0020453 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class ExtensionBootstrap { /** * @var non-empty-string */ private string $className; /** * @var array<string,string> */ private array $parameters; /** * @param non-empty-string $className * @param array<string,string> $parameters */ public function __construct(string $className, array $parameters) { $this->className = $className; $this->parameters = $parameters; } /** * @return non-empty-string */ public function className(): string { return $this->className; } /** * @return array<string,string> */ public function parameters(): array { return $this->parameters; } } phpunit/src/TextUI/Configuration/Value/ConstantCollection.php 0000644 00000002453 15253321353 0020413 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Countable; use IteratorAggregate; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable * * @template-implements IteratorAggregate<int, Constant> */ final readonly class ConstantCollection implements Countable, IteratorAggregate { /** * @var list<Constant> */ private array $constants; /** * @param list<Constant> $constants */ public static function fromArray(array $constants): self { return new self(...$constants); } private function __construct(Constant ...$constants) { $this->constants = $constants; } /** * @return list<Constant> */ public function asArray(): array { return $this->constants; } public function count(): int { return count($this->constants); } public function getIterator(): ConstantCollectionIterator { return new ConstantCollectionIterator($this); } } phpunit/src/TextUI/Configuration/Value/GroupCollectionIterator.php 0000644 00000002254 15253321353 0021427 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function count; use Iterator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @template-implements Iterator<int, Group> */ final class GroupCollectionIterator implements Iterator { /** * @var list<Group> */ private readonly array $groups; private int $position = 0; public function __construct(GroupCollection $groups) { $this->groups = $groups->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->groups); } public function key(): int { return $this->position; } public function current(): Group { return $this->groups[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/TextUI/Configuration/SourceFilter.php 0000644 00000001277 15253321353 0016143 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class SourceFilter { public function includes(Source $source, string $path): bool { $files = (new SourceMapper)->map($source); return isset($files[$path]); } } phpunit/src/TextUI/Configuration/PhpHandler.php 0000644 00000007465 15253321353 0015567 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use const PATH_SEPARATOR; use function constant; use function define; use function defined; use function getenv; use function implode; use function ini_get; use function ini_set; use function putenv; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class PhpHandler { public function handle(Php $configuration): void { $this->handleIncludePaths($configuration->includePaths()); $this->handleIniSettings($configuration->iniSettings()); $this->handleConstants($configuration->constants()); $this->handleGlobalVariables($configuration->globalVariables()); $this->handleServerVariables($configuration->serverVariables()); $this->handleEnvVariables($configuration->envVariables()); $this->handleVariables('_POST', $configuration->postVariables()); $this->handleVariables('_GET', $configuration->getVariables()); $this->handleVariables('_COOKIE', $configuration->cookieVariables()); $this->handleVariables('_FILES', $configuration->filesVariables()); $this->handleVariables('_REQUEST', $configuration->requestVariables()); } private function handleIncludePaths(DirectoryCollection $includePaths): void { if (!$includePaths->isEmpty()) { $includePathsAsStrings = []; foreach ($includePaths as $includePath) { $includePathsAsStrings[] = $includePath->path(); } ini_set( 'include_path', implode(PATH_SEPARATOR, $includePathsAsStrings) . PATH_SEPARATOR . ini_get('include_path'), ); } } private function handleIniSettings(IniSettingCollection $iniSettings): void { foreach ($iniSettings as $iniSetting) { $value = $iniSetting->value(); if (defined($value)) { $value = (string) constant($value); } ini_set($iniSetting->name(), $value); } } private function handleConstants(ConstantCollection $constants): void { foreach ($constants as $constant) { if (!defined($constant->name())) { define($constant->name(), $constant->value()); } } } private function handleGlobalVariables(VariableCollection $variables): void { foreach ($variables as $variable) { $GLOBALS[$variable->name()] = $variable->value(); } } private function handleServerVariables(VariableCollection $variables): void { foreach ($variables as $variable) { $_SERVER[$variable->name()] = $variable->value(); } } private function handleVariables(string $target, VariableCollection $variables): void { foreach ($variables as $variable) { $GLOBALS[$target][$variable->name()] = $variable->value(); } } private function handleEnvVariables(VariableCollection $variables): void { foreach ($variables as $variable) { $name = $variable->name(); $value = $variable->value(); $force = $variable->force(); if ($force || getenv($name) === false) { putenv("{$name}={$value}"); } $value = getenv($name); if ($force || !isset($_ENV[$name])) { $_ENV[$name] = $value; } } } } phpunit/src/TextUI/Configuration/Cli/Exception.php 0000644 00000001132 15253321353 0016170 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\CliArguments; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Exception extends RuntimeException implements \PHPUnit\Exception { } phpunit/src/TextUI/Configuration/Cli/Builder.php 0000644 00000077344 15253321353 0015642 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\CliArguments; use const DIRECTORY_SEPARATOR; use function array_map; use function array_merge; use function assert; use function basename; use function explode; use function getcwd; use function is_file; use function is_numeric; use function sprintf; use function str_contains; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\Util\Filesystem; use SebastianBergmann\CliParser\Exception as CliParserException; use SebastianBergmann\CliParser\Parser as CliParser; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Builder { private const LONG_OPTIONS = [ 'atleast-version=', 'bootstrap=', 'cache-result', 'do-not-cache-result', 'cache-directory=', 'check-version', 'colors==', 'columns=', 'configuration=', 'warm-coverage-cache', 'coverage-filter=', 'coverage-clover=', 'coverage-cobertura=', 'coverage-crap4j=', 'coverage-html=', 'coverage-php=', 'coverage-text==', 'only-summary-for-coverage-text', 'show-uncovered-for-coverage-text', 'coverage-xml=', 'path-coverage', 'disallow-test-output', 'display-incomplete', 'display-skipped', 'display-deprecations', 'display-errors', 'display-notices', 'display-warnings', 'default-time-limit=', 'enforce-time-limit', 'exclude-group=', 'filter=', 'exclude-filter=', 'generate-baseline=', 'use-baseline=', 'ignore-baseline', 'generate-configuration', 'globals-backup', 'group=', 'covers=', 'uses=', 'help', 'resolve-dependencies', 'ignore-dependencies', 'include-path=', 'list-groups', 'list-suites', 'list-test-files', 'list-tests', 'list-tests-xml=', 'log-junit=', 'log-teamcity=', 'migrate-configuration', 'no-configuration', 'no-coverage', 'no-logging', 'no-extensions', 'no-output', 'no-progress', 'no-results', 'order-by=', 'process-isolation', 'dont-report-useless-tests', 'random-order', 'random-order-seed=', 'reverse-order', 'reverse-list', 'static-backup', 'stderr', 'fail-on-deprecation', 'fail-on-empty-test-suite', 'fail-on-incomplete', 'fail-on-notice', 'fail-on-risky', 'fail-on-skipped', 'fail-on-warning', 'stop-on-defect', 'stop-on-deprecation', 'stop-on-error', 'stop-on-failure', 'stop-on-incomplete', 'stop-on-notice', 'stop-on-risky', 'stop-on-skipped', 'stop-on-warning', 'strict-coverage', 'disable-coverage-ignore', 'strict-global-state', 'teamcity', 'testdox', 'testdox-summary', 'testdox-html=', 'testdox-text=', 'test-suffix=', 'testsuite=', 'exclude-testsuite=', 'log-events-text=', 'log-events-verbose-text=', 'version', 'debug', 'extension=', ]; private const SHORT_OPTIONS = 'd:c:h'; /** * @var array<string, non-negative-int> */ private array $processed = []; /** * @param list<string> $parameters * * @throws Exception */ public function fromParameters(array $parameters): Configuration { try { $options = (new CliParser)->parse( $parameters, self::SHORT_OPTIONS, self::LONG_OPTIONS, ); } catch (CliParserException $e) { throw new Exception( $e->getMessage(), $e->getCode(), $e, ); } $atLeastVersion = null; $backupGlobals = null; $backupStaticProperties = null; $beStrictAboutChangesToGlobalState = null; $bootstrap = null; $cacheDirectory = null; $cacheResult = null; $checkVersion = false; $colors = null; $columns = null; $configuration = null; $warmCoverageCache = false; $coverageFilter = null; $coverageClover = null; $coverageCobertura = null; $coverageCrap4J = null; $coverageHtml = null; $coveragePhp = null; $coverageText = null; $coverageTextShowUncoveredFiles = null; $coverageTextShowOnlySummary = null; $coverageXml = null; $pathCoverage = null; $defaultTimeLimit = null; $disableCodeCoverageIgnore = null; $disallowTestOutput = null; $displayIncomplete = null; $displaySkipped = null; $displayDeprecations = null; $displayErrors = null; $displayNotices = null; $displayWarnings = null; $enforceTimeLimit = null; $excludeGroups = null; $executionOrder = null; $executionOrderDefects = null; $failOnDeprecation = null; $failOnEmptyTestSuite = null; $failOnIncomplete = null; $failOnNotice = null; $failOnRisky = null; $failOnSkipped = null; $failOnWarning = null; $stopOnDefect = null; $stopOnDeprecation = null; $stopOnError = null; $stopOnFailure = null; $stopOnIncomplete = null; $stopOnNotice = null; $stopOnRisky = null; $stopOnSkipped = null; $stopOnWarning = null; $filter = null; $excludeFilter = null; $generateBaseline = null; $useBaseline = null; $ignoreBaseline = false; $generateConfiguration = false; $migrateConfiguration = false; $groups = null; $testsCovering = null; $testsUsing = null; $help = false; $includePath = null; $iniSettings = []; $junitLogfile = null; $listGroups = false; $listSuites = false; $listTestFiles = false; $listTests = false; $listTestsXml = null; $noCoverage = null; $noExtensions = null; $noOutput = null; $noProgress = null; $noResults = null; $noLogging = null; $processIsolation = null; $randomOrderSeed = null; $reportUselessTests = null; $resolveDependencies = null; $reverseList = null; $stderr = null; $strictCoverage = null; $teamcityLogfile = null; $testdoxHtmlFile = null; $testdoxTextFile = null; $testSuffixes = null; $testSuite = null; $excludeTestSuite = null; $useDefaultConfiguration = true; $version = false; $logEventsText = null; $logEventsVerboseText = null; $printerTeamCity = null; $printerTestDox = null; $printerTestDoxSummary = null; $debug = false; $extensions = []; foreach ($options[0] as $option) { $optionAllowedMultipleTimes = false; switch ($option[0]) { case '--colors': $colors = $option[1] ?: \PHPUnit\TextUI\Configuration\Configuration::COLOR_AUTO; break; case '--bootstrap': $bootstrap = $option[1]; break; case '--cache-directory': $cacheDirectory = $option[1]; break; case '--cache-result': $cacheResult = true; break; case '--do-not-cache-result': $cacheResult = false; break; case '--columns': if (is_numeric($option[1])) { $columns = (int) $option[1]; } elseif ($option[1] === 'max') { $columns = 'max'; } break; case 'c': case '--configuration': $configuration = $option[1]; break; case '--warm-coverage-cache': $warmCoverageCache = true; break; case '--coverage-clover': $coverageClover = $option[1]; break; case '--coverage-cobertura': $coverageCobertura = $option[1]; break; case '--coverage-crap4j': $coverageCrap4J = $option[1]; break; case '--coverage-html': $coverageHtml = $option[1]; break; case '--coverage-php': $coveragePhp = $option[1]; break; case '--coverage-text': if ($option[1] === null) { $option[1] = 'php://stdout'; } $coverageText = $option[1]; break; case '--only-summary-for-coverage-text': $coverageTextShowOnlySummary = true; break; case '--show-uncovered-for-coverage-text': $coverageTextShowUncoveredFiles = true; break; case '--coverage-xml': $coverageXml = $option[1]; break; case '--path-coverage': $pathCoverage = true; break; case 'd': $tmp = explode('=', $option[1]); if (isset($tmp[0])) { assert($tmp[0] !== ''); if (isset($tmp[1])) { assert($tmp[1] !== ''); $iniSettings[$tmp[0]] = $tmp[1]; } else { $iniSettings[$tmp[0]] = '1'; } } $optionAllowedMultipleTimes = true; break; case 'h': case '--help': $help = true; break; case '--filter': $filter = $option[1]; break; case '--exclude-filter': $excludeFilter = $option[1]; break; case '--testsuite': $testSuite = $option[1]; break; case '--exclude-testsuite': $excludeTestSuite = $option[1]; break; case '--generate-baseline': $generateBaseline = $option[1]; if (basename($generateBaseline) === $generateBaseline) { $generateBaseline = getcwd() . DIRECTORY_SEPARATOR . $generateBaseline; } break; case '--use-baseline': $useBaseline = $option[1]; if (basename($useBaseline) === $useBaseline && !is_file($useBaseline)) { $useBaseline = getcwd() . DIRECTORY_SEPARATOR . $useBaseline; } break; case '--ignore-baseline': $ignoreBaseline = true; break; case '--generate-configuration': $generateConfiguration = true; break; case '--migrate-configuration': $migrateConfiguration = true; break; case '--group': if (str_contains($option[1], ',')) { EventFacade::emitter()->testRunnerTriggeredWarning( 'Using comma-separated values with --group is deprecated and will no longer work in PHPUnit 12. You can use --group multiple times instead.', ); } if ($groups === null) { $groups = []; } $groups = array_merge($groups, explode(',', $option[1])); $optionAllowedMultipleTimes = true; break; case '--exclude-group': if (str_contains($option[1], ',')) { EventFacade::emitter()->testRunnerTriggeredWarning( 'Using comma-separated values with --exclude-group is deprecated and will no longer work in PHPUnit 12. You can use --exclude-group multiple times instead.', ); } if ($excludeGroups === null) { $excludeGroups = []; } $excludeGroups = array_merge($excludeGroups, explode(',', $option[1])); $optionAllowedMultipleTimes = true; break; case '--covers': if (str_contains($option[1], ',')) { EventFacade::emitter()->testRunnerTriggeredWarning( 'Using comma-separated values with --covers is deprecated and will no longer work in PHPUnit 12. You can use --covers multiple times instead.', ); } if ($testsCovering === null) { $testsCovering = []; } $testsCovering = array_merge($testsCovering, array_map('strtolower', explode(',', $option[1]))); $optionAllowedMultipleTimes = true; break; case '--uses': if (str_contains($option[1], ',')) { EventFacade::emitter()->testRunnerTriggeredWarning( 'Using comma-separated values with --uses is deprecated and will no longer work in PHPUnit 12. You can use --uses multiple times instead.', ); } if ($testsUsing === null) { $testsUsing = []; } $testsUsing = array_merge($testsUsing, array_map('strtolower', explode(',', $option[1]))); $optionAllowedMultipleTimes = true; break; case '--test-suffix': if (str_contains($option[1], ',')) { EventFacade::emitter()->testRunnerTriggeredWarning( 'Using comma-separated values with --test-suffix is deprecated and will no longer work in PHPUnit 12. You can use --test-suffix multiple times instead.', ); } if ($testSuffixes === null) { $testSuffixes = []; } $testSuffixes = array_merge($testSuffixes, explode(',', $option[1])); $optionAllowedMultipleTimes = true; break; case '--include-path': $includePath = $option[1]; break; case '--list-groups': $listGroups = true; break; case '--list-suites': $listSuites = true; break; case '--list-test-files': $listTestFiles = true; break; case '--list-tests': $listTests = true; break; case '--list-tests-xml': $listTestsXml = $option[1]; break; case '--log-junit': $junitLogfile = $option[1]; break; case '--log-teamcity': $teamcityLogfile = $option[1]; break; case '--order-by': foreach (explode(',', $option[1]) as $order) { switch ($order) { case 'default': $executionOrder = TestSuiteSorter::ORDER_DEFAULT; $executionOrderDefects = TestSuiteSorter::ORDER_DEFAULT; $resolveDependencies = true; break; case 'defects': $executionOrderDefects = TestSuiteSorter::ORDER_DEFECTS_FIRST; break; case 'depends': $resolveDependencies = true; break; case 'duration': $executionOrder = TestSuiteSorter::ORDER_DURATION; break; case 'no-depends': $resolveDependencies = false; break; case 'random': $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; break; case 'reverse': $executionOrder = TestSuiteSorter::ORDER_REVERSED; break; case 'size': $executionOrder = TestSuiteSorter::ORDER_SIZE; break; default: throw new Exception( sprintf( 'unrecognized --order-by option: %s', $order, ), ); } } break; case '--process-isolation': $processIsolation = true; break; case '--stderr': $stderr = true; break; case '--fail-on-deprecation': $failOnDeprecation = true; break; case '--fail-on-empty-test-suite': $failOnEmptyTestSuite = true; break; case '--fail-on-incomplete': $failOnIncomplete = true; break; case '--fail-on-notice': $failOnNotice = true; break; case '--fail-on-risky': $failOnRisky = true; break; case '--fail-on-skipped': $failOnSkipped = true; break; case '--fail-on-warning': $failOnWarning = true; break; case '--stop-on-defect': $stopOnDefect = true; break; case '--stop-on-deprecation': $stopOnDeprecation = true; break; case '--stop-on-error': $stopOnError = true; break; case '--stop-on-failure': $stopOnFailure = true; break; case '--stop-on-incomplete': $stopOnIncomplete = true; break; case '--stop-on-notice': $stopOnNotice = true; break; case '--stop-on-risky': $stopOnRisky = true; break; case '--stop-on-skipped': $stopOnSkipped = true; break; case '--stop-on-warning': $stopOnWarning = true; break; case '--teamcity': $printerTeamCity = true; break; case '--testdox': $printerTestDox = true; break; case '--testdox-summary': $printerTestDoxSummary = true; break; case '--testdox-html': $testdoxHtmlFile = $option[1]; break; case '--testdox-text': $testdoxTextFile = $option[1]; break; case '--no-configuration': $useDefaultConfiguration = false; break; case '--no-extensions': $noExtensions = true; break; case '--no-coverage': $noCoverage = true; break; case '--no-logging': $noLogging = true; break; case '--no-output': $noOutput = true; break; case '--no-progress': $noProgress = true; break; case '--no-results': $noResults = true; break; case '--globals-backup': $backupGlobals = true; break; case '--static-backup': $backupStaticProperties = true; break; case '--atleast-version': $atLeastVersion = $option[1]; break; case '--version': $version = true; break; case '--dont-report-useless-tests': $reportUselessTests = false; break; case '--strict-coverage': $strictCoverage = true; break; case '--disable-coverage-ignore': $disableCodeCoverageIgnore = true; break; case '--strict-global-state': $beStrictAboutChangesToGlobalState = true; break; case '--disallow-test-output': $disallowTestOutput = true; break; case '--display-incomplete': $displayIncomplete = true; break; case '--display-skipped': $displaySkipped = true; break; case '--display-deprecations': $displayDeprecations = true; break; case '--display-errors': $displayErrors = true; break; case '--display-notices': $displayNotices = true; break; case '--display-warnings': $displayWarnings = true; break; case '--default-time-limit': $defaultTimeLimit = (int) $option[1]; break; case '--enforce-time-limit': $enforceTimeLimit = true; break; case '--reverse-list': $reverseList = true; break; case '--check-version': $checkVersion = true; break; case '--coverage-filter': if ($coverageFilter === null) { $coverageFilter = []; } $coverageFilter[] = $option[1]; $optionAllowedMultipleTimes = true; break; case '--random-order': $executionOrder = TestSuiteSorter::ORDER_RANDOMIZED; break; case '--random-order-seed': $randomOrderSeed = (int) $option[1]; break; case '--resolve-dependencies': $resolveDependencies = true; break; case '--ignore-dependencies': $resolveDependencies = false; break; case '--reverse-order': $executionOrder = TestSuiteSorter::ORDER_REVERSED; break; case '--log-events-text': $logEventsText = Filesystem::resolveStreamOrFile($option[1]); if ($logEventsText === false) { throw new Exception( sprintf( 'The path "%s" specified for the --log-events-text option could not be resolved', $option[1], ), ); } break; case '--log-events-verbose-text': $logEventsVerboseText = Filesystem::resolveStreamOrFile($option[1]); if ($logEventsVerboseText === false) { throw new Exception( sprintf( 'The path "%s" specified for the --log-events-verbose-text option could not be resolved', $option[1], ), ); } break; case '--debug': $debug = true; break; case '--extension': $extensions[] = $option[1]; $optionAllowedMultipleTimes = true; break; } if (!$optionAllowedMultipleTimes) { $this->markProcessed($option[0]); } } if (empty($iniSettings)) { $iniSettings = null; } if (empty($coverageFilter)) { $coverageFilter = null; } if (empty($extensions)) { $extensions = null; } return new Configuration( $options[1], $atLeastVersion, $backupGlobals, $backupStaticProperties, $beStrictAboutChangesToGlobalState, $bootstrap, $cacheDirectory, $cacheResult, $checkVersion, $colors, $columns, $configuration, $coverageClover, $coverageCobertura, $coverageCrap4J, $coverageHtml, $coveragePhp, $coverageText, $coverageTextShowUncoveredFiles, $coverageTextShowOnlySummary, $coverageXml, $pathCoverage, $warmCoverageCache, $defaultTimeLimit, $disableCodeCoverageIgnore, $disallowTestOutput, $enforceTimeLimit, $excludeGroups, $executionOrder, $executionOrderDefects, $failOnDeprecation, $failOnEmptyTestSuite, $failOnIncomplete, $failOnNotice, $failOnRisky, $failOnSkipped, $failOnWarning, $stopOnDefect, $stopOnDeprecation, $stopOnError, $stopOnFailure, $stopOnIncomplete, $stopOnNotice, $stopOnRisky, $stopOnSkipped, $stopOnWarning, $filter, $excludeFilter, $generateBaseline, $useBaseline, $ignoreBaseline, $generateConfiguration, $migrateConfiguration, $groups, $testsCovering, $testsUsing, $help, $includePath, $iniSettings, $junitLogfile, $listGroups, $listSuites, $listTestFiles, $listTests, $listTestsXml, $noCoverage, $noExtensions, $noOutput, $noProgress, $noResults, $noLogging, $processIsolation, $randomOrderSeed, $reportUselessTests, $resolveDependencies, $reverseList, $stderr, $strictCoverage, $teamcityLogfile, $testdoxHtmlFile, $testdoxTextFile, $testSuffixes, $testSuite, $excludeTestSuite, $useDefaultConfiguration, $displayIncomplete, $displaySkipped, $displayDeprecations, $displayErrors, $displayNotices, $displayWarnings, $version, $coverageFilter, $logEventsText, $logEventsVerboseText, $printerTeamCity, $printerTestDox, $printerTestDoxSummary, $debug, $extensions, ); } /** * @param non-empty-string $option */ private function markProcessed(string $option): void { if (!isset($this->processed[$option])) { $this->processed[$option] = 1; return; } $this->processed[$option]++; if ($this->processed[$option] === 2) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Option %s cannot be used more than once', $option, ), ); } } } phpunit/src/TextUI/Configuration/Cli/XmlConfigurationFileFinder.php 0000644 00000003742 15253321353 0021463 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\CliArguments; use function getcwd; use function is_dir; use function is_file; use function realpath; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class XmlConfigurationFileFinder { public function find(Configuration $configuration): false|string { $useDefaultConfiguration = $configuration->useDefaultConfiguration(); if ($configuration->hasConfigurationFile()) { if (is_dir($configuration->configurationFile())) { $candidate = $this->configurationFileInDirectory($configuration->configurationFile()); if ($candidate !== false) { return $candidate; } return false; } return $configuration->configurationFile(); } if ($useDefaultConfiguration) { $directory = getcwd(); if ($directory !== false) { $candidate = $this->configurationFileInDirectory($directory); if ($candidate !== false) { return $candidate; } } } return false; } private function configurationFileInDirectory(string $directory): false|string { $candidates = [ $directory . '/phpunit.xml', $directory . '/phpunit.dist.xml', $directory . '/phpunit.xml.dist', ]; foreach ($candidates as $candidate) { if (is_file($candidate)) { return realpath($candidate); } } return false; } } phpunit/src/TextUI/Configuration/Cli/Configuration.php 0000644 00000150153 15253321353 0017051 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\CliArguments; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class Configuration { /** * @var list<non-empty-string> */ private array $arguments; private ?string $atLeastVersion; private ?bool $backupGlobals; private ?bool $backupStaticProperties; private ?bool $beStrictAboutChangesToGlobalState; private ?string $bootstrap; private ?string $cacheDirectory; private ?bool $cacheResult; private bool $checkVersion; private ?string $colors; private null|int|string $columns; private ?string $configurationFile; /** * @var ?non-empty-list<non-empty-string> */ private ?array $coverageFilter; private ?string $coverageClover; private ?string $coverageCobertura; private ?string $coverageCrap4J; private ?string $coverageHtml; private ?string $coveragePhp; private ?string $coverageText; private ?bool $coverageTextShowUncoveredFiles; private ?bool $coverageTextShowOnlySummary; private ?string $coverageXml; private ?bool $pathCoverage; private bool $warmCoverageCache; private ?int $defaultTimeLimit; private ?bool $disableCodeCoverageIgnore; private ?bool $disallowTestOutput; private ?bool $enforceTimeLimit; /** * @var ?non-empty-list<non-empty-string> */ private ?array $excludeGroups; private ?int $executionOrder; private ?int $executionOrderDefects; private ?bool $failOnDeprecation; private ?bool $failOnEmptyTestSuite; private ?bool $failOnIncomplete; private ?bool $failOnNotice; private ?bool $failOnRisky; private ?bool $failOnSkipped; private ?bool $failOnWarning; private ?bool $stopOnDefect; private ?bool $stopOnDeprecation; private ?bool $stopOnError; private ?bool $stopOnFailure; private ?bool $stopOnIncomplete; private ?bool $stopOnNotice; private ?bool $stopOnRisky; private ?bool $stopOnSkipped; private ?bool $stopOnWarning; private ?string $filter; private ?string $excludeFilter; private ?string $generateBaseline; private ?string $useBaseline; private bool $ignoreBaseline; private bool $generateConfiguration; private bool $migrateConfiguration; /** * @var ?non-empty-list<non-empty-string> */ private ?array $groups; /** * @var ?non-empty-list<non-empty-string> */ private ?array $testsCovering; /** * @var ?non-empty-list<non-empty-string> */ private ?array $testsUsing; private bool $help; private ?string $includePath; /** * @var ?non-empty-array<non-empty-string, non-empty-string> */ private ?array $iniSettings; private ?string $junitLogfile; private bool $listGroups; private bool $listSuites; private bool $listTestFiles; private bool $listTests; private ?string $listTestsXml; private ?bool $noCoverage; private ?bool $noExtensions; private ?bool $noOutput; private ?bool $noProgress; private ?bool $noResults; private ?bool $noLogging; private ?bool $processIsolation; private ?int $randomOrderSeed; private ?bool $reportUselessTests; private ?bool $resolveDependencies; private ?bool $reverseList; private ?bool $stderr; private ?bool $strictCoverage; private ?string $teamcityLogfile; private ?bool $teamCityPrinter; private ?string $testdoxHtmlFile; private ?string $testdoxTextFile; private ?bool $testdoxPrinter; private ?bool $testdoxPrinterSummary; /** * @var ?non-empty-list<non-empty-string> */ private ?array $testSuffixes; private ?string $testSuite; private ?string $excludeTestSuite; private bool $useDefaultConfiguration; private ?bool $displayDetailsOnIncompleteTests; private ?bool $displayDetailsOnSkippedTests; private ?bool $displayDetailsOnTestsThatTriggerDeprecations; private ?bool $displayDetailsOnTestsThatTriggerErrors; private ?bool $displayDetailsOnTestsThatTriggerNotices; private ?bool $displayDetailsOnTestsThatTriggerWarnings; private bool $version; private ?string $logEventsText; private ?string $logEventsVerboseText; private bool $debug; /** * @var ?non-empty-list<non-empty-string> */ private ?array $extensions; /** * @param list<non-empty-string> $arguments * @param ?non-empty-list<non-empty-string> $excludeGroups * @param ?non-empty-list<non-empty-string> $groups * @param ?non-empty-list<non-empty-string> $testsCovering * @param ?non-empty-list<non-empty-string> $testsUsing * @param ?non-empty-array<non-empty-string, non-empty-string> $iniSettings * @param ?non-empty-list<non-empty-string> $testSuffixes * @param ?non-empty-list<non-empty-string> $coverageFilter * @param ?non-empty-list<non-empty-string> $extensions */ public function __construct(array $arguments, ?string $atLeastVersion, ?bool $backupGlobals, ?bool $backupStaticProperties, ?bool $beStrictAboutChangesToGlobalState, ?string $bootstrap, ?string $cacheDirectory, ?bool $cacheResult, bool $checkVersion, ?string $colors, null|int|string $columns, ?string $configurationFile, ?string $coverageClover, ?string $coverageCobertura, ?string $coverageCrap4J, ?string $coverageHtml, ?string $coveragePhp, ?string $coverageText, ?bool $coverageTextShowUncoveredFiles, ?bool $coverageTextShowOnlySummary, ?string $coverageXml, ?bool $pathCoverage, bool $warmCoverageCache, ?int $defaultTimeLimit, ?bool $disableCodeCoverageIgnore, ?bool $disallowTestOutput, ?bool $enforceTimeLimit, ?array $excludeGroups, ?int $executionOrder, ?int $executionOrderDefects, ?bool $failOnDeprecation, ?bool $failOnEmptyTestSuite, ?bool $failOnIncomplete, ?bool $failOnNotice, ?bool $failOnRisky, ?bool $failOnSkipped, ?bool $failOnWarning, ?bool $stopOnDefect, ?bool $stopOnDeprecation, ?bool $stopOnError, ?bool $stopOnFailure, ?bool $stopOnIncomplete, ?bool $stopOnNotice, ?bool $stopOnRisky, ?bool $stopOnSkipped, ?bool $stopOnWarning, ?string $filter, ?string $excludeFilter, ?string $generateBaseline, ?string $useBaseline, bool $ignoreBaseline, bool $generateConfiguration, bool $migrateConfiguration, ?array $groups, ?array $testsCovering, ?array $testsUsing, bool $help, ?string $includePath, ?array $iniSettings, ?string $junitLogfile, bool $listGroups, bool $listSuites, bool $listTestFiles, bool $listTests, ?string $listTestsXml, ?bool $noCoverage, ?bool $noExtensions, ?bool $noOutput, ?bool $noProgress, ?bool $noResults, ?bool $noLogging, ?bool $processIsolation, ?int $randomOrderSeed, ?bool $reportUselessTests, ?bool $resolveDependencies, ?bool $reverseList, ?bool $stderr, ?bool $strictCoverage, ?string $teamcityLogfile, ?string $testdoxHtmlFile, ?string $testdoxTextFile, ?array $testSuffixes, ?string $testSuite, ?string $excludeTestSuite, bool $useDefaultConfiguration, ?bool $displayDetailsOnIncompleteTests, ?bool $displayDetailsOnSkippedTests, ?bool $displayDetailsOnTestsThatTriggerDeprecations, ?bool $displayDetailsOnTestsThatTriggerErrors, ?bool $displayDetailsOnTestsThatTriggerNotices, ?bool $displayDetailsOnTestsThatTriggerWarnings, bool $version, ?array $coverageFilter, ?string $logEventsText, ?string $logEventsVerboseText, ?bool $printerTeamCity, ?bool $testdoxPrinter, ?bool $testdoxPrinterSummary, bool $debug, ?array $extensions) { $this->arguments = $arguments; $this->atLeastVersion = $atLeastVersion; $this->backupGlobals = $backupGlobals; $this->backupStaticProperties = $backupStaticProperties; $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; $this->bootstrap = $bootstrap; $this->cacheDirectory = $cacheDirectory; $this->cacheResult = $cacheResult; $this->checkVersion = $checkVersion; $this->colors = $colors; $this->columns = $columns; $this->configurationFile = $configurationFile; $this->coverageFilter = $coverageFilter; $this->coverageClover = $coverageClover; $this->coverageCobertura = $coverageCobertura; $this->coverageCrap4J = $coverageCrap4J; $this->coverageHtml = $coverageHtml; $this->coveragePhp = $coveragePhp; $this->coverageText = $coverageText; $this->coverageTextShowUncoveredFiles = $coverageTextShowUncoveredFiles; $this->coverageTextShowOnlySummary = $coverageTextShowOnlySummary; $this->coverageXml = $coverageXml; $this->pathCoverage = $pathCoverage; $this->warmCoverageCache = $warmCoverageCache; $this->defaultTimeLimit = $defaultTimeLimit; $this->disableCodeCoverageIgnore = $disableCodeCoverageIgnore; $this->disallowTestOutput = $disallowTestOutput; $this->enforceTimeLimit = $enforceTimeLimit; $this->excludeGroups = $excludeGroups; $this->executionOrder = $executionOrder; $this->executionOrderDefects = $executionOrderDefects; $this->failOnDeprecation = $failOnDeprecation; $this->failOnEmptyTestSuite = $failOnEmptyTestSuite; $this->failOnIncomplete = $failOnIncomplete; $this->failOnNotice = $failOnNotice; $this->failOnRisky = $failOnRisky; $this->failOnSkipped = $failOnSkipped; $this->failOnWarning = $failOnWarning; $this->stopOnDefect = $stopOnDefect; $this->stopOnDeprecation = $stopOnDeprecation; $this->stopOnError = $stopOnError; $this->stopOnFailure = $stopOnFailure; $this->stopOnIncomplete = $stopOnIncomplete; $this->stopOnNotice = $stopOnNotice; $this->stopOnRisky = $stopOnRisky; $this->stopOnSkipped = $stopOnSkipped; $this->stopOnWarning = $stopOnWarning; $this->filter = $filter; $this->excludeFilter = $excludeFilter; $this->generateBaseline = $generateBaseline; $this->useBaseline = $useBaseline; $this->ignoreBaseline = $ignoreBaseline; $this->generateConfiguration = $generateConfiguration; $this->migrateConfiguration = $migrateConfiguration; $this->groups = $groups; $this->testsCovering = $testsCovering; $this->testsUsing = $testsUsing; $this->help = $help; $this->includePath = $includePath; $this->iniSettings = $iniSettings; $this->junitLogfile = $junitLogfile; $this->listGroups = $listGroups; $this->listSuites = $listSuites; $this->listTestFiles = $listTestFiles; $this->listTests = $listTests; $this->listTestsXml = $listTestsXml; $this->noCoverage = $noCoverage; $this->noExtensions = $noExtensions; $this->noOutput = $noOutput; $this->noProgress = $noProgress; $this->noResults = $noResults; $this->noLogging = $noLogging; $this->processIsolation = $processIsolation; $this->randomOrderSeed = $randomOrderSeed; $this->reportUselessTests = $reportUselessTests; $this->resolveDependencies = $resolveDependencies; $this->reverseList = $reverseList; $this->stderr = $stderr; $this->strictCoverage = $strictCoverage; $this->teamcityLogfile = $teamcityLogfile; $this->testdoxHtmlFile = $testdoxHtmlFile; $this->testdoxTextFile = $testdoxTextFile; $this->testSuffixes = $testSuffixes; $this->testSuite = $testSuite; $this->excludeTestSuite = $excludeTestSuite; $this->useDefaultConfiguration = $useDefaultConfiguration; $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; $this->version = $version; $this->logEventsText = $logEventsText; $this->logEventsVerboseText = $logEventsVerboseText; $this->teamCityPrinter = $printerTeamCity; $this->testdoxPrinter = $testdoxPrinter; $this->testdoxPrinterSummary = $testdoxPrinterSummary; $this->debug = $debug; $this->extensions = $extensions; } /** * @return list<non-empty-string> */ public function arguments(): array { return $this->arguments; } /** * @phpstan-assert-if-true !null $this->atLeastVersion */ public function hasAtLeastVersion(): bool { return $this->atLeastVersion !== null; } /** * @throws Exception */ public function atLeastVersion(): string { if (!$this->hasAtLeastVersion()) { throw new Exception; } return $this->atLeastVersion; } /** * @phpstan-assert-if-true !null $this->backupGlobals */ public function hasBackupGlobals(): bool { return $this->backupGlobals !== null; } /** * @throws Exception */ public function backupGlobals(): bool { if (!$this->hasBackupGlobals()) { throw new Exception; } return $this->backupGlobals; } /** * @phpstan-assert-if-true !null $this->backupStaticProperties */ public function hasBackupStaticProperties(): bool { return $this->backupStaticProperties !== null; } /** * @throws Exception */ public function backupStaticProperties(): bool { if (!$this->hasBackupStaticProperties()) { throw new Exception; } return $this->backupStaticProperties; } /** * @phpstan-assert-if-true !null $this->beStrictAboutChangesToGlobalState */ public function hasBeStrictAboutChangesToGlobalState(): bool { return $this->beStrictAboutChangesToGlobalState !== null; } /** * @throws Exception */ public function beStrictAboutChangesToGlobalState(): bool { if (!$this->hasBeStrictAboutChangesToGlobalState()) { throw new Exception; } return $this->beStrictAboutChangesToGlobalState; } /** * @phpstan-assert-if-true !null $this->bootstrap */ public function hasBootstrap(): bool { return $this->bootstrap !== null; } /** * @throws Exception */ public function bootstrap(): string { if (!$this->hasBootstrap()) { throw new Exception; } return $this->bootstrap; } /** * @phpstan-assert-if-true !null $this->cacheDirectory */ public function hasCacheDirectory(): bool { return $this->cacheDirectory !== null; } /** * @throws Exception */ public function cacheDirectory(): string { if (!$this->hasCacheDirectory()) { throw new Exception; } return $this->cacheDirectory; } /** * @phpstan-assert-if-true !null $this->cacheResult */ public function hasCacheResult(): bool { return $this->cacheResult !== null; } /** * @throws Exception */ public function cacheResult(): bool { if (!$this->hasCacheResult()) { throw new Exception; } return $this->cacheResult; } public function checkVersion(): bool { return $this->checkVersion; } /** * @phpstan-assert-if-true !null $this->colors */ public function hasColors(): bool { return $this->colors !== null; } /** * @throws Exception */ public function colors(): string { if (!$this->hasColors()) { throw new Exception; } return $this->colors; } /** * @phpstan-assert-if-true !null $this->columns */ public function hasColumns(): bool { return $this->columns !== null; } /** * @throws Exception */ public function columns(): int|string { if (!$this->hasColumns()) { throw new Exception; } return $this->columns; } /** * @phpstan-assert-if-true !null $this->configurationFile */ public function hasConfigurationFile(): bool { return $this->configurationFile !== null; } /** * @throws Exception */ public function configurationFile(): string { if (!$this->hasConfigurationFile()) { throw new Exception; } return $this->configurationFile; } /** * @phpstan-assert-if-true !null $this->coverageFilter */ public function hasCoverageFilter(): bool { return $this->coverageFilter !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function coverageFilter(): array { if (!$this->hasCoverageFilter()) { throw new Exception; } return $this->coverageFilter; } /** * @phpstan-assert-if-true !null $this->coverageClover */ public function hasCoverageClover(): bool { return $this->coverageClover !== null; } /** * @throws Exception */ public function coverageClover(): string { if (!$this->hasCoverageClover()) { throw new Exception; } return $this->coverageClover; } /** * @phpstan-assert-if-true !null $this->coverageCobertura */ public function hasCoverageCobertura(): bool { return $this->coverageCobertura !== null; } /** * @throws Exception */ public function coverageCobertura(): string { if (!$this->hasCoverageCobertura()) { throw new Exception; } return $this->coverageCobertura; } /** * @phpstan-assert-if-true !null $this->coverageCrap4J */ public function hasCoverageCrap4J(): bool { return $this->coverageCrap4J !== null; } /** * @throws Exception */ public function coverageCrap4J(): string { if (!$this->hasCoverageCrap4J()) { throw new Exception; } return $this->coverageCrap4J; } /** * @phpstan-assert-if-true !null $this->coverageHtml */ public function hasCoverageHtml(): bool { return $this->coverageHtml !== null; } /** * @throws Exception */ public function coverageHtml(): string { if (!$this->hasCoverageHtml()) { throw new Exception; } return $this->coverageHtml; } /** * @phpstan-assert-if-true !null $this->coveragePhp */ public function hasCoveragePhp(): bool { return $this->coveragePhp !== null; } /** * @throws Exception */ public function coveragePhp(): string { if (!$this->hasCoveragePhp()) { throw new Exception; } return $this->coveragePhp; } /** * @phpstan-assert-if-true !null $this->coverageText */ public function hasCoverageText(): bool { return $this->coverageText !== null; } /** * @throws Exception */ public function coverageText(): string { if (!$this->hasCoverageText()) { throw new Exception; } return $this->coverageText; } /** * @phpstan-assert-if-true !null $this->coverageTextShowUncoveredFiles */ public function hasCoverageTextShowUncoveredFiles(): bool { return $this->coverageTextShowUncoveredFiles !== null; } /** * @throws Exception */ public function coverageTextShowUncoveredFiles(): bool { if (!$this->hasCoverageTextShowUncoveredFiles()) { throw new Exception; } return $this->coverageTextShowUncoveredFiles; } /** * @phpstan-assert-if-true !null $this->coverageTextShowOnlySummary */ public function hasCoverageTextShowOnlySummary(): bool { return $this->coverageTextShowOnlySummary !== null; } /** * @throws Exception */ public function coverageTextShowOnlySummary(): bool { if (!$this->hasCoverageTextShowOnlySummary()) { throw new Exception; } return $this->coverageTextShowOnlySummary; } /** * @phpstan-assert-if-true !null $this->coverageXml */ public function hasCoverageXml(): bool { return $this->coverageXml !== null; } /** * @throws Exception */ public function coverageXml(): string { if (!$this->hasCoverageXml()) { throw new Exception; } return $this->coverageXml; } /** * @phpstan-assert-if-true !null $this->pathCoverage */ public function hasPathCoverage(): bool { return $this->pathCoverage !== null; } /** * @throws Exception */ public function pathCoverage(): bool { if (!$this->hasPathCoverage()) { throw new Exception; } return $this->pathCoverage; } public function warmCoverageCache(): bool { return $this->warmCoverageCache; } /** * @phpstan-assert-if-true !null $this->defaultTimeLimit */ public function hasDefaultTimeLimit(): bool { return $this->defaultTimeLimit !== null; } /** * @throws Exception */ public function defaultTimeLimit(): int { if (!$this->hasDefaultTimeLimit()) { throw new Exception; } return $this->defaultTimeLimit; } /** * @phpstan-assert-if-true !null $this->disableCodeCoverageIgnore */ public function hasDisableCodeCoverageIgnore(): bool { return $this->disableCodeCoverageIgnore !== null; } /** * @throws Exception */ public function disableCodeCoverageIgnore(): bool { if (!$this->hasDisableCodeCoverageIgnore()) { throw new Exception; } return $this->disableCodeCoverageIgnore; } /** * @phpstan-assert-if-true !null $this->disallowTestOutput */ public function hasDisallowTestOutput(): bool { return $this->disallowTestOutput !== null; } /** * @throws Exception */ public function disallowTestOutput(): bool { if (!$this->hasDisallowTestOutput()) { throw new Exception; } return $this->disallowTestOutput; } /** * @phpstan-assert-if-true !null $this->enforceTimeLimit */ public function hasEnforceTimeLimit(): bool { return $this->enforceTimeLimit !== null; } /** * @throws Exception */ public function enforceTimeLimit(): bool { if (!$this->hasEnforceTimeLimit()) { throw new Exception; } return $this->enforceTimeLimit; } /** * @phpstan-assert-if-true !null $this->excludeGroups */ public function hasExcludeGroups(): bool { return $this->excludeGroups !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function excludeGroups(): array { if (!$this->hasExcludeGroups()) { throw new Exception; } return $this->excludeGroups; } /** * @phpstan-assert-if-true !null $this->executionOrder */ public function hasExecutionOrder(): bool { return $this->executionOrder !== null; } /** * @throws Exception */ public function executionOrder(): int { if (!$this->hasExecutionOrder()) { throw new Exception; } return $this->executionOrder; } /** * @phpstan-assert-if-true !null $this->executionOrderDefects */ public function hasExecutionOrderDefects(): bool { return $this->executionOrderDefects !== null; } /** * @throws Exception */ public function executionOrderDefects(): int { if (!$this->hasExecutionOrderDefects()) { throw new Exception; } return $this->executionOrderDefects; } /** * @phpstan-assert-if-true !null $this->failOnDeprecation */ public function hasFailOnDeprecation(): bool { return $this->failOnDeprecation !== null; } /** * @throws Exception */ public function failOnDeprecation(): bool { if (!$this->hasFailOnDeprecation()) { throw new Exception; } return $this->failOnDeprecation; } /** * @phpstan-assert-if-true !null $this->failOnEmptyTestSuite */ public function hasFailOnEmptyTestSuite(): bool { return $this->failOnEmptyTestSuite !== null; } /** * @throws Exception */ public function failOnEmptyTestSuite(): bool { if (!$this->hasFailOnEmptyTestSuite()) { throw new Exception; } return $this->failOnEmptyTestSuite; } /** * @phpstan-assert-if-true !null $this->failOnIncomplete */ public function hasFailOnIncomplete(): bool { return $this->failOnIncomplete !== null; } /** * @throws Exception */ public function failOnIncomplete(): bool { if (!$this->hasFailOnIncomplete()) { throw new Exception; } return $this->failOnIncomplete; } /** * @phpstan-assert-if-true !null $this->failOnNotice */ public function hasFailOnNotice(): bool { return $this->failOnNotice !== null; } /** * @throws Exception */ public function failOnNotice(): bool { if (!$this->hasFailOnNotice()) { throw new Exception; } return $this->failOnNotice; } /** * @phpstan-assert-if-true !null $this->failOnRisky */ public function hasFailOnRisky(): bool { return $this->failOnRisky !== null; } /** * @throws Exception */ public function failOnRisky(): bool { if (!$this->hasFailOnRisky()) { throw new Exception; } return $this->failOnRisky; } /** * @phpstan-assert-if-true !null $this->failOnSkipped */ public function hasFailOnSkipped(): bool { return $this->failOnSkipped !== null; } /** * @throws Exception */ public function failOnSkipped(): bool { if (!$this->hasFailOnSkipped()) { throw new Exception; } return $this->failOnSkipped; } /** * @phpstan-assert-if-true !null $this->failOnWarning */ public function hasFailOnWarning(): bool { return $this->failOnWarning !== null; } /** * @throws Exception */ public function failOnWarning(): bool { if (!$this->hasFailOnWarning()) { throw new Exception; } return $this->failOnWarning; } /** * @phpstan-assert-if-true !null $this->stopOnDefect */ public function hasStopOnDefect(): bool { return $this->stopOnDefect !== null; } /** * @throws Exception */ public function stopOnDefect(): bool { if (!$this->hasStopOnDefect()) { throw new Exception; } return $this->stopOnDefect; } /** * @phpstan-assert-if-true !null $this->stopOnDeprecation */ public function hasStopOnDeprecation(): bool { return $this->stopOnDeprecation !== null; } /** * @throws Exception */ public function stopOnDeprecation(): bool { if (!$this->hasStopOnDeprecation()) { throw new Exception; } return $this->stopOnDeprecation; } /** * @phpstan-assert-if-true !null $this->stopOnError */ public function hasStopOnError(): bool { return $this->stopOnError !== null; } /** * @throws Exception */ public function stopOnError(): bool { if (!$this->hasStopOnError()) { throw new Exception; } return $this->stopOnError; } /** * @phpstan-assert-if-true !null $this->stopOnFailure */ public function hasStopOnFailure(): bool { return $this->stopOnFailure !== null; } /** * @throws Exception */ public function stopOnFailure(): bool { if (!$this->hasStopOnFailure()) { throw new Exception; } return $this->stopOnFailure; } /** * @phpstan-assert-if-true !null $this->stopOnIncomplete */ public function hasStopOnIncomplete(): bool { return $this->stopOnIncomplete !== null; } /** * @throws Exception */ public function stopOnIncomplete(): bool { if (!$this->hasStopOnIncomplete()) { throw new Exception; } return $this->stopOnIncomplete; } /** * @phpstan-assert-if-true !null $this->stopOnNotice */ public function hasStopOnNotice(): bool { return $this->stopOnNotice !== null; } /** * @throws Exception */ public function stopOnNotice(): bool { if (!$this->hasStopOnNotice()) { throw new Exception; } return $this->stopOnNotice; } /** * @phpstan-assert-if-true !null $this->stopOnRisky */ public function hasStopOnRisky(): bool { return $this->stopOnRisky !== null; } /** * @throws Exception */ public function stopOnRisky(): bool { if (!$this->hasStopOnRisky()) { throw new Exception; } return $this->stopOnRisky; } /** * @phpstan-assert-if-true !null $this->stopOnSkipped */ public function hasStopOnSkipped(): bool { return $this->stopOnSkipped !== null; } /** * @throws Exception */ public function stopOnSkipped(): bool { if (!$this->hasStopOnSkipped()) { throw new Exception; } return $this->stopOnSkipped; } /** * @phpstan-assert-if-true !null $this->stopOnWarning */ public function hasStopOnWarning(): bool { return $this->stopOnWarning !== null; } /** * @throws Exception */ public function stopOnWarning(): bool { if (!$this->hasStopOnWarning()) { throw new Exception; } return $this->stopOnWarning; } /** * @phpstan-assert-if-true !null $this->excludeFilter */ public function hasExcludeFilter(): bool { return $this->excludeFilter !== null; } /** * @throws Exception */ public function excludeFilter(): string { if (!$this->hasExcludeFilter()) { throw new Exception; } return $this->excludeFilter; } /** * @phpstan-assert-if-true !null $this->filter */ public function hasFilter(): bool { return $this->filter !== null; } /** * @throws Exception */ public function filter(): string { if (!$this->hasFilter()) { throw new Exception; } return $this->filter; } /** * @phpstan-assert-if-true !null $this->generateBaseline */ public function hasGenerateBaseline(): bool { return $this->generateBaseline !== null; } /** * @throws Exception */ public function generateBaseline(): string { if (!$this->hasGenerateBaseline()) { throw new Exception; } return $this->generateBaseline; } /** * @phpstan-assert-if-true !null $this->useBaseline */ public function hasUseBaseline(): bool { return $this->useBaseline !== null; } /** * @throws Exception */ public function useBaseline(): string { if (!$this->hasUseBaseline()) { throw new Exception; } return $this->useBaseline; } public function ignoreBaseline(): bool { return $this->ignoreBaseline; } public function generateConfiguration(): bool { return $this->generateConfiguration; } public function migrateConfiguration(): bool { return $this->migrateConfiguration; } /** * @phpstan-assert-if-true !null $this->groups */ public function hasGroups(): bool { return $this->groups !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function groups(): array { if (!$this->hasGroups()) { throw new Exception; } return $this->groups; } /** * @phpstan-assert-if-true !null $this->testsCovering */ public function hasTestsCovering(): bool { return $this->testsCovering !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function testsCovering(): array { if (!$this->hasTestsCovering()) { throw new Exception; } return $this->testsCovering; } /** * @phpstan-assert-if-true !null $this->testsUsing */ public function hasTestsUsing(): bool { return $this->testsUsing !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function testsUsing(): array { if (!$this->hasTestsUsing()) { throw new Exception; } return $this->testsUsing; } public function help(): bool { return $this->help; } /** * @phpstan-assert-if-true !null $this->includePath */ public function hasIncludePath(): bool { return $this->includePath !== null; } /** * @throws Exception */ public function includePath(): string { if (!$this->hasIncludePath()) { throw new Exception; } return $this->includePath; } /** * @phpstan-assert-if-true !null $this->iniSettings */ public function hasIniSettings(): bool { return $this->iniSettings !== null; } /** * @throws Exception * * @return non-empty-array<non-empty-string, non-empty-string> */ public function iniSettings(): array { if (!$this->hasIniSettings()) { throw new Exception; } return $this->iniSettings; } /** * @phpstan-assert-if-true !null $this->junitLogfile */ public function hasJunitLogfile(): bool { return $this->junitLogfile !== null; } /** * @throws Exception */ public function junitLogfile(): string { if (!$this->hasJunitLogfile()) { throw new Exception; } return $this->junitLogfile; } public function listGroups(): bool { return $this->listGroups; } public function listSuites(): bool { return $this->listSuites; } public function listTestFiles(): bool { return $this->listTestFiles; } public function listTests(): bool { return $this->listTests; } /** * @phpstan-assert-if-true !null $this->listTestsXml */ public function hasListTestsXml(): bool { return $this->listTestsXml !== null; } /** * @throws Exception */ public function listTestsXml(): string { if (!$this->hasListTestsXml()) { throw new Exception; } return $this->listTestsXml; } /** * @phpstan-assert-if-true !null $this->noCoverage */ public function hasNoCoverage(): bool { return $this->noCoverage !== null; } /** * @throws Exception */ public function noCoverage(): bool { if (!$this->hasNoCoverage()) { throw new Exception; } return $this->noCoverage; } /** * @phpstan-assert-if-true !null $this->noExtensions */ public function hasNoExtensions(): bool { return $this->noExtensions !== null; } /** * @throws Exception */ public function noExtensions(): bool { if (!$this->hasNoExtensions()) { throw new Exception; } return $this->noExtensions; } /** * @phpstan-assert-if-true !null $this->noOutput */ public function hasNoOutput(): bool { return $this->noOutput !== null; } /** * @throws Exception */ public function noOutput(): bool { if ($this->noOutput === null) { throw new Exception; } return $this->noOutput; } /** * @phpstan-assert-if-true !null $this->noProgress */ public function hasNoProgress(): bool { return $this->noProgress !== null; } /** * @throws Exception */ public function noProgress(): bool { if ($this->noProgress === null) { throw new Exception; } return $this->noProgress; } /** * @phpstan-assert-if-true !null $this->noResults */ public function hasNoResults(): bool { return $this->noResults !== null; } /** * @throws Exception */ public function noResults(): bool { if ($this->noResults === null) { throw new Exception; } return $this->noResults; } /** * @phpstan-assert-if-true !null $this->noLogging */ public function hasNoLogging(): bool { return $this->noLogging !== null; } /** * @throws Exception */ public function noLogging(): bool { if (!$this->hasNoLogging()) { throw new Exception; } return $this->noLogging; } /** * @phpstan-assert-if-true !null $this->processIsolation */ public function hasProcessIsolation(): bool { return $this->processIsolation !== null; } /** * @throws Exception */ public function processIsolation(): bool { if (!$this->hasProcessIsolation()) { throw new Exception; } return $this->processIsolation; } /** * @phpstan-assert-if-true !null $this->randomOrderSeed */ public function hasRandomOrderSeed(): bool { return $this->randomOrderSeed !== null; } /** * @throws Exception */ public function randomOrderSeed(): int { if (!$this->hasRandomOrderSeed()) { throw new Exception; } return $this->randomOrderSeed; } /** * @phpstan-assert-if-true !null $this->reportUselessTests */ public function hasReportUselessTests(): bool { return $this->reportUselessTests !== null; } /** * @throws Exception */ public function reportUselessTests(): bool { if (!$this->hasReportUselessTests()) { throw new Exception; } return $this->reportUselessTests; } /** * @phpstan-assert-if-true !null $this->resolveDependencies */ public function hasResolveDependencies(): bool { return $this->resolveDependencies !== null; } /** * @throws Exception */ public function resolveDependencies(): bool { if (!$this->hasResolveDependencies()) { throw new Exception; } return $this->resolveDependencies; } /** * @phpstan-assert-if-true !null $this->reverseList */ public function hasReverseList(): bool { return $this->reverseList !== null; } /** * @throws Exception */ public function reverseList(): bool { if (!$this->hasReverseList()) { throw new Exception; } return $this->reverseList; } /** * @phpstan-assert-if-true !null $this->stderr */ public function hasStderr(): bool { return $this->stderr !== null; } /** * @throws Exception */ public function stderr(): bool { if (!$this->hasStderr()) { throw new Exception; } return $this->stderr; } /** * @phpstan-assert-if-true !null $this->strictCoverage */ public function hasStrictCoverage(): bool { return $this->strictCoverage !== null; } /** * @throws Exception */ public function strictCoverage(): bool { if (!$this->hasStrictCoverage()) { throw new Exception; } return $this->strictCoverage; } /** * @phpstan-assert-if-true !null $this->teamcityLogfile */ public function hasTeamcityLogfile(): bool { return $this->teamcityLogfile !== null; } /** * @throws Exception */ public function teamcityLogfile(): string { if (!$this->hasTeamcityLogfile()) { throw new Exception; } return $this->teamcityLogfile; } /** * @phpstan-assert-if-true !null $this->teamcityPrinter */ public function hasTeamCityPrinter(): bool { return $this->teamCityPrinter !== null; } /** * @throws Exception */ public function teamCityPrinter(): bool { if (!$this->hasTeamCityPrinter()) { throw new Exception; } return $this->teamCityPrinter; } /** * @phpstan-assert-if-true !null $this->testdoxHtmlFile */ public function hasTestdoxHtmlFile(): bool { return $this->testdoxHtmlFile !== null; } /** * @throws Exception */ public function testdoxHtmlFile(): string { if (!$this->hasTestdoxHtmlFile()) { throw new Exception; } return $this->testdoxHtmlFile; } /** * @phpstan-assert-if-true !null $this->testdoxTextFile */ public function hasTestdoxTextFile(): bool { return $this->testdoxTextFile !== null; } /** * @throws Exception */ public function testdoxTextFile(): string { if (!$this->hasTestdoxTextFile()) { throw new Exception; } return $this->testdoxTextFile; } /** * @phpstan-assert-if-true !null $this->testdoxPrinter */ public function hasTestDoxPrinter(): bool { return $this->testdoxPrinter !== null; } /** * @throws Exception */ public function testdoxPrinter(): bool { if (!$this->hasTestdoxPrinter()) { throw new Exception; } return $this->testdoxPrinter; } /** * @phpstan-assert-if-true !null $this->testdoxPrinterSummary */ public function hasTestDoxPrinterSummary(): bool { return $this->testdoxPrinterSummary !== null; } /** * @throws Exception */ public function testdoxPrinterSummary(): bool { if (!$this->hasTestdoxPrinterSummary()) { throw new Exception; } return $this->testdoxPrinterSummary; } /** * @phpstan-assert-if-true !null $this->testSuffixes */ public function hasTestSuffixes(): bool { return $this->testSuffixes !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function testSuffixes(): array { if (!$this->hasTestSuffixes()) { throw new Exception; } return $this->testSuffixes; } /** * @phpstan-assert-if-true !null $this->testSuite */ public function hasTestSuite(): bool { return $this->testSuite !== null; } /** * @throws Exception */ public function testSuite(): string { if (!$this->hasTestSuite()) { throw new Exception; } return $this->testSuite; } /** * @phpstan-assert-if-true !null $this->excludedTestSuite */ public function hasExcludedTestSuite(): bool { return $this->excludeTestSuite !== null; } /** * @throws Exception */ public function excludedTestSuite(): string { if (!$this->hasExcludedTestSuite()) { throw new Exception; } return $this->excludeTestSuite; } public function useDefaultConfiguration(): bool { return $this->useDefaultConfiguration; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnIncompleteTests */ public function hasDisplayDetailsOnIncompleteTests(): bool { return $this->displayDetailsOnIncompleteTests !== null; } /** * @throws Exception */ public function displayDetailsOnIncompleteTests(): bool { if (!$this->hasDisplayDetailsOnIncompleteTests()) { throw new Exception; } return $this->displayDetailsOnIncompleteTests; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnSkippedTests */ public function hasDisplayDetailsOnSkippedTests(): bool { return $this->displayDetailsOnSkippedTests !== null; } /** * @throws Exception */ public function displayDetailsOnSkippedTests(): bool { if (!$this->hasDisplayDetailsOnSkippedTests()) { throw new Exception; } return $this->displayDetailsOnSkippedTests; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnTestsThatTriggerDeprecations */ public function hasDisplayDetailsOnTestsThatTriggerDeprecations(): bool { return $this->displayDetailsOnTestsThatTriggerDeprecations !== null; } /** * @throws Exception */ public function displayDetailsOnTestsThatTriggerDeprecations(): bool { if (!$this->hasDisplayDetailsOnTestsThatTriggerDeprecations()) { throw new Exception; } return $this->displayDetailsOnTestsThatTriggerDeprecations; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnTestsThatTriggerErrors */ public function hasDisplayDetailsOnTestsThatTriggerErrors(): bool { return $this->displayDetailsOnTestsThatTriggerErrors !== null; } /** * @throws Exception */ public function displayDetailsOnTestsThatTriggerErrors(): bool { if (!$this->hasDisplayDetailsOnTestsThatTriggerErrors()) { throw new Exception; } return $this->displayDetailsOnTestsThatTriggerErrors; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnTestsThatTriggerNotices */ public function hasDisplayDetailsOnTestsThatTriggerNotices(): bool { return $this->displayDetailsOnTestsThatTriggerNotices !== null; } /** * @throws Exception */ public function displayDetailsOnTestsThatTriggerNotices(): bool { if (!$this->hasDisplayDetailsOnTestsThatTriggerNotices()) { throw new Exception; } return $this->displayDetailsOnTestsThatTriggerNotices; } /** * @phpstan-assert-if-true !null $this->displayDetailsOnTestsThatTriggerWarnings */ public function hasDisplayDetailsOnTestsThatTriggerWarnings(): bool { return $this->displayDetailsOnTestsThatTriggerWarnings !== null; } /** * @throws Exception */ public function displayDetailsOnTestsThatTriggerWarnings(): bool { if (!$this->hasDisplayDetailsOnTestsThatTriggerWarnings()) { throw new Exception; } return $this->displayDetailsOnTestsThatTriggerWarnings; } public function version(): bool { return $this->version; } /** * @phpstan-assert-if-true !null $this->logEventsText */ public function hasLogEventsText(): bool { return $this->logEventsText !== null; } /** * @throws Exception */ public function logEventsText(): string { if (!$this->hasLogEventsText()) { throw new Exception; } return $this->logEventsText; } /** * @phpstan-assert-if-true !null $this->logEventsVerboseText */ public function hasLogEventsVerboseText(): bool { return $this->logEventsVerboseText !== null; } /** * @throws Exception */ public function logEventsVerboseText(): string { if (!$this->hasLogEventsVerboseText()) { throw new Exception; } return $this->logEventsVerboseText; } public function debug(): bool { return $this->debug; } /** * @phpstan-assert-if-true !null $this->extensions */ public function hasExtensions(): bool { return $this->extensions !== null; } /** * @throws Exception * * @return non-empty-list<non-empty-string> */ public function extensions(): array { if (!$this->hasExtensions()) { throw new Exception; } return $this->extensions; } } phpunit/src/TextUI/Configuration/CodeCoverageFilterRegistry.php 0000644 00000003603 15253321353 0020755 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use function array_keys; use function assert; use SebastianBergmann\CodeCoverage\Filter; /** * CLI options and XML configuration are static within a single PHPUnit process. * It is therefore okay to use a Singleton registry here. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CodeCoverageFilterRegistry { private static ?self $instance = null; private ?Filter $filter = null; private bool $configured = false; public static function instance(): self { if (self::$instance === null) { self::$instance = new self; } return self::$instance; } /** * @codeCoverageIgnore */ public function get(): Filter { assert($this->filter !== null); return $this->filter; } /** * @codeCoverageIgnore */ public function init(Configuration $configuration, bool $force = false): void { if (!$configuration->hasCoverageReport() && !$force) { return; } if ($this->configured && !$force) { return; } $this->filter = new Filter; if ($configuration->source()->notEmpty()) { $this->filter->includeFiles(array_keys((new SourceMapper)->map($configuration->source()))); $this->configured = true; } } /** * @codeCoverageIgnore */ public function configured(): bool { return $this->configured; } } phpunit/src/TextUI/Configuration/TestSuiteBuilder.php 0000644 00000010277 15253321353 0016775 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Configuration; use const PHP_EOL; use function assert; use function count; use function is_dir; use function is_file; use function realpath; use function str_ends_with; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Exception; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\TestSuiteLoader; use PHPUnit\TextUI\RuntimeException; use PHPUnit\TextUI\TestDirectoryNotFoundException; use PHPUnit\TextUI\TestFileNotFoundException; use PHPUnit\TextUI\XmlConfiguration\TestSuiteMapper; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteBuilder { /** * @throws \PHPUnit\Framework\Exception * @throws RuntimeException * @throws TestDirectoryNotFoundException * @throws TestFileNotFoundException */ public function build(Configuration $configuration): TestSuite { if ($configuration->hasCliArguments()) { $arguments = []; foreach ($configuration->cliArguments() as $cliArgument) { $argument = realpath($cliArgument); if (!$argument) { throw new TestFileNotFoundException($cliArgument); } $arguments[] = $argument; } if (count($arguments) === 1) { $testSuite = $this->testSuiteFromPath( $arguments[0], $configuration->testSuffixes(), ); } else { $testSuite = $this->testSuiteFromPathList( $arguments, $configuration->testSuffixes(), ); } } if (!isset($testSuite)) { $xmlConfigurationFile = $configuration->hasConfigurationFile() ? $configuration->configurationFile() : 'Root Test Suite'; assert(!empty($xmlConfigurationFile)); $testSuite = (new TestSuiteMapper)->map( $xmlConfigurationFile, $configuration->testSuite(), $configuration->includeTestSuite(), $configuration->excludeTestSuite(), ); } EventFacade::emitter()->testSuiteLoaded(\PHPUnit\Event\TestSuite\TestSuiteBuilder::from($testSuite)); return $testSuite; } /** * @param non-empty-string $path * @param list<non-empty-string> $suffixes * * @throws \PHPUnit\Framework\Exception */ private function testSuiteFromPath(string $path, array $suffixes, ?TestSuite $suite = null): TestSuite { if (str_ends_with($path, '.phpt') && is_file($path)) { $suite = $suite ?: TestSuite::empty($path); $suite->addTestFile($path); return $suite; } if (is_dir($path)) { $files = (new FileIteratorFacade)->getFilesAsArray($path, $suffixes); $suite = $suite ?: TestSuite::empty('CLI Arguments'); $suite->addTestFiles($files); return $suite; } try { $testClass = (new TestSuiteLoader)->load($path); } catch (Exception $e) { print $e->getMessage() . PHP_EOL; exit(1); } if (!$suite) { return TestSuite::fromClassReflector($testClass); } $suite->addTestSuite($testClass); return $suite; } /** * @param list<non-empty-string> $paths * @param list<non-empty-string> $suffixes * * @throws \PHPUnit\Framework\Exception */ private function testSuiteFromPathList(array $paths, array $suffixes): TestSuite { $suite = TestSuite::empty('CLI Arguments'); foreach ($paths as $path) { $this->testSuiteFromPath($path, $suffixes, $suite); } return $suite; } } phpunit/src/TextUI/TestRunner.php 0000644 00000004754 15253321353 0013042 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function mt_srand; use PHPUnit\Event; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\ResultCache\ResultCache; use PHPUnit\Runner\TestSuiteSorter; use PHPUnit\TextUI\Configuration\Configuration; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestRunner { /** * @throws RuntimeException */ public function run(Configuration $configuration, ResultCache $resultCache, TestSuite $suite): void { try { Event\Facade::emitter()->testRunnerStarted(); if ($configuration->executionOrder() === TestSuiteSorter::ORDER_RANDOMIZED) { mt_srand($configuration->randomOrderSeed()); } if ($configuration->executionOrder() !== TestSuiteSorter::ORDER_DEFAULT || $configuration->executionOrderDefects() !== TestSuiteSorter::ORDER_DEFAULT || $configuration->resolveDependencies()) { $resultCache->load(); (new TestSuiteSorter($resultCache))->reorderTestsInSuite( $suite, $configuration->executionOrder(), $configuration->resolveDependencies(), $configuration->executionOrderDefects(), ); Event\Facade::emitter()->testSuiteSorted( $configuration->executionOrder(), $configuration->executionOrderDefects(), $configuration->resolveDependencies(), ); } (new TestSuiteFilterProcessor)->process($configuration, $suite); Event\Facade::emitter()->testRunnerExecutionStarted( Event\TestSuite\TestSuiteBuilder::from($suite), ); $suite->run(); Event\Facade::emitter()->testRunnerExecutionFinished(); Event\Facade::emitter()->testRunnerFinished(); } catch (Throwable $t) { throw new RuntimeException( $t->getMessage(), (int) $t->getCode(), $t, ); } } } phpunit/src/TextUI/Help.php 0000644 00000040450 15253321353 0011612 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use const PHP_EOL; use function count; use function defined; use function explode; use function max; use function preg_replace_callback; use function str_pad; use function str_repeat; use function strlen; use function wordwrap; use PHPUnit\Util\Color; use SebastianBergmann\Environment\Console; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Help { private const LEFT_MARGIN = ' '; private int $lengthOfLongestOptionName = 0; private readonly int $columnsAvailableForDescription; private ?bool $hasColor; public function __construct(?int $width = null, ?bool $withColor = null) { if ($width === null) { $width = (new Console)->getNumberOfColumns(); } if ($withColor === null) { $this->hasColor = (new Console)->hasColorSupport(); } else { $this->hasColor = $withColor; } foreach ($this->elements() as $options) { foreach ($options as $option) { if (isset($option['arg'])) { $this->lengthOfLongestOptionName = max($this->lengthOfLongestOptionName, strlen($option['arg'])); } } } $this->columnsAvailableForDescription = $width - $this->lengthOfLongestOptionName - 4; } public function generate(): string { if ($this->hasColor) { return $this->writeWithColor(); } return $this->writeWithoutColor(); } private function writeWithoutColor(): string { $buffer = ''; foreach ($this->elements() as $section => $options) { $buffer .= "{$section}:" . PHP_EOL; if ($section !== 'Usage') { $buffer .= PHP_EOL; } foreach ($options as $option) { if (isset($option['spacer'])) { $buffer .= PHP_EOL; } if (isset($option['text'])) { $buffer .= self::LEFT_MARGIN . $option['text'] . PHP_EOL; } if (isset($option['arg'])) { $arg = str_pad($option['arg'], $this->lengthOfLongestOptionName); $buffer .= self::LEFT_MARGIN . $arg . ' ' . $option['desc'] . PHP_EOL; } } $buffer .= PHP_EOL; } return $buffer; } private function writeWithColor(): string { $buffer = ''; foreach ($this->elements() as $section => $options) { $buffer .= Color::colorize('fg-yellow', "{$section}:") . PHP_EOL; if ($section !== 'Usage') { $buffer .= PHP_EOL; } foreach ($options as $option) { if (isset($option['spacer'])) { $buffer .= PHP_EOL; } if (isset($option['text'])) { $buffer .= self::LEFT_MARGIN . $option['text'] . PHP_EOL; } if (isset($option['arg'])) { $arg = Color::colorize('fg-green', str_pad($option['arg'], $this->lengthOfLongestOptionName)); $arg = preg_replace_callback( '/(<[^>]+>)/', static fn ($matches) => Color::colorize('fg-cyan', $matches[0]), $arg, ); $desc = explode(PHP_EOL, wordwrap($option['desc'], $this->columnsAvailableForDescription, PHP_EOL)); $buffer .= self::LEFT_MARGIN . $arg . ' ' . $desc[0] . PHP_EOL; for ($i = 1; $i < count($desc); $i++) { $buffer .= str_repeat(' ', $this->lengthOfLongestOptionName + 3) . $desc[$i] . PHP_EOL; } } } $buffer .= PHP_EOL; } return $buffer; } /** * @return array<non-empty-string, non-empty-list<array{arg: non-empty-string, desc: non-empty-string}|array{spacer: ''}|array{text: non-empty-string}>> */ private function elements(): array { $elements = [ 'Usage' => [ ['text' => 'phpunit [options] <directory|file> ...'], ], 'Configuration' => [ ['arg' => '--bootstrap <file>', 'desc' => 'A PHP script that is included before the tests run'], ['arg' => '-c|--configuration <file>', 'desc' => 'Read configuration from XML file'], ['arg' => '--no-configuration', 'desc' => 'Ignore default configuration file (phpunit.xml)'], ['arg' => '--extension <class>', 'desc' => 'Register test runner extension with bootstrap <class>'], ['arg' => '--no-extensions', 'desc' => 'Do not register test runner extensions'], ['arg' => '--include-path <path(s)>', 'desc' => 'Prepend PHP\'s include_path with given path(s)'], ['arg' => '-d <key[=value]>', 'desc' => 'Sets a php.ini value'], ['arg' => '--cache-directory <dir>', 'desc' => 'Specify cache directory'], ['arg' => '--generate-configuration', 'desc' => 'Generate configuration file with suggested settings'], ['arg' => '--migrate-configuration', 'desc' => 'Migrate configuration file to current format'], ['arg' => '--generate-baseline <file>', 'desc' => 'Generate baseline for issues'], ['arg' => '--use-baseline <file>', 'desc' => 'Use baseline to ignore issues'], ['arg' => '--ignore-baseline', 'desc' => 'Do not use baseline to ignore issues'], ], 'Selection' => [ ['arg' => '--list-suites', 'desc' => 'List available test suites'], ['arg' => '--testsuite <name>', 'desc' => 'Only run tests from the specified test suite(s)'], ['arg' => '--exclude-testsuite <name>', 'desc' => 'Exclude tests from the specified test suite(s)'], ['arg' => '--list-groups', 'desc' => 'List available test groups'], ['arg' => '--group <name>', 'desc' => 'Only run tests from the specified group(s)'], ['arg' => '--exclude-group <name>', 'desc' => 'Exclude tests from the specified group(s)'], ['arg' => '--covers <name>', 'desc' => 'Only run tests that intend to cover <name>'], ['arg' => '--uses <name>', 'desc' => 'Only run tests that intend to use <name>'], ['arg' => '--list-test-files', 'desc' => 'List available test files'], ['arg' => '--list-tests', 'desc' => 'List available tests'], ['arg' => '--list-tests-xml <file>', 'desc' => 'List available tests in XML format'], ['arg' => '--filter <pattern>', 'desc' => 'Filter which tests to run'], ['arg' => '--exclude-filter <pattern>', 'desc' => 'Exclude tests for the specified filter pattern'], ['arg' => '--test-suffix <suffixes>', 'desc' => 'Only search for test in files with specified suffix(es). Default: Test.php,.phpt'], ], 'Execution' => [ ['arg' => '--process-isolation', 'desc' => 'Run each test in a separate PHP process'], ['arg' => '--globals-backup', 'desc' => 'Backup and restore $GLOBALS for each test'], ['arg' => '--static-backup', 'desc' => 'Backup and restore static properties for each test'], ['spacer' => ''], ['arg' => '--strict-coverage', 'desc' => 'Be strict about code coverage metadata'], ['arg' => '--strict-global-state', 'desc' => 'Be strict about changes to global state'], ['arg' => '--disallow-test-output', 'desc' => 'Be strict about output during tests'], ['arg' => '--enforce-time-limit', 'desc' => 'Enforce time limit based on test size'], ['arg' => '--default-time-limit <sec>', 'desc' => 'Timeout in seconds for tests that have no declared size'], ['arg' => '--dont-report-useless-tests', 'desc' => 'Do not report tests that do not test anything'], ['spacer' => ''], ['arg' => '--stop-on-defect', 'desc' => 'Stop after first error, failure, warning, or risky test'], ['arg' => '--stop-on-error', 'desc' => 'Stop after first error'], ['arg' => '--stop-on-failure', 'desc' => 'Stop after first failure'], ['arg' => '--stop-on-warning', 'desc' => 'Stop after first warning'], ['arg' => '--stop-on-risky', 'desc' => 'Stop after first risky test'], ['arg' => '--stop-on-deprecation', 'desc' => 'Stop after first test that triggered a deprecation'], ['arg' => '--stop-on-notice', 'desc' => 'Stop after first test that triggered a notice'], ['arg' => '--stop-on-skipped', 'desc' => 'Stop after first skipped test'], ['arg' => '--stop-on-incomplete', 'desc' => 'Stop after first incomplete test'], ['spacer' => ''], ['arg' => '--fail-on-empty-test-suite', 'desc' => 'Signal failure using shell exit code when no tests were run'], ['arg' => '--fail-on-warning', 'desc' => 'Signal failure using shell exit code when a warning was triggered'], ['arg' => '--fail-on-risky', 'desc' => 'Signal failure using shell exit code when a test was considered risky'], ['arg' => '--fail-on-deprecation', 'desc' => 'Signal failure using shell exit code when a deprecation was triggered'], ['arg' => '--fail-on-notice', 'desc' => 'Signal failure using shell exit code when a notice was triggered'], ['arg' => '--fail-on-skipped', 'desc' => 'Signal failure using shell exit code when a test was skipped'], ['arg' => '--fail-on-incomplete', 'desc' => 'Signal failure using shell exit code when a test was marked incomplete'], ['spacer' => ''], ['arg' => '--cache-result', 'desc' => 'Write test results to cache file'], ['arg' => '--do-not-cache-result', 'desc' => 'Do not write test results to cache file'], ['spacer' => ''], ['arg' => '--order-by <order>', 'desc' => 'Run tests in order: default|defects|depends|duration|no-depends|random|reverse|size'], ['arg' => '--random-order-seed <N>', 'desc' => 'Use the specified random seed when running tests in random order'], ], 'Reporting' => [ ['arg' => '--colors <flag>', 'desc' => 'Use colors in output ("never", "auto" or "always")'], ['arg' => '--columns <n>', 'desc' => 'Number of columns to use for progress output'], ['arg' => '--columns max', 'desc' => 'Use maximum number of columns for progress output'], ['arg' => '--stderr', 'desc' => 'Write to STDERR instead of STDOUT'], ['spacer' => ''], ['arg' => '--no-progress', 'desc' => 'Disable output of test execution progress'], ['arg' => '--no-results', 'desc' => 'Disable output of test results'], ['arg' => '--no-output', 'desc' => 'Disable all output'], ['spacer' => ''], ['arg' => '--display-incomplete', 'desc' => 'Display details for incomplete tests'], ['arg' => '--display-skipped', 'desc' => 'Display details for skipped tests'], ['arg' => '--display-deprecations', 'desc' => 'Display details for deprecations triggered by tests'], ['arg' => '--display-errors', 'desc' => 'Display details for errors triggered by tests'], ['arg' => '--display-notices', 'desc' => 'Display details for notices triggered by tests'], ['arg' => '--display-warnings', 'desc' => 'Display details for warnings triggered by tests'], ['arg' => '--reverse-list', 'desc' => 'Print defects in reverse order'], ['spacer' => ''], ['arg' => '--teamcity', 'desc' => 'Replace default progress and result output with TeamCity format'], ['arg' => '--testdox', 'desc' => 'Replace default result output with TestDox format'], ['arg' => '--testdox-summary', 'desc' => 'Repeat TestDox output for tests with errors, failures, or issues'], ['spacer' => ''], ['arg' => '--debug', 'desc' => 'Replace default progress and result output with debugging information'], ], 'Logging' => [ ['arg' => '--log-junit <file>', 'desc' => 'Write test results in JUnit XML format to file'], ['arg' => '--log-teamcity <file>', 'desc' => 'Write test results in TeamCity format to file'], ['arg' => '--testdox-html <file>', 'desc' => 'Write test results in TestDox format (HTML) to file'], ['arg' => '--testdox-text <file>', 'desc' => 'Write test results in TestDox format (plain text) to file'], ['arg' => '--log-events-text <file>', 'desc' => 'Stream events as plain text to file'], ['arg' => '--log-events-verbose-text <file>', 'desc' => 'Stream events as plain text with extended information to file'], ['arg' => '--no-logging', 'desc' => 'Ignore logging configured in the XML configuration file'], ], 'Code Coverage' => [ ['arg' => '--coverage-clover <file>', 'desc' => 'Write code coverage report in Clover XML format to file'], ['arg' => '--coverage-cobertura <file>', 'desc' => 'Write code coverage report in Cobertura XML format to file'], ['arg' => '--coverage-crap4j <file>', 'desc' => 'Write code coverage report in Crap4J XML format to file'], ['arg' => '--coverage-html <dir>', 'desc' => 'Write code coverage report in HTML format to directory'], ['arg' => '--coverage-php <file>', 'desc' => 'Write serialized code coverage data to file'], ['arg' => '--coverage-text=<file>', 'desc' => 'Write code coverage report in text format to file [default: standard output]'], ['arg' => '--only-summary-for-coverage-text', 'desc' => 'Option for code coverage report in text format: only show summary'], ['arg' => '--show-uncovered-for-coverage-text', 'desc' => 'Option for code coverage report in text format: show uncovered files'], ['arg' => '--coverage-xml <dir>', 'desc' => 'Write code coverage report in XML format to directory'], ['arg' => '--warm-coverage-cache', 'desc' => 'Warm static analysis cache'], ['arg' => '--coverage-filter <dir>', 'desc' => 'Include <dir> in code coverage reporting'], ['arg' => '--path-coverage', 'desc' => 'Report path coverage in addition to line coverage'], ['arg' => '--disable-coverage-ignore', 'desc' => 'Disable metadata for ignoring code coverage'], ['arg' => '--no-coverage', 'desc' => 'Ignore code coverage reporting configured in the XML configuration file'], ], ]; if (defined('__PHPUNIT_PHAR__')) { $elements['PHAR'] = [ ['arg' => '--manifest', 'desc' => 'Print Software Bill of Materials (SBOM) in plain-text format'], ['arg' => '--sbom', 'desc' => 'Print Software Bill of Materials (SBOM) in CycloneDX XML format'], ['arg' => '--composer-lock', 'desc' => 'Print composer.lock file used to build the PHAR'], ]; } $elements['Miscellaneous'] = [ ['arg' => '-h|--help', 'desc' => 'Prints this usage information'], ['arg' => '--version', 'desc' => 'Prints the version and exits'], ['arg' => '--atleast-version <min>', 'desc' => 'Checks that version is greater than <min> and exits'], ['arg' => '--check-version', 'desc' => 'Checks whether PHPUnit is the latest version and exits'], ]; return $elements; } } phpunit/src/TextUI/Output/TestDox/ResultPrinter.php 0000644 00000026000 15253321353 0016431 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\TestDox; use const PHP_EOL; use function array_map; use function assert; use function explode; use function implode; use function preg_match; use function preg_split; use function rtrim; use function str_starts_with; use function trim; use PHPUnit\Event\Code\Throwable; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\Logging\TestDox\TestResult as TestDoxTestResult; use PHPUnit\Logging\TestDox\TestResultCollection; use PHPUnit\TextUI\Output\Printer; use PHPUnit\Util\Color; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ResultPrinter { private Printer $printer; private bool $colors; private int $columns; private bool $printSummary; public function __construct(Printer $printer, bool $colors, int $columns, bool $printSummary) { $this->printer = $printer; $this->colors = $colors; $this->columns = $columns; $this->printSummary = $printSummary; } /** * @param array<string, TestResultCollection> $tests */ public function print(array $tests): void { $this->doPrint($tests, false); if ($this->printSummary) { $this->printer->print('Summary of tests with errors, failures, or issues:' . PHP_EOL . PHP_EOL); $this->doPrint($tests, true); } } public function flush(): void { $this->printer->flush(); } /** * @param array<string, TestResultCollection> $tests */ private function doPrint(array $tests, bool $onlySummary): void { foreach ($tests as $prettifiedClassName => $_tests) { $print = true; if ($onlySummary) { $found = false; foreach ($_tests as $test) { if ($test->status()->isSuccess()) { continue; } $found = true; break; } if (!$found) { $print = false; } } if (!$print) { continue; } $this->printPrettifiedClassName($prettifiedClassName); foreach ($_tests as $test) { if ($onlySummary && $test->status()->isSuccess()) { continue; } $this->printTestResult($test); } $this->printer->print(PHP_EOL); } } private function printPrettifiedClassName(string $prettifiedClassName): void { $buffer = $prettifiedClassName; if ($this->colors) { $buffer = Color::colorizeTextBox('underlined', $buffer); } $this->printer->print($buffer . PHP_EOL); } private function printTestResult(TestDoxTestResult $test): void { $this->printTestResultHeader($test); $this->printTestResultBody($test); } private function printTestResultHeader(TestDoxTestResult $test): void { $buffer = ' ' . $this->symbolFor($test->status()) . ' '; if ($this->colors) { $this->printer->print( Color::colorizeTextBox( $this->colorFor($test->status()), $buffer, ), ); } else { $this->printer->print($buffer); } $this->printer->print($test->test()->testDox()->prettifiedMethodName($this->colors) . PHP_EOL); } private function printTestResultBody(TestDoxTestResult $test): void { if ($test->status()->isSuccess()) { return; } if (!$test->hasThrowable()) { return; } $this->printTestResultBodyStart($test); $this->printThrowable($test); $this->printTestResultBodyEnd($test); } private function printTestResultBodyStart(TestDoxTestResult $test): void { $this->printer->print( $this->prefixLines( $this->prefixFor('start', $test->status()), '', ), ); $this->printer->print(PHP_EOL); } private function printTestResultBodyEnd(TestDoxTestResult $test): void { $this->printer->print(PHP_EOL); $this->printer->print( $this->prefixLines( $this->prefixFor('last', $test->status()), '', ), ); $this->printer->print(PHP_EOL); } private function printThrowable(TestDoxTestResult $test): void { $throwable = $test->throwable(); assert($throwable instanceof Throwable); $message = trim($throwable->description()); $stackTrace = $this->formatStackTrace($throwable->stackTrace()); $diff = ''; if (!empty($message) && $this->colors) { ['message' => $message, 'diff' => $diff] = $this->colorizeMessageAndDiff( $message, $this->messageColorFor($test->status()), ); } if (!empty($message)) { $this->printer->print( $this->prefixLines( $this->prefixFor('message', $test->status()), $message, ), ); $this->printer->print(PHP_EOL); } if (!empty($diff)) { $this->printer->print( $this->prefixLines( $this->prefixFor('diff', $test->status()), $diff, ), ); $this->printer->print(PHP_EOL); } if (!empty($stackTrace)) { if (!empty($message) || !empty($diff)) { $prefix = $this->prefixFor('default', $test->status()); } else { $prefix = $this->prefixFor('trace', $test->status()); } $this->printer->print( $this->prefixLines($prefix, PHP_EOL . $stackTrace), ); } } /** * @return array{message: string, diff: string} */ private function colorizeMessageAndDiff(string $buffer, string $style): array { $lines = $buffer ? array_map('\rtrim', explode(PHP_EOL, $buffer)) : []; $message = []; $diff = []; $insideDiff = false; foreach ($lines as $line) { if ($line === '--- Expected') { $insideDiff = true; } if (!$insideDiff) { $message[] = $line; } else { if (str_starts_with($line, '-')) { $line = Color::colorize('fg-red', Color::visualizeWhitespace($line, true)); } elseif (str_starts_with($line, '+')) { $line = Color::colorize('fg-green', Color::visualizeWhitespace($line, true)); } elseif ($line === '@@ @@') { $line = Color::colorize('fg-cyan', $line); } $diff[] = $line; } } $message = implode(PHP_EOL, $message); $diff = implode(PHP_EOL, $diff); if (!empty($message)) { // Testdox output has a left-margin of 5; keep right-margin to prevent terminal scrolling $message = Color::colorizeTextBox($style, $message, $this->columns - 7); } return [ 'message' => $message, 'diff' => $diff, ]; } private function formatStackTrace(string $stackTrace): string { if (!$this->colors) { return rtrim($stackTrace); } $lines = []; $previousPath = ''; foreach (explode(PHP_EOL, $stackTrace) as $line) { if (preg_match('/^(.*):(\d+)$/', $line, $matches)) { $lines[] = Color::colorizePath($matches[1], $previousPath) . Color::dim(':') . Color::colorize('fg-blue', $matches[2]) . "\n"; $previousPath = $matches[1]; continue; } $lines[] = $line; $previousPath = ''; } return rtrim(implode('', $lines)); } private function prefixLines(string $prefix, string $message): string { return implode( PHP_EOL, array_map( static fn (string $line) => ' ' . $prefix . ($line ? ' ' . $line : ''), preg_split('/\r\n|\r|\n/', $message), ), ); } /** * @param 'default'|'diff'|'last'|'message'|'start'|'trace' $type */ private function prefixFor(string $type, TestStatus $status): string { if (!$this->colors) { return '│'; } return Color::colorize( $this->colorFor($status), match ($type) { 'default' => '│', 'start' => '┐', 'message' => '├', 'diff' => '┊', 'trace' => '╵', 'last' => '┴', }, ); } private function colorFor(TestStatus $status): string { if ($status->isSuccess()) { return 'fg-green'; } if ($status->isError()) { return 'fg-yellow'; } if ($status->isFailure()) { return 'fg-red'; } if ($status->isSkipped()) { return 'fg-cyan'; } if ($status->isIncomplete() || $status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { return 'fg-yellow'; } return 'fg-blue'; } private function messageColorFor(TestStatus $status): string { if ($status->isSuccess()) { return ''; } if ($status->isError()) { return 'bg-yellow,fg-black'; } if ($status->isFailure()) { return 'bg-red,fg-white'; } if ($status->isSkipped()) { return 'fg-cyan'; } if ($status->isIncomplete() || $status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { return 'fg-yellow'; } return 'fg-white,bg-blue'; } private function symbolFor(TestStatus $status): string { if ($status->isSuccess()) { return '✔'; } if ($status->isError() || $status->isFailure()) { return '✘'; } if ($status->isSkipped()) { return '↩'; } if ($status->isDeprecation() || $status->isNotice() || $status->isRisky() || $status->isWarning()) { return '⚠'; } if ($status->isIncomplete()) { return '∅'; } return '?'; } } phpunit/src/TextUI/Output/Printer/Printer.php 0000644 00000001133 15253321353 0015263 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Printer { public function print(string $buffer): void; public function flush(): void; } phpunit/src/TextUI/Output/Printer/DefaultPrinter.php 0000644 00000006175 15253321353 0016603 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output; use function assert; use function count; use function dirname; use function explode; use function fclose; use function fopen; use function fsockopen; use function fwrite; use function str_replace; use function str_starts_with; use PHPUnit\Runner\DirectoryDoesNotExistException; use PHPUnit\TextUI\CannotOpenSocketException; use PHPUnit\TextUI\InvalidSocketException; use PHPUnit\Util\Filesystem; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DefaultPrinter implements Printer { /** * @var closed-resource|resource */ private $stream; private readonly bool $isPhpStream; private bool $isOpen; /** * @throws CannotOpenSocketException * @throws DirectoryDoesNotExistException * @throws InvalidSocketException */ public static function from(string $out): self { return new self($out); } /** * @throws CannotOpenSocketException * @throws DirectoryDoesNotExistException * @throws InvalidSocketException */ public static function standardOutput(): self { return new self('php://stdout'); } /** * @throws CannotOpenSocketException * @throws DirectoryDoesNotExistException * @throws InvalidSocketException */ public static function standardError(): self { return new self('php://stderr'); } /** * @throws CannotOpenSocketException * @throws DirectoryDoesNotExistException * @throws InvalidSocketException */ private function __construct(string $out) { $this->isPhpStream = str_starts_with($out, 'php://'); if (str_starts_with($out, 'socket://')) { $tmp = explode(':', str_replace('socket://', '', $out)); if (count($tmp) !== 2) { throw new InvalidSocketException($out); } $stream = @fsockopen($tmp[0], (int) $tmp[1]); if ($stream === false) { throw new CannotOpenSocketException($tmp[0], (int) $tmp[1]); } $this->stream = $stream; $this->isOpen = true; return; } if (!$this->isPhpStream && !Filesystem::createDirectory(dirname($out))) { throw new DirectoryDoesNotExistException(dirname($out)); } $stream = fopen($out, 'wb'); assert($stream !== false); $this->stream = $stream; $this->isOpen = true; } public function print(string $buffer): void { assert($this->isOpen); fwrite($this->stream, $buffer); } public function flush(): void { if ($this->isOpen && $this->isPhpStream) { fclose($this->stream); $this->isOpen = false; } } } phpunit/src/TextUI/Output/Printer/NullPrinter.php 0000644 00000001217 15253321353 0016121 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class NullPrinter implements Printer { public function print(string $buffer): void { } public function flush(): void { } } phpunit/src/TextUI/Output/Default/ProgressPrinter/ProgressPrinter.php 0000644 00000031317 15253321353 0022130 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use function floor; use function sprintf; use function str_contains; use function str_repeat; use function strlen; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErrorTriggered; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\TestRunner\ExecutionStarted; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\TextUI\Configuration\Source; use PHPUnit\TextUI\Configuration\SourceFilter; use PHPUnit\TextUI\Output\Printer; use PHPUnit\Util\Color; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ProgressPrinter { private readonly Printer $printer; private readonly bool $colors; private readonly int $numberOfColumns; private readonly Source $source; private int $column = 0; private int $numberOfTests = 0; private int $numberOfTestsWidth = 0; private int $maxColumn = 0; private int $numberOfTestsRun = 0; private ?TestStatus $status = null; private bool $prepared = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Printer $printer, Facade $facade, bool $colors, int $numberOfColumns, Source $source) { $this->printer = $printer; $this->colors = $colors; $this->numberOfColumns = $numberOfColumns; $this->source = $source; $this->registerSubscribers($facade); } public function testRunnerExecutionStarted(ExecutionStarted $event): void { $this->numberOfTestsRun = 0; $this->numberOfTests = $event->testSuite()->count(); $this->numberOfTestsWidth = strlen((string) $this->numberOfTests); $this->column = 0; $this->maxColumn = $this->numberOfColumns - strlen(' / (XXX%)') - (2 * $this->numberOfTestsWidth); } public function beforeTestClassMethodErrored(): void { $this->printProgressForError(); $this->updateTestStatus(TestStatus::error()); } public function testPrepared(): void { $this->prepared = true; } public function testSkipped(): void { if (!$this->prepared) { $this->printProgressForSkipped(); } else { $this->updateTestStatus(TestStatus::skipped()); } } public function testMarkedIncomplete(): void { $this->updateTestStatus(TestStatus::incomplete()); } public function testTriggeredNotice(NoticeTriggered $event): void { if ($event->ignoredByBaseline()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfNotices() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void { if ($event->ignoredByBaseline()) { return; } if ($this->source->restrictNotices() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfPhpNotices() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredDeprecation(DeprecationTriggered $event): void { if ($event->ignoredByBaseline() || $event->ignoredByTest()) { return; } if ($this->source->ignoreSelfDeprecations() && $event->trigger()->isSelf()) { return; } if ($this->source->ignoreDirectDeprecations() && $event->trigger()->isDirect()) { return; } if ($this->source->ignoreIndirectDeprecations() && $event->trigger()->isIndirect()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfDeprecations() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void { if ($event->ignoredByBaseline() || $event->ignoredByTest()) { return; } if ($this->source->ignoreSelfDeprecations() && $event->trigger()->isSelf()) { return; } if ($this->source->ignoreDirectDeprecations() && $event->trigger()->isDirect()) { return; } if ($this->source->ignoreIndirectDeprecations() && $event->trigger()->isIndirect()) { return; } if ($this->source->restrictDeprecations() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfPhpDeprecations() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpunitDeprecation(): void { $this->updateTestStatus(TestStatus::deprecation()); } public function testConsideredRisky(): void { $this->updateTestStatus(TestStatus::risky()); } public function testTriggeredWarning(WarningTriggered $event): void { if ($event->ignoredByBaseline()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfWarnings() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpWarning(PhpWarningTriggered $event): void { if ($event->ignoredByBaseline()) { return; } if ($this->source->restrictWarnings() && !(new SourceFilter)->includes($this->source, $event->file())) { return; } if (!$this->source->ignoreSuppressionOfPhpWarnings() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpunitWarning(): void { $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredError(ErrorTriggered $event): void { if (!$this->source->ignoreSuppressionOfErrors() && $event->wasSuppressed()) { return; } $this->updateTestStatus(TestStatus::error()); } public function testFailed(): void { $this->updateTestStatus(TestStatus::failure()); } public function testErrored(Errored $event): void { /* * @todo Eliminate this special case */ if (str_contains($event->asString(), 'Test was run in child process and ended unexpectedly')) { $this->updateTestStatus(TestStatus::error()); return; } if (!$this->prepared) { $this->printProgressForError(); } else { $this->updateTestStatus(TestStatus::error()); } } public function testFinished(): void { if ($this->status === null) { $this->printProgressForSuccess(); } elseif ($this->status->isSkipped()) { $this->printProgressForSkipped(); } elseif ($this->status->isIncomplete()) { $this->printProgressForIncomplete(); } elseif ($this->status->isRisky()) { $this->printProgressForRisky(); } elseif ($this->status->isNotice()) { $this->printProgressForNotice(); } elseif ($this->status->isDeprecation()) { $this->printProgressForDeprecation(); } elseif ($this->status->isWarning()) { $this->printProgressForWarning(); } elseif ($this->status->isFailure()) { $this->printProgressForFailure(); } else { $this->printProgressForError(); } $this->status = null; $this->prepared = false; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new BeforeTestClassMethodErroredSubscriber($this), new TestConsideredRiskySubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestFinishedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestPreparedSubscriber($this), new TestRunnerExecutionStartedSubscriber($this), new TestSkippedSubscriber($this), new TestTriggeredDeprecationSubscriber($this), new TestTriggeredNoticeSubscriber($this), new TestTriggeredPhpDeprecationSubscriber($this), new TestTriggeredPhpNoticeSubscriber($this), new TestTriggeredPhpunitDeprecationSubscriber($this), new TestTriggeredPhpunitWarningSubscriber($this), new TestTriggeredPhpWarningSubscriber($this), new TestTriggeredWarningSubscriber($this), ); } private function updateTestStatus(TestStatus $status): void { if ($this->status !== null && $this->status->isMoreImportantThan($status)) { return; } $this->status = $status; } private function printProgressForSuccess(): void { $this->printProgress('.'); } private function printProgressForSkipped(): void { $this->printProgressWithColor('fg-cyan, bold', 'S'); } private function printProgressForIncomplete(): void { $this->printProgressWithColor('fg-yellow, bold', 'I'); } private function printProgressForNotice(): void { $this->printProgressWithColor('fg-yellow, bold', 'N'); } private function printProgressForDeprecation(): void { $this->printProgressWithColor('fg-yellow, bold', 'D'); } private function printProgressForRisky(): void { $this->printProgressWithColor('fg-yellow, bold', 'R'); } private function printProgressForWarning(): void { $this->printProgressWithColor('fg-yellow, bold', 'W'); } private function printProgressForFailure(): void { $this->printProgressWithColor('bg-red, fg-white', 'F'); } private function printProgressForError(): void { $this->printProgressWithColor('fg-red, bold', 'E'); } private function printProgressWithColor(string $color, string $progress): void { if ($this->colors) { $progress = Color::colorizeTextBox($color, $progress); } $this->printProgress($progress); } private function printProgress(string $progress): void { $this->printer->print($progress); $this->column++; $this->numberOfTestsRun++; if ($this->column === $this->maxColumn || $this->numberOfTestsRun === $this->numberOfTests) { if ($this->numberOfTestsRun === $this->numberOfTests) { $this->printer->print(str_repeat(' ', $this->maxColumn - $this->column)); } $this->printer->print( sprintf( ' %' . $this->numberOfTestsWidth . 'd / %' . $this->numberOfTestsWidth . 'd (%3s%%)', $this->numberOfTestsRun, $this->numberOfTests, floor(($this->numberOfTestsRun / $this->numberOfTests) * 100), ), ); if ($this->column === $this->maxColumn) { $this->column = 0; $this->printer->print("\n"); } } } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredNoticeSubscriber.php 0000644 00000001512 15253321353 0027017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\NoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber { public function notify(NoticeTriggered $event): void { $this->printer()->testTriggeredNotice($event); } } src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpDeprecationSubscriber.php 0000644 00000001572 15253321353 0030432 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber { public function notify(PhpDeprecationTriggered $event): void { $this->printer()->testTriggeredPhpDeprecation($event); } } src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php 0000644 00000001614 15253321353 0031327 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber { public function notify(PhpunitDeprecationTriggered $event): void { $this->printer()->testTriggeredPhpunitDeprecation(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestErroredSubscriber.php 0000644 00000001432 15253321353 0025344 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { public function notify(Errored $event): void { $this->printer()->testErrored($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001512 15253321353 0027164 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { public function notify(MarkedIncomplete $event): void { $this->printer()->testMarkedIncomplete(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFinishedSubscriber.php 0000644 00000001432 15253321353 0025473 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->printer()->testFinished(); } } src/TextUI/Output/Default/ProgressPrinter/Subscriber/BeforeTestClassMethodErroredSubscriber.php 0000644 00000001612 15253321353 0030537 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\BeforeFirstTestMethodErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeTestClassMethodErroredSubscriber extends Subscriber implements BeforeFirstTestMethodErroredSubscriber { public function notify(BeforeFirstTestMethodErrored $event): void { $this->printer()->beforeTestClassMethodErrored(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredWarningSubscriber.php 0000644 00000001520 15253321353 0027202 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\Test\WarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber { public function notify(WarningTriggered $event): void { $this->printer()->testTriggeredWarning($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/Subscriber.php 0000644 00000001431 15253321353 0023160 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private ProgressPrinter $printer; public function __construct(ProgressPrinter $printer) { $this->printer = $printer; } protected function printer(): ProgressPrinter { return $this->printer; } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestFailedSubscriber.php 0000644 00000001416 15253321353 0025130 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { public function notify(Failed $event): void { $this->printer()->testFailed(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestPreparedSubscriber.php 0000644 00000001432 15253321353 0025504 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->printer()->testPrepared(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpNoticeSubscriber.php 0000644 00000001534 15253321353 0027473 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber { public function notify(PhpNoticeTriggered $event): void { $this->printer()->testTriggeredPhpNotice($event); } } src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpunitWarningSubscriber.php 0000644 00000001564 15253321353 0030503 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber { public function notify(PhpunitWarningTriggered $event): void { $this->printer()->testTriggeredPhpunitWarning(); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredPhpWarningSubscriber.php 0000644 00000001542 15253321353 0027656 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber { public function notify(PhpWarningTriggered $event): void { $this->printer()->testTriggeredPhpWarning($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredErrorSubscriber.php 0000644 00000001504 15253321353 0026670 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\ErrorTriggered; use PHPUnit\Event\Test\ErrorTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredErrorSubscriber extends Subscriber implements ErrorTriggeredSubscriber { public function notify(ErrorTriggered $event): void { $this->printer()->testTriggeredError($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestTriggeredDeprecationSubscriber.php 0000644 00000001550 15253321353 0030035 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { public function notify(DeprecationTriggered $event): void { $this->printer()->testTriggeredDeprecation($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php 0000644 00000001424 15253321353 0025342 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { public function notify(Skipped $event): void { $this->printer()->testSkipped(); } } src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestRunnerExecutionStartedSubscriber.php 0000644 00000001550 15253321353 0030350 0 ustar 00 phpunit <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\TestRunner\ExecutionStarted; use PHPUnit\Event\TestRunner\ExecutionStartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestRunnerExecutionStartedSubscriber extends Subscriber implements ExecutionStartedSubscriber { public function notify(ExecutionStarted $event): void { $this->printer()->testRunnerExecutionStarted($event); } } phpunit/src/TextUI/Output/Default/ProgressPrinter/Subscriber/TestConsideredRiskySubscriber.php 0000644 00000001504 15253321353 0027043 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default\ProgressPrinter; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\ConsideredRiskySubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber { public function notify(ConsideredRisky $event): void { $this->printer()->testConsideredRisky(); } } phpunit/src/TextUI/Output/Default/UnexpectedOutputPrinter.php 0000644 00000002065 15253321353 0020477 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\Test\PrintedUnexpectedOutput; use PHPUnit\Event\Test\PrintedUnexpectedOutputSubscriber; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\TextUI\Output\Printer; final readonly class UnexpectedOutputPrinter implements PrintedUnexpectedOutputSubscriber { private Printer $printer; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Printer $printer, Facade $facade) { $this->printer = $printer; $facade->registerSubscriber($this); } public function notify(PrintedUnexpectedOutput $event): void { $this->printer->print($event->output()); } } phpunit/src/TextUI/Output/Default/ResultPrinter.php 0000644 00000050521 15253321353 0016430 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output\Default; use const PHP_EOL; use function array_keys; use function array_merge; use function array_reverse; use function array_unique; use function assert; use function count; use function explode; use function ksort; use function range; use function sprintf; use function str_starts_with; use function strlen; use function substr; use function trim; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Test\BeforeFirstTestMethodErrored; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\ErrorTriggered; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\TestRunner\TestResult\Issues\Issue; use PHPUnit\TestRunner\TestResult\TestResult; use PHPUnit\TextUI\Output\Printer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ResultPrinter { private readonly Printer $printer; private readonly bool $displayPhpunitErrors; private readonly bool $displayPhpunitWarnings; private readonly bool $displayTestsWithErrors; private readonly bool $displayTestsWithFailedAssertions; private readonly bool $displayRiskyTests; private readonly bool $displayPhpunitDeprecations; private readonly bool $displayDetailsOnIncompleteTests; private readonly bool $displayDetailsOnSkippedTests; private readonly bool $displayDetailsOnTestsThatTriggerDeprecations; private readonly bool $displayDetailsOnTestsThatTriggerErrors; private readonly bool $displayDetailsOnTestsThatTriggerNotices; private readonly bool $displayDetailsOnTestsThatTriggerWarnings; private readonly bool $displayDefectsInReverseOrder; private bool $listPrinted = false; public function __construct(Printer $printer, bool $displayPhpunitErrors, bool $displayPhpunitWarnings, bool $displayPhpunitDeprecations, bool $displayTestsWithErrors, bool $displayTestsWithFailedAssertions, bool $displayRiskyTests, bool $displayDetailsOnIncompleteTests, bool $displayDetailsOnSkippedTests, bool $displayDetailsOnTestsThatTriggerDeprecations, bool $displayDetailsOnTestsThatTriggerErrors, bool $displayDetailsOnTestsThatTriggerNotices, bool $displayDetailsOnTestsThatTriggerWarnings, bool $displayDefectsInReverseOrder) { $this->printer = $printer; $this->displayPhpunitErrors = $displayPhpunitErrors; $this->displayPhpunitWarnings = $displayPhpunitWarnings; $this->displayPhpunitDeprecations = $displayPhpunitDeprecations; $this->displayTestsWithErrors = $displayTestsWithErrors; $this->displayTestsWithFailedAssertions = $displayTestsWithFailedAssertions; $this->displayRiskyTests = $displayRiskyTests; $this->displayDetailsOnIncompleteTests = $displayDetailsOnIncompleteTests; $this->displayDetailsOnSkippedTests = $displayDetailsOnSkippedTests; $this->displayDetailsOnTestsThatTriggerDeprecations = $displayDetailsOnTestsThatTriggerDeprecations; $this->displayDetailsOnTestsThatTriggerErrors = $displayDetailsOnTestsThatTriggerErrors; $this->displayDetailsOnTestsThatTriggerNotices = $displayDetailsOnTestsThatTriggerNotices; $this->displayDetailsOnTestsThatTriggerWarnings = $displayDetailsOnTestsThatTriggerWarnings; $this->displayDefectsInReverseOrder = $displayDefectsInReverseOrder; } public function print(TestResult $result): void { if ($this->displayPhpunitErrors) { $this->printPhpunitErrors($result); } if ($this->displayPhpunitWarnings) { $this->printTestRunnerWarnings($result); } if ($this->displayPhpunitDeprecations) { $this->printTestRunnerDeprecations($result); } if ($this->displayTestsWithErrors) { $this->printTestsWithErrors($result); } if ($this->displayTestsWithFailedAssertions) { $this->printTestsWithFailedAssertions($result); } if ($this->displayPhpunitWarnings) { $this->printDetailsOnTestsThatTriggeredPhpunitWarnings($result); } if ($this->displayPhpunitDeprecations) { $this->printDetailsOnTestsThatTriggeredPhpunitDeprecations($result); } if ($this->displayRiskyTests) { $this->printRiskyTests($result); } if ($this->displayDetailsOnIncompleteTests) { $this->printIncompleteTests($result); } if ($this->displayDetailsOnSkippedTests) { $this->printSkippedTestSuites($result); $this->printSkippedTests($result); } if ($this->displayDetailsOnTestsThatTriggerErrors) { $this->printIssueList('error', $result->errors()); } if ($this->displayDetailsOnTestsThatTriggerWarnings) { $this->printIssueList('PHP warning', $result->phpWarnings()); $this->printIssueList('warning', $result->warnings()); } if ($this->displayDetailsOnTestsThatTriggerNotices) { $this->printIssueList('PHP notice', $result->phpNotices()); $this->printIssueList('notice', $result->notices()); } if ($this->displayDetailsOnTestsThatTriggerDeprecations) { $this->printIssueList('PHP deprecation', $result->phpDeprecations()); $this->printIssueList('deprecation', $result->deprecations()); } } public function flush(): void { $this->printer->flush(); } private function printPhpunitErrors(TestResult $result): void { if (!$result->hasTestTriggeredPhpunitErrorEvents()) { return; } $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitErrorEvents()); $this->printListHeaderWithNumber($elements['numberOfTestsWithIssues'], 'PHPUnit error'); $this->printList($elements['elements']); } private function printDetailsOnTestsThatTriggeredPhpunitDeprecations(TestResult $result): void { if (!$result->hasTestTriggeredPhpunitDeprecationEvents()) { return; } $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitDeprecationEvents()); $this->printListHeaderWithNumberOfTestsAndNumberOfIssues( $elements['numberOfTestsWithIssues'], $elements['numberOfIssues'], 'PHPUnit deprecation', ); $this->printList($elements['elements']); } private function printTestRunnerWarnings(TestResult $result): void { if (!$result->hasTestRunnerTriggeredWarningEvents()) { return; } $elements = []; foreach ($result->testRunnerTriggeredWarningEvents() as $event) { $elements[] = [ 'title' => $event->message(), 'body' => '', ]; } $this->printListHeaderWithNumber(count($elements), 'PHPUnit test runner warning'); $this->printList($elements); } private function printTestRunnerDeprecations(TestResult $result): void { if (!$result->hasTestRunnerTriggeredDeprecationEvents()) { return; } $elements = []; foreach ($result->testRunnerTriggeredDeprecationEvents() as $event) { $elements[] = [ 'title' => $event->message(), 'body' => '', ]; } $this->printListHeaderWithNumber(count($elements), 'PHPUnit test runner deprecation'); $this->printList($elements); } private function printDetailsOnTestsThatTriggeredPhpunitWarnings(TestResult $result): void { if (!$result->hasTestTriggeredPhpunitWarningEvents()) { return; } $elements = $this->mapTestsWithIssuesEventsToElements($result->testTriggeredPhpunitWarningEvents()); $this->printListHeaderWithNumberOfTestsAndNumberOfIssues( $elements['numberOfTestsWithIssues'], $elements['numberOfIssues'], 'PHPUnit warning', ); $this->printList($elements['elements']); } private function printTestsWithErrors(TestResult $result): void { if (!$result->hasTestErroredEvents()) { return; } $elements = []; foreach ($result->testErroredEvents() as $event) { if ($event instanceof BeforeFirstTestMethodErrored) { $title = $event->testClassName(); } else { $title = $this->name($event->test()); } $elements[] = [ 'title' => $title, 'body' => $event->throwable()->asString(), ]; } $this->printListHeaderWithNumber(count($elements), 'error'); $this->printList($elements); } private function printTestsWithFailedAssertions(TestResult $result): void { if (!$result->hasTestFailedEvents()) { return; } $elements = []; foreach ($result->testFailedEvents() as $event) { $body = $event->throwable()->asString(); if (str_starts_with($body, 'AssertionError: ')) { $body = substr($body, strlen('AssertionError: ')); } $elements[] = [ 'title' => $this->name($event->test()), 'body' => $body, ]; } $this->printListHeaderWithNumber(count($elements), 'failure'); $this->printList($elements); } private function printRiskyTests(TestResult $result): void { if (!$result->hasTestConsideredRiskyEvents()) { return; } $elements = $this->mapTestsWithIssuesEventsToElements($result->testConsideredRiskyEvents()); $this->printListHeaderWithNumber($elements['numberOfTestsWithIssues'], 'risky test'); $this->printList($elements['elements']); } private function printIncompleteTests(TestResult $result): void { if (!$result->hasTestMarkedIncompleteEvents()) { return; } $elements = []; foreach ($result->testMarkedIncompleteEvents() as $event) { $elements[] = [ 'title' => $this->name($event->test()), 'body' => $event->throwable()->asString(), ]; } $this->printListHeaderWithNumber(count($elements), 'incomplete test'); $this->printList($elements); } private function printSkippedTestSuites(TestResult $result): void { if (!$result->hasTestSuiteSkippedEvents()) { return; } $elements = []; foreach ($result->testSuiteSkippedEvents() as $event) { $elements[] = [ 'title' => $event->testSuite()->name(), 'body' => $event->message(), ]; } $this->printListHeaderWithNumber(count($elements), 'skipped test suite'); $this->printList($elements); } private function printSkippedTests(TestResult $result): void { if (!$result->hasTestSkippedEvents()) { return; } $elements = []; foreach ($result->testSkippedEvents() as $event) { $elements[] = [ 'title' => $this->name($event->test()), 'body' => $event->message(), ]; } $this->printListHeaderWithNumber(count($elements), 'skipped test'); $this->printList($elements); } /** * @param non-empty-string $type * @param list<Issue> $issues */ private function printIssueList(string $type, array $issues): void { if (empty($issues)) { return; } $numberOfUniqueIssues = count($issues); $triggeringTests = []; foreach ($issues as $issue) { $triggeringTests = array_merge($triggeringTests, array_keys($issue->triggeringTests())); } $numberOfTests = count(array_unique($triggeringTests)); unset($triggeringTests); $this->printListHeader( sprintf( '%d test%s triggered %d %s%s:' . PHP_EOL . PHP_EOL, $numberOfTests, $numberOfTests !== 1 ? 's' : '', $numberOfUniqueIssues, $type, $numberOfUniqueIssues !== 1 ? 's' : '', ), ); $i = 1; foreach ($issues as $issue) { $title = sprintf( '%s:%d', $issue->file(), $issue->line(), ); $body = trim($issue->description()) . PHP_EOL . PHP_EOL . 'Triggered by:'; $triggeringTests = $issue->triggeringTests(); ksort($triggeringTests); foreach ($triggeringTests as $triggeringTest) { $body .= PHP_EOL . PHP_EOL . '* ' . $triggeringTest['test']->id(); if ($triggeringTest['count'] > 1) { $body .= sprintf( ' (%d times)', $triggeringTest['count'], ); } if ($triggeringTest['test']->isTestMethod()) { $body .= PHP_EOL . ' ' . $triggeringTest['test']->file() . ':' . $triggeringTest['test']->line(); } } $this->printIssueListElement($i++, $title, $body); $this->printer->print(PHP_EOL); } } private function printListHeaderWithNumberOfTestsAndNumberOfIssues(int $numberOfTestsWithIssues, int $numberOfIssues, string $type): void { $this->printListHeader( sprintf( "%d test%s triggered %d %s%s:\n\n", $numberOfTestsWithIssues, $numberOfTestsWithIssues !== 1 ? 's' : '', $numberOfIssues, $type, $numberOfIssues !== 1 ? 's' : '', ), ); } private function printListHeaderWithNumber(int $number, string $type): void { $this->printListHeader( sprintf( "There %s %d %s%s:\n\n", ($number === 1) ? 'was' : 'were', $number, $type, ($number === 1) ? '' : 's', ), ); } private function printListHeader(string $header): void { if ($this->listPrinted) { $this->printer->print("--\n\n"); } $this->listPrinted = true; $this->printer->print($header); } /** * @param list<array{title: string, body: string}> $elements */ private function printList(array $elements): void { $i = 1; if ($this->displayDefectsInReverseOrder) { $elements = array_reverse($elements); } foreach ($elements as $element) { $this->printListElement($i++, $element['title'], $element['body']); } $this->printer->print("\n"); } private function printListElement(int $number, string $title, string $body): void { $body = trim($body); $this->printer->print( sprintf( "%s%d) %s\n%s%s", $number > 1 ? "\n" : '', $number, $title, $body, !empty($body) ? "\n" : '', ), ); } private function printIssueListElement(int $number, string $title, string $body): void { $body = trim($body); $this->printer->print( sprintf( "%d) %s\n%s%s", $number, $title, $body, !empty($body) ? "\n" : '', ), ); } private function name(Test $test): string { if ($test->isTestMethod()) { assert($test instanceof TestMethod); if (!$test->testData()->hasDataFromDataProvider()) { return $test->nameWithClass(); } return $test->className() . '::' . $test->methodName() . $test->testData()->dataFromDataProvider()->dataAsStringForResultOutput(); } return $test->name(); } /** * @param array<string,list<ConsideredRisky|DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpunitDeprecationTriggered|PhpunitErrorTriggered|PhpunitWarningTriggered|PhpWarningTriggered|WarningTriggered>> $events * * @return array{numberOfTestsWithIssues: int, numberOfIssues: int, elements: list<array{title: string, body: string}>} */ private function mapTestsWithIssuesEventsToElements(array $events): array { $elements = []; $issues = 0; foreach ($events as $reasons) { $test = $reasons[0]->test(); $testLocation = $this->testLocation($test); $title = $this->name($test); $body = ''; $first = true; $single = count($reasons) === 1; foreach ($reasons as $reason) { if ($first) { $first = false; } else { $body .= PHP_EOL; } $body .= $this->reasonMessage($reason, $single); $body .= $this->reasonLocation($reason, $single); $issues++; } if (!empty($testLocation)) { $body .= $testLocation; } $elements[] = [ 'title' => $title, 'body' => $body, ]; } return [ 'numberOfTestsWithIssues' => count($events), 'numberOfIssues' => $issues, 'elements' => $elements, ]; } private function testLocation(Test $test): string { if (!$test->isTestMethod()) { return ''; } assert($test instanceof TestMethod); return sprintf( '%s%s:%d%s', PHP_EOL, $test->file(), $test->line(), PHP_EOL, ); } private function reasonMessage(ConsideredRisky|DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpunitDeprecationTriggered|PhpunitErrorTriggered|PhpunitWarningTriggered|PhpWarningTriggered|WarningTriggered $reason, bool $single): string { $message = trim($reason->message()); if ($single) { return $message . PHP_EOL; } $lines = explode(PHP_EOL, $message); $buffer = '* ' . $lines[0] . PHP_EOL; if (count($lines) > 1) { foreach (range(1, count($lines) - 1) as $line) { $buffer .= ' ' . $lines[$line] . PHP_EOL; } } return $buffer; } private function reasonLocation(ConsideredRisky|DeprecationTriggered|ErrorTriggered|NoticeTriggered|PhpDeprecationTriggered|PhpNoticeTriggered|PhpunitDeprecationTriggered|PhpunitErrorTriggered|PhpunitWarningTriggered|PhpWarningTriggered|WarningTriggered $reason, bool $single): string { if (!$reason instanceof DeprecationTriggered && !$reason instanceof PhpDeprecationTriggered && !$reason instanceof ErrorTriggered && !$reason instanceof NoticeTriggered && !$reason instanceof PhpNoticeTriggered && !$reason instanceof WarningTriggered && !$reason instanceof PhpWarningTriggered) { return ''; } return sprintf( '%s%s:%d%s', $single ? '' : ' ', $reason->file(), $reason->line(), PHP_EOL, ); } } phpunit/src/TextUI/Output/Facade.php 0000644 00000021200 15253321353 0013355 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output; use const PHP_EOL; use function assert; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Logging\TeamCity\TeamCityLogger; use PHPUnit\Logging\TestDox\TestResultCollection; use PHPUnit\Runner\DirectoryDoesNotExistException; use PHPUnit\TestRunner\TestResult\TestResult; use PHPUnit\TextUI\CannotOpenSocketException; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\InvalidSocketException; use PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter as DefaultProgressPrinter; use PHPUnit\TextUI\Output\Default\ResultPrinter as DefaultResultPrinter; use PHPUnit\TextUI\Output\Default\UnexpectedOutputPrinter; use PHPUnit\TextUI\Output\TestDox\ResultPrinter as TestDoxResultPrinter; use SebastianBergmann\Timer\Duration; use SebastianBergmann\Timer\ResourceUsageFormatter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Facade { private static ?Printer $printer = null; private static ?DefaultResultPrinter $defaultResultPrinter = null; private static ?TestDoxResultPrinter $testDoxResultPrinter = null; private static ?SummaryPrinter $summaryPrinter = null; private static bool $defaultProgressPrinter = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public static function init(Configuration $configuration, bool $extensionReplacesProgressOutput, bool $extensionReplacesResultOutput): Printer { self::createPrinter($configuration); assert(self::$printer !== null); if ($configuration->debug()) { return self::$printer; } self::createUnexpectedOutputPrinter(); if (!$extensionReplacesProgressOutput) { self::createProgressPrinter($configuration); } if (!$extensionReplacesResultOutput) { self::createResultPrinter($configuration); self::createSummaryPrinter($configuration); } if ($configuration->outputIsTeamCity()) { new TeamCityLogger( DefaultPrinter::standardOutput(), EventFacade::instance(), ); } return self::$printer; } /** * @param ?array<string, TestResultCollection> $testDoxResult */ public static function printResult(TestResult $result, ?array $testDoxResult, Duration $duration): void { assert(self::$printer !== null); if ($result->numberOfTestsRun() > 0) { if (self::$defaultProgressPrinter) { self::$printer->print(PHP_EOL . PHP_EOL); } self::$printer->print((new ResourceUsageFormatter)->resourceUsage($duration) . PHP_EOL . PHP_EOL); } if (self::$testDoxResultPrinter !== null && $testDoxResult !== null) { self::$testDoxResultPrinter->print($testDoxResult); } if (self::$defaultResultPrinter !== null) { self::$defaultResultPrinter->print($result); } if (self::$summaryPrinter !== null) { self::$summaryPrinter->print($result); } } /** * @throws CannotOpenSocketException * @throws DirectoryDoesNotExistException * @throws InvalidSocketException */ public static function printerFor(string $target): Printer { if ($target === 'php://stdout') { if (!self::$printer instanceof NullPrinter) { return self::$printer; } return DefaultPrinter::standardOutput(); } return DefaultPrinter::from($target); } private static function createPrinter(Configuration $configuration): void { $printerNeeded = false; if ($configuration->debug()) { $printerNeeded = true; } if ($configuration->outputIsTeamCity()) { $printerNeeded = true; } if ($configuration->outputIsTestDox()) { $printerNeeded = true; } if (!$configuration->noOutput() && !$configuration->noProgress()) { $printerNeeded = true; } if (!$configuration->noOutput() && !$configuration->noResults()) { $printerNeeded = true; } if ($printerNeeded) { if ($configuration->outputToStandardErrorStream()) { self::$printer = DefaultPrinter::standardError(); return; } self::$printer = DefaultPrinter::standardOutput(); return; } self::$printer = new NullPrinter; } private static function createProgressPrinter(Configuration $configuration): void { assert(self::$printer !== null); if (!self::useDefaultProgressPrinter($configuration)) { return; } new DefaultProgressPrinter( self::$printer, EventFacade::instance(), $configuration->colors(), $configuration->columns(), $configuration->source(), ); self::$defaultProgressPrinter = true; } private static function useDefaultProgressPrinter(Configuration $configuration): bool { if ($configuration->noOutput()) { return false; } if ($configuration->noProgress()) { return false; } if ($configuration->outputIsTeamCity()) { return false; } return true; } private static function createResultPrinter(Configuration $configuration): void { assert(self::$printer !== null); if ($configuration->outputIsTestDox()) { self::$defaultResultPrinter = new DefaultResultPrinter( self::$printer, true, true, true, false, false, true, false, false, $configuration->displayDetailsOnTestsThatTriggerDeprecations(), $configuration->displayDetailsOnTestsThatTriggerErrors(), $configuration->displayDetailsOnTestsThatTriggerNotices(), $configuration->displayDetailsOnTestsThatTriggerWarnings(), $configuration->reverseDefectList(), ); } if ($configuration->outputIsTestDox()) { self::$testDoxResultPrinter = new TestDoxResultPrinter( self::$printer, $configuration->colors(), $configuration->columns(), $configuration->testDoxOutputWithSummary(), ); } if ($configuration->noOutput() || $configuration->noResults()) { return; } if (self::$defaultResultPrinter !== null) { return; } self::$defaultResultPrinter = new DefaultResultPrinter( self::$printer, true, true, true, true, true, true, $configuration->displayDetailsOnIncompleteTests(), $configuration->displayDetailsOnSkippedTests(), $configuration->displayDetailsOnTestsThatTriggerDeprecations(), $configuration->displayDetailsOnTestsThatTriggerErrors(), $configuration->displayDetailsOnTestsThatTriggerNotices(), $configuration->displayDetailsOnTestsThatTriggerWarnings(), $configuration->reverseDefectList(), ); } private static function createSummaryPrinter(Configuration $configuration): void { assert(self::$printer !== null); if (($configuration->noOutput() || $configuration->noResults()) && !($configuration->outputIsTeamCity() || $configuration->outputIsTestDox())) { return; } self::$summaryPrinter = new SummaryPrinter( self::$printer, $configuration->colors(), ); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private static function createUnexpectedOutputPrinter(): void { assert(self::$printer !== null); new UnexpectedOutputPrinter(self::$printer, EventFacade::instance()); } } phpunit/src/TextUI/Output/SummaryPrinter.php 0000644 00000013223 15253321353 0015221 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI\Output; use const PHP_EOL; use function sprintf; use PHPUnit\TestRunner\TestResult\TestResult; use PHPUnit\Util\Color; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class SummaryPrinter { private readonly Printer $printer; private readonly bool $colors; private bool $countPrinted = false; public function __construct(Printer $printer, bool $colors) { $this->printer = $printer; $this->colors = $colors; } public function print(TestResult $result): void { if ($result->numberOfTestsRun() === 0) { $this->printWithColor( 'fg-black, bg-yellow', 'No tests executed!', ); return; } if ($result->wasSuccessfulAndNoTestHasIssues() && !$result->hasTestSuiteSkippedEvents() && !$result->hasTestSkippedEvents()) { $this->printWithColor( 'fg-black, bg-green', sprintf( 'OK (%d test%s, %d assertion%s)', $result->numberOfTestsRun(), $result->numberOfTestsRun() === 1 ? '' : 's', $result->numberOfAssertions(), $result->numberOfAssertions() === 1 ? '' : 's', ), ); $this->printNumberOfIssuesIgnoredByBaseline($result); return; } $color = 'fg-black, bg-yellow'; if ($result->wasSuccessful()) { if (!$result->hasTestsWithIssues()) { $this->printWithColor( $color, 'OK, but some tests were skipped!', ); } else { $this->printWithColor( $color, 'OK, but there were issues!', ); } } else { if ($result->hasTestErroredEvents() || $result->hasTestTriggeredPhpunitErrorEvents()) { $color = 'fg-white, bg-red'; $this->printWithColor( $color, 'ERRORS!', ); } elseif ($result->hasTestFailedEvents()) { $color = 'fg-white, bg-red'; $this->printWithColor( $color, 'FAILURES!', ); } elseif ($result->hasWarnings()) { $this->printWithColor( $color, 'WARNINGS!', ); } elseif ($result->hasDeprecations()) { $this->printWithColor( $color, 'DEPRECATIONS!', ); } elseif ($result->hasNotices()) { $this->printWithColor( $color, 'NOTICES!', ); } } $this->printCountString($result->numberOfTestsRun(), 'Tests', $color, true); $this->printCountString($result->numberOfAssertions(), 'Assertions', $color, true); $this->printCountString($result->numberOfErrors(), 'Errors', $color); $this->printCountString($result->numberOfTestFailedEvents(), 'Failures', $color); $this->printCountString($result->numberOfWarnings(), 'Warnings', $color); $this->printCountString($result->numberOfDeprecations(), 'Deprecations', $color); $this->printCountString($result->numberOfNotices(), 'Notices', $color); $this->printCountString($result->numberOfTestSuiteSkippedEvents() + $result->numberOfTestSkippedEvents(), 'Skipped', $color); $this->printCountString($result->numberOfTestMarkedIncompleteEvents(), 'Incomplete', $color); $this->printCountString($result->numberOfTestsWithTestConsideredRiskyEvents(), 'Risky', $color); $this->printWithColor($color, '.'); $this->printNumberOfIssuesIgnoredByBaseline($result); } private function printCountString(int $count, string $name, string $color, bool $always = false): void { if ($always || $count > 0) { $this->printWithColor( $color, sprintf( '%s%s: %d', $this->countPrinted ? ', ' : '', $name, $count, ), false, ); $this->countPrinted = true; } } private function printWithColor(string $color, string $buffer, bool $lf = true): void { if ($this->colors) { $buffer = Color::colorizeTextBox($color, $buffer); } $this->printer->print($buffer); if ($lf) { $this->printer->print(PHP_EOL); } } private function printNumberOfIssuesIgnoredByBaseline(TestResult $result): void { if ($result->hasIssuesIgnoredByBaseline()) { $this->printer->print( sprintf( '%s%d issue%s %s ignored by baseline.%s', PHP_EOL, $result->numberOfIssuesIgnoredByBaseline(), $result->numberOfIssuesIgnoredByBaseline() > 1 ? 's' : '', $result->numberOfIssuesIgnoredByBaseline() > 1 ? 'were' : 'was', PHP_EOL, ), ); } } } phpunit/src/TextUI/TestSuiteFilterProcessor.php 0000644 00000005237 15253321353 0015725 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use function array_map; use PHPUnit\Event; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\Filter\Factory; use PHPUnit\TextUI\Configuration\Configuration; use PHPUnit\TextUI\Configuration\FilterNotConfiguredException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteFilterProcessor { /** * @throws Event\RuntimeException * @throws FilterNotConfiguredException */ public function process(Configuration $configuration, TestSuite $suite): void { $factory = new Factory; if (!$configuration->hasFilter() && !$configuration->hasGroups() && !$configuration->hasExcludeGroups() && !$configuration->hasExcludeFilter() && !$configuration->hasTestsCovering() && !$configuration->hasTestsUsing()) { return; } if ($configuration->hasExcludeGroups()) { $factory->addExcludeGroupFilter( $configuration->excludeGroups(), ); } if ($configuration->hasGroups()) { $factory->addIncludeGroupFilter( $configuration->groups(), ); } if ($configuration->hasTestsCovering()) { $factory->addIncludeGroupFilter( array_map( static fn (string $name): string => '__phpunit_covers_' . $name, $configuration->testsCovering(), ), ); } if ($configuration->hasTestsUsing()) { $factory->addIncludeGroupFilter( array_map( static fn (string $name): string => '__phpunit_uses_' . $name, $configuration->testsUsing(), ), ); } if ($configuration->hasExcludeFilter()) { $factory->addExcludeNameFilter( $configuration->excludeFilter(), ); } if ($configuration->hasFilter()) { $factory->addIncludeNameFilter( $configuration->filter(), ); } $suite->injectFilter($factory); Event\Facade::emitter()->testSuiteFiltered( Event\TestSuite\TestSuiteBuilder::from($suite), ); } } phpunit/src/Util/Xml/Loader.php 0000644 00000005307 15253321353 0012425 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\Xml; use function error_reporting; use function file_get_contents; use function libxml_get_errors; use function libxml_use_internal_errors; use function sprintf; use DOMDocument; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Loader { /** * @throws XmlException */ public function loadFile(string $filename): DOMDocument { $reporting = error_reporting(0); $contents = file_get_contents($filename); error_reporting($reporting); if ($contents === false) { throw new XmlException( sprintf( 'Could not read XML from file "%s"', $filename, ), ); } return $this->load($contents, $filename); } /** * @throws XmlException */ public function load(string $actual, ?string $filename = null): DOMDocument { if ($actual === '') { if ($filename === null) { throw new XmlException('Could not parse XML from empty string'); } throw new XmlException( sprintf( 'Could not parse XML from empty file "%s"', $filename, ), ); } $document = new DOMDocument; $document->preserveWhiteSpace = false; $internal = libxml_use_internal_errors(true); $message = ''; $reporting = error_reporting(0); $loaded = $document->loadXML($actual); foreach (libxml_get_errors() as $error) { $message .= "\n" . $error->message; } libxml_use_internal_errors($internal); error_reporting($reporting); if ($loaded === false || $message !== '') { if ($filename !== null) { throw new XmlException( sprintf( 'Could not load "%s"%s', $filename, $message !== '' ? ":\n" . $message : '', ), ); } if ($message === '') { $message = 'Could not load XML for unknown reason'; } throw new XmlException($message); } return $document; } } phpunit/src/Util/Xml/Xml.php 0000644 00000004236 15253321353 0011757 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const ENT_QUOTES; use function htmlspecialchars; use function mb_convert_encoding; use function ord; use function preg_replace; use function strlen; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Xml { /** * Escapes a string for the use in XML documents. * * Any Unicode character is allowed, excluding the surrogate blocks, FFFE, * and FFFF (not even as character reference). * * @see https://www.w3.org/TR/xml/#charsets */ public static function prepareString(string $string): string { return preg_replace( '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/', '', htmlspecialchars( self::convertToUtf8($string), ENT_QUOTES, ), ); } private static function convertToUtf8(string $string): string { if (!self::isUtf8($string)) { $string = mb_convert_encoding($string, 'UTF-8'); } return $string; } private static function isUtf8(string $string): bool { $length = strlen($string); for ($i = 0; $i < $length; $i++) { if (ord($string[$i]) < 0x80) { $n = 0; } elseif ((ord($string[$i]) & 0xE0) === 0xC0) { $n = 1; } elseif ((ord($string[$i]) & 0xF0) === 0xE0) { $n = 2; } elseif ((ord($string[$i]) & 0xF0) === 0xF0) { $n = 3; } else { return false; } for ($j = 0; $j < $n; $j++) { if ((++$i === $length) || ((ord($string[$i]) & 0xC0) !== 0x80)) { return false; } } } return true; } } phpunit/src/Util/Color.php 0000644 00000011623 15253321353 0011533 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const DIRECTORY_SEPARATOR; use const PHP_EOL; use function array_map; use function array_walk; use function count; use function explode; use function implode; use function max; use function min; use function preg_replace; use function preg_replace_callback; use function preg_split; use function sprintf; use function str_pad; use function strtr; use function trim; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Color { /** * @var array<string,string> */ private const WHITESPACE_MAP = [ ' ' => '·', "\t" => '⇥', ]; /** * @var array<string,string> */ private const WHITESPACE_EOL_MAP = [ ' ' => '·', "\t" => '⇥', "\n" => '↵', "\r" => '⟵', ]; /** * @var array<string,string> */ private static array $ansiCodes = [ 'reset' => '0', 'bold' => '1', 'dim' => '2', 'dim-reset' => '22', 'underlined' => '4', 'fg-default' => '39', 'fg-black' => '30', 'fg-red' => '31', 'fg-green' => '32', 'fg-yellow' => '33', 'fg-blue' => '34', 'fg-magenta' => '35', 'fg-cyan' => '36', 'fg-white' => '37', 'bg-default' => '49', 'bg-black' => '40', 'bg-red' => '41', 'bg-green' => '42', 'bg-yellow' => '43', 'bg-blue' => '44', 'bg-magenta' => '45', 'bg-cyan' => '46', 'bg-white' => '47', ]; public static function colorize(string $color, string $buffer): string { if (trim($buffer) === '') { return $buffer; } $codes = array_map('\trim', explode(',', $color)); $styles = []; foreach ($codes as $code) { if (isset(self::$ansiCodes[$code])) { $styles[] = self::$ansiCodes[$code]; } } if (empty($styles)) { return $buffer; } return self::optimizeColor(sprintf("\x1b[%sm", implode(';', $styles)) . $buffer . "\x1b[0m"); } public static function colorizeTextBox(string $color, string $buffer, ?int $columns = null): string { $lines = preg_split('/\r\n|\r|\n/', $buffer); $maxBoxWidth = max(array_map('\strlen', $lines)); if ($columns !== null) { $maxBoxWidth = min($maxBoxWidth, $columns); } array_walk($lines, static function (string &$line) use ($color, $maxBoxWidth): void { $line = self::colorize($color, str_pad($line, $maxBoxWidth)); }); return implode(PHP_EOL, $lines); } public static function colorizePath(string $path, ?string $previousPath = null, bool $colorizeFilename = false): string { if ($previousPath === null) { $previousPath = ''; } $path = explode(DIRECTORY_SEPARATOR, $path); $previousPath = explode(DIRECTORY_SEPARATOR, $previousPath); for ($i = 0; $i < min(count($path), count($previousPath)); $i++) { if ($path[$i] === $previousPath[$i]) { $path[$i] = self::dim($path[$i]); } } if ($colorizeFilename) { $last = count($path) - 1; $path[$last] = preg_replace_callback( '/([\-_.]+|phpt$)/', static fn ($matches) => self::dim($matches[0]), $path[$last], ); } return self::optimizeColor(implode(self::dim(DIRECTORY_SEPARATOR), $path)); } public static function dim(string $buffer): string { if (trim($buffer) === '') { return $buffer; } return "\e[2m{$buffer}\e[22m"; } public static function visualizeWhitespace(string $buffer, bool $visualizeEOL = false): string { $replaceMap = $visualizeEOL ? self::WHITESPACE_EOL_MAP : self::WHITESPACE_MAP; return preg_replace_callback( '/\s+/', static fn ($matches) => self::dim(strtr($matches[0], $replaceMap)), $buffer, ); } private static function optimizeColor(string $buffer): string { return preg_replace( [ "/\e\\[22m\e\\[2m/", "/\e\\[([^m]*)m\e\\[([1-9][0-9;]*)m/", "/(\e\\[[^m]*m)+(\e\\[0m)/", ], [ '', "\e[$1;$2m", '$2', ], $buffer, ); } } phpunit/src/Util/Reflection.php 0000644 00000006243 15253321353 0012551 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function array_keys; use function array_merge; use function array_reverse; use function assert; use PHPUnit\Framework\Assert; use PHPUnit\Framework\TestCase; use ReflectionClass; use ReflectionException; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Reflection { /** * @param class-string $className * @param non-empty-string $methodName * * @return array{file: non-empty-string, line: non-negative-int} */ public static function sourceLocationFor(string $className, string $methodName): array { try { $reflector = new ReflectionMethod($className, $methodName); $file = $reflector->getFileName(); $line = $reflector->getStartLine(); } catch (ReflectionException) { $file = 'unknown'; $line = 0; } assert($file !== false && $file !== ''); assert($line !== false && $line >= 0); return [ 'file' => $file, 'line' => $line, ]; } /** * @param ReflectionClass<TestCase> $class * * @return list<ReflectionMethod> */ public static function publicMethodsDeclaredDirectlyInTestClass(ReflectionClass $class): array { return self::filterAndSortMethods($class, ReflectionMethod::IS_PUBLIC, true); } /** * @param ReflectionClass<TestCase> $class * * @return list<ReflectionMethod> */ public static function methodsDeclaredDirectlyInTestClass(ReflectionClass $class): array { return self::filterAndSortMethods($class, null, false); } /** * @param ReflectionClass<TestCase> $class * * @return list<ReflectionMethod> */ private static function filterAndSortMethods(ReflectionClass $class, ?int $filter, bool $sortHighestToLowest): array { $methodsByClass = []; foreach ($class->getMethods($filter) as $method) { $declaringClassName = $method->getDeclaringClass()->getName(); if ($declaringClassName === TestCase::class) { continue; } if ($declaringClassName === Assert::class) { continue; } if (!isset($methodsByClass[$declaringClassName])) { $methodsByClass[$declaringClassName] = []; } $methodsByClass[$declaringClassName][] = $method; } $classNames = array_keys($methodsByClass); if ($sortHighestToLowest) { $classNames = array_reverse($classNames); } $methods = []; foreach ($classNames as $className) { $methods = array_merge($methods, $methodsByClass[$className]); } return $methods; } } phpunit/src/Util/ThrowableToStringMapper.php 0000644 00000002661 15253321353 0015245 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function trim; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\PhptAssertionFailedError; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Runner\ErrorException; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ThrowableToStringMapper { public static function map(Throwable $t): string { if ($t instanceof ErrorException) { return $t->getMessage(); } if ($t instanceof SelfDescribing) { $buffer = $t->toString(); if ($t instanceof ExpectationFailedException && $t->getComparisonFailure()) { $buffer .= $t->getComparisonFailure()->getDiff(); } if ($t instanceof PhptAssertionFailedError) { $buffer .= $t->diff(); } if (!empty($buffer)) { $buffer = trim($buffer) . "\n"; } return $buffer; } return $t::class . ': ' . $t->getMessage() . "\n"; } } phpunit/src/Util/ExcludeList.php 0000644 00000013217 15253321353 0012703 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const PHP_OS_FAMILY; use function class_exists; use function defined; use function dirname; use function is_dir; use function realpath; use function str_starts_with; use function sys_get_temp_dir; use Composer\Autoload\ClassLoader; use DeepCopy\DeepCopy; use PharIo\Manifest\Manifest; use PharIo\Version\Version as PharIoVersion; use PhpParser\Parser; use PHPUnit\Framework\TestCase; use ReflectionClass; use SebastianBergmann\CliParser\Parser as CliParser; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeUnit\CodeUnit; use SebastianBergmann\CodeUnitReverseLookup\Wizard; use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Complexity\Calculator; use SebastianBergmann\Diff\Diff; use SebastianBergmann\Environment\Runtime; use SebastianBergmann\Exporter\Exporter; use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; use SebastianBergmann\GlobalState\Snapshot; use SebastianBergmann\Invoker\Invoker; use SebastianBergmann\LinesOfCode\Counter; use SebastianBergmann\ObjectEnumerator\Enumerator; use SebastianBergmann\ObjectReflector\ObjectReflector; use SebastianBergmann\RecursionContext\Context; use SebastianBergmann\Template\Template; use SebastianBergmann\Timer\Timer; use SebastianBergmann\Type\TypeName; use SebastianBergmann\Version; use TheSeer\Tokenizer\Tokenizer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class ExcludeList { /** * @var array<string,int> */ private const EXCLUDED_CLASS_NAMES = [ // composer ClassLoader::class => 1, // myclabs/deepcopy DeepCopy::class => 1, // nikic/php-parser Parser::class => 1, // phar-io/manifest Manifest::class => 1, // phar-io/version PharIoVersion::class => 1, // phpunit/phpunit TestCase::class => 2, // phpunit/php-code-coverage CodeCoverage::class => 1, // phpunit/php-file-iterator FileIteratorFacade::class => 1, // phpunit/php-invoker Invoker::class => 1, // phpunit/php-text-template Template::class => 1, // phpunit/php-timer Timer::class => 1, // sebastian/cli-parser CliParser::class => 1, // sebastian/code-unit CodeUnit::class => 1, // sebastian/code-unit-reverse-lookup Wizard::class => 1, // sebastian/comparator Comparator::class => 1, // sebastian/complexity Calculator::class => 1, // sebastian/diff Diff::class => 1, // sebastian/environment Runtime::class => 1, // sebastian/exporter Exporter::class => 1, // sebastian/global-state Snapshot::class => 1, // sebastian/lines-of-code Counter::class => 1, // sebastian/object-enumerator Enumerator::class => 1, // sebastian/object-reflector ObjectReflector::class => 1, // sebastian/recursion-context Context::class => 1, // sebastian/type TypeName::class => 1, // sebastian/version Version::class => 1, // theseer/tokenizer Tokenizer::class => 1, ]; /** * @var list<string> */ private static array $directories = []; private static bool $initialized = false; private readonly bool $enabled; /** * @param non-empty-string $directory * * @throws InvalidDirectoryException */ public static function addDirectory(string $directory): void { if (!is_dir($directory)) { throw new InvalidDirectoryException($directory); } self::$directories[] = realpath($directory); } public function __construct(?bool $enabled = null) { if ($enabled === null) { $enabled = !defined('PHPUNIT_TESTSUITE'); } $this->enabled = $enabled; } /** * @return list<string> */ public function getExcludedDirectories(): array { self::initialize(); return self::$directories; } public function isExcluded(string $file): bool { if (!$this->enabled) { return false; } self::initialize(); foreach (self::$directories as $directory) { if (str_starts_with($file, $directory)) { return true; } } return false; } private static function initialize(): void { if (self::$initialized) { return; } foreach (self::EXCLUDED_CLASS_NAMES as $className => $parent) { if (!class_exists($className)) { continue; } $directory = (new ReflectionClass($className))->getFileName(); for ($i = 0; $i < $parent; $i++) { $directory = dirname($directory); } self::$directories[] = $directory; } /** * Hide process isolation workaround on Windows: * tempnam() prefix is limited to first 3 characters. * * @see https://php.net/manual/en/function.tempnam.php */ if (PHP_OS_FAMILY === 'Windows') { // @codeCoverageIgnoreStart self::$directories[] = sys_get_temp_dir() . '\\PHP'; // @codeCoverageIgnoreEnd } self::$initialized = true; } } phpunit/src/Util/Json.php 0000644 00000005445 15253321353 0011373 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const JSON_PRETTY_PRINT; use const JSON_UNESCAPED_SLASHES; use const JSON_UNESCAPED_UNICODE; use function count; use function is_array; use function is_object; use function json_decode; use function json_encode; use function json_last_error; use function ksort; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Json { /** * @throws InvalidJsonException */ public static function prettify(string $json): string { $decodedJson = json_decode($json, false); if (json_last_error()) { throw new InvalidJsonException; } return json_encode($decodedJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } /** * Element 0 is true and element 1 is null when JSON decoding did not work. * * Element 0 is false and element 1 has the decoded value when JSON decoding did work. * * This is used to avoid ambiguity with JSON strings consisting entirely of 'null' or 'false'. * * @return array{0: false, 1: mixed}|array{0: true, 1: null} */ public static function canonicalize(string $json): array { $decodedJson = json_decode($json); if (json_last_error()) { return [true, null]; } self::recursiveSort($decodedJson); $reencodedJson = json_encode($decodedJson); return [false, $reencodedJson]; } /** * JSON object keys are unordered while PHP array keys are ordered. * * Sort all array keys to ensure both the expected and actual values have * their keys in the same order. */ private static function recursiveSort(mixed &$json): void { if (!is_array($json)) { // If the object is not empty, change it to an associative array // so we can sort the keys (and we will still re-encode it // correctly, since PHP encodes associative arrays as JSON objects.) // But EMPTY objects MUST remain empty objects. (Otherwise we will // re-encode it as a JSON array rather than a JSON object.) // See #2919. if (is_object($json) && count((array) $json) > 0) { $json = (array) $json; } else { return; } } ksort($json); foreach ($json as &$value) { self::recursiveSort($value); } } } phpunit/src/Util/Exception/InvalidJsonException.php 0000644 00000001115 15253321353 0016505 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidJsonException extends RuntimeException implements Exception { } phpunit/src/Util/Exception/Exception.php 0000644 00000001041 15253321353 0014342 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface Exception extends Throwable { } phpunit/src/Util/Exception/InvalidVersionOperatorException.php 0000644 00000001525 15253321353 0020742 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidVersionOperatorException extends RuntimeException implements Exception { public function __construct(string $operator) { parent::__construct( sprintf( '"%s" is not a valid version_compare() operator', $operator, ), ); } } phpunit/src/Util/Exception/XmlException.php 0000644 00000001145 15253321353 0015030 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\Xml; use PHPUnit\Util\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class XmlException extends RuntimeException implements Exception { } phpunit/src/Util/Exception/InvalidDirectoryException.php 0000644 00000001472 15253321353 0017546 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function sprintf; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class InvalidDirectoryException extends RuntimeException implements Exception { public function __construct(string $directory) { parent::__construct( sprintf( '"%s" is not a directory', $directory, ), ); } } phpunit/src/Util/Exception/PhpProcessException.php 0000644 00000001154 15253321353 0016356 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; use PHPUnit\Util\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class PhpProcessException extends RuntimeException implements Exception { } phpunit/src/Util/Cloner.php 0000644 00000001617 15253321353 0011701 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Cloner { /** * @template OriginalType of object * * @param OriginalType $original * * @return OriginalType */ public static function clone(object $original): object { try { return clone $original; /** @phpstan-ignore catch.neverThrown */ } catch (Throwable) { return $original; } } } phpunit/src/Util/Exporter.php 0000644 00000002546 15253321353 0012271 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry; use SebastianBergmann\Exporter\Exporter as OriginalExporter; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class Exporter { private static ?OriginalExporter $exporter = null; public static function export(mixed $value): string { return self::exporter()->export($value); } /** * @param array<mixed> $data */ public static function shortenedRecursiveExport(array $data): string { return self::exporter()->shortenedRecursiveExport($data); } public static function shortenedExport(mixed $value): string { return self::exporter()->shortenedExport($value); } private static function exporter(): OriginalExporter { if (self::$exporter !== null) { return self::$exporter; } self::$exporter = new OriginalExporter( ConfigurationRegistry::get()->shortenArraysForExportThreshold(), ); return self::$exporter; } } phpunit/src/Util/GlobalState.php 0000644 00000022134 15253321353 0012655 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const PHP_MAJOR_VERSION; use const PHP_MINOR_VERSION; use function array_keys; use function array_reverse; use function array_shift; use function assert; use function defined; use function get_defined_constants; use function get_included_files; use function in_array; use function ini_get_all; use function is_array; use function is_file; use function is_scalar; use function preg_match; use function serialize; use function sprintf; use function str_ends_with; use function str_starts_with; use function strtr; use function var_export; use Closure; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class GlobalState { /** * @var list<string> */ private const SUPER_GLOBAL_ARRAYS = [ '_ENV', '_POST', '_GET', '_COOKIE', '_SERVER', '_FILES', '_REQUEST', ]; /** * @var array<string, array<string, true>> */ private const DEPRECATED_INI_SETTINGS = [ '7.3' => [ 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.func_overload' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, 'string.strip_tags' => true, ], '7.4' => [ 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.func_overload' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, 'pdo_odbc.db2_instance_name' => true, 'string.strip_tags' => true, ], '8.0' => [ 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, ], '8.1' => [ 'auto_detect_line_endings' => true, 'filter.default' => true, 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, 'oci8.old_oci_close_semantics' => true, ], '8.2' => [ 'auto_detect_line_endings' => true, 'filter.default' => true, 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, 'oci8.old_oci_close_semantics' => true, ], '8.3' => [ 'auto_detect_line_endings' => true, 'filter.default' => true, 'iconv.input_encoding' => true, 'iconv.output_encoding' => true, 'iconv.internal_encoding' => true, 'mbstring.http_input' => true, 'mbstring.http_output' => true, 'mbstring.internal_encoding' => true, 'oci8.old_oci_close_semantics' => true, ], ]; /** * @throws Exception */ public static function getIncludedFilesAsString(): string { return self::processIncludedFilesAsString(get_included_files()); } /** * @param list<string> $files * * @throws Exception */ public static function processIncludedFilesAsString(array $files): string { $excludeList = new ExcludeList; $prefix = false; $result = ''; if (defined('__PHPUNIT_PHAR__')) { // @codeCoverageIgnoreStart $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/'; // @codeCoverageIgnoreEnd } // Do not process bootstrap script array_shift($files); // If bootstrap script was a Composer bin proxy, skip the second entry as well if (str_ends_with(strtr($files[0], '\\', '/'), '/phpunit/phpunit/phpunit')) { // @codeCoverageIgnoreStart array_shift($files); // @codeCoverageIgnoreEnd } foreach (array_reverse($files) as $file) { if (!empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) && in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) { continue; } if ($prefix !== false && str_starts_with($file, $prefix)) { continue; } // Skip virtual file system protocols if (preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) { continue; } if (!$excludeList->isExcluded($file) && is_file($file)) { $result = 'require_once \'' . $file . "';\n" . $result; } } return $result; } public static function getIniSettingsAsString(): string { $result = ''; $iniSettings = ini_get_all(null, false); assert($iniSettings !== false); foreach ($iniSettings as $key => $value) { if (self::isIniSettingDeprecated($key)) { continue; } $result .= sprintf( '@ini_set(%s, %s);' . "\n", self::exportVariable($key), self::exportVariable((string) $value), ); } return $result; } public static function getConstantsAsString(): string { $constants = get_defined_constants(true); $result = ''; if (isset($constants['user'])) { foreach ($constants['user'] as $name => $value) { $result .= sprintf( 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", $name, $name, self::exportVariable($value), ); } } return $result; } public static function getGlobalsAsString(): string { $result = ''; foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) { if (isset($GLOBALS[$superGlobalArray]) && is_array($GLOBALS[$superGlobalArray])) { foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) { if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { continue; } $result .= sprintf( '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", $superGlobalArray, $key, self::exportVariable($GLOBALS[$superGlobalArray][$key]), ); } } } $excludeList = self::SUPER_GLOBAL_ARRAYS; $excludeList[] = 'GLOBALS'; foreach (array_keys($GLOBALS) as $key) { if (!$GLOBALS[$key] instanceof Closure && !in_array($key, $excludeList, true)) { $result .= sprintf( '$GLOBALS[\'%s\'] = %s;' . "\n", $key, self::exportVariable($GLOBALS[$key]), ); } } return $result; } private static function exportVariable(mixed $variable): string { if (is_scalar($variable) || $variable === null || (is_array($variable) && self::arrayOnlyContainsScalars($variable))) { return var_export($variable, true); } return 'unserialize(' . var_export(serialize($variable), true) . ')'; } /** * @param array<mixed> $array */ private static function arrayOnlyContainsScalars(array $array): bool { $result = true; foreach ($array as $element) { if (is_array($element)) { $result = self::arrayOnlyContainsScalars($element); } elseif (!is_scalar($element) && $element !== null) { $result = false; } if (!$result) { break; } } return $result; } private static function isIniSettingDeprecated(string $iniSetting): bool { return isset(self::DEPRECATED_INI_SETTINGS[PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION][$iniSetting]); } } phpunit/src/Util/Filter.php 0000644 00000007403 15253321353 0011703 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function array_unshift; use function defined; use function in_array; use function is_file; use function realpath; use function sprintf; use function str_starts_with; use PHPUnit\Framework\Exception; use PHPUnit\Framework\PhptAssertionFailedError; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Filter { /** * @throws Exception */ public static function getFilteredStacktrace(Throwable $t, bool $unwrap = true): string { $filteredStacktrace = ''; if ($t instanceof PhptAssertionFailedError) { $eTrace = $t->syntheticTrace(); $eFile = $t->syntheticFile(); $eLine = $t->syntheticLine(); } elseif ($t instanceof Exception) { $eTrace = $t->getSerializableTrace(); $eFile = $t->getFile(); $eLine = $t->getLine(); } else { if ($unwrap && $t->getPrevious()) { $t = $t->getPrevious(); } $eTrace = $t->getTrace(); $eFile = $t->getFile(); $eLine = $t->getLine(); } if (!self::frameExists($eTrace, $eFile, $eLine)) { array_unshift( $eTrace, ['file' => $eFile, 'line' => $eLine], ); } $prefix = defined('__PHPUNIT_PHAR_ROOT__') ? __PHPUNIT_PHAR_ROOT__ : false; $excludeList = new ExcludeList; foreach ($eTrace as $frame) { if (self::shouldPrintFrame($frame, $prefix, $excludeList)) { $filteredStacktrace .= sprintf( "%s:%s\n", $frame['file'], $frame['line'] ?? '?', ); } } return $filteredStacktrace; } /** * @param array{file?: non-empty-string} $frame */ private static function shouldPrintFrame(array $frame, false|string $prefix, ExcludeList $excludeList): bool { if (!isset($frame['file'])) { return false; } $file = $frame['file']; $fileIsNotPrefixed = $prefix === false || !str_starts_with($file, $prefix); // @see https://github.com/sebastianbergmann/phpunit/issues/4033 if (isset($GLOBALS['_SERVER']['SCRIPT_NAME'])) { $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); } else { // @codeCoverageIgnoreStart $script = ''; // @codeCoverageIgnoreEnd } return $fileIsNotPrefixed && $file !== $script && self::fileIsExcluded($file, $excludeList) && is_file($file); } private static function fileIsExcluded(string $file, ExcludeList $excludeList): bool { return (empty($GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST']) || !in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_EXCLUDE_LIST'], true)) && !$excludeList->isExcluded($file); } /** * @param list<array{file?: non-empty-string, line?: int}> $trace */ private static function frameExists(array $trace, string $file, int $line): bool { foreach ($trace as $frame) { if (isset($frame['file'], $frame['line']) && $frame['file'] === $file && $frame['line'] === $line) { return true; } } return false; } } phpunit/src/Util/Filesystem.php 0000644 00000002524 15253321353 0012601 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use const DIRECTORY_SEPARATOR; use function basename; use function dirname; use function is_dir; use function mkdir; use function realpath; use function str_starts_with; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Filesystem { public static function createDirectory(string $directory): bool { return !(!is_dir($directory) && !@mkdir($directory, 0o777, true) && !is_dir($directory)); } /** * @param non-empty-string $path * * @return false|non-empty-string */ public static function resolveStreamOrFile(string $path): false|string { if (str_starts_with($path, 'php://') || str_starts_with($path, 'socket://')) { return $path; } $directory = dirname($path); if (is_dir($directory)) { return realpath($directory) . DIRECTORY_SEPARATOR . basename($path); } return false; } } phpunit/src/Util/PHP/Result.php 0000644 00000001577 15253321353 0012371 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Result { private string $stdout; private string $stderr; public function __construct(string $stdout, string $stderr) { $this->stdout = $stdout; $this->stderr = $stderr; } public function stdout(): string { return $this->stdout; } public function stderr(): string { return $this->stderr; } } phpunit/src/Util/PHP/Job.php 0000644 00000006145 15253321353 0011621 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Job { /** * @var non-empty-string */ private string $code; /** * @var list<string> */ private array $phpSettings; /** * @var array<string, string> */ private array $environmentVariables; /** * @var list<non-empty-string> */ private array $arguments; /** * @var ?non-empty-string */ private ?string $input; private bool $redirectErrors; /** * @param non-empty-string $code * @param list<string> $phpSettings * @param array<string, string> $environmentVariables * @param list<non-empty-string> $arguments * @param ?non-empty-string $input */ public function __construct(string $code, array $phpSettings = [], array $environmentVariables = [], array $arguments = [], ?string $input = null, bool $redirectErrors = false) { $this->code = $code; $this->phpSettings = $phpSettings; $this->environmentVariables = $environmentVariables; $this->arguments = $arguments; $this->input = $input; $this->redirectErrors = $redirectErrors; } /** * @return non-empty-string */ public function code(): string { return $this->code; } /** * @return list<string> */ public function phpSettings(): array { return $this->phpSettings; } /** * @phpstan-assert-if-true !empty $this->environmentVariables */ public function hasEnvironmentVariables(): bool { return $this->environmentVariables !== []; } /** * @return array<string, string> */ public function environmentVariables(): array { return $this->environmentVariables; } /** * @phpstan-assert-if-true !empty $this->arguments */ public function hasArguments(): bool { return $this->arguments !== []; } /** * @return list<non-empty-string> */ public function arguments(): array { return $this->arguments; } /** * @phpstan-assert-if-true !empty $this->input */ public function hasInput(): bool { return $this->input !== null; } /** * @throws PhpProcessException * * @return non-empty-string */ public function input(): string { if ($this->input === null) { throw new PhpProcessException('No input specified'); } return $this->input; } public function redirectErrors(): bool { return $this->redirectErrors; } } phpunit/src/Util/PHP/JobRunner.php 0000644 00000001056 15253321353 0013007 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This interface is not covered by the backward compatibility promise for PHPUnit */ interface JobRunner { public function run(Job $job): Result; } phpunit/src/Util/PHP/JobRunnerRegistry.php 0000644 00000001547 15253321353 0014545 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class JobRunnerRegistry { private static ?JobRunner $runner = null; public static function run(Job $job): Result { if (self::$runner === null) { self::$runner = new DefaultJobRunner; } return self::$runner->run($job); } public static function set(JobRunner $runner): void { self::$runner = $runner; } } phpunit/src/Util/PHP/DefaultJobRunner.php 0000644 00000013456 15253321353 0014323 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; use const PHP_BINARY; use const PHP_SAPI; use function array_keys; use function array_merge; use function assert; use function fclose; use function file_put_contents; use function fwrite; use function ini_get_all; use function is_array; use function is_resource; use function proc_close; use function proc_open; use function stream_get_contents; use function sys_get_temp_dir; use function tempnam; use function trim; use function unlink; use SebastianBergmann\Environment\Runtime; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class DefaultJobRunner implements JobRunner { /** * @throws PhpProcessException */ public function run(Job $job): Result { $temporaryFile = null; if ($job->hasInput()) { $temporaryFile = tempnam(sys_get_temp_dir(), 'phpunit_'); if ($temporaryFile === false || file_put_contents($temporaryFile, $job->code()) === false) { // @codeCoverageIgnoreStart throw new PhpProcessException( 'Unable to write temporary file', ); // @codeCoverageIgnoreEnd } $job = new Job( $job->input(), $job->phpSettings(), $job->environmentVariables(), $job->arguments(), null, $job->redirectErrors(), ); } assert($temporaryFile !== ''); return $this->runProcess($job, $temporaryFile); } /** * @param ?non-empty-string $temporaryFile * * @throws PhpProcessException */ private function runProcess(Job $job, ?string $temporaryFile): Result { $environmentVariables = null; if ($job->hasEnvironmentVariables()) { /** @phpstan-ignore nullCoalesce.variable */ $environmentVariables = $_SERVER ?? []; unset($environmentVariables['argv'], $environmentVariables['argc']); $environmentVariables = array_merge($environmentVariables, $job->environmentVariables()); foreach ($environmentVariables as $key => $value) { if (is_array($value)) { unset($environmentVariables[$key]); } } unset($key, $value); } $pipeSpec = [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; if ($job->redirectErrors()) { $pipeSpec[2] = ['redirect', 1]; } $process = proc_open( $this->buildCommand($job, $temporaryFile), $pipeSpec, $pipes, null, $environmentVariables, ); if (!is_resource($process)) { // @codeCoverageIgnoreStart throw new PhpProcessException( 'Unable to spawn worker process', ); // @codeCoverageIgnoreEnd } fwrite($pipes[0], $job->code()); fclose($pipes[0]); $stdout = ''; $stderr = ''; if (isset($pipes[1])) { $stdout = stream_get_contents($pipes[1]); fclose($pipes[1]); } if (isset($pipes[2])) { $stderr = stream_get_contents($pipes[2]); fclose($pipes[2]); } proc_close($process); if ($temporaryFile !== null) { unlink($temporaryFile); } assert($stdout !== false); assert($stderr !== false); return new Result($stdout, $stderr); } /** * @return non-empty-list<string> */ private function buildCommand(Job $job, ?string $file): array { $runtime = new Runtime; $command = [PHP_BINARY]; $phpSettings = $job->phpSettings(); if ($runtime->hasPCOV()) { $pcovSettings = ini_get_all('pcov'); assert($pcovSettings !== false); $phpSettings = array_merge( $phpSettings, $runtime->getCurrentSettings( array_keys($pcovSettings), ), ); } elseif ($runtime->hasXdebug()) { $xdebugSettings = ini_get_all('xdebug'); assert($xdebugSettings !== false); $phpSettings = array_merge( $phpSettings, $runtime->getCurrentSettings( array_keys($xdebugSettings), ), ); } $command = array_merge($command, $this->settingsToParameters($phpSettings)); if (PHP_SAPI === 'phpdbg') { $command[] = '-qrr'; if ($file === null) { $command[] = 's='; } } if ($file !== null) { $command[] = '-f'; $command[] = $file; } if ($job->hasArguments()) { if ($file === null) { $command[] = '--'; } foreach ($job->arguments() as $argument) { $command[] = trim($argument); } } return $command; } /** * @param list<string> $settings * * @return list<string> */ private function settingsToParameters(array $settings): array { $buffer = []; foreach ($settings as $setting) { $buffer[] = '-d'; $buffer[] = $setting; } return $buffer; } } phpunit/src/Util/VersionComparisonOperator.php 0000644 00000003007 15253321353 0015646 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function in_array; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @immutable */ final readonly class VersionComparisonOperator { /** * @var '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne' */ private string $operator; /** * @param '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne' $operator * * @throws InvalidVersionOperatorException */ public function __construct(string $operator) { $this->ensureOperatorIsValid($operator); $this->operator = $operator; } /** * @return '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne' */ public function asString(): string { return $this->operator; } /** * @param '!='|'<'|'<='|'<>'|'='|'=='|'>'|'>='|'eq'|'ge'|'gt'|'le'|'lt'|'ne' $operator * * @throws InvalidVersionOperatorException */ private function ensureOperatorIsValid(string $operator): void { if (!in_array($operator, ['<', 'lt', '<=', 'le', '>', 'gt', '>=', 'ge', '==', '=', 'eq', '!=', '<>', 'ne'], true)) { throw new InvalidVersionOperatorException($operator); } } } phpunit/src/Util/Test.php 0000644 00000002036 15253321353 0011372 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use function str_starts_with; use PHPUnit\Metadata\Parser\Registry; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Test { public static function isTestMethod(ReflectionMethod $method): bool { if (!$method->isPublic()) { return false; } if (str_starts_with($method->getName(), 'test')) { return true; } $metadata = Registry::parser()->forMethod( $method->getDeclaringClass()->getName(), $method->getName(), ); return $metadata->isTest()->isNotEmpty(); } } phpunit/src/Logging/Exception.php 0000644 00000001116 15253321353 0013060 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Exception extends RuntimeException implements \PHPUnit\Exception { } phpunit/src/Logging/EventLogger.php 0000644 00000003540 15253321353 0013346 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging; use const FILE_APPEND; use const LOCK_EX; use const PHP_EOL; use const PHP_OS_FAMILY; use function file_put_contents; use function implode; use function preg_split; use function str_repeat; use function strlen; use PHPUnit\Event\Event; use PHPUnit\Event\Tracer\Tracer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class EventLogger implements Tracer { private string $path; private bool $includeTelemetryInfo; public function __construct(string $path, bool $includeTelemetryInfo) { $this->path = $path; $this->includeTelemetryInfo = $includeTelemetryInfo; } public function trace(Event $event): void { $telemetryInfo = $this->telemetryInfo($event); $indentation = PHP_EOL . str_repeat(' ', strlen($telemetryInfo)); $lines = preg_split('/\r\n|\r|\n/', $event->asString()); $flags = FILE_APPEND; if (!(PHP_OS_FAMILY === 'Windows' || PHP_OS_FAMILY === 'Darwin') || $this->path !== 'php://stdout') { $flags |= LOCK_EX; } file_put_contents( $this->path, $telemetryInfo . implode($indentation, $lines) . PHP_EOL, $flags, ); } private function telemetryInfo(Event $event): string { if (!$this->includeTelemetryInfo) { return ''; } return $event->telemetryInfo()->asString() . ' '; } } phpunit/src/Logging/TestDox/NamePrettifier.php 0000644 00000021335 15253321353 0015437 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function array_key_exists; use function array_keys; use function array_map; use function array_pop; use function array_values; use function assert; use function class_exists; use function explode; use function gettype; use function implode; use function is_bool; use function is_float; use function is_int; use function is_object; use function is_scalar; use function method_exists; use function preg_quote; use function preg_replace; use function rtrim; use function sprintf; use function str_contains; use function str_ends_with; use function str_replace; use function str_starts_with; use function strlen; use function strtolower; use function strtoupper; use function substr; use function trim; use PHPUnit\Framework\TestCase; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Metadata\TestDox; use PHPUnit\Util\Color; use PHPUnit\Util\Exporter; use ReflectionEnum; use ReflectionMethod; use ReflectionObject; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class NamePrettifier { /** * @var array<string, int> */ private static array $strings = []; /** * @param class-string $className */ public function prettifyTestClassName(string $className): string { if (class_exists($className)) { $classLevelTestDox = MetadataRegistry::parser()->forClass($className)->isTestDox(); if ($classLevelTestDox->isNotEmpty()) { $classLevelTestDox = $classLevelTestDox->asArray()[0]; assert($classLevelTestDox instanceof TestDox); return $classLevelTestDox->text(); } } $parts = explode('\\', $className); $className = array_pop($parts); if (str_ends_with($className, 'Test')) { $className = substr($className, 0, strlen($className) - strlen('Test')); } if (str_starts_with($className, 'Tests')) { $className = substr($className, strlen('Tests')); } elseif (str_starts_with($className, 'Test')) { $className = substr($className, strlen('Test')); } if (empty($className)) { $className = 'UnnamedTests'; } if (!empty($parts)) { $parts[] = $className; $fullyQualifiedName = implode('\\', $parts); } else { $fullyQualifiedName = $className; } $result = preg_replace('/(?<=[[:lower:]])(?=[[:upper:]])/u', ' ', $className); if ($fullyQualifiedName !== $className) { return $result . ' (' . $fullyQualifiedName . ')'; } return $result; } // NOTE: this method is on a hot path and very performance sensitive. change with care. public function prettifyTestMethodName(string $name): string { if ($name === '') { return ''; } $string = rtrim($name, '0123456789'); if (array_key_exists($string, self::$strings)) { $name = $string; } elseif ($string === $name) { self::$strings[$string] = 1; } if (str_starts_with($name, 'test_')) { $name = substr($name, 5); } elseif (str_starts_with($name, 'test')) { $name = substr($name, 4); } if ($name === '') { return ''; } $name[0] = strtoupper($name[0]); $noUnderscore = str_replace('_', ' ', $name); if ($noUnderscore !== $name) { return trim($noUnderscore); } $wasNumeric = false; $buffer = ''; $len = strlen($name); for ($i = 0; $i < $len; $i++) { if ($i > 0 && $name[$i] >= 'A' && $name[$i] <= 'Z') { $buffer .= ' ' . strtolower($name[$i]); } else { $isNumeric = $name[$i] >= '0' && $name[$i] <= '9'; if (!$wasNumeric && $isNumeric) { $buffer .= ' '; $wasNumeric = true; } if ($wasNumeric && !$isNumeric) { $wasNumeric = false; } $buffer .= $name[$i]; } } return $buffer; } public function prettifyTestCase(TestCase $test, bool $colorize): string { $annotationWithPlaceholders = false; $methodLevelTestDox = MetadataRegistry::parser()->forMethod($test::class, $test->name())->isTestDox()->isMethodLevel(); if ($methodLevelTestDox->isNotEmpty()) { $methodLevelTestDox = $methodLevelTestDox->asArray()[0]; assert($methodLevelTestDox instanceof TestDox); $result = $methodLevelTestDox->text(); if (str_contains($result, '$')) { $annotation = $result; $providedData = $this->mapTestMethodParameterNamesToProvidedDataValues($test, $colorize); $variables = array_map( static fn (string $variable): string => sprintf( '/%s(?=\b)/', preg_quote($variable, '/'), ), array_keys($providedData), ); $result = trim(preg_replace($variables, $providedData, $annotation)); $annotationWithPlaceholders = true; } } else { $result = $this->prettifyTestMethodName($test->name()); } if (!$annotationWithPlaceholders && $test->usesDataProvider()) { $result .= $this->prettifyDataSet($test, $colorize); } return $result; } public function prettifyDataSet(TestCase $test, bool $colorize): string { if (!$colorize) { return $test->dataSetAsString(); } if (is_int($test->dataName())) { return Color::dim(' with data set ') . Color::colorize('fg-cyan', (string) $test->dataName()); } return Color::dim(' with ') . Color::colorize('fg-cyan', Color::visualizeWhitespace($test->dataName())); } /** * @return array<non-empty-string, non-empty-string> */ private function mapTestMethodParameterNamesToProvidedDataValues(TestCase $test, bool $colorize): array { assert(method_exists($test, $test->name())); /** @noinspection PhpUnhandledExceptionInspection */ $reflector = new ReflectionMethod($test::class, $test->name()); $providedData = []; $providedDataValues = array_values($test->providedData()); $i = 0; $providedData['$_dataName'] = $test->dataName(); foreach ($reflector->getParameters() as $parameter) { if (!array_key_exists($i, $providedDataValues) && $parameter->isDefaultValueAvailable()) { $providedDataValues[$i] = $parameter->getDefaultValue(); } $value = $providedDataValues[$i++] ?? null; if (is_object($value)) { $reflector = new ReflectionObject($value); if ($reflector->isEnum()) { $enumReflector = new ReflectionEnum($value); if ($enumReflector->isBacked()) { $value = $value->value; } else { $value = $value->name; } } elseif ($reflector->hasMethod('__toString')) { $value = (string) $value; } else { $value = $value::class; } } if (!is_scalar($value)) { $value = gettype($value); if ($value === 'NULL') { $value = 'null'; } } if (is_bool($value) || is_int($value) || is_float($value)) { $value = Exporter::export($value); } if ($value === '') { if ($colorize) { $value = Color::colorize('dim,underlined', 'empty'); } else { $value = "''"; } } $providedData['$' . $parameter->getName()] = $value; } if ($colorize) { $providedData = array_map( static fn ($value) => Color::colorize('fg-cyan', Color::visualizeWhitespace((string) $value, true)), $providedData, ); } return $providedData; } } phpunit/src/Logging/TestDox/PlainTextRenderer.php 0000644 00000003764 15253321353 0016126 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class PlainTextRenderer { /** * @param array<string, TestResultCollection> $tests */ public function render(array $tests): string { $buffer = ''; foreach ($tests as $prettifiedClassName => $_tests) { $buffer .= $prettifiedClassName . "\n"; foreach ($this->reduce($_tests) as $prettifiedMethodName => $outcome) { $buffer .= sprintf( ' [%s] %s' . "\n", $outcome, $prettifiedMethodName, ); } $buffer .= "\n"; } return $buffer; } /** * @return array<string, ' '|'x'> */ private function reduce(TestResultCollection $tests): array { $result = []; foreach ($tests as $test) { $prettifiedMethodName = $test->test()->testDox()->prettifiedMethodName(); $success = true; if ($test->status()->isError() || $test->status()->isFailure() || $test->status()->isIncomplete() || $test->status()->isSkipped()) { $success = false; } if (!isset($result[$prettifiedMethodName])) { $result[$prettifiedMethodName] = $success ? 'x' : ' '; continue; } if ($success) { continue; } $result[$prettifiedMethodName] = ' '; } return $result; } } phpunit/src/Logging/TestDox/TestResult/TestResultCollection.php 0000644 00000002436 15253321353 0020772 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, TestResult> * * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestResultCollection implements IteratorAggregate { /** * @var list<TestResult> */ private array $testResults; /** * @param list<TestResult> $testResults */ public static function fromArray(array $testResults): self { return new self(...$testResults); } private function __construct(TestResult ...$testResults) { $this->testResults = $testResults; } /** * @return list<TestResult> */ public function asArray(): array { return $this->testResults; } public function getIterator(): TestResultCollectionIterator { return new TestResultCollectionIterator($this); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitErrorSubscriber.php 0000644 00000001532 15253321353 0026121 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitErrorSubscriber extends Subscriber implements PhpunitErrorTriggeredSubscriber { public function notify(PhpunitErrorTriggered $event): void { $this->collector()->testTriggeredPhpunitError($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredNoticeSubscriber.php 0000644 00000001466 15253321353 0024707 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\NoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredNoticeSubscriber extends Subscriber implements NoticeTriggeredSubscriber { public function notify(NoticeTriggered $event): void { $this->collector()->testTriggeredNotice($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpDeprecationSubscriber.php 0000644 00000001546 15253321353 0026372 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpDeprecationSubscriber extends Subscriber implements PhpDeprecationTriggeredSubscriber { public function notify(PhpDeprecationTriggered $event): void { $this->collector()->testTriggeredPhpDeprecation($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitDeprecationSubscriber.php 0000644 00000001576 15253321353 0027275 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitDeprecationSubscriber extends Subscriber implements PhpunitDeprecationTriggeredSubscriber { public function notify(PhpunitDeprecationTriggered $event): void { $this->collector()->testTriggeredPhpunitDeprecation($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestErroredSubscriber.php 0000644 00000001406 15253321353 0023225 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { public function notify(Errored $event): void { $this->collector()->testErrored($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001474 15253321353 0025053 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { public function notify(MarkedIncomplete $event): void { $this->collector()->testMarkedIncomplete($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFinishedSubscriber.php 0000644 00000001560 15253321353 0023355 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Finished $event): void { $this->collector()->testFinished($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPassedSubscriber.php 0000644 00000001400 15253321353 0023034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\Passed; use PHPUnit\Event\Test\PassedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPassedSubscriber extends Subscriber implements PassedSubscriber { public function notify(Passed $event): void { $this->collector()->testPassed($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredWarningSubscriber.php 0000644 00000001474 15253321353 0025072 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\Test\WarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredWarningSubscriber extends Subscriber implements WarningTriggeredSubscriber { public function notify(WarningTriggered $event): void { $this->collector()->testTriggeredWarning($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/Subscriber.php 0000644 00000001433 15253321353 0021042 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private TestResultCollector $collector; public function __construct(TestResultCollector $collector) { $this->collector = $collector; } protected function collector(): TestResultCollector { return $this->collector; } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestFailedSubscriber.php 0000644 00000001400 15253321353 0023001 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { public function notify(Failed $event): void { $this->collector()->testFailed($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestPreparedSubscriber.php 0000644 00000001414 15253321353 0023364 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->collector()->testPrepared($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpNoticeSubscriber.php 0000644 00000001510 15253321353 0025345 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpNoticeTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpNoticeSubscriber extends Subscriber implements PhpNoticeTriggeredSubscriber { public function notify(PhpNoticeTriggered $event): void { $this->collector()->testTriggeredPhpNotice($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpunitWarningSubscriber.php 0000644 00000001546 15253321353 0026442 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpunitWarningSubscriber extends Subscriber implements PhpunitWarningTriggeredSubscriber { public function notify(PhpunitWarningTriggered $event): void { $this->collector()->testTriggeredPhpunitWarning($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredPhpWarningSubscriber.php 0000644 00000001516 15253321353 0025537 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredPhpWarningSubscriber extends Subscriber implements PhpWarningTriggeredSubscriber { public function notify(PhpWarningTriggered $event): void { $this->collector()->testTriggeredPhpWarning($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestTriggeredDeprecationSubscriber.php 0000644 00000001524 15253321353 0025716 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\DeprecationTriggeredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber { public function notify(DeprecationTriggered $event): void { $this->collector()->testTriggeredDeprecation($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestSkippedSubscriber.php 0000644 00000001406 15253321353 0023222 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { public function notify(Skipped $event): void { $this->collector()->testSkipped($event); } } phpunit/src/Logging/TestDox/TestResult/Subscriber/TestConsideredRiskySubscriber.php 0000644 00000001466 15253321353 0024732 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\ConsideredRiskySubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber { public function notify(ConsideredRisky $event): void { $this->collector()->testConsideredRisky($event); } } phpunit/src/Logging/TestDox/TestResult/TestResultCollectionIterator.php 0000644 00000002472 15253321353 0022504 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function count; use Iterator; /** * @template-implements Iterator<int, TestResult> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestResultCollectionIterator implements Iterator { /** * @var list<TestResult> */ private readonly array $testResults; private int $position = 0; public function __construct(TestResultCollection $testResults) { $this->testResults = $testResults->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->testResults); } public function key(): int { return $this->position; } public function current(): TestResult { return $this->testResults[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/Logging/TestDox/TestResult/TestResult.php 0000644 00000002562 15253321353 0016756 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; use PHPUnit\Framework\TestStatus\TestStatus; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestResult { private TestMethod $test; private TestStatus $status; private ?Throwable $throwable; public function __construct(TestMethod $test, TestStatus $status, ?Throwable $throwable) { $this->test = $test; $this->status = $status; $this->throwable = $throwable; } public function test(): TestMethod { return $this->test; } public function status(): TestStatus { return $this->status; } /** * @phpstan-assert-if-true !null $this->throwable */ public function hasThrowable(): bool { return $this->throwable !== null; } public function throwable(): ?Throwable { return $this->throwable; } } phpunit/src/Logging/TestDox/TestResult/TestResultCollector.php 0000644 00000024100 15253321353 0020615 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function array_keys; use function array_merge; use function assert; use function is_subclass_of; use function ksort; use function uksort; use function usort; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\DeprecationTriggered; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\NoticeTriggered; use PHPUnit\Event\Test\Passed; use PHPUnit\Event\Test\PhpDeprecationTriggered; use PHPUnit\Event\Test\PhpNoticeTriggered; use PHPUnit\Event\Test\PhpunitDeprecationTriggered; use PHPUnit\Event\Test\PhpunitErrorTriggered; use PHPUnit\Event\Test\PhpunitWarningTriggered; use PHPUnit\Event\Test\PhpWarningTriggered; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\WarningTriggered; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\TestStatus\TestStatus; use PHPUnit\Logging\TestDox\TestResult as TestDoxTestMethod; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TestResultCollector { /** * @var array<string, list<TestDoxTestMethod>> */ private array $tests = []; private ?TestStatus $status = null; private ?Throwable $throwable = null; private bool $prepared = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Facade $facade) { $this->registerSubscribers($facade); } /** * @return array<string, TestResultCollection> */ public function testMethodsGroupedByClass(): array { $result = []; foreach ($this->tests as $prettifiedClassName => $tests) { $testsByDeclaringClass = []; foreach ($tests as $test) { $declaringClassName = (new ReflectionMethod($test->test()->className(), $test->test()->methodName()))->getDeclaringClass()->getName(); if (!isset($testsByDeclaringClass[$declaringClassName])) { $testsByDeclaringClass[$declaringClassName] = []; } $testsByDeclaringClass[$declaringClassName][] = $test; } foreach (array_keys($testsByDeclaringClass) as $declaringClassName) { usort( $testsByDeclaringClass[$declaringClassName], static function (TestDoxTestMethod $a, TestDoxTestMethod $b): int { return $a->test()->line() <=> $b->test()->line(); }, ); } uksort( $testsByDeclaringClass, /** * @param class-string $a * @param class-string $b */ static function (string $a, string $b): int { if (is_subclass_of($b, $a)) { return -1; } if (is_subclass_of($a, $b)) { return 1; } return 0; }, ); $tests = []; foreach ($testsByDeclaringClass as $_tests) { $tests = array_merge($tests, $_tests); } $result[$prettifiedClassName] = TestResultCollection::fromArray($tests); } ksort($result); return $result; } public function testPrepared(Prepared $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::unknown(); $this->throwable = null; $this->prepared = true; } public function testErrored(Errored $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::error($event->throwable()->message()); $this->throwable = $event->throwable(); if (!$this->prepared) { $test = $event->test(); assert($test instanceof TestMethod); $this->process($test); } } public function testFailed(Failed $event): void { if (!$event->test()->isTestMethod()) { return; } $this->status = TestStatus::failure($event->throwable()->message()); $this->throwable = $event->throwable(); } public function testPassed(Passed $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::success()); } public function testSkipped(Skipped $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::skipped($event->message())); } public function testMarkedIncomplete(MarkedIncomplete $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::incomplete($event->throwable()->message())); $this->throwable = $event->throwable(); } public function testConsideredRisky(ConsideredRisky $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::risky()); } public function testTriggeredDeprecation(DeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredNotice(NoticeTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredWarning(WarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpDeprecation(PhpDeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpNotice(PhpNoticeTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::notice()); } public function testTriggeredPhpWarning(PhpWarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::warning()); } public function testTriggeredPhpunitDeprecation(PhpunitDeprecationTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::deprecation()); } public function testTriggeredPhpunitError(PhpunitErrorTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::error()); } public function testTriggeredPhpunitWarning(PhpunitWarningTriggered $event): void { if (!$event->test()->isTestMethod()) { return; } $this->updateTestStatus(TestStatus::warning()); } /** * @throws InvalidArgumentException */ public function testFinished(Finished $event): void { if (!$event->test()->isTestMethod()) { return; } $test = $event->test(); assert($test instanceof TestMethod); $this->process($test); $this->status = null; $this->throwable = null; $this->prepared = false; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new TestConsideredRiskySubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestFinishedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestPassedSubscriber($this), new TestPreparedSubscriber($this), new TestSkippedSubscriber($this), new TestTriggeredDeprecationSubscriber($this), new TestTriggeredNoticeSubscriber($this), new TestTriggeredPhpDeprecationSubscriber($this), new TestTriggeredPhpNoticeSubscriber($this), new TestTriggeredPhpunitDeprecationSubscriber($this), new TestTriggeredPhpunitErrorSubscriber($this), new TestTriggeredPhpunitWarningSubscriber($this), new TestTriggeredPhpWarningSubscriber($this), new TestTriggeredWarningSubscriber($this), ); } private function updateTestStatus(TestStatus $status): void { if ($this->status !== null && $this->status->isMoreImportantThan($status)) { return; } $this->status = $status; } private function process(TestMethod $test): void { if (!isset($this->tests[$test->testDox()->prettifiedClassName()])) { $this->tests[$test->testDox()->prettifiedClassName()] = []; } $this->tests[$test->testDox()->prettifiedClassName()][] = new TestDoxTestMethod( $test, $this->status, $this->throwable, ); } } phpunit/src/Logging/TestDox/HtmlRenderer.php 0000644 00000007232 15253321353 0015114 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TestDox; use function sprintf; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class HtmlRenderer { /** * @var string */ private const PAGE_HEADER = <<<'EOT' <!doctype html> <html lang="en"> <head> <meta charset="utf-8"/> <title>Test Documentation</title> <style> body { text-rendering: optimizeLegibility; font-family: Source SansSerif Pro, Arial, sans-serif; font-variant-ligatures: common-ligatures; font-kerning: normal; margin-left: 2rem; background-color: #fff; color: #000; } body > ul > li { font-size: larger; } h2 { font-size: larger; text-decoration-line: underline; text-decoration-thickness: 2px; margin: 0; padding: 0.5rem 0; } ul { list-style: none; margin: 0 0 2rem; padding: 0 0 0 1rem; text-indent: -1rem; } .success:before { color: #4e9a06; content: '✓'; padding-right: 0.5rem; } .defect { color: #a40000; } .defect:before { color: #a40000; content: '✗'; padding-right: 0.5rem; } </style> </head> <body> EOT; /** * @var string */ private const CLASS_HEADER = <<<'EOT' <h2>%s</h2> <ul> EOT; /** * @var string */ private const CLASS_FOOTER = <<<'EOT' </ul> EOT; /** * @var string */ private const PAGE_FOOTER = <<<'EOT' </body> </html> EOT; /** * @param array<string, TestResultCollection> $tests */ public function render(array $tests): string { $buffer = self::PAGE_HEADER; foreach ($tests as $prettifiedClassName => $_tests) { $buffer .= sprintf( self::CLASS_HEADER, $prettifiedClassName, ); foreach ($this->reduce($_tests) as $prettifiedMethodName => $outcome) { $buffer .= sprintf( " <li class=\"%s\">%s</li>\n", $outcome, $prettifiedMethodName, ); } $buffer .= self::CLASS_FOOTER; } return $buffer . self::PAGE_FOOTER; } /** * @return array<string, 'defect'|'success'> */ private function reduce(TestResultCollection $tests): array { $result = []; foreach ($tests as $test) { $prettifiedMethodName = $test->test()->testDox()->prettifiedMethodName(); if (!isset($result[$prettifiedMethodName])) { $result[$prettifiedMethodName] = $test->status()->isSuccess() ? 'success' : 'defect'; continue; } if ($test->status()->isSuccess()) { continue; } $result[$prettifiedMethodName] = 'defect'; } return $result; } } phpunit/src/Logging/JUnit/JunitXmlLogger.php 0000644 00000031040 15253321353 0015064 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use const PHP_EOL; use function assert; use function basename; use function is_int; use function sprintf; use function str_replace; use function trim; use DOMDocument; use DOMElement; use PHPUnit\Event\Code\Test; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Telemetry\HRTime; use PHPUnit\Event\Telemetry\Info; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\PreparationStarted; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\TestSuite\Started; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\TextUI\Output\Printer; use PHPUnit\Util\Xml; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class JunitXmlLogger { private readonly Printer $printer; private DOMDocument $document; private DOMElement $root; /** * @var DOMElement[] */ private array $testSuites = []; /** * @var array<int,int> */ private array $testSuiteTests = [0]; /** * @var array<int,int> */ private array $testSuiteAssertions = [0]; /** * @var array<int,int> */ private array $testSuiteErrors = [0]; /** * @var array<int,int> */ private array $testSuiteFailures = [0]; /** * @var array<int,int> */ private array $testSuiteSkipped = [0]; /** * @var array<int,int> */ private array $testSuiteTimes = [0]; private int $testSuiteLevel = 0; private ?DOMElement $currentTestCase = null; private ?HRTime $time = null; private bool $prepared = false; private bool $preparationFailed = false; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Printer $printer, Facade $facade) { $this->printer = $printer; $this->registerSubscribers($facade); $this->createDocument(); } public function flush(): void { $this->printer->print($this->document->saveXML()); $this->printer->flush(); } public function testSuiteStarted(Started $event): void { $testSuite = $this->document->createElement('testsuite'); $testSuite->setAttribute('name', $event->testSuite()->name()); if ($event->testSuite()->isForTestClass()) { $testSuite->setAttribute('file', $event->testSuite()->file()); } if ($this->testSuiteLevel > 0) { $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite); } else { $this->root->appendChild($testSuite); } $this->testSuiteLevel++; $this->testSuites[$this->testSuiteLevel] = $testSuite; $this->testSuiteTests[$this->testSuiteLevel] = 0; $this->testSuiteAssertions[$this->testSuiteLevel] = 0; $this->testSuiteErrors[$this->testSuiteLevel] = 0; $this->testSuiteFailures[$this->testSuiteLevel] = 0; $this->testSuiteSkipped[$this->testSuiteLevel] = 0; $this->testSuiteTimes[$this->testSuiteLevel] = 0; } public function testSuiteFinished(): void { $this->testSuites[$this->testSuiteLevel]->setAttribute( 'tests', (string) $this->testSuiteTests[$this->testSuiteLevel], ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'assertions', (string) $this->testSuiteAssertions[$this->testSuiteLevel], ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'errors', (string) $this->testSuiteErrors[$this->testSuiteLevel], ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'failures', (string) $this->testSuiteFailures[$this->testSuiteLevel], ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'skipped', (string) $this->testSuiteSkipped[$this->testSuiteLevel], ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'time', sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]), ); if ($this->testSuiteLevel > 1) { $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel]; $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel]; $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel]; $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel]; $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel]; $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel]; } $this->testSuiteLevel--; } /** * @throws InvalidArgumentException */ public function testPreparationStarted(PreparationStarted $event): void { $this->createTestCase($event); } /** * @throws InvalidArgumentException */ public function testPreparationFailed(): void { $this->preparationFailed = true; } /** * @throws InvalidArgumentException */ public function testPrepared(): void { $this->prepared = true; } /** * @throws InvalidArgumentException */ public function testFinished(Finished $event): void { if (!$this->prepared || $this->preparationFailed) { return; } $this->handleFinish($event->telemetryInfo(), $event->numberOfAssertionsPerformed()); } /** * @throws InvalidArgumentException */ public function testMarkedIncomplete(MarkedIncomplete $event): void { $this->handleIncompleteOrSkipped($event); } /** * @throws InvalidArgumentException */ public function testSkipped(Skipped $event): void { $this->handleIncompleteOrSkipped($event); } /** * @throws InvalidArgumentException */ public function testErrored(Errored $event): void { $this->handleFault($event, 'error'); $this->testSuiteErrors[$this->testSuiteLevel]++; } /** * @throws InvalidArgumentException */ public function testFailed(Failed $event): void { $this->handleFault($event, 'failure'); $this->testSuiteFailures[$this->testSuiteLevel]++; } /** * @throws InvalidArgumentException */ private function handleFinish(Info $telemetryInfo, int $numberOfAssertionsPerformed): void { assert($this->currentTestCase !== null); assert($this->time !== null); $time = $telemetryInfo->time()->duration($this->time)->asFloat(); $this->testSuiteAssertions[$this->testSuiteLevel] += $numberOfAssertionsPerformed; $this->currentTestCase->setAttribute( 'assertions', (string) $numberOfAssertionsPerformed, ); $this->currentTestCase->setAttribute( 'time', sprintf('%F', $time), ); $this->testSuites[$this->testSuiteLevel]->appendChild( $this->currentTestCase, ); $this->testSuiteTests[$this->testSuiteLevel]++; $this->testSuiteTimes[$this->testSuiteLevel] += $time; $this->currentTestCase = null; $this->time = null; $this->prepared = false; } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new TestSuiteStartedSubscriber($this), new TestSuiteFinishedSubscriber($this), new TestPreparationStartedSubscriber($this), new TestPreparationFailedSubscriber($this), new TestPreparedSubscriber($this), new TestFinishedSubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestSkippedSubscriber($this), new TestRunnerExecutionFinishedSubscriber($this), ); } private function createDocument(): void { $this->document = new DOMDocument('1.0', 'UTF-8'); $this->document->formatOutput = true; $this->root = $this->document->createElement('testsuites'); $this->document->appendChild($this->root); } /** * @throws InvalidArgumentException */ private function handleFault(Errored|Failed $event, string $type): void { if (!$this->prepared) { $this->createTestCase($event); } assert($this->currentTestCase !== null); $buffer = $this->testAsString($event->test()); $throwable = $event->throwable(); $buffer .= trim( $throwable->description() . PHP_EOL . $throwable->stackTrace(), ); $fault = $this->document->createElement( $type, Xml::prepareString($buffer), ); $fault->setAttribute('type', $throwable->className()); $this->currentTestCase->appendChild($fault); if (!$this->prepared) { $this->handleFinish($event->telemetryInfo(), 0); } } /** * @throws InvalidArgumentException */ private function handleIncompleteOrSkipped(MarkedIncomplete|Skipped $event): void { if (!$this->prepared) { $this->createTestCase($event); } assert($this->currentTestCase !== null); $skipped = $this->document->createElement('skipped'); $this->currentTestCase->appendChild($skipped); $this->testSuiteSkipped[$this->testSuiteLevel]++; if (!$this->prepared) { $this->handleFinish($event->telemetryInfo(), 0); } } /** * @throws InvalidArgumentException */ private function testAsString(Test $test): string { if ($test->isPhpt()) { return basename($test->file()); } assert($test instanceof TestMethod); return sprintf( '%s::%s%s', $test->className(), $this->name($test), PHP_EOL, ); } /** * @throws InvalidArgumentException */ private function name(Test $test): string { if ($test->isPhpt()) { return basename($test->file()); } assert($test instanceof TestMethod); if (!$test->testData()->hasDataFromDataProvider()) { return $test->methodName(); } $dataSetName = $test->testData()->dataFromDataProvider()->dataSetName(); if (is_int($dataSetName)) { return sprintf( '%s with data set #%d', $test->methodName(), $dataSetName, ); } return sprintf( '%s with data set "%s"', $test->methodName(), $dataSetName, ); } /** * @throws InvalidArgumentException * * @phpstan-assert !null $this->currentTestCase */ private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void { $testCase = $this->document->createElement('testcase'); $test = $event->test(); $testCase->setAttribute('name', $this->name($test)); $testCase->setAttribute('file', $test->file()); if ($test->isTestMethod()) { assert($test instanceof TestMethod); $testCase->setAttribute('line', (string) $test->line()); $testCase->setAttribute('class', $test->className()); $testCase->setAttribute('classname', str_replace('\\', '.', $test->className())); } $this->currentTestCase = $testCase; $this->time = $event->telemetryInfo()->time(); } } phpunit/src/Logging/JUnit/Subscriber/TestSuiteStartedSubscriber.php 0000644 00000001425 15253321353 0021565 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\TestSuite\Started; use PHPUnit\Event\TestSuite\StartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber { public function notify(Started $event): void { $this->logger()->testSuiteStarted($event); } } phpunit/src/Logging/JUnit/Subscriber/TestRunnerExecutionFinishedSubscriber.php 0000644 00000001471 15253321353 0023755 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\TestRunner\ExecutionFinished; use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestRunnerExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber { public function notify(ExecutionFinished $event): void { $this->logger()->flush(); } } phpunit/src/Logging/JUnit/Subscriber/TestPreparationFailedSubscriber.php 0000644 00000001633 15253321353 0022537 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\PreparationFailed; use PHPUnit\Event\Test\PreparationFailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparationFailedSubscriber extends Subscriber implements PreparationFailedSubscriber { /** * @throws InvalidArgumentException */ public function notify(PreparationFailed $event): void { $this->logger()->testPreparationFailed(); } } phpunit/src/Logging/JUnit/Subscriber/TestPreparationStartedSubscriber.php 0000644 00000001647 15253321353 0022766 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\PreparationStarted; use PHPUnit\Event\Test\PreparationStartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparationStartedSubscriber extends Subscriber implements PreparationStartedSubscriber { /** * @throws InvalidArgumentException */ public function notify(PreparationStarted $event): void { $this->logger()->testPreparationStarted($event); } } phpunit/src/Logging/JUnit/Subscriber/TestErroredSubscriber.php 0000644 00000001545 15253321353 0020552 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { /** * @throws InvalidArgumentException */ public function notify(Errored $event): void { $this->logger()->testErrored($event); } } phpunit/src/Logging/JUnit/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001633 15253321353 0022371 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { /** * @throws InvalidArgumentException */ public function notify(MarkedIncomplete $event): void { $this->logger()->testMarkedIncomplete($event); } } phpunit/src/Logging/JUnit/Subscriber/TestFinishedSubscriber.php 0000644 00000001553 15253321353 0020700 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Finished $event): void { $this->logger()->testFinished($event); } } phpunit/src/Logging/JUnit/Subscriber/Subscriber.php 0000644 00000001370 15253321353 0016363 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private JunitXmlLogger $logger; public function __construct(JunitXmlLogger $logger) { $this->logger = $logger; } protected function logger(): JunitXmlLogger { return $this->logger; } } phpunit/src/Logging/JUnit/Subscriber/TestFailedSubscriber.php 0000644 00000001537 15253321353 0020335 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Failed $event): void { $this->logger()->testFailed($event); } } phpunit/src/Logging/JUnit/Subscriber/TestPreparedSubscriber.php 0000644 00000001545 15253321353 0020712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Prepared $event): void { $this->logger()->testPrepared(); } } phpunit/src/Logging/JUnit/Subscriber/TestSkippedSubscriber.php 0000644 00000001545 15253321353 0020547 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Skipped $event): void { $this->logger()->testSkipped($event); } } phpunit/src/Logging/JUnit/Subscriber/TestSuiteFinishedSubscriber.php 0000644 00000001425 15253321353 0021710 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\JUnit; use PHPUnit\Event\TestSuite\Finished; use PHPUnit\Event\TestSuite\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->logger()->testSuiteFinished(); } } phpunit/src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php 0000644 00000001430 15253321353 0022247 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\TestSuite\Started; use PHPUnit\Event\TestSuite\StartedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber { public function notify(Started $event): void { $this->logger()->testSuiteStarted($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestRunnerExecutionFinishedSubscriber.php 0000644 00000001474 15253321353 0024446 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\TestRunner\ExecutionFinished; use PHPUnit\Event\TestRunner\ExecutionFinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestRunnerExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber { public function notify(ExecutionFinished $event): void { $this->logger()->flush(); } } phpunit/src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php 0000644 00000001550 15253321353 0021234 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\ErroredSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestErroredSubscriber extends Subscriber implements ErroredSubscriber { /** * @throws InvalidArgumentException */ public function notify(Errored $event): void { $this->logger()->testErrored($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestMarkedIncompleteSubscriber.php 0000644 00000001636 15253321353 0023062 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\MarkedIncompleteSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestMarkedIncompleteSubscriber extends Subscriber implements MarkedIncompleteSubscriber { /** * @throws InvalidArgumentException */ public function notify(MarkedIncomplete $event): void { $this->logger()->testMarkedIncomplete($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php 0000644 00000001556 15253321353 0021371 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Finished $event): void { $this->logger()->testFinished($event); } } phpunit/src/Logging/TeamCity/Subscriber/Subscriber.php 0000644 00000001373 15253321353 0017054 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Subscriber { private TeamCityLogger $logger; public function __construct(TeamCityLogger $logger) { $this->logger = $logger; } protected function logger(): TeamCityLogger { return $this->logger; } } phpunit/src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php 0000644 00000001542 15253321353 0021017 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\FailedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestFailedSubscriber extends Subscriber implements FailedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Failed $event): void { $this->logger()->testFailed($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php 0000644 00000001412 15253321353 0021371 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\PreparedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber { public function notify(Prepared $event): void { $this->logger()->testPrepared($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php 0000644 00000001550 15253321353 0021231 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\Test\SkippedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber { /** * @throws InvalidArgumentException */ public function notify(Skipped $event): void { $this->logger()->testSkipped($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php 0000644 00000001630 15253321353 0022732 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\ConsideredRiskySubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber { /** * @throws InvalidArgumentException */ public function notify(ConsideredRisky $event): void { $this->logger()->testConsideredRisky($event); } } phpunit/src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php 0000644 00000001436 15253321353 0022400 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use PHPUnit\Event\TestSuite\Finished; use PHPUnit\Event\TestSuite\FinishedSubscriber; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber { public function notify(Finished $event): void { $this->logger()->testSuiteFinished($event); } } phpunit/src/Logging/TeamCity/TeamCityLogger.php 0000644 00000024545 15253321353 0015533 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Logging\TeamCity; use function assert; use function getmypid; use function ini_get; use function is_a; use function round; use function sprintf; use function str_replace; use function stripos; use PHPUnit\Event\Code\TestMethod; use PHPUnit\Event\Code\Throwable; use PHPUnit\Event\Event; use PHPUnit\Event\EventFacadeIsSealedException; use PHPUnit\Event\Facade; use PHPUnit\Event\InvalidArgumentException; use PHPUnit\Event\Telemetry\HRTime; use PHPUnit\Event\Test\ConsideredRisky; use PHPUnit\Event\Test\Errored; use PHPUnit\Event\Test\Failed; use PHPUnit\Event\Test\Finished; use PHPUnit\Event\Test\MarkedIncomplete; use PHPUnit\Event\Test\Prepared; use PHPUnit\Event\Test\Skipped; use PHPUnit\Event\TestSuite\Finished as TestSuiteFinished; use PHPUnit\Event\TestSuite\Started as TestSuiteStarted; use PHPUnit\Event\TestSuite\TestSuiteForTestClass; use PHPUnit\Event\TestSuite\TestSuiteForTestMethodWithDataProvider; use PHPUnit\Event\UnknownSubscriberTypeException; use PHPUnit\Framework\Exception as FrameworkException; use PHPUnit\TextUI\Output\Printer; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class TeamCityLogger { private readonly Printer $printer; private bool $isSummaryTestCountPrinted = false; private ?HRTime $time = null; private ?int $flowId; /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ public function __construct(Printer $printer, Facade $facade) { $this->printer = $printer; $this->registerSubscribers($facade); $this->setFlowId(); } public function testSuiteStarted(TestSuiteStarted $event): void { $testSuite = $event->testSuite(); if (!$this->isSummaryTestCountPrinted) { $this->isSummaryTestCountPrinted = true; $this->writeMessage( 'testCount', ['count' => $testSuite->count()], ); } $parameters = ['name' => $testSuite->name()]; if ($testSuite->isForTestClass()) { assert($testSuite instanceof TestSuiteForTestClass); $parameters['locationHint'] = sprintf( 'php_qn://%s::\\%s', $testSuite->file(), $testSuite->name(), ); } elseif ($testSuite->isForTestMethodWithDataProvider()) { assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); $parameters['locationHint'] = sprintf( 'php_qn://%s::\\%s', $testSuite->file(), $testSuite->name(), ); $parameters['name'] = $testSuite->methodName(); } $this->writeMessage('testSuiteStarted', $parameters); } public function testSuiteFinished(TestSuiteFinished $event): void { $testSuite = $event->testSuite(); $parameters = ['name' => $testSuite->name()]; if ($testSuite->isForTestMethodWithDataProvider()) { assert($testSuite instanceof TestSuiteForTestMethodWithDataProvider); $parameters['name'] = $testSuite->methodName(); } $this->writeMessage('testSuiteFinished', $parameters); } public function testPrepared(Prepared $event): void { $test = $event->test(); $parameters = [ 'name' => $test->name(), ]; if ($test->isTestMethod()) { assert($test instanceof TestMethod); $parameters['locationHint'] = sprintf( 'php_qn://%s::\\%s::%s', $test->file(), $test->className(), $test->name(), ); } $this->writeMessage('testStarted', $parameters); $this->time = $event->telemetryInfo()->time(); } /** * @throws InvalidArgumentException */ public function testMarkedIncomplete(MarkedIncomplete $event): void { if ($this->time === null) { $this->time = $event->telemetryInfo()->time(); } $this->writeMessage( 'testIgnored', [ 'name' => $event->test()->name(), 'message' => $event->throwable()->message(), 'details' => $this->details($event->throwable()), 'duration' => $this->duration($event), ], ); } /** * @throws InvalidArgumentException */ public function testSkipped(Skipped $event): void { if ($this->time === null) { $this->time = $event->telemetryInfo()->time(); } $parameters = [ 'name' => $event->test()->name(), 'message' => $event->message(), ]; $parameters['duration'] = $this->duration($event); $this->writeMessage('testIgnored', $parameters); } /** * @throws InvalidArgumentException */ public function testErrored(Errored $event): void { if ($this->time === null) { $this->time = $event->telemetryInfo()->time(); } $this->writeMessage( 'testFailed', [ 'name' => $event->test()->name(), 'message' => $this->message($event->throwable()), 'details' => $this->details($event->throwable()), 'duration' => $this->duration($event), ], ); } /** * @throws InvalidArgumentException */ public function testFailed(Failed $event): void { if ($this->time === null) { $this->time = $event->telemetryInfo()->time(); } $parameters = [ 'name' => $event->test()->name(), 'message' => $this->message($event->throwable()), 'details' => $this->details($event->throwable()), 'duration' => $this->duration($event), ]; if ($event->hasComparisonFailure()) { $parameters['type'] = 'comparisonFailure'; $parameters['actual'] = $event->comparisonFailure()->actual(); $parameters['expected'] = $event->comparisonFailure()->expected(); } $this->writeMessage('testFailed', $parameters); } /** * @throws InvalidArgumentException */ public function testConsideredRisky(ConsideredRisky $event): void { if ($this->time === null) { $this->time = $event->telemetryInfo()->time(); } $this->writeMessage( 'testFailed', [ 'name' => $event->test()->name(), 'message' => $event->message(), 'details' => '', 'duration' => $this->duration($event), ], ); } /** * @throws InvalidArgumentException */ public function testFinished(Finished $event): void { $this->writeMessage( 'testFinished', [ 'name' => $event->test()->name(), 'duration' => $this->duration($event), ], ); $this->time = null; } public function flush(): void { $this->printer->flush(); } /** * @throws EventFacadeIsSealedException * @throws UnknownSubscriberTypeException */ private function registerSubscribers(Facade $facade): void { $facade->registerSubscribers( new TestSuiteStartedSubscriber($this), new TestSuiteFinishedSubscriber($this), new TestPreparedSubscriber($this), new TestFinishedSubscriber($this), new TestErroredSubscriber($this), new TestFailedSubscriber($this), new TestMarkedIncompleteSubscriber($this), new TestSkippedSubscriber($this), new TestConsideredRiskySubscriber($this), new TestRunnerExecutionFinishedSubscriber($this), ); } private function setFlowId(): void { if (stripos(ini_get('disable_functions'), 'getmypid') === false) { $this->flowId = getmypid(); } } /** * @param array<non-empty-string, int|string> $parameters */ private function writeMessage(string $eventName, array $parameters = []): void { $this->printer->print( sprintf( "\n##teamcity[%s", $eventName, ), ); if ($this->flowId !== null) { $parameters['flowId'] = $this->flowId; } foreach ($parameters as $key => $value) { $this->printer->print( sprintf( " %s='%s'", $key, $this->escape((string) $value), ), ); } $this->printer->print("]\n"); } /** * @throws InvalidArgumentException */ private function duration(Event $event): int { if ($this->time === null) { return 0; } return (int) round($event->telemetryInfo()->time()->duration($this->time)->asFloat() * 1000); } private function escape(string $string): string { return str_replace( ['|', "'", "\n", "\r", ']', '['], ['||', "|'", '|n', '|r', '|]', '|['], $string, ); } private function message(Throwable $throwable): string { if (is_a($throwable->className(), FrameworkException::class, true)) { return $throwable->message(); } $buffer = $throwable->className(); if (!empty($throwable->message())) { $buffer .= ': ' . $throwable->message(); } return $buffer; } private function details(Throwable $throwable): string { $buffer = $throwable->stackTrace(); while ($throwable->hasPrevious()) { $throwable = $throwable->previous(); $buffer .= sprintf( "\nCaused by\n%s\n%s", $throwable->description(), $throwable->stackTrace(), ); } return $buffer; } } phpunit/src/Metadata/RequiresOperatingSystem.php 0000644 00000002053 15253321353 0016132 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresOperatingSystem extends Metadata { /** * @var non-empty-string */ private string $operatingSystem; /** * @param 0|1 $level * @param non-empty-string $operatingSystem */ public function __construct(int $level, string $operatingSystem) { parent::__construct($level); $this->operatingSystem = $operatingSystem; } public function isRequiresOperatingSystem(): true { return true; } /** * @return non-empty-string */ public function operatingSystem(): string { return $this->operatingSystem; } } phpunit/src/Metadata/WithoutErrorHandler.php 0000644 00000001055 15253321353 0015231 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class WithoutErrorHandler extends Metadata { public function isWithoutErrorHandler(): true { return true; } } phpunit/src/Metadata/ExcludeStaticPropertyFromBackup.php 0000644 00000002533 15253321353 0017540 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExcludeStaticPropertyFromBackup extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $propertyName; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $propertyName */ protected function __construct(int $level, string $className, string $propertyName) { parent::__construct($level); $this->className = $className; $this->propertyName = $propertyName; } public function isExcludeStaticPropertyFromBackup(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function propertyName(): string { return $this->propertyName; } } phpunit/src/Metadata/ExcludeGlobalVariableFromBackup.php 0000644 00000002123 15253321353 0017405 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ExcludeGlobalVariableFromBackup extends Metadata { /** * @var non-empty-string */ private string $globalVariableName; /** * @param 0|1 $level * @param non-empty-string $globalVariableName */ protected function __construct(int $level, string $globalVariableName) { parent::__construct($level); $this->globalVariableName = $globalVariableName; } public function isExcludeGlobalVariableFromBackup(): true { return true; } /** * @return non-empty-string */ public function globalVariableName(): string { return $this->globalVariableName; } } phpunit/src/Metadata/RequiresMethod.php 0000644 00000002451 15253321353 0014217 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresMethod extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $methodName */ protected function __construct(int $level, string $className, string $methodName) { parent::__construct($level); $this->className = $className; $this->methodName = $methodName; } public function isRequiresMethod(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Metadata/RequiresPhp.php 0000644 00000001710 15253321353 0013523 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use PHPUnit\Metadata\Version\Requirement; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresPhp extends Metadata { private Requirement $versionRequirement; /** * @param 0|1 $level */ protected function __construct(int $level, Requirement $versionRequirement) { parent::__construct($level); $this->versionRequirement = $versionRequirement; } public function isRequiresPhp(): true { return true; } public function versionRequirement(): Requirement { return $this->versionRequirement; } } phpunit/src/Metadata/DependsOnClass.php 0000644 00000002514 15253321353 0014124 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DependsOnClass extends Metadata { /** * @var class-string */ private string $className; private bool $deepClone; private bool $shallowClone; /** * @param 0|1 $level * @param class-string $className */ protected function __construct(int $level, string $className, bool $deepClone, bool $shallowClone) { parent::__construct($level); $this->className = $className; $this->deepClone = $deepClone; $this->shallowClone = $shallowClone; } public function isDependsOnClass(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } public function deepClone(): bool { return $this->deepClone; } public function shallowClone(): bool { return $this->shallowClone; } } phpunit/src/Metadata/Version/ConstraintRequirement.php 0000644 00000002265 15253321353 0017254 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Version; use function preg_replace; use PharIo\Version\Version; use PharIo\Version\VersionConstraint; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ConstraintRequirement extends Requirement { private VersionConstraint $constraint; public function __construct(VersionConstraint $constraint) { $this->constraint = $constraint; } public function isSatisfiedBy(string $version): bool { return $this->constraint->complies( new Version($this->sanitize($version)), ); } public function asString(): string { return $this->constraint->asString(); } private function sanitize(string $version): string { return preg_replace( '/^(\d+\.\d+(?:.\d+)?).*$/', '$1', $version, ); } } phpunit/src/Metadata/Version/ComparisonRequirement.php 0000644 00000002100 15253321353 0017226 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Version; use function version_compare; use PHPUnit\Util\VersionComparisonOperator; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class ComparisonRequirement extends Requirement { private string $version; private VersionComparisonOperator $operator; public function __construct(string $version, VersionComparisonOperator $operator) { $this->version = $version; $this->operator = $operator; } public function isSatisfiedBy(string $version): bool { return version_compare($version, $this->version, $this->operator->asString()); } public function asString(): string { return $this->operator->asString() . ' ' . $this->version; } } phpunit/src/Metadata/Version/Requirement.php 0000644 00000003507 15253321353 0015207 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Version; use function preg_match; use PharIo\Version\UnsupportedVersionConstraintException; use PharIo\Version\VersionConstraintParser; use PHPUnit\Metadata\InvalidVersionRequirementException; use PHPUnit\Util\InvalidVersionOperatorException; use PHPUnit\Util\VersionComparisonOperator; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Requirement { private const VERSION_COMPARISON = '/(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; /** * @throws InvalidVersionOperatorException * @throws InvalidVersionRequirementException */ public static function from(string $versionRequirement): self { try { return new ConstraintRequirement( (new VersionConstraintParser)->parse( $versionRequirement, ), ); } catch (UnsupportedVersionConstraintException) { if (preg_match(self::VERSION_COMPARISON, $versionRequirement, $matches)) { return new ComparisonRequirement( $matches['version'], new VersionComparisonOperator( !empty($matches['operator']) ? $matches['operator'] : '>=', ), ); } } throw new InvalidVersionRequirementException; } abstract public function isSatisfiedBy(string $version): bool; abstract public function asString(): string; } phpunit/src/Metadata/UsesMethod.php 0000644 00000003067 15253321353 0013343 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class UsesMethod extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $methodName */ protected function __construct(int $level, string $className, string $methodName) { parent::__construct($level); $this->className = $className; $this->methodName = $methodName; } public function isUsesMethod(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @return non-empty-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->className . '::' . $this->methodName; } } phpunit/src/Metadata/UsesFunction.php 0000644 00000002336 15253321353 0013706 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class UsesFunction extends Metadata { /** * @var non-empty-string */ private string $functionName; /** * @param 0|1 $level * @param non-empty-string $functionName */ public function __construct(int $level, string $functionName) { parent::__construct($level); $this->functionName = $functionName; } public function isUsesFunction(): true { return true; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return '::' . $this->functionName; } } phpunit/src/Metadata/PreCondition.php 0000644 00000001736 15253321353 0013661 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreCondition extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isPreCondition(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/TestWith.php 0000644 00000002606 15253321353 0013034 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestWith extends Metadata { /** * @var array<array<mixed>> */ private array $data; /** * @var ?non-empty-string */ private ?string $name; /** * @param 0|1 $level * @param array<array<mixed>> $data * @param ?non-empty-string $name */ protected function __construct(int $level, array $data, ?string $name = null) { parent::__construct($level); $this->data = $data; $this->name = $name; } public function isTestWith(): true { return true; } /** * @return array<array<mixed>> */ public function data(): array { return $this->data; } /** * @phpstan-assert-if-true !null $this->name */ public function hasName(): bool { return $this->name !== null; } /** * @return ?non-empty-string */ public function name(): ?string { return $this->name; } } phpunit/src/Metadata/DataProvider.php 0000644 00000002445 15253321353 0013646 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DataProvider extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $methodName */ protected function __construct(int $level, string $className, string $methodName) { parent::__construct($level); $this->className = $className; $this->methodName = $methodName; } public function isDataProvider(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } } phpunit/src/Metadata/UsesClass.php 0000644 00000002317 15253321353 0013165 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class UsesClass extends Metadata { /** * @var class-string */ private string $className; /** * @param 0|1 $level * @param class-string $className */ protected function __construct(int $level, string $className) { parent::__construct($level); $this->className = $className; } public function isUsesClass(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return class-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->className; } } phpunit/src/Metadata/IgnorePhpunitDeprecations.php 0000644 00000001225 15253321353 0016411 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class IgnorePhpunitDeprecations extends Metadata { public function isIgnorePhpunitDeprecations(): true { return true; } } phpunit/src/Metadata/CoversClass.php 0000644 00000002323 15253321353 0013504 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversClass extends Metadata { /** * @var class-string */ private string $className; /** * @param 0|1 $level * @param class-string $className */ protected function __construct(int $level, string $className) { parent::__construct($level); $this->className = $className; } public function isCoversClass(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return class-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->className; } } phpunit/src/Metadata/Group.php 0000644 00000001740 15253321353 0012353 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Group extends Metadata { /** * @var non-empty-string */ private string $groupName; /** * @param 0|1 $level * @param non-empty-string $groupName */ protected function __construct(int $level, string $groupName) { parent::__construct($level); $this->groupName = $groupName; } public function isGroup(): true { return true; } /** * @return non-empty-string */ public function groupName(): string { return $this->groupName; } } phpunit/src/Metadata/Exception/Exception.php 0000644 00000000515 15253321353 0015152 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; interface Exception extends \PHPUnit\Exception { } phpunit/src/Metadata/Exception/AnnotationsAreNotSupportedForInternalClassesException.php 0000644 00000001763 15253321353 0026077 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use function sprintf; use PHPUnit\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class AnnotationsAreNotSupportedForInternalClassesException extends RuntimeException implements Exception { /** * @param class-string $className */ public function __construct(string $className) { parent::__construct( sprintf( 'Annotations can only be parsed for user-defined classes, trying to parse annotations for class "%s"', $className, ), ); } } phpunit/src/Metadata/Exception/NoVersionRequirementException.php 0000644 00000000615 15253321353 0021237 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use RuntimeException; final class NoVersionRequirementException extends RuntimeException implements Exception { } phpunit/src/Metadata/Exception/ReflectionException.php 0000644 00000001147 15253321353 0017167 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use PHPUnit\Exception; use RuntimeException; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class ReflectionException extends RuntimeException implements Exception { } phpunit/src/Metadata/Exception/InvalidVersionRequirementException.php 0000644 00000000622 15253321353 0022247 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use RuntimeException; final class InvalidVersionRequirementException extends RuntimeException implements Exception { } phpunit/src/Metadata/MetadataCollectionIterator.php 0000644 00000002273 15253321353 0016527 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use function count; use Iterator; /** * @template-implements Iterator<int, Metadata> * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final class MetadataCollectionIterator implements Iterator { /** * @var list<Metadata> */ private readonly array $metadata; private int $position = 0; public function __construct(MetadataCollection $metadata) { $this->metadata = $metadata->asArray(); } public function rewind(): void { $this->position = 0; } public function valid(): bool { return $this->position < count($this->metadata); } public function key(): int { return $this->position; } public function current(): Metadata { return $this->metadata[$this->position]; } public function next(): void { $this->position++; } } phpunit/src/Metadata/CoversNothing.php 0000644 00000001041 15253321353 0014041 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversNothing extends Metadata { public function isCoversNothing(): true { return true; } } phpunit/src/Metadata/CoversTrait.php 0000644 00000002323 15253321353 0013522 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversTrait extends Metadata { /** * @var trait-string */ private string $traitName; /** * @param 0|1 $level * @param trait-string $traitName */ protected function __construct(int $level, string $traitName) { parent::__construct($level); $this->traitName = $traitName; } public function isCoversTrait(): true { return true; } /** * @return trait-string */ public function traitName(): string { return $this->traitName; } /** * @return trait-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->traitName; } } phpunit/src/Metadata/CoversDefaultClass.php 0000644 00000001752 15253321353 0015016 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversDefaultClass extends Metadata { /** * @var class-string */ private string $className; /** * @param 0|1 $level * @param class-string $className */ protected function __construct(int $level, string $className) { parent::__construct($level); $this->className = $className; } public function isCoversDefaultClass(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Metadata/RequiresPhpunit.php 0000644 00000001720 15253321353 0014424 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use PHPUnit\Metadata\Version\Requirement; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresPhpunit extends Metadata { private Requirement $versionRequirement; /** * @param 0|1 $level */ protected function __construct(int $level, Requirement $versionRequirement) { parent::__construct($level); $this->versionRequirement = $versionRequirement; } public function isRequiresPhpunit(): true { return true; } public function versionRequirement(): Requirement { return $this->versionRequirement; } } phpunit/src/Metadata/TestDox.php 0000644 00000001701 15253321353 0012646 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class TestDox extends Metadata { /** * @var non-empty-string */ private string $text; /** * @param 0|1 $level * @param non-empty-string $text */ protected function __construct(int $level, string $text) { parent::__construct($level); $this->text = $text; } public function isTestDox(): true { return true; } /** * @return non-empty-string */ public function text(): string { return $this->text; } } phpunit/src/Metadata/PostCondition.php 0000644 00000001740 15253321353 0014053 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PostCondition extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isPostCondition(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/Before.php 0000644 00000001722 15253321353 0012461 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Before extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isBefore(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/DisableReturnValueGenerationForTestDoubles.php 0000644 00000001133 15253321353 0021654 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DisableReturnValueGenerationForTestDoubles extends Metadata { public function isDisableReturnValueGenerationForTestDoubles(): true { return true; } } phpunit/src/Metadata/DependsOnMethod.php 0000644 00000003226 15253321353 0014300 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DependsOnMethod extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; private bool $deepClone; private bool $shallowClone; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $methodName */ protected function __construct(int $level, string $className, string $methodName, bool $deepClone, bool $shallowClone) { parent::__construct($level); $this->className = $className; $this->methodName = $methodName; $this->deepClone = $deepClone; $this->shallowClone = $shallowClone; } public function isDependsOnMethod(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } public function deepClone(): bool { return $this->deepClone; } public function shallowClone(): bool { return $this->shallowClone; } } phpunit/src/Metadata/CoversMethod.php 0000644 00000003073 15253321353 0013662 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversMethod extends Metadata { /** * @var class-string */ private string $className; /** * @var non-empty-string */ private string $methodName; /** * @param 0|1 $level * @param class-string $className * @param non-empty-string $methodName */ protected function __construct(int $level, string $className, string $methodName) { parent::__construct($level); $this->className = $className; $this->methodName = $methodName; } public function isCoversMethod(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } /** * @return non-empty-string */ public function methodName(): string { return $this->methodName; } /** * @return non-empty-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->className . '::' . $this->methodName; } } phpunit/src/Metadata/RunClassInSeparateProcess.php 0000644 00000001071 15253321353 0016321 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RunClassInSeparateProcess extends Metadata { public function isRunClassInSeparateProcess(): true { return true; } } phpunit/src/Metadata/RequiresSetting.php 0000644 00000002403 15253321353 0014411 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresSetting extends Metadata { /** * @var non-empty-string */ private string $setting; /** * @var non-empty-string */ private string $value; /** * @param 0|1 $level * @param non-empty-string $setting * @param non-empty-string $value */ protected function __construct(int $level, string $setting, string $value) { parent::__construct($level); $this->setting = $setting; $this->value = $value; } public function isRequiresSetting(): true { return true; } /** * @return non-empty-string */ public function setting(): string { return $this->setting; } /** * @return non-empty-string */ public function value(): string { return $this->value; } } phpunit/src/Metadata/Metadata.php 0000644 00000054772 15253321353 0013014 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use PHPUnit\Metadata\Version\Requirement; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ abstract readonly class Metadata { private const CLASS_LEVEL = 0; private const METHOD_LEVEL = 1; /** * @var 0|1 */ private int $level; /** * @param non-negative-int $priority */ public static function after(int $priority): After { return new After(self::METHOD_LEVEL, $priority); } /** * @param non-negative-int $priority */ public static function afterClass(int $priority): AfterClass { return new AfterClass(self::METHOD_LEVEL, $priority); } public static function backupGlobalsOnClass(bool $enabled): BackupGlobals { return new BackupGlobals(self::CLASS_LEVEL, $enabled); } public static function backupGlobalsOnMethod(bool $enabled): BackupGlobals { return new BackupGlobals(self::METHOD_LEVEL, $enabled); } public static function backupStaticPropertiesOnClass(bool $enabled): BackupStaticProperties { return new BackupStaticProperties(self::CLASS_LEVEL, $enabled); } public static function backupStaticPropertiesOnMethod(bool $enabled): BackupStaticProperties { return new BackupStaticProperties(self::METHOD_LEVEL, $enabled); } /** * @param non-negative-int $priority */ public static function before(int $priority): Before { return new Before(self::METHOD_LEVEL, $priority); } /** * @param non-negative-int $priority */ public static function beforeClass(int $priority): BeforeClass { return new BeforeClass(self::METHOD_LEVEL, $priority); } /** * @param class-string $className */ public static function coversClass(string $className): CoversClass { return new CoversClass(self::CLASS_LEVEL, $className); } /** * @param trait-string $traitName */ public static function coversTrait(string $traitName): CoversTrait { return new CoversTrait(self::CLASS_LEVEL, $traitName); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function coversMethod(string $className, string $methodName): CoversMethod { return new CoversMethod(self::CLASS_LEVEL, $className, $methodName); } /** * @param non-empty-string $functionName */ public static function coversFunction(string $functionName): CoversFunction { return new CoversFunction(self::CLASS_LEVEL, $functionName); } /** * @param non-empty-string $target */ public static function coversOnClass(string $target): Covers { return new Covers(self::CLASS_LEVEL, $target); } /** * @param non-empty-string $target */ public static function coversOnMethod(string $target): Covers { return new Covers(self::METHOD_LEVEL, $target); } /** * @param class-string $className */ public static function coversDefaultClass(string $className): CoversDefaultClass { return new CoversDefaultClass(self::CLASS_LEVEL, $className); } public static function coversNothingOnClass(): CoversNothing { return new CoversNothing(self::CLASS_LEVEL); } public static function coversNothingOnMethod(): CoversNothing { return new CoversNothing(self::METHOD_LEVEL); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function dataProvider(string $className, string $methodName): DataProvider { return new DataProvider(self::METHOD_LEVEL, $className, $methodName); } /** * @param class-string $className */ public static function dependsOnClass(string $className, bool $deepClone, bool $shallowClone): DependsOnClass { return new DependsOnClass(self::METHOD_LEVEL, $className, $deepClone, $shallowClone); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function dependsOnMethod(string $className, string $methodName, bool $deepClone, bool $shallowClone): DependsOnMethod { return new DependsOnMethod(self::METHOD_LEVEL, $className, $methodName, $deepClone, $shallowClone); } public static function disableReturnValueGenerationForTestDoubles(): DisableReturnValueGenerationForTestDoubles { return new DisableReturnValueGenerationForTestDoubles(self::CLASS_LEVEL); } public static function doesNotPerformAssertionsOnClass(): DoesNotPerformAssertions { return new DoesNotPerformAssertions(self::CLASS_LEVEL); } public static function doesNotPerformAssertionsOnMethod(): DoesNotPerformAssertions { return new DoesNotPerformAssertions(self::METHOD_LEVEL); } /** * @param non-empty-string $globalVariableName */ public static function excludeGlobalVariableFromBackupOnClass(string $globalVariableName): ExcludeGlobalVariableFromBackup { return new ExcludeGlobalVariableFromBackup(self::CLASS_LEVEL, $globalVariableName); } /** * @param non-empty-string $globalVariableName */ public static function excludeGlobalVariableFromBackupOnMethod(string $globalVariableName): ExcludeGlobalVariableFromBackup { return new ExcludeGlobalVariableFromBackup(self::METHOD_LEVEL, $globalVariableName); } /** * @param class-string $className * @param non-empty-string $propertyName */ public static function excludeStaticPropertyFromBackupOnClass(string $className, string $propertyName): ExcludeStaticPropertyFromBackup { return new ExcludeStaticPropertyFromBackup(self::CLASS_LEVEL, $className, $propertyName); } /** * @param class-string $className * @param non-empty-string $propertyName */ public static function excludeStaticPropertyFromBackupOnMethod(string $className, string $propertyName): ExcludeStaticPropertyFromBackup { return new ExcludeStaticPropertyFromBackup(self::METHOD_LEVEL, $className, $propertyName); } /** * @param non-empty-string $groupName */ public static function groupOnClass(string $groupName): Group { return new Group(self::CLASS_LEVEL, $groupName); } /** * @param non-empty-string $groupName */ public static function groupOnMethod(string $groupName): Group { return new Group(self::METHOD_LEVEL, $groupName); } public static function ignoreDeprecationsOnClass(): IgnoreDeprecations { return new IgnoreDeprecations(self::CLASS_LEVEL); } public static function ignoreDeprecationsOnMethod(): IgnoreDeprecations { return new IgnoreDeprecations(self::METHOD_LEVEL); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public static function ignorePhpunitDeprecationsOnClass(): IgnorePhpunitDeprecations { return new IgnorePhpunitDeprecations(self::CLASS_LEVEL); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public static function ignorePhpunitDeprecationsOnMethod(): IgnorePhpunitDeprecations { return new IgnorePhpunitDeprecations(self::METHOD_LEVEL); } /** * @param non-negative-int $priority */ public static function postCondition(int $priority): PostCondition { return new PostCondition(self::METHOD_LEVEL, $priority); } /** * @param non-negative-int $priority */ public static function preCondition(int $priority): PreCondition { return new PreCondition(self::METHOD_LEVEL, $priority); } public static function preserveGlobalStateOnClass(bool $enabled): PreserveGlobalState { return new PreserveGlobalState(self::CLASS_LEVEL, $enabled); } public static function preserveGlobalStateOnMethod(bool $enabled): PreserveGlobalState { return new PreserveGlobalState(self::METHOD_LEVEL, $enabled); } /** * @param non-empty-string $functionName */ public static function requiresFunctionOnClass(string $functionName): RequiresFunction { return new RequiresFunction(self::CLASS_LEVEL, $functionName); } /** * @param non-empty-string $functionName */ public static function requiresFunctionOnMethod(string $functionName): RequiresFunction { return new RequiresFunction(self::METHOD_LEVEL, $functionName); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function requiresMethodOnClass(string $className, string $methodName): RequiresMethod { return new RequiresMethod(self::CLASS_LEVEL, $className, $methodName); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function requiresMethodOnMethod(string $className, string $methodName): RequiresMethod { return new RequiresMethod(self::METHOD_LEVEL, $className, $methodName); } /** * @param non-empty-string $operatingSystem */ public static function requiresOperatingSystemOnClass(string $operatingSystem): RequiresOperatingSystem { return new RequiresOperatingSystem(self::CLASS_LEVEL, $operatingSystem); } /** * @param non-empty-string $operatingSystem */ public static function requiresOperatingSystemOnMethod(string $operatingSystem): RequiresOperatingSystem { return new RequiresOperatingSystem(self::METHOD_LEVEL, $operatingSystem); } /** * @param non-empty-string $operatingSystemFamily */ public static function requiresOperatingSystemFamilyOnClass(string $operatingSystemFamily): RequiresOperatingSystemFamily { return new RequiresOperatingSystemFamily(self::CLASS_LEVEL, $operatingSystemFamily); } /** * @param non-empty-string $operatingSystemFamily */ public static function requiresOperatingSystemFamilyOnMethod(string $operatingSystemFamily): RequiresOperatingSystemFamily { return new RequiresOperatingSystemFamily(self::METHOD_LEVEL, $operatingSystemFamily); } public static function requiresPhpOnClass(Requirement $versionRequirement): RequiresPhp { return new RequiresPhp(self::CLASS_LEVEL, $versionRequirement); } public static function requiresPhpOnMethod(Requirement $versionRequirement): RequiresPhp { return new RequiresPhp(self::METHOD_LEVEL, $versionRequirement); } /** * @param non-empty-string $extension */ public static function requiresPhpExtensionOnClass(string $extension, ?Requirement $versionRequirement): RequiresPhpExtension { return new RequiresPhpExtension(self::CLASS_LEVEL, $extension, $versionRequirement); } /** * @param non-empty-string $extension */ public static function requiresPhpExtensionOnMethod(string $extension, ?Requirement $versionRequirement): RequiresPhpExtension { return new RequiresPhpExtension(self::METHOD_LEVEL, $extension, $versionRequirement); } public static function requiresPhpunitOnClass(Requirement $versionRequirement): RequiresPhpunit { return new RequiresPhpunit(self::CLASS_LEVEL, $versionRequirement); } public static function requiresPhpunitOnMethod(Requirement $versionRequirement): RequiresPhpunit { return new RequiresPhpunit(self::METHOD_LEVEL, $versionRequirement); } /** * @param non-empty-string $setting * @param non-empty-string $value */ public static function requiresSettingOnClass(string $setting, string $value): RequiresSetting { return new RequiresSetting(self::CLASS_LEVEL, $setting, $value); } /** * @param non-empty-string $setting * @param non-empty-string $value */ public static function requiresSettingOnMethod(string $setting, string $value): RequiresSetting { return new RequiresSetting(self::METHOD_LEVEL, $setting, $value); } public static function runClassInSeparateProcess(): RunClassInSeparateProcess { return new RunClassInSeparateProcess(self::CLASS_LEVEL); } public static function runTestsInSeparateProcesses(): RunTestsInSeparateProcesses { return new RunTestsInSeparateProcesses(self::CLASS_LEVEL); } public static function runInSeparateProcess(): RunInSeparateProcess { return new RunInSeparateProcess(self::METHOD_LEVEL); } public static function test(): Test { return new Test(self::METHOD_LEVEL); } /** * @param non-empty-string $text */ public static function testDoxOnClass(string $text): TestDox { return new TestDox(self::CLASS_LEVEL, $text); } /** * @param non-empty-string $text */ public static function testDoxOnMethod(string $text): TestDox { return new TestDox(self::METHOD_LEVEL, $text); } /** * @param array<array<mixed>> $data * @param ?non-empty-string $name */ public static function testWith(array $data, ?string $name = null): TestWith { return new TestWith(self::METHOD_LEVEL, $data, $name); } /** * @param class-string $className */ public static function usesClass(string $className): UsesClass { return new UsesClass(self::CLASS_LEVEL, $className); } /** * @param trait-string $traitName */ public static function UsesTrait(string $traitName): UsesTrait { return new UsesTrait(self::CLASS_LEVEL, $traitName); } /** * @param non-empty-string $functionName */ public static function usesFunction(string $functionName): UsesFunction { return new UsesFunction(self::CLASS_LEVEL, $functionName); } /** * @param class-string $className * @param non-empty-string $methodName */ public static function usesMethod(string $className, string $methodName): UsesMethod { return new UsesMethod(self::CLASS_LEVEL, $className, $methodName); } /** * @param non-empty-string $target */ public static function usesOnClass(string $target): Uses { return new Uses(self::CLASS_LEVEL, $target); } /** * @param non-empty-string $target */ public static function usesOnMethod(string $target): Uses { return new Uses(self::METHOD_LEVEL, $target); } /** * @param class-string $className */ public static function usesDefaultClass(string $className): UsesDefaultClass { return new UsesDefaultClass(self::CLASS_LEVEL, $className); } public static function withoutErrorHandler(): WithoutErrorHandler { return new WithoutErrorHandler(self::METHOD_LEVEL); } /** * @param 0|1 $level */ protected function __construct(int $level) { $this->level = $level; } public function isClassLevel(): bool { return $this->level === self::CLASS_LEVEL; } public function isMethodLevel(): bool { return $this->level === self::METHOD_LEVEL; } /** * @phpstan-assert-if-true After $this */ public function isAfter(): bool { return false; } /** * @phpstan-assert-if-true AfterClass $this */ public function isAfterClass(): bool { return false; } /** * @phpstan-assert-if-true BackupGlobals $this */ public function isBackupGlobals(): bool { return false; } /** * @phpstan-assert-if-true BackupStaticProperties $this */ public function isBackupStaticProperties(): bool { return false; } /** * @phpstan-assert-if-true BeforeClass $this */ public function isBeforeClass(): bool { return false; } /** * @phpstan-assert-if-true Before $this */ public function isBefore(): bool { return false; } /** * @phpstan-assert-if-true Covers $this */ public function isCovers(): bool { return false; } /** * @phpstan-assert-if-true CoversClass $this */ public function isCoversClass(): bool { return false; } /** * @phpstan-assert-if-true CoversDefaultClass $this */ public function isCoversDefaultClass(): bool { return false; } /** * @phpstan-assert-if-true CoversTrait $this */ public function isCoversTrait(): bool { return false; } /** * @phpstan-assert-if-true CoversFunction $this */ public function isCoversFunction(): bool { return false; } /** * @phpstan-assert-if-true CoversMethod $this */ public function isCoversMethod(): bool { return false; } /** * @phpstan-assert-if-true CoversNothing $this */ public function isCoversNothing(): bool { return false; } /** * @phpstan-assert-if-true DataProvider $this */ public function isDataProvider(): bool { return false; } /** * @phpstan-assert-if-true DependsOnClass $this */ public function isDependsOnClass(): bool { return false; } /** * @phpstan-assert-if-true DependsOnMethod $this */ public function isDependsOnMethod(): bool { return false; } /** * @phpstan-assert-if-true DisableReturnValueGenerationForTestDoubles $this */ public function isDisableReturnValueGenerationForTestDoubles(): bool { return false; } /** * @phpstan-assert-if-true DoesNotPerformAssertions $this */ public function isDoesNotPerformAssertions(): bool { return false; } /** * @phpstan-assert-if-true ExcludeGlobalVariableFromBackup $this */ public function isExcludeGlobalVariableFromBackup(): bool { return false; } /** * @phpstan-assert-if-true ExcludeStaticPropertyFromBackup $this */ public function isExcludeStaticPropertyFromBackup(): bool { return false; } /** * @phpstan-assert-if-true Group $this */ public function isGroup(): bool { return false; } /** * @phpstan-assert-if-true IgnoreDeprecations $this */ public function isIgnoreDeprecations(): bool { return false; } /** * @phpstan-assert-if-true IgnorePhpunitDeprecations $this * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function isIgnorePhpunitDeprecations(): bool { return false; } /** * @phpstan-assert-if-true RunClassInSeparateProcess $this */ public function isRunClassInSeparateProcess(): bool { return false; } /** * @phpstan-assert-if-true RunInSeparateProcess $this */ public function isRunInSeparateProcess(): bool { return false; } /** * @phpstan-assert-if-true RunTestsInSeparateProcesses $this */ public function isRunTestsInSeparateProcesses(): bool { return false; } /** * @phpstan-assert-if-true Test $this */ public function isTest(): bool { return false; } /** * @phpstan-assert-if-true PreCondition $this */ public function isPreCondition(): bool { return false; } /** * @phpstan-assert-if-true PostCondition $this */ public function isPostCondition(): bool { return false; } /** * @phpstan-assert-if-true PreserveGlobalState $this */ public function isPreserveGlobalState(): bool { return false; } /** * @phpstan-assert-if-true RequiresMethod $this */ public function isRequiresMethod(): bool { return false; } /** * @phpstan-assert-if-true RequiresFunction $this */ public function isRequiresFunction(): bool { return false; } /** * @phpstan-assert-if-true RequiresOperatingSystem $this */ public function isRequiresOperatingSystem(): bool { return false; } /** * @phpstan-assert-if-true RequiresOperatingSystemFamily $this */ public function isRequiresOperatingSystemFamily(): bool { return false; } /** * @phpstan-assert-if-true RequiresPhp $this */ public function isRequiresPhp(): bool { return false; } /** * @phpstan-assert-if-true RequiresPhpExtension $this */ public function isRequiresPhpExtension(): bool { return false; } /** * @phpstan-assert-if-true RequiresPhpunit $this */ public function isRequiresPhpunit(): bool { return false; } /** * @phpstan-assert-if-true RequiresSetting $this */ public function isRequiresSetting(): bool { return false; } /** * @phpstan-assert-if-true TestDox $this */ public function isTestDox(): bool { return false; } /** * @phpstan-assert-if-true TestWith $this */ public function isTestWith(): bool { return false; } /** * @phpstan-assert-if-true Uses $this */ public function isUses(): bool { return false; } /** * @phpstan-assert-if-true UsesClass $this */ public function isUsesClass(): bool { return false; } /** * @phpstan-assert-if-true UsesDefaultClass $this */ public function isUsesDefaultClass(): bool { return false; } /** * @phpstan-assert-if-true UsesTrait $this */ public function isUsesTrait(): bool { return false; } /** * @phpstan-assert-if-true UsesFunction $this */ public function isUsesFunction(): bool { return false; } /** * @phpstan-assert-if-true UsesMethod $this */ public function isUsesMethod(): bool { return false; } /** * @phpstan-assert-if-true WithoutErrorHandler $this */ public function isWithoutErrorHandler(): bool { return false; } } phpunit/src/Metadata/RequiresFunction.php 0000644 00000002013 15253321353 0014556 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresFunction extends Metadata { /** * @var non-empty-string */ private string $functionName; /** * @param 0|1 $level * @param non-empty-string $functionName */ protected function __construct(int $level, string $functionName) { parent::__construct($level); $this->functionName = $functionName; } public function isRequiresFunction(): true { return true; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } } phpunit/src/Metadata/CoversFunction.php 0000644 00000002345 15253321353 0014230 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class CoversFunction extends Metadata { /** * @var non-empty-string */ private string $functionName; /** * @param 0|1 $level * @param non-empty-string $functionName */ protected function __construct(int $level, string $functionName) { parent::__construct($level); $this->functionName = $functionName; } public function isCoversFunction(): true { return true; } /** * @return non-empty-string */ public function functionName(): string { return $this->functionName; } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return '::' . $this->functionName; } } phpunit/src/Metadata/BackupGlobals.php 0000644 00000001512 15253321353 0013765 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BackupGlobals extends Metadata { private bool $enabled; /** * @param 0|1 $level */ protected function __construct(int $level, bool $enabled) { parent::__construct($level); $this->enabled = $enabled; } public function isBackupGlobals(): true { return true; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Metadata/RequiresPhpExtension.php 0000644 00000003230 15253321353 0015417 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use PHPUnit\Metadata\Version\Requirement; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresPhpExtension extends Metadata { /** * @var non-empty-string */ private string $extension; private ?Requirement $versionRequirement; /** * @param 0|1 $level * @param non-empty-string $extension */ protected function __construct(int $level, string $extension, ?Requirement $versionRequirement) { parent::__construct($level); $this->extension = $extension; $this->versionRequirement = $versionRequirement; } public function isRequiresPhpExtension(): true { return true; } /** * @return non-empty-string */ public function extension(): string { return $this->extension; } /** * @phpstan-assert-if-true !null $this->versionRequirement */ public function hasVersionRequirement(): bool { return $this->versionRequirement !== null; } /** * @throws NoVersionRequirementException */ public function versionRequirement(): Requirement { if ($this->versionRequirement === null) { throw new NoVersionRequirementException; } return $this->versionRequirement; } } phpunit/src/Metadata/BackupStaticProperties.php 0000644 00000001534 15253321353 0015712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BackupStaticProperties extends Metadata { private bool $enabled; /** * @param 0|1 $level */ protected function __construct(int $level, bool $enabled) { parent::__construct($level); $this->enabled = $enabled; } public function isBackupStaticProperties(): true { return true; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Metadata/BeforeClass.php 0000644 00000001734 15253321353 0013452 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class BeforeClass extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isBeforeClass(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/Parser/AnnotationParser.php 0000644 00000050316 15253321353 0016005 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; use function array_merge; use function assert; use function count; use function explode; use function method_exists; use function preg_replace; use function rtrim; use function sprintf; use function str_contains; use function str_starts_with; use function strlen; use function substr; use function trim; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Metadata\Annotation\Parser\Registry as AnnotationRegistry; use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; use PHPUnit\Metadata\InvalidVersionRequirementException; use PHPUnit\Metadata\Metadata; use PHPUnit\Metadata\MetadataCollection; use PHPUnit\Metadata\ReflectionException; use PHPUnit\Metadata\Version\ComparisonRequirement; use PHPUnit\Metadata\Version\ConstraintRequirement; use PHPUnit\Util\InvalidVersionOperatorException; use PHPUnit\Util\VersionComparisonOperator; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class AnnotationParser implements Parser { /** * @var array<string, true> */ private static array $deprecationEmittedForClass = []; /** * @var array<string, true> */ private static array $deprecationEmittedForMethod = []; /** * @param class-string $className * * @throws AnnotationsAreNotSupportedForInternalClassesException * @throws InvalidVersionOperatorException * @throws ReflectionException */ public function forClass(string $className): MetadataCollection { $result = []; foreach (AnnotationRegistry::getInstance()->forClassName($className)->symbolAnnotations() as $annotation => $values) { switch ($annotation) { case 'backupGlobals': $result[] = Metadata::backupGlobalsOnClass($this->stringToBool($values[0])); break; case 'backupStaticAttributes': case 'backupStaticProperties': $result[] = Metadata::backupStaticPropertiesOnClass($this->stringToBool($values[0])); break; case 'covers': foreach ($values as $value) { $value = $this->cleanUpCoversOrUsesTarget($value); $result[] = Metadata::coversOnClass($value); } break; case 'coversDefaultClass': foreach ($values as $value) { $result[] = Metadata::coversDefaultClass($value); } break; case 'coversNothing': $result[] = Metadata::coversNothingOnClass(); break; case 'doesNotPerformAssertions': $result[] = Metadata::doesNotPerformAssertionsOnClass(); break; case 'group': case 'ticket': foreach ($values as $value) { $result[] = Metadata::groupOnClass($value); } break; case 'large': $result[] = Metadata::groupOnClass('large'); break; case 'medium': $result[] = Metadata::groupOnClass('medium'); break; case 'preserveGlobalState': $result[] = Metadata::preserveGlobalStateOnClass($this->stringToBool($values[0])); break; case 'runClassInSeparateProcess': $result[] = Metadata::runClassInSeparateProcess(); break; case 'runTestsInSeparateProcesses': $result[] = Metadata::runTestsInSeparateProcesses(); break; case 'small': $result[] = Metadata::groupOnClass('small'); break; case 'testdox': $result[] = Metadata::testDoxOnClass($values[0]); break; case 'uses': foreach ($values as $value) { $value = $this->cleanUpCoversOrUsesTarget($value); $result[] = Metadata::usesOnClass($value); } break; case 'usesDefaultClass': foreach ($values as $value) { $result[] = Metadata::usesDefaultClass($value); } break; } } try { $result = array_merge( $result, $this->parseRequirements( AnnotationRegistry::getInstance()->forClassName($className)->requirements(), 'class', ), ); } catch (InvalidVersionRequirementException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Class %s is annotated using an invalid version requirement: %s', $className, $e->getMessage(), ), ); } if (!empty($result) && !isset(self::$deprecationEmittedForClass[$className]) && !str_starts_with($className, 'PHPUnit\TestFixture')) { EventFacade::emitter()->testRunnerTriggeredDeprecation( sprintf( 'Metadata found in doc-comment for class %s. Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12. Update your test code to use attributes instead.', $className, ), ); self::$deprecationEmittedForClass[$className] = true; } return MetadataCollection::fromArray($result); } /** * @param class-string $className * @param non-empty-string $methodName * * @throws AnnotationsAreNotSupportedForInternalClassesException * @throws InvalidVersionOperatorException * @throws ReflectionException */ public function forMethod(string $className, string $methodName): MetadataCollection { $result = []; foreach (AnnotationRegistry::getInstance()->forMethod($className, $methodName)->symbolAnnotations() as $annotation => $values) { switch ($annotation) { case 'after': $result[] = Metadata::after(0); break; case 'afterClass': $result[] = Metadata::afterClass(0); break; case 'backupGlobals': $result[] = Metadata::backupGlobalsOnMethod($this->stringToBool($values[0])); break; case 'backupStaticAttributes': case 'backupStaticProperties': $result[] = Metadata::backupStaticPropertiesOnMethod($this->stringToBool($values[0])); break; case 'before': $result[] = Metadata::before(0); break; case 'beforeClass': $result[] = Metadata::beforeClass(0); break; case 'covers': foreach ($values as $value) { $value = $this->cleanUpCoversOrUsesTarget($value); $result[] = Metadata::coversOnMethod($value); } break; case 'coversNothing': $result[] = Metadata::coversNothingOnMethod(); break; case 'dataProvider': foreach ($values as $value) { $value = rtrim($value, " ()\n\r\t\v\x00"); if (str_contains($value, '::')) { $result[] = Metadata::dataProvider(...explode('::', $value)); continue; } $result[] = Metadata::dataProvider($className, $value); } break; case 'depends': foreach ($values as $value) { $deepClone = false; $shallowClone = false; if (str_starts_with($value, 'clone ')) { $deepClone = true; $value = substr($value, strlen('clone ')); } elseif (str_starts_with($value, '!clone ')) { $value = substr($value, strlen('!clone ')); } elseif (str_starts_with($value, 'shallowClone ')) { $shallowClone = true; $value = substr($value, strlen('shallowClone ')); } elseif (str_starts_with($value, '!shallowClone ')) { $value = substr($value, strlen('!shallowClone ')); } if (str_contains($value, '::')) { [$_className, $_methodName] = explode('::', $value); assert($_className !== ''); assert($_methodName !== ''); if ($_methodName === 'class') { $result[] = Metadata::dependsOnClass($_className, $deepClone, $shallowClone); continue; } $result[] = Metadata::dependsOnMethod($_className, $_methodName, $deepClone, $shallowClone); continue; } $result[] = Metadata::dependsOnMethod($className, $value, $deepClone, $shallowClone); } break; case 'doesNotPerformAssertions': $result[] = Metadata::doesNotPerformAssertionsOnMethod(); break; case 'excludeGlobalVariableFromBackup': foreach ($values as $value) { $result[] = Metadata::excludeGlobalVariableFromBackupOnMethod($value); } break; case 'excludeStaticPropertyFromBackup': foreach ($values as $value) { $tmp = explode(' ', $value); if (count($tmp) !== 2) { continue; } $result[] = Metadata::excludeStaticPropertyFromBackupOnMethod( trim($tmp[0]), trim($tmp[1]), ); } break; case 'group': case 'ticket': foreach ($values as $value) { $result[] = Metadata::groupOnMethod($value); } break; case 'large': $result[] = Metadata::groupOnMethod('large'); break; case 'medium': $result[] = Metadata::groupOnMethod('medium'); break; case 'postCondition': $result[] = Metadata::postCondition(0); break; case 'preCondition': $result[] = Metadata::preCondition(0); break; case 'preserveGlobalState': $result[] = Metadata::preserveGlobalStateOnMethod($this->stringToBool($values[0])); break; case 'runInSeparateProcess': $result[] = Metadata::runInSeparateProcess(); break; case 'small': $result[] = Metadata::groupOnMethod('small'); break; case 'test': $result[] = Metadata::test(); break; case 'testdox': $result[] = Metadata::testDoxOnMethod($values[0]); break; case 'uses': foreach ($values as $value) { $value = $this->cleanUpCoversOrUsesTarget($value); $result[] = Metadata::usesOnMethod($value); } break; } } if (method_exists($className, $methodName)) { try { $result = array_merge( $result, $this->parseRequirements( AnnotationRegistry::getInstance()->forMethod($className, $methodName)->requirements(), 'method', ), ); } catch (InvalidVersionRequirementException $e) { EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Method %s::%s is annotated using an invalid version requirement: %s', $className, $methodName, $e->getMessage(), ), ); } } if (!empty($result) && !isset(self::$deprecationEmittedForMethod[$className . '::' . $methodName]) && !str_starts_with($className, 'PHPUnit\TestFixture')) { EventFacade::emitter()->testRunnerTriggeredDeprecation( sprintf( 'Metadata found in doc-comment for method %s::%s(). Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12. Update your test code to use attributes instead.', $className, $methodName, ), ); self::$deprecationEmittedForMethod[$className . '::' . $methodName] = true; } return MetadataCollection::fromArray($result); } /** * @param class-string $className * @param non-empty-string $methodName * * @throws AnnotationsAreNotSupportedForInternalClassesException * @throws InvalidVersionOperatorException * @throws ReflectionException */ public function forClassAndMethod(string $className, string $methodName): MetadataCollection { return $this->forClass($className)->mergeWith( $this->forMethod($className, $methodName), ); } private function stringToBool(string $value): bool { if ($value === 'enabled') { return true; } return false; } private function cleanUpCoversOrUsesTarget(string $value): string { $value = preg_replace('/[\s()]+$/', '', $value); return explode(' ', $value, 2)[0]; } /** * @throws InvalidVersionOperatorException * * @return list<Metadata> * * @phpstan-ignore missingType.iterableValue */ private function parseRequirements(array $requirements, string $level): array { $result = []; if (!empty($requirements['PHP'])) { $versionRequirement = new ComparisonRequirement( $requirements['PHP']['version'], new VersionComparisonOperator(empty($requirements['PHP']['operator']) ? '>=' : $requirements['PHP']['operator']), ); if ($level === 'class') { $result[] = Metadata::requiresPhpOnClass($versionRequirement); } else { $result[] = Metadata::requiresPhpOnMethod($versionRequirement); } } elseif (!empty($requirements['PHP_constraint'])) { $versionRequirement = new ConstraintRequirement($requirements['PHP_constraint']['constraint']); if ($level === 'class') { $result[] = Metadata::requiresPhpOnClass($versionRequirement); } else { $result[] = Metadata::requiresPhpOnMethod($versionRequirement); } } if (!empty($requirements['extensions'])) { foreach ($requirements['extensions'] as $extension) { if (isset($requirements['extension_versions'][$extension])) { continue; } if ($level === 'class') { $result[] = Metadata::requiresPhpExtensionOnClass($extension, null); } else { $result[] = Metadata::requiresPhpExtensionOnMethod($extension, null); } } } if (!empty($requirements['extension_versions'])) { foreach ($requirements['extension_versions'] as $extension => $version) { $versionRequirement = new ComparisonRequirement( $version['version'], new VersionComparisonOperator(empty($version['operator']) ? '>=' : $version['operator']), ); if ($level === 'class') { $result[] = Metadata::requiresPhpExtensionOnClass($extension, $versionRequirement); } else { $result[] = Metadata::requiresPhpExtensionOnMethod($extension, $versionRequirement); } } } if (!empty($requirements['PHPUnit'])) { $versionRequirement = new ComparisonRequirement( $requirements['PHPUnit']['version'], new VersionComparisonOperator(empty($requirements['PHPUnit']['operator']) ? '>=' : $requirements['PHPUnit']['operator']), ); if ($level === 'class') { $result[] = Metadata::requiresPhpunitOnClass($versionRequirement); } else { $result[] = Metadata::requiresPhpunitOnMethod($versionRequirement); } } elseif (!empty($requirements['PHPUnit_constraint'])) { $versionRequirement = new ConstraintRequirement($requirements['PHPUnit_constraint']['constraint']); if ($level === 'class') { $result[] = Metadata::requiresPhpunitOnClass($versionRequirement); } else { $result[] = Metadata::requiresPhpunitOnMethod($versionRequirement); } } if (!empty($requirements['OSFAMILY'])) { if ($level === 'class') { $result[] = Metadata::requiresOperatingSystemFamilyOnClass($requirements['OSFAMILY']); } else { $result[] = Metadata::requiresOperatingSystemFamilyOnMethod($requirements['OSFAMILY']); } } if (!empty($requirements['OS'])) { if ($level === 'class') { $result[] = Metadata::requiresOperatingSystemOnClass($requirements['OS']); } else { $result[] = Metadata::requiresOperatingSystemOnMethod($requirements['OS']); } } if (!empty($requirements['functions'])) { foreach ($requirements['functions'] as $function) { $pieces = explode('::', $function); if (count($pieces) === 2) { if ($level === 'class') { $result[] = Metadata::requiresMethodOnClass($pieces[0], $pieces[1]); } else { $result[] = Metadata::requiresMethodOnMethod($pieces[0], $pieces[1]); } } elseif ($level === 'class') { $result[] = Metadata::requiresFunctionOnClass($function); } else { $result[] = Metadata::requiresFunctionOnMethod($function); } } } if (!empty($requirements['setting'])) { foreach ($requirements['setting'] as $setting => $value) { if ($level === 'class') { $result[] = Metadata::requiresSettingOnClass($setting, $value); } else { $result[] = Metadata::requiresSettingOnMethod($setting, $value); } } } return $result; } } phpunit/src/Metadata/Parser/Annotation/DocBlock.php 0000644 00000023455 15253321353 0016314 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Annotation\Parser; use function array_filter; use function array_map; use function array_merge; use function array_values; use function count; use function preg_match; use function preg_match_all; use function preg_replace; use function preg_split; use function realpath; use function substr; use function trim; use PharIo\Version\Exception as PharIoVersionException; use PharIo\Version\VersionConstraintParser; use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; use PHPUnit\Metadata\InvalidVersionRequirementException; use ReflectionClass; use ReflectionFunctionAbstract; use ReflectionMethod; /** * This is an abstraction around a PHPUnit-specific docBlock, * allowing us to ask meaningful questions about a specific * reflection symbol. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class DocBlock { private const REGEX_REQUIRES_VERSION = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t \-.|~^]+)[ \t]*\r?$/m'; private const REGEX_REQUIRES_OS = '/@requires\s+(?P<name>OS(?:FAMILY)?)\s+(?P<value>.+?)[ \t]*\r?$/m'; private const REGEX_REQUIRES_SETTING = '/@requires\s+(?P<name>setting)\s+(?P<setting>([^ ]+?))\s*(?P<value>[\w\.-]+[\w\.]?)?[ \t]*\r?$/m'; private const REGEX_REQUIRES = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^\s<>=!]+))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m'; private readonly string $docComment; /** * @var array<string, array<int, string>> pre-parsed annotations indexed by name and occurrence index */ private readonly array $symbolAnnotations; /** * @psalm-var null|(array{ * __OFFSET: array<string, int>&array{__FILE: string}, * setting?: array<string, string>, * extension_versions?: array<string, array{version: string, operator: string}> * }&array< * string, * string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string> * >) * * @phpstan-ignore missingType.iterableValue */ private ?array $parsedRequirements = null; private readonly int $startLine; private readonly string $fileName; /** * @throws AnnotationsAreNotSupportedForInternalClassesException * * @phpstan-ignore missingType.generics */ public static function ofClass(ReflectionClass $class): self { if ($class->isInternal()) { throw new AnnotationsAreNotSupportedForInternalClassesException($class->getName()); } return new self( (string) $class->getDocComment(), self::extractAnnotationsFromReflector($class), $class->getStartLine(), $class->getFileName(), ); } /** * @throws AnnotationsAreNotSupportedForInternalClassesException */ public static function ofMethod(ReflectionMethod $method): self { if ($method->getDeclaringClass()->isInternal()) { throw new AnnotationsAreNotSupportedForInternalClassesException($method->getDeclaringClass()->getName()); } return new self( (string) $method->getDocComment(), self::extractAnnotationsFromReflector($method), $method->getStartLine(), $method->getFileName(), ); } /** * Note: we do not preserve an instance of the reflection object, since it cannot be safely (de-)serialized. * * @param array<string, array<int, string>> $symbolAnnotations */ private function __construct(string $docComment, array $symbolAnnotations, int $startLine, string $fileName) { $this->docComment = $docComment; $this->symbolAnnotations = $symbolAnnotations; $this->startLine = $startLine; $this->fileName = $fileName; } /** * @psalm-return array{ * __OFFSET: array<string, int>&array{__FILE: string}, * setting?: array<string, string>, * extension_versions?: array<string, array{version: string, operator: string}> * }&array< * string, * string|array{version: string, operator: string}|array{constraint: string}|array<int|string, string> * > * * @phpstan-ignore missingType.iterableValue */ public function requirements(): array { if ($this->parsedRequirements !== null) { return $this->parsedRequirements; } $offset = $this->startLine; $requires = []; $recordedSettings = []; $extensionVersions = []; $recordedOffsets = [ '__FILE' => realpath($this->fileName), ]; // Trim docblock markers, split it into lines and rewind offset to start of docblock $lines = preg_replace(['#^/\*{2}#', '#\*/$#'], '', preg_split('/\r\n|\r|\n/', $this->docComment)); $offset -= count($lines); foreach ($lines as $line) { if (preg_match(self::REGEX_REQUIRES_OS, $line, $matches)) { $requires[$matches['name']] = $matches['value']; $recordedOffsets[$matches['name']] = $offset; } if (preg_match(self::REGEX_REQUIRES_VERSION, $line, $matches)) { $requires[$matches['name']] = [ 'version' => $matches['version'], 'operator' => $matches['operator'], ]; $recordedOffsets[$matches['name']] = $offset; } if (preg_match(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $line, $matches)) { if (!empty($requires[$matches['name']])) { $offset++; continue; } try { $versionConstraintParser = new VersionConstraintParser; $requires[$matches['name'] . '_constraint'] = [ 'constraint' => $versionConstraintParser->parse(trim($matches['constraint'])), ]; $recordedOffsets[$matches['name'] . '_constraint'] = $offset; } catch (PharIoVersionException $e) { throw new InvalidVersionRequirementException( $e->getMessage(), $e->getCode(), $e, ); } } if (preg_match(self::REGEX_REQUIRES_SETTING, $line, $matches)) { $recordedSettings[$matches['setting']] = $matches['value']; $recordedOffsets['__SETTING_' . $matches['setting']] = $offset; } if (preg_match(self::REGEX_REQUIRES, $line, $matches)) { $name = $matches['name'] . 's'; if (!isset($requires[$name])) { $requires[$name] = []; } $requires[$name][] = $matches['value']; $recordedOffsets[$matches['name'] . '_' . $matches['value']] = $offset; if ($name === 'extensions' && !empty($matches['version'])) { $extensionVersions[$matches['value']] = [ 'version' => $matches['version'], 'operator' => $matches['operator'], ]; } } $offset++; } return $this->parsedRequirements = array_merge( $requires, ['__OFFSET' => $recordedOffsets], array_filter( [ 'setting' => $recordedSettings, 'extension_versions' => $extensionVersions, ], ), ); } /** * @return array<string, array<int, string>> */ public function symbolAnnotations(): array { return $this->symbolAnnotations; } /** * @return array<string, array<int, string>> */ private static function parseDocBlock(string $docBlock): array { // Strip away the docblock header and footer to ease parsing of one line annotations $docBlock = substr($docBlock, 3, -2); $annotations = []; if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docBlock, $matches)) { $numMatches = count($matches[0]); for ($i = 0; $i < $numMatches; $i++) { $annotations[$matches['name'][$i]][] = $matches['value'][$i]; } } return $annotations; } /** * @phpstan-ignore missingType.iterableValue, missingType.generics */ private static function extractAnnotationsFromReflector(ReflectionClass|ReflectionFunctionAbstract $reflector): array { $annotations = []; if ($reflector instanceof ReflectionClass) { $annotations = array_merge( $annotations, ...array_map( static fn (ReflectionClass $trait): array => self::parseDocBlock((string) $trait->getDocComment()), array_values($reflector->getTraits()), ), ); } return array_merge( $annotations, self::parseDocBlock((string) $reflector->getDocComment()), ); } } phpunit/src/Metadata/Parser/Annotation/Registry.php 0000644 00000005730 15253321353 0016440 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Annotation\Parser; use function array_key_exists; use PHPUnit\Metadata\AnnotationsAreNotSupportedForInternalClassesException; use PHPUnit\Metadata\ReflectionException; use ReflectionClass; use ReflectionMethod; /** * Reflection information, and therefore DocBlock information, is static within * a single PHP process. It is therefore okay to use a Singleton registry here. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Registry { private static ?Registry $instance = null; /** * @var array<string, DocBlock> indexed by class name */ private array $classDocBlocks = []; /** * @var array<string, array<string, DocBlock>> indexed by class name and method name */ private array $methodDocBlocks = []; public static function getInstance(): self { return self::$instance ?? self::$instance = new self; } /** * @param class-string $class * * @throws AnnotationsAreNotSupportedForInternalClassesException * @throws ReflectionException */ public function forClassName(string $class): DocBlock { if (array_key_exists($class, $this->classDocBlocks)) { return $this->classDocBlocks[$class]; } try { $reflection = new ReflectionClass($class); // @codeCoverageIgnoreStart /** @phpstan-ignore catch.neverThrown */ } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd return $this->classDocBlocks[$class] = DocBlock::ofClass($reflection); } /** * @param class-string $classInHierarchy * * @throws AnnotationsAreNotSupportedForInternalClassesException * @throws ReflectionException */ public function forMethod(string $classInHierarchy, string $method): DocBlock { if (isset($this->methodDocBlocks[$classInHierarchy][$method])) { return $this->methodDocBlocks[$classInHierarchy][$method]; } try { $reflection = new ReflectionMethod($classInHierarchy, $method); // @codeCoverageIgnoreStart } catch (\ReflectionException $e) { throw new ReflectionException( $e->getMessage(), $e->getCode(), $e, ); } // @codeCoverageIgnoreEnd return $this->methodDocBlocks[$classInHierarchy][$method] = DocBlock::ofMethod($reflection); } } phpunit/src/Metadata/Parser/Registry.php 0000644 00000002031 15253321353 0014315 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; /** * Attribute and annotation information is static within a single PHP process. * It is therefore okay to use a Singleton registry here. * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Registry { private static ?Parser $instance = null; public static function parser(): Parser { return self::$instance ?? self::$instance = self::build(); } private static function build(): Parser { return new CachingParser( new ParserChain( new AttributeParser, new AnnotationParser, ), ); } } phpunit/src/Metadata/Parser/AttributeParser.php 0000644 00000064266 15253321353 0015647 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; use const JSON_THROW_ON_ERROR; use function assert; use function json_decode; use function sprintf; use function str_starts_with; use function strtolower; use function trim; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\Attributes\After; use PHPUnit\Framework\Attributes\AfterClass; use PHPUnit\Framework\Attributes\BackupGlobals; use PHPUnit\Framework\Attributes\BackupStaticProperties; use PHPUnit\Framework\Attributes\Before; use PHPUnit\Framework\Attributes\BeforeClass; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\CoversFunction; use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\Attributes\CoversNothing; use PHPUnit\Framework\Attributes\CoversTrait; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProviderExternal; use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\Attributes\DependsExternal; use PHPUnit\Framework\Attributes\DependsExternalUsingDeepClone; use PHPUnit\Framework\Attributes\DependsExternalUsingShallowClone; use PHPUnit\Framework\Attributes\DependsOnClass; use PHPUnit\Framework\Attributes\DependsOnClassUsingDeepClone; use PHPUnit\Framework\Attributes\DependsOnClassUsingShallowClone; use PHPUnit\Framework\Attributes\DependsUsingDeepClone; use PHPUnit\Framework\Attributes\DependsUsingShallowClone; use PHPUnit\Framework\Attributes\DisableReturnValueGenerationForTestDoubles; use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use PHPUnit\Framework\Attributes\ExcludeGlobalVariableFromBackup; use PHPUnit\Framework\Attributes\ExcludeStaticPropertyFromBackup; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\IgnoreDeprecations; use PHPUnit\Framework\Attributes\IgnorePhpunitDeprecations; use PHPUnit\Framework\Attributes\Large; use PHPUnit\Framework\Attributes\Medium; use PHPUnit\Framework\Attributes\PostCondition; use PHPUnit\Framework\Attributes\PreCondition; use PHPUnit\Framework\Attributes\PreserveGlobalState; use PHPUnit\Framework\Attributes\RequiresFunction; use PHPUnit\Framework\Attributes\RequiresMethod; use PHPUnit\Framework\Attributes\RequiresOperatingSystem; use PHPUnit\Framework\Attributes\RequiresOperatingSystemFamily; use PHPUnit\Framework\Attributes\RequiresPhp; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\Attributes\RequiresPhpunit; use PHPUnit\Framework\Attributes\RequiresSetting; use PHPUnit\Framework\Attributes\RunClassInSeparateProcess; use PHPUnit\Framework\Attributes\RunInSeparateProcess; use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses; use PHPUnit\Framework\Attributes\Small; use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\Attributes\TestWithJson; use PHPUnit\Framework\Attributes\Ticket; use PHPUnit\Framework\Attributes\UsesClass; use PHPUnit\Framework\Attributes\UsesFunction; use PHPUnit\Framework\Attributes\UsesMethod; use PHPUnit\Framework\Attributes\UsesTrait; use PHPUnit\Framework\Attributes\WithoutErrorHandler; use PHPUnit\Metadata\Metadata; use PHPUnit\Metadata\MetadataCollection; use PHPUnit\Metadata\Version\ConstraintRequirement; use ReflectionClass; use ReflectionMethod; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class AttributeParser implements Parser { /** * @param class-string $className */ public function forClass(string $className): MetadataCollection { $result = []; foreach ((new ReflectionClass($className))->getAttributes() as $attribute) { if (!str_starts_with($attribute->getName(), 'PHPUnit\\Framework\\Attributes\\')) { continue; } $attributeInstance = $attribute->newInstance(); switch ($attribute->getName()) { case BackupGlobals::class: assert($attributeInstance instanceof BackupGlobals); $result[] = Metadata::backupGlobalsOnClass($attributeInstance->enabled()); break; case BackupStaticProperties::class: assert($attributeInstance instanceof BackupStaticProperties); $result[] = Metadata::backupStaticPropertiesOnClass($attributeInstance->enabled()); break; case CoversClass::class: assert($attributeInstance instanceof CoversClass); $result[] = Metadata::coversClass($attributeInstance->className()); break; case CoversTrait::class: assert($attributeInstance instanceof CoversTrait); $result[] = Metadata::coversTrait($attributeInstance->traitName()); break; case CoversFunction::class: assert($attributeInstance instanceof CoversFunction); $result[] = Metadata::coversFunction($attributeInstance->functionName()); break; case CoversMethod::class: assert($attributeInstance instanceof CoversMethod); $result[] = Metadata::coversMethod( $attributeInstance->className(), $attributeInstance->methodName(), ); break; case CoversNothing::class: $result[] = Metadata::coversNothingOnClass(); break; case DisableReturnValueGenerationForTestDoubles::class: $result[] = Metadata::disableReturnValueGenerationForTestDoubles(); break; case DoesNotPerformAssertions::class: $result[] = Metadata::doesNotPerformAssertionsOnClass(); break; case ExcludeGlobalVariableFromBackup::class: assert($attributeInstance instanceof ExcludeGlobalVariableFromBackup); $result[] = Metadata::excludeGlobalVariableFromBackupOnClass($attributeInstance->globalVariableName()); break; case ExcludeStaticPropertyFromBackup::class: assert($attributeInstance instanceof ExcludeStaticPropertyFromBackup); $result[] = Metadata::excludeStaticPropertyFromBackupOnClass( $attributeInstance->className(), $attributeInstance->propertyName(), ); break; case Group::class: assert($attributeInstance instanceof Group); if (!$this->isSizeGroup($attributeInstance->name(), $className)) { $result[] = Metadata::groupOnClass($attributeInstance->name()); } break; case Large::class: $result[] = Metadata::groupOnClass('large'); break; case Medium::class: $result[] = Metadata::groupOnClass('medium'); break; case IgnoreDeprecations::class: assert($attributeInstance instanceof IgnoreDeprecations); $result[] = Metadata::ignoreDeprecationsOnClass(); break; case IgnorePhpunitDeprecations::class: assert($attributeInstance instanceof IgnorePhpunitDeprecations); $result[] = Metadata::ignorePhpunitDeprecationsOnClass(); break; case PreserveGlobalState::class: assert($attributeInstance instanceof PreserveGlobalState); $result[] = Metadata::preserveGlobalStateOnClass($attributeInstance->enabled()); break; case RequiresMethod::class: assert($attributeInstance instanceof RequiresMethod); $result[] = Metadata::requiresMethodOnClass( $attributeInstance->className(), $attributeInstance->methodName(), ); break; case RequiresFunction::class: assert($attributeInstance instanceof RequiresFunction); $result[] = Metadata::requiresFunctionOnClass($attributeInstance->functionName()); break; case RequiresOperatingSystem::class: assert($attributeInstance instanceof RequiresOperatingSystem); $result[] = Metadata::requiresOperatingSystemOnClass($attributeInstance->regularExpression()); break; case RequiresOperatingSystemFamily::class: assert($attributeInstance instanceof RequiresOperatingSystemFamily); $result[] = Metadata::requiresOperatingSystemFamilyOnClass($attributeInstance->operatingSystemFamily()); break; case RequiresPhp::class: assert($attributeInstance instanceof RequiresPhp); $result[] = Metadata::requiresPhpOnClass( ConstraintRequirement::from( $attributeInstance->versionRequirement(), ), ); break; case RequiresPhpExtension::class: assert($attributeInstance instanceof RequiresPhpExtension); $versionConstraint = null; $versionRequirement = $attributeInstance->versionRequirement(); if ($versionRequirement !== null) { $versionConstraint = ConstraintRequirement::from($versionRequirement); } $result[] = Metadata::requiresPhpExtensionOnClass( $attributeInstance->extension(), $versionConstraint, ); break; case RequiresPhpunit::class: assert($attributeInstance instanceof RequiresPhpunit); $result[] = Metadata::requiresPhpunitOnClass( ConstraintRequirement::from( $attributeInstance->versionRequirement(), ), ); break; case RequiresSetting::class: assert($attributeInstance instanceof RequiresSetting); $result[] = Metadata::requiresSettingOnClass( $attributeInstance->setting(), $attributeInstance->value(), ); break; case RunClassInSeparateProcess::class: $result[] = Metadata::runClassInSeparateProcess(); break; case RunTestsInSeparateProcesses::class: $result[] = Metadata::runTestsInSeparateProcesses(); break; case Small::class: $result[] = Metadata::groupOnClass('small'); break; case TestDox::class: assert($attributeInstance instanceof TestDox); $result[] = Metadata::testDoxOnClass($attributeInstance->text()); break; case Ticket::class: assert($attributeInstance instanceof Ticket); $result[] = Metadata::groupOnClass($attributeInstance->text()); break; case UsesClass::class: assert($attributeInstance instanceof UsesClass); $result[] = Metadata::usesClass($attributeInstance->className()); break; case UsesTrait::class: assert($attributeInstance instanceof UsesTrait); $result[] = Metadata::usesTrait($attributeInstance->traitName()); break; case UsesFunction::class: assert($attributeInstance instanceof UsesFunction); $result[] = Metadata::usesFunction($attributeInstance->functionName()); break; case UsesMethod::class: assert($attributeInstance instanceof UsesMethod); $result[] = Metadata::usesMethod( $attributeInstance->className(), $attributeInstance->methodName(), ); break; } } return MetadataCollection::fromArray($result); } /** * @param class-string $className * @param non-empty-string $methodName */ public function forMethod(string $className, string $methodName): MetadataCollection { $result = []; foreach ((new ReflectionMethod($className, $methodName))->getAttributes() as $attribute) { if (!str_starts_with($attribute->getName(), 'PHPUnit\\Framework\\Attributes\\')) { continue; } $attributeInstance = $attribute->newInstance(); switch ($attribute->getName()) { case After::class: assert($attributeInstance instanceof After); $result[] = Metadata::after($attributeInstance->priority()); break; case AfterClass::class: assert($attributeInstance instanceof AfterClass); $result[] = Metadata::afterClass($attributeInstance->priority()); break; case BackupGlobals::class: assert($attributeInstance instanceof BackupGlobals); $result[] = Metadata::backupGlobalsOnMethod($attributeInstance->enabled()); break; case BackupStaticProperties::class: assert($attributeInstance instanceof BackupStaticProperties); $result[] = Metadata::backupStaticPropertiesOnMethod($attributeInstance->enabled()); break; case Before::class: assert($attributeInstance instanceof Before); $result[] = Metadata::before($attributeInstance->priority()); break; case BeforeClass::class: assert($attributeInstance instanceof BeforeClass); $result[] = Metadata::beforeClass($attributeInstance->priority()); break; case CoversNothing::class: $result[] = Metadata::coversNothingOnMethod(); break; case DataProvider::class: assert($attributeInstance instanceof DataProvider); $result[] = Metadata::dataProvider($className, $attributeInstance->methodName()); break; case DataProviderExternal::class: assert($attributeInstance instanceof DataProviderExternal); $result[] = Metadata::dataProvider($attributeInstance->className(), $attributeInstance->methodName()); break; case Depends::class: assert($attributeInstance instanceof Depends); $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), false, false); break; case DependsUsingDeepClone::class: assert($attributeInstance instanceof DependsUsingDeepClone); $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), true, false); break; case DependsUsingShallowClone::class: assert($attributeInstance instanceof DependsUsingShallowClone); $result[] = Metadata::dependsOnMethod($className, $attributeInstance->methodName(), false, true); break; case DependsExternal::class: assert($attributeInstance instanceof DependsExternal); $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), false, false); break; case DependsExternalUsingDeepClone::class: assert($attributeInstance instanceof DependsExternalUsingDeepClone); $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), true, false); break; case DependsExternalUsingShallowClone::class: assert($attributeInstance instanceof DependsExternalUsingShallowClone); $result[] = Metadata::dependsOnMethod($attributeInstance->className(), $attributeInstance->methodName(), false, true); break; case DependsOnClass::class: assert($attributeInstance instanceof DependsOnClass); $result[] = Metadata::dependsOnClass($attributeInstance->className(), false, false); break; case DependsOnClassUsingDeepClone::class: assert($attributeInstance instanceof DependsOnClassUsingDeepClone); $result[] = Metadata::dependsOnClass($attributeInstance->className(), true, false); break; case DependsOnClassUsingShallowClone::class: assert($attributeInstance instanceof DependsOnClassUsingShallowClone); $result[] = Metadata::dependsOnClass($attributeInstance->className(), false, true); break; case DoesNotPerformAssertions::class: assert($attributeInstance instanceof DoesNotPerformAssertions); $result[] = Metadata::doesNotPerformAssertionsOnMethod(); break; case ExcludeGlobalVariableFromBackup::class: assert($attributeInstance instanceof ExcludeGlobalVariableFromBackup); $result[] = Metadata::excludeGlobalVariableFromBackupOnMethod($attributeInstance->globalVariableName()); break; case ExcludeStaticPropertyFromBackup::class: assert($attributeInstance instanceof ExcludeStaticPropertyFromBackup); $result[] = Metadata::excludeStaticPropertyFromBackupOnMethod( $attributeInstance->className(), $attributeInstance->propertyName(), ); break; case Group::class: assert($attributeInstance instanceof Group); if (!$this->isSizeGroup($attributeInstance->name(), $className, $methodName)) { $result[] = Metadata::groupOnMethod($attributeInstance->name()); } break; case IgnoreDeprecations::class: assert($attributeInstance instanceof IgnoreDeprecations); $result[] = Metadata::ignoreDeprecationsOnMethod(); break; case IgnorePhpunitDeprecations::class: assert($attributeInstance instanceof IgnorePhpunitDeprecations); $result[] = Metadata::ignorePhpunitDeprecationsOnMethod(); break; case PostCondition::class: assert($attributeInstance instanceof PostCondition); $result[] = Metadata::postCondition($attributeInstance->priority()); break; case PreCondition::class: assert($attributeInstance instanceof PreCondition); $result[] = Metadata::preCondition($attributeInstance->priority()); break; case PreserveGlobalState::class: assert($attributeInstance instanceof PreserveGlobalState); $result[] = Metadata::preserveGlobalStateOnMethod($attributeInstance->enabled()); break; case RequiresMethod::class: assert($attributeInstance instanceof RequiresMethod); $result[] = Metadata::requiresMethodOnMethod( $attributeInstance->className(), $attributeInstance->methodName(), ); break; case RequiresFunction::class: assert($attributeInstance instanceof RequiresFunction); $result[] = Metadata::requiresFunctionOnMethod($attributeInstance->functionName()); break; case RequiresOperatingSystem::class: assert($attributeInstance instanceof RequiresOperatingSystem); $result[] = Metadata::requiresOperatingSystemOnMethod($attributeInstance->regularExpression()); break; case RequiresOperatingSystemFamily::class: assert($attributeInstance instanceof RequiresOperatingSystemFamily); $result[] = Metadata::requiresOperatingSystemFamilyOnMethod($attributeInstance->operatingSystemFamily()); break; case RequiresPhp::class: assert($attributeInstance instanceof RequiresPhp); $result[] = Metadata::requiresPhpOnMethod( ConstraintRequirement::from( $attributeInstance->versionRequirement(), ), ); break; case RequiresPhpExtension::class: assert($attributeInstance instanceof RequiresPhpExtension); $versionConstraint = null; $versionRequirement = $attributeInstance->versionRequirement(); if ($versionRequirement !== null) { $versionConstraint = ConstraintRequirement::from($versionRequirement); } $result[] = Metadata::requiresPhpExtensionOnMethod( $attributeInstance->extension(), $versionConstraint, ); break; case RequiresPhpunit::class: assert($attributeInstance instanceof RequiresPhpunit); $result[] = Metadata::requiresPhpunitOnMethod( ConstraintRequirement::from( $attributeInstance->versionRequirement(), ), ); break; case RequiresSetting::class: assert($attributeInstance instanceof RequiresSetting); $result[] = Metadata::requiresSettingOnMethod( $attributeInstance->setting(), $attributeInstance->value(), ); break; case RunInSeparateProcess::class: $result[] = Metadata::runInSeparateProcess(); break; case Test::class: $result[] = Metadata::test(); break; case TestDox::class: assert($attributeInstance instanceof TestDox); $result[] = Metadata::testDoxOnMethod($attributeInstance->text()); break; case TestWith::class: assert($attributeInstance instanceof TestWith); $result[] = Metadata::testWith($attributeInstance->data(), $attributeInstance->name()); break; case TestWithJson::class: assert($attributeInstance instanceof TestWithJson); $result[] = Metadata::testWith( json_decode($attributeInstance->json(), true, 512, JSON_THROW_ON_ERROR), $attributeInstance->name(), ); break; case Ticket::class: assert($attributeInstance instanceof Ticket); $result[] = Metadata::groupOnMethod($attributeInstance->text()); break; case WithoutErrorHandler::class: assert($attributeInstance instanceof WithoutErrorHandler); $result[] = Metadata::withoutErrorHandler(); break; } } return MetadataCollection::fromArray($result); } /** * @param class-string $className * @param non-empty-string $methodName */ public function forClassAndMethod(string $className, string $methodName): MetadataCollection { return $this->forClass($className)->mergeWith( $this->forMethod($className, $methodName), ); } /** * @param non-empty-string $groupName * @param class-string $testClassName * @param ?non-empty-string $testMethodName */ private function isSizeGroup(string $groupName, string $testClassName, ?string $testMethodName = null): bool { $_groupName = strtolower(trim($groupName)); if ($_groupName !== 'small' && $_groupName !== 'medium' && $_groupName !== 'large') { return false; } EventFacade::emitter()->testRunnerTriggeredWarning( sprintf( 'Group name "%s" is not allowed for %s %s%s%s', $_groupName, $testMethodName !== null ? 'method' : 'class', $testClassName, $testMethodName !== null ? '::' : '', $testMethodName !== null ? $testMethodName : '', ), ); return true; } } phpunit/src/Metadata/Parser/Parser.php 0000644 00000002060 15253321353 0013743 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; use PHPUnit\Metadata\MetadataCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ interface Parser { /** * @param class-string $className */ public function forClass(string $className): MetadataCollection; /** * @param class-string $className * @param non-empty-string $methodName */ public function forMethod(string $className, string $methodName): MetadataCollection; /** * @param class-string $className * @param non-empty-string $methodName */ public function forClassAndMethod(string $className, string $methodName): MetadataCollection; } phpunit/src/Metadata/Parser/ParserChain.php 0000644 00000003673 15253321353 0014721 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; use PHPUnit\Metadata\MetadataCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class ParserChain implements Parser { private Parser $attributeReader; private Parser $annotationReader; public function __construct(Parser $attributeReader, Parser $annotationReader) { $this->attributeReader = $attributeReader; $this->annotationReader = $annotationReader; } /** * @param class-string $className */ public function forClass(string $className): MetadataCollection { $metadata = $this->attributeReader->forClass($className); if (!$metadata->isEmpty()) { return $metadata; } return $this->annotationReader->forClass($className); } /** * @param class-string $className * @param non-empty-string $methodName */ public function forMethod(string $className, string $methodName): MetadataCollection { $metadata = $this->attributeReader->forMethod($className, $methodName); if (!$metadata->isEmpty()) { return $metadata; } return $this->annotationReader->forMethod($className, $methodName); } /** * @param class-string $className * @param non-empty-string $methodName */ public function forClassAndMethod(string $className, string $methodName): MetadataCollection { return $this->forClass($className)->mergeWith( $this->forMethod($className, $methodName), ); } } phpunit/src/Metadata/Parser/CachingParser.php 0000644 00000004661 15253321353 0015231 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Parser; use PHPUnit\Metadata\MetadataCollection; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CachingParser implements Parser { private readonly Parser $reader; /** * @var array<class-string, MetadataCollection> */ private array $classCache = []; /** * @var array<non-empty-string, MetadataCollection> */ private array $methodCache = []; /** * @var array<non-empty-string, MetadataCollection> */ private array $classAndMethodCache = []; public function __construct(Parser $reader) { $this->reader = $reader; } /** * @param class-string $className */ public function forClass(string $className): MetadataCollection { if (isset($this->classCache[$className])) { return $this->classCache[$className]; } $this->classCache[$className] = $this->reader->forClass($className); return $this->classCache[$className]; } /** * @param class-string $className * @param non-empty-string $methodName */ public function forMethod(string $className, string $methodName): MetadataCollection { $key = $className . '::' . $methodName; if (isset($this->methodCache[$key])) { return $this->methodCache[$key]; } $this->methodCache[$key] = $this->reader->forMethod($className, $methodName); return $this->methodCache[$key]; } /** * @param class-string $className * @param non-empty-string $methodName */ public function forClassAndMethod(string $className, string $methodName): MetadataCollection { $key = $className . '::' . $methodName; if (isset($this->classAndMethodCache[$key])) { return $this->classAndMethodCache[$key]; } $this->classAndMethodCache[$key] = $this->forClass($className)->mergeWith( $this->forMethod($className, $methodName), ); return $this->classAndMethodCache[$key]; } } phpunit/src/Metadata/MetadataCollection.php 0000644 00000035061 15253321353 0015016 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; use function array_filter; use function array_merge; use function count; use Countable; use IteratorAggregate; /** * @template-implements IteratorAggregate<int, Metadata> * * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class MetadataCollection implements Countable, IteratorAggregate { /** * @var list<Metadata> */ private array $metadata; /** * @param list<Metadata> $metadata */ public static function fromArray(array $metadata): self { return new self(...$metadata); } private function __construct(Metadata ...$metadata) { $this->metadata = $metadata; } /** * @return list<Metadata> */ public function asArray(): array { return $this->metadata; } public function count(): int { return count($this->metadata); } public function isEmpty(): bool { return $this->count() === 0; } public function isNotEmpty(): bool { return $this->count() > 0; } public function getIterator(): MetadataCollectionIterator { return new MetadataCollectionIterator($this); } public function mergeWith(self $other): self { return new self( ...array_merge( $this->asArray(), $other->asArray(), ), ); } public function isClassLevel(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isClassLevel(), ), ); } public function isMethodLevel(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isMethodLevel(), ), ); } public function isAfter(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isAfter(), ), ); } public function isAfterClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isAfterClass(), ), ); } public function isBackupGlobals(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isBackupGlobals(), ), ); } public function isBackupStaticProperties(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isBackupStaticProperties(), ), ); } public function isBeforeClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isBeforeClass(), ), ); } public function isBefore(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isBefore(), ), ); } public function isCovers(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCovers(), ), ); } public function isCoversClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversClass(), ), ); } public function isCoversDefaultClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversDefaultClass(), ), ); } public function isCoversTrait(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversTrait(), ), ); } public function isCoversFunction(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversFunction(), ), ); } public function isCoversMethod(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversMethod(), ), ); } public function isExcludeGlobalVariableFromBackup(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isExcludeGlobalVariableFromBackup(), ), ); } public function isExcludeStaticPropertyFromBackup(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isExcludeStaticPropertyFromBackup(), ), ); } public function isCoversNothing(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isCoversNothing(), ), ); } public function isDataProvider(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDataProvider(), ), ); } public function isDepends(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDependsOnClass() || $metadata->isDependsOnMethod(), ), ); } public function isDependsOnClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDependsOnClass(), ), ); } public function isDependsOnMethod(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDependsOnMethod(), ), ); } public function isDisableReturnValueGenerationForTestDoubles(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDisableReturnValueGenerationForTestDoubles(), ), ); } public function isDoesNotPerformAssertions(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isDoesNotPerformAssertions(), ), ); } public function isGroup(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isGroup(), ), ); } public function isIgnoreDeprecations(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isIgnoreDeprecations(), ), ); } /** * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function isIgnorePhpunitDeprecations(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isIgnorePhpunitDeprecations(), ), ); } public function isRunClassInSeparateProcess(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRunClassInSeparateProcess(), ), ); } public function isRunInSeparateProcess(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRunInSeparateProcess(), ), ); } public function isRunTestsInSeparateProcesses(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRunTestsInSeparateProcesses(), ), ); } public function isTest(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isTest(), ), ); } public function isPreCondition(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isPreCondition(), ), ); } public function isPostCondition(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isPostCondition(), ), ); } public function isPreserveGlobalState(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isPreserveGlobalState(), ), ); } public function isRequiresMethod(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresMethod(), ), ); } public function isRequiresFunction(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresFunction(), ), ); } public function isRequiresOperatingSystem(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresOperatingSystem(), ), ); } public function isRequiresOperatingSystemFamily(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresOperatingSystemFamily(), ), ); } public function isRequiresPhp(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresPhp(), ), ); } public function isRequiresPhpExtension(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresPhpExtension(), ), ); } public function isRequiresPhpunit(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresPhpunit(), ), ); } public function isRequiresSetting(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isRequiresSetting(), ), ); } public function isTestDox(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isTestDox(), ), ); } public function isTestWith(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isTestWith(), ), ); } public function isUses(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUses(), ), ); } public function isUsesClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUsesClass(), ), ); } public function isUsesDefaultClass(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUsesDefaultClass(), ), ); } public function isUsesTrait(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUsesTrait(), ), ); } public function isUsesFunction(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUsesFunction(), ), ); } public function isUsesMethod(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isUsesMethod(), ), ); } public function isWithoutErrorHandler(): self { return new self( ...array_filter( $this->metadata, static fn (Metadata $metadata): bool => $metadata->isWithoutErrorHandler(), ), ); } } phpunit/src/Metadata/RunInSeparateProcess.php 0000644 00000001057 15253321353 0015337 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RunInSeparateProcess extends Metadata { public function isRunInSeparateProcess(): true { return true; } } phpunit/src/Metadata/AfterClass.php 0000644 00000001732 15253321353 0013307 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class AfterClass extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isAfterClass(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/Covers.php 0000644 00000001715 15253321353 0012522 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Covers extends Metadata { /** * @var non-empty-string */ private string $target; /** * @param 0|1 $level * @param non-empty-string $target */ protected function __construct(int $level, string $target) { parent::__construct($level); $this->target = $target; } public function isCovers(): true { return true; } /** * @return non-empty-string */ public function target(): string { return $this->target; } } phpunit/src/Metadata/After.php 0000644 00000001720 15253321353 0012316 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class After extends Metadata { /** * @var non-negative-int */ private int $priority; /** * @param 0|1 $level * @param non-negative-int $priority */ protected function __construct(int $level, int $priority) { parent::__construct($level); $this->priority = $priority; } public function isAfter(): true { return true; } /** * @return non-negative-int */ public function priority(): int { return $this->priority; } } phpunit/src/Metadata/RequiresOperatingSystemFamily.php 0000644 00000002144 15253321353 0017275 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RequiresOperatingSystemFamily extends Metadata { /** * @var non-empty-string */ private string $operatingSystemFamily; /** * @param 0|1 $level * @param non-empty-string $operatingSystemFamily */ protected function __construct(int $level, string $operatingSystemFamily) { parent::__construct($level); $this->operatingSystemFamily = $operatingSystemFamily; } public function isRequiresOperatingSystemFamily(): true { return true; } /** * @return non-empty-string */ public function operatingSystemFamily(): string { return $this->operatingSystemFamily; } } phpunit/src/Metadata/Api/CodeCoverage.php 0000644 00000027103 15253321353 0014317 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use function assert; use function class_exists; use function count; use function interface_exists; use function sprintf; use function str_starts_with; use function trait_exists; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Framework\CodeCoverageException; use PHPUnit\Framework\InvalidCoversTargetException; use PHPUnit\Metadata\Covers; use PHPUnit\Metadata\CoversClass; use PHPUnit\Metadata\CoversDefaultClass; use PHPUnit\Metadata\CoversFunction; use PHPUnit\Metadata\CoversMethod; use PHPUnit\Metadata\CoversTrait; use PHPUnit\Metadata\Parser\Registry; use PHPUnit\Metadata\Uses; use PHPUnit\Metadata\UsesClass; use PHPUnit\Metadata\UsesDefaultClass; use PHPUnit\Metadata\UsesFunction; use PHPUnit\Metadata\UsesMethod; use PHPUnit\Metadata\UsesTrait; use ReflectionClass; use SebastianBergmann\CodeUnit\CodeUnitCollection; use SebastianBergmann\CodeUnit\Exception as CodeUnitException; use SebastianBergmann\CodeUnit\InvalidCodeUnitException; use SebastianBergmann\CodeUnit\Mapper; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class CodeCoverage { /** * @var array<class-string, non-empty-list<class-string>> */ private array $withParents = []; /** * @param class-string $className * @param non-empty-string $methodName * * @throws CodeCoverageException * * @return array<string,list<int>>|false */ public function linesToBeCovered(string $className, string $methodName): array|false { if (!$this->shouldCodeCoverageBeCollectedFor($className, $methodName)) { return false; } $metadataForClass = Registry::parser()->forClass($className); $classShortcut = null; if ($metadataForClass->isCoversDefaultClass()->isNotEmpty()) { if (count($metadataForClass->isCoversDefaultClass()) > 1) { throw new CodeCoverageException( sprintf( 'More than one @coversDefaultClass annotation for class or interface "%s"', $className, ), ); } $metadata = $metadataForClass->isCoversDefaultClass()->asArray()[0]; assert($metadata instanceof CoversDefaultClass); $classShortcut = $metadata->className(); } $codeUnits = CodeUnitCollection::fromList(); $mapper = new Mapper; foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { if (!$metadata->isCoversClass() && !$metadata->isCoversTrait() && !$metadata->isCoversMethod() && !$metadata->isCoversFunction() && !$metadata->isCovers()) { continue; } /** @phpstan-ignore booleanOr.alwaysTrue */ assert($metadata instanceof CoversClass || $metadata instanceof CoversTrait || $metadata instanceof CoversMethod || $metadata instanceof CoversFunction || $metadata instanceof Covers); if ($metadata->isCoversClass() || $metadata->isCoversTrait() || $metadata->isCoversMethod() || $metadata->isCoversFunction()) { $codeUnits = $codeUnits->mergeWith($this->mapToCodeUnits($metadata)); } elseif ($metadata->isCovers()) { assert($metadata instanceof Covers); $target = $metadata->target(); if (interface_exists($target)) { throw new InvalidCoversTargetException( sprintf( 'Trying to @cover interface "%s".', $target, ), ); } if ($classShortcut !== null && str_starts_with($target, '::')) { $target = $classShortcut . $target; } try { $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($target)); } catch (InvalidCodeUnitException $e) { throw new InvalidCoversTargetException( sprintf( '"@covers %s" is invalid', $target, ), $e->getCode(), $e, ); } } } return $mapper->codeUnitsToSourceLines($codeUnits); } /** * @param class-string $className * @param non-empty-string $methodName * * @throws CodeCoverageException * * @return array<string,list<int>> */ public function linesToBeUsed(string $className, string $methodName): array { $metadataForClass = Registry::parser()->forClass($className); $classShortcut = null; if ($metadataForClass->isUsesDefaultClass()->isNotEmpty()) { if (count($metadataForClass->isUsesDefaultClass()) > 1) { throw new CodeCoverageException( sprintf( 'More than one @usesDefaultClass annotation for class or interface "%s"', $className, ), ); } $metadata = $metadataForClass->isUsesDefaultClass()->asArray()[0]; assert($metadata instanceof UsesDefaultClass); $classShortcut = $metadata->className(); } $codeUnits = CodeUnitCollection::fromList(); $mapper = new Mapper; foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { if (!$metadata->isUsesClass() && !$metadata->isUsesTrait() && !$metadata->isUsesMethod() && !$metadata->isUsesFunction() && !$metadata->isUses()) { continue; } /** @phpstan-ignore booleanOr.alwaysTrue */ assert($metadata instanceof UsesClass || $metadata instanceof UsesTrait || $metadata instanceof UsesMethod || $metadata instanceof UsesFunction || $metadata instanceof Uses); if ($metadata->isUsesClass() || $metadata->isUsesTrait() || $metadata->isUsesMethod() || $metadata->isUsesFunction()) { $codeUnits = $codeUnits->mergeWith($this->mapToCodeUnits($metadata)); } elseif ($metadata->isUses()) { assert($metadata instanceof Uses); $target = $metadata->target(); if ($classShortcut !== null && str_starts_with($target, '::')) { $target = $classShortcut . $target; } try { $codeUnits = $codeUnits->mergeWith($mapper->stringToCodeUnits($target)); } catch (InvalidCodeUnitException $e) { throw new InvalidCoversTargetException( sprintf( '"@uses %s" is invalid', $target, ), $e->getCode(), $e, ); } } } return $mapper->codeUnitsToSourceLines($codeUnits); } /** * @param class-string $className * @param non-empty-string $methodName */ public function shouldCodeCoverageBeCollectedFor(string $className, string $methodName): bool { $metadataForClass = Registry::parser()->forClass($className); $metadataForMethod = Registry::parser()->forMethod($className, $methodName); if ($metadataForMethod->isCoversNothing()->isNotEmpty()) { return false; } if ($metadataForMethod->isCovers()->isNotEmpty() || $metadataForMethod->isCoversClass()->isNotEmpty() || $metadataForMethod->isCoversFunction()->isNotEmpty()) { return true; } if ($metadataForClass->isCoversNothing()->isNotEmpty()) { return false; } return true; } /** * @throws InvalidCoversTargetException */ private function mapToCodeUnits(CoversClass|CoversFunction|CoversMethod|CoversTrait|UsesClass|UsesFunction|UsesMethod|UsesTrait $metadata): CodeUnitCollection { $mapper = new Mapper; $names = $this->names($metadata); try { if (count($names) === 1) { return $mapper->stringToCodeUnits($names[0]); } $codeUnits = CodeUnitCollection::fromList(); foreach ($names as $name) { $codeUnits = $codeUnits->mergeWith( $mapper->stringToCodeUnits($name), ); } return $codeUnits; } catch (CodeUnitException $e) { throw new InvalidCoversTargetException( sprintf( '%s is not a valid target for code coverage', $metadata->asStringForCodeUnitMapper(), ), $e->getCode(), $e, ); } } /** * @throws InvalidCoversTargetException * * @return non-empty-list<non-empty-string> */ private function names(CoversClass|CoversFunction|CoversMethod|CoversTrait|UsesClass|UsesFunction|UsesMethod|UsesTrait $metadata): array { $name = $metadata->asStringForCodeUnitMapper(); $names = [$name]; if ($metadata->isCoversClass() || $metadata->isUsesClass()) { if (isset($this->withParents[$name])) { return $this->withParents[$name]; } if (interface_exists($name)) { throw new InvalidCoversTargetException( sprintf( 'Interface "%s" is not a valid target for code coverage', $name, ), ); } if (!(class_exists($name) || trait_exists($name))) { throw new InvalidCoversTargetException( sprintf( '"%s" is not a valid target for code coverage', $name, ), ); } assert(class_exists($names[0]) || trait_exists($names[0])); if ($metadata->isCoversClass() && trait_exists($names[0])) { EventFacade::emitter()->testRunnerTriggeredDeprecation( sprintf( 'Targeting a trait such as %s with #[CoversClass] is deprecated, please refactor your test to use #[CoversTrait] instead.', $names[0], ), ); } if ($metadata->isUsesClass() && trait_exists($names[0])) { EventFacade::emitter()->testRunnerTriggeredDeprecation( sprintf( 'Targeting a trait such as %s with #[UsesClass] is deprecated, please refactor your test to use #[UsesTrait] instead.', $names[0], ), ); } $reflector = new ReflectionClass($name); while ($reflector = $reflector->getParentClass()) { if (!$reflector->isUserDefined()) { break; } $names[] = $reflector->getName(); } $this->withParents[$name] = $names; } return $names; } } phpunit/src/Metadata/Api/Groups.php 0000644 00000007625 15253321353 0013257 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use function array_flip; use function array_key_exists; use function array_unique; use function assert; use function strtolower; use function trim; use PHPUnit\Framework\TestSize\TestSize; use PHPUnit\Metadata\Covers; use PHPUnit\Metadata\CoversClass; use PHPUnit\Metadata\CoversFunction; use PHPUnit\Metadata\Group; use PHPUnit\Metadata\Parser\Registry; use PHPUnit\Metadata\Uses; use PHPUnit\Metadata\UsesClass; use PHPUnit\Metadata\UsesFunction; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class Groups { /** * @var array<string, array<int, string>> */ private static array $groupCache = []; /** * @param class-string $className * @param non-empty-string $methodName * * @return array<int, string> */ public function groups(string $className, string $methodName, bool $includeVirtual = true): array { $key = $className . '::' . $methodName . '::' . $includeVirtual; if (array_key_exists($key, self::$groupCache)) { return self::$groupCache[$key]; } $groups = []; foreach (Registry::parser()->forClassAndMethod($className, $methodName)->isGroup() as $group) { assert($group instanceof Group); $groups[] = $group->groupName(); } if ($groups === []) { $groups[] = 'default'; } if (!$includeVirtual) { return self::$groupCache[$key] = array_unique($groups); } foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { if ($metadata->isCoversClass() || $metadata->isCoversFunction()) { /** @phpstan-ignore booleanOr.alwaysTrue */ assert($metadata instanceof CoversClass || $metadata instanceof CoversFunction); $groups[] = '__phpunit_covers_' . $this->canonicalizeName($metadata->asStringForCodeUnitMapper()); continue; } if ($metadata->isCovers()) { assert($metadata instanceof Covers); $groups[] = '__phpunit_covers_' . $this->canonicalizeName($metadata->target()); continue; } if ($metadata->isUsesClass() || $metadata->isUsesFunction()) { /** @phpstan-ignore booleanOr.alwaysTrue */ assert($metadata instanceof UsesClass || $metadata instanceof UsesFunction); $groups[] = '__phpunit_uses_' . $this->canonicalizeName($metadata->asStringForCodeUnitMapper()); continue; } if ($metadata->isUses()) { assert($metadata instanceof Uses); $groups[] = '__phpunit_uses_' . $this->canonicalizeName($metadata->target()); } } return self::$groupCache[$key] = array_unique($groups); } /** * @param class-string $className * @param non-empty-string $methodName */ public function size(string $className, string $methodName): TestSize { $groups = array_flip($this->groups($className, $methodName)); if (isset($groups['large'])) { return TestSize::large(); } if (isset($groups['medium'])) { return TestSize::medium(); } if (isset($groups['small'])) { return TestSize::small(); } return TestSize::unknown(); } private function canonicalizeName(string $name): string { return strtolower(trim($name, '\\')); } } phpunit/src/Metadata/Api/DataProvider.php 0000644 00000021560 15253321353 0014356 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use const JSON_ERROR_NONE; use const PREG_OFFSET_CAPTURE; use function array_key_exists; use function assert; use function explode; use function is_array; use function is_int; use function json_decode; use function json_last_error; use function json_last_error_msg; use function preg_match; use function preg_replace; use function rtrim; use function sprintf; use function str_replace; use function strlen; use function substr; use function trim; use PHPUnit\Event; use PHPUnit\Framework\InvalidDataProviderException; use PHPUnit\Metadata\DataProvider as DataProviderMetadata; use PHPUnit\Metadata\MetadataCollection; use PHPUnit\Metadata\Parser\Registry as MetadataRegistry; use PHPUnit\Metadata\TestWith; use ReflectionClass; use ReflectionMethod; use Throwable; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class DataProvider { /** * @param class-string $className * @param non-empty-string $methodName * * @throws InvalidDataProviderException * * @return ?array<array<mixed>> */ public function providedData(string $className, string $methodName): ?array { $dataProvider = MetadataRegistry::parser()->forMethod($className, $methodName)->isDataProvider(); $testWith = MetadataRegistry::parser()->forMethod($className, $methodName)->isTestWith(); if ($dataProvider->isEmpty() && $testWith->isEmpty()) { return $this->dataProvidedByTestWithAnnotation($className, $methodName); } if ($dataProvider->isNotEmpty()) { $data = $this->dataProvidedByMethods($className, $methodName, $dataProvider); } else { $data = $this->dataProvidedByMetadata($testWith); } if ($data === []) { throw new InvalidDataProviderException( 'Empty data set provided by data provider', ); } foreach ($data as $key => $value) { if (!is_array($value)) { throw new InvalidDataProviderException( sprintf( 'Data set %s is invalid', is_int($key) ? '#' . $key : '"' . $key . '"', ), ); } } return $data; } /** * @param class-string $className * @param non-empty-string $methodName * * @throws InvalidDataProviderException * * @return array<array<mixed>> */ private function dataProvidedByMethods(string $className, string $methodName, MetadataCollection $dataProvider): array { $testMethod = new Event\Code\ClassMethod($className, $methodName); $methodsCalled = []; $result = []; foreach ($dataProvider as $_dataProvider) { assert($_dataProvider instanceof DataProviderMetadata); $dataProviderMethod = new Event\Code\ClassMethod($_dataProvider->className(), $_dataProvider->methodName()); Event\Facade::emitter()->dataProviderMethodCalled( $testMethod, $dataProviderMethod, ); $methodsCalled[] = $dataProviderMethod; try { $class = new ReflectionClass($_dataProvider->className()); $method = $class->getMethod($_dataProvider->methodName()); if (!$method->isPublic()) { throw new InvalidDataProviderException( sprintf( 'Data Provider method %s::%s() is not public', $_dataProvider->className(), $_dataProvider->methodName(), ), ); } if (!$method->isStatic()) { throw new InvalidDataProviderException( sprintf( 'Data Provider method %s::%s() is not static', $_dataProvider->className(), $_dataProvider->methodName(), ), ); } if ($method->getNumberOfParameters() > 0) { throw new InvalidDataProviderException( sprintf( 'Data Provider method %s::%s() expects an argument', $_dataProvider->className(), $_dataProvider->methodName(), ), ); } $className = $_dataProvider->className(); $methodName = $_dataProvider->methodName(); $data = $className::$methodName(); } catch (Throwable $e) { Event\Facade::emitter()->dataProviderMethodFinished( $testMethod, ...$methodsCalled, ); throw new InvalidDataProviderException( $e->getMessage(), $e->getCode(), $e, ); } foreach ($data as $key => $value) { if (is_int($key)) { $result[] = $value; } elseif (array_key_exists($key, $result)) { Event\Facade::emitter()->dataProviderMethodFinished( $testMethod, ...$methodsCalled, ); throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous data provider', $key, ), ); } else { $result[$key] = $value; } } } Event\Facade::emitter()->dataProviderMethodFinished( $testMethod, ...$methodsCalled, ); return $result; } /** * @return array<array<mixed>> */ private function dataProvidedByMetadata(MetadataCollection $testWith): array { $result = []; foreach ($testWith as $_testWith) { assert($_testWith instanceof TestWith); if ($_testWith->hasName()) { $key = $_testWith->name(); if (array_key_exists($key, $result)) { throw new InvalidDataProviderException( sprintf( 'The key "%s" has already been defined by a previous TestWith attribute', $key, ), ); } $result[$key] = $_testWith->data(); } else { $result[] = $_testWith->data(); } } return $result; } /** * @param class-string $className * * @throws InvalidDataProviderException * * @return ?array<array<mixed>> */ private function dataProvidedByTestWithAnnotation(string $className, string $methodName): ?array { $docComment = (new ReflectionMethod($className, $methodName))->getDocComment(); if ($docComment === false) { return null; } $docComment = str_replace("\r\n", "\n", $docComment); $docComment = preg_replace('/\n\s*\*\s?/', "\n", $docComment); $docComment = substr($docComment, 0, -1); $docComment = rtrim($docComment, "\n"); if (!preg_match('/@testWith\s+/', $docComment, $matches, PREG_OFFSET_CAPTURE)) { return null; } $offset = strlen($matches[0][0]) + (int) $matches[0][1]; $annotationContent = substr($docComment, $offset); $data = []; foreach (explode("\n", $annotationContent) as $candidateRow) { $candidateRow = trim($candidateRow); if ($candidateRow === '' || $candidateRow[0] !== '[') { break; } $dataSet = json_decode($candidateRow, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new InvalidDataProviderException( 'The data set for the @testWith annotation cannot be parsed: ' . json_last_error_msg(), ); } $data[] = $dataSet; } if (!$data) { throw new InvalidDataProviderException( 'The data set for the @testWith annotation cannot be parsed.', ); } return $data; } } phpunit/src/Metadata/Api/Dependencies.php 0000644 00000003215 15253321353 0014355 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use function assert; use PHPUnit\Framework\ExecutionOrderDependency; use PHPUnit\Metadata\DependsOnClass; use PHPUnit\Metadata\DependsOnMethod; use PHPUnit\Metadata\Parser\Registry; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Dependencies { /** * @param class-string $className * @param non-empty-string $methodName * * @return list<ExecutionOrderDependency> */ public static function dependencies(string $className, string $methodName): array { $dependencies = []; foreach (Registry::parser()->forClassAndMethod($className, $methodName)->isDepends() as $metadata) { if ($metadata->isDependsOnClass()) { assert($metadata instanceof DependsOnClass); $dependencies[] = ExecutionOrderDependency::forClass($metadata); continue; } assert($metadata instanceof DependsOnMethod); if (empty($metadata->methodName())) { $dependencies[] = ExecutionOrderDependency::invalid(); continue; } $dependencies[] = ExecutionOrderDependency::forMethod($metadata); } return $dependencies; } } phpunit/src/Metadata/Api/Requirements.php 0000644 00000012462 15253321353 0014456 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use const PHP_OS; use const PHP_OS_FAMILY; use const PHP_VERSION; use function addcslashes; use function assert; use function extension_loaded; use function function_exists; use function ini_get; use function method_exists; use function phpversion; use function preg_match; use function sprintf; use PHPUnit\Metadata\Parser\Registry; use PHPUnit\Metadata\RequiresFunction; use PHPUnit\Metadata\RequiresMethod; use PHPUnit\Metadata\RequiresOperatingSystem; use PHPUnit\Metadata\RequiresOperatingSystemFamily; use PHPUnit\Metadata\RequiresPhp; use PHPUnit\Metadata\RequiresPhpExtension; use PHPUnit\Metadata\RequiresPhpunit; use PHPUnit\Metadata\RequiresSetting; use PHPUnit\Runner\Version; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final readonly class Requirements { /** * @param class-string $className * @param non-empty-string $methodName * * @return list<string> */ public function requirementsNotSatisfiedFor(string $className, string $methodName): array { $notSatisfied = []; foreach (Registry::parser()->forClassAndMethod($className, $methodName) as $metadata) { if ($metadata->isRequiresPhp()) { assert($metadata instanceof RequiresPhp); if (!$metadata->versionRequirement()->isSatisfiedBy(PHP_VERSION)) { $notSatisfied[] = sprintf( 'PHP %s is required.', $metadata->versionRequirement()->asString(), ); } } if ($metadata->isRequiresPhpExtension()) { assert($metadata instanceof RequiresPhpExtension); if (!extension_loaded($metadata->extension()) || ($metadata->hasVersionRequirement() && !$metadata->versionRequirement()->isSatisfiedBy(phpversion($metadata->extension())))) { $notSatisfied[] = sprintf( 'PHP extension %s%s is required.', $metadata->extension(), $metadata->hasVersionRequirement() ? (' ' . $metadata->versionRequirement()->asString()) : '', ); } } if ($metadata->isRequiresPhpunit()) { assert($metadata instanceof RequiresPhpunit); if (!$metadata->versionRequirement()->isSatisfiedBy(Version::id())) { $notSatisfied[] = sprintf( 'PHPUnit %s is required.', $metadata->versionRequirement()->asString(), ); } } if ($metadata->isRequiresOperatingSystemFamily()) { assert($metadata instanceof RequiresOperatingSystemFamily); if ($metadata->operatingSystemFamily() !== PHP_OS_FAMILY) { $notSatisfied[] = sprintf( 'Operating system %s is required.', $metadata->operatingSystemFamily(), ); } } if ($metadata->isRequiresOperatingSystem()) { assert($metadata instanceof RequiresOperatingSystem); $pattern = sprintf( '/%s/i', addcslashes($metadata->operatingSystem(), '/'), ); if (!preg_match($pattern, PHP_OS)) { $notSatisfied[] = sprintf( 'Operating system %s is required.', $metadata->operatingSystem(), ); } } if ($metadata->isRequiresFunction()) { assert($metadata instanceof RequiresFunction); if (!function_exists($metadata->functionName())) { $notSatisfied[] = sprintf( 'Function %s() is required.', $metadata->functionName(), ); } } if ($metadata->isRequiresMethod()) { assert($metadata instanceof RequiresMethod); if (!method_exists($metadata->className(), $metadata->methodName())) { $notSatisfied[] = sprintf( 'Method %s::%s() is required.', $metadata->className(), $metadata->methodName(), ); } } if ($metadata->isRequiresSetting()) { assert($metadata instanceof RequiresSetting); if (ini_get($metadata->setting()) !== $metadata->value()) { $notSatisfied[] = sprintf( 'Setting "%s" is required to be "%s".', $metadata->setting(), $metadata->value(), ); } } } return $notSatisfied; } } phpunit/src/Metadata/Api/HookMethods.php 0000644 00000012261 15253321353 0014214 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata\Api; use function assert; use function class_exists; use PHPUnit\Framework\TestCase; use PHPUnit\Metadata\After; use PHPUnit\Metadata\AfterClass; use PHPUnit\Metadata\Before; use PHPUnit\Metadata\BeforeClass; use PHPUnit\Metadata\Parser\Registry; use PHPUnit\Metadata\PostCondition; use PHPUnit\Metadata\PreCondition; use PHPUnit\Runner\HookMethod; use PHPUnit\Runner\HookMethodCollection; use PHPUnit\Util\Reflection; use ReflectionClass; /** * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit * * @internal This class is not covered by the backward compatibility promise for PHPUnit */ final class HookMethods { /** * @var array<class-string, array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection}> */ private static array $hookMethods = []; /** * @param class-string<TestCase> $className * * @return array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} */ public function hookMethods(string $className): array { if (!class_exists($className)) { return self::emptyHookMethodsArray(); } if (isset(self::$hookMethods[$className])) { return self::$hookMethods[$className]; } self::$hookMethods[$className] = self::emptyHookMethodsArray(); foreach (Reflection::methodsDeclaredDirectlyInTestClass(new ReflectionClass($className)) as $method) { $methodName = $method->getName(); assert(!empty($methodName)); $metadata = Registry::parser()->forMethod($className, $methodName); if ($method->isStatic()) { if ($metadata->isBeforeClass()->isNotEmpty()) { $beforeClass = $metadata->isBeforeClass()->asArray()[0]; assert($beforeClass instanceof BeforeClass); self::$hookMethods[$className]['beforeClass']->add( new HookMethod($methodName, $beforeClass->priority()), ); } if ($metadata->isAfterClass()->isNotEmpty()) { $afterClass = $metadata->isAfterClass()->asArray()[0]; assert($afterClass instanceof AfterClass); self::$hookMethods[$className]['afterClass']->add( new HookMethod($methodName, $afterClass->priority()), ); } } if ($metadata->isBefore()->isNotEmpty()) { $before = $metadata->isBefore()->asArray()[0]; assert($before instanceof Before); self::$hookMethods[$className]['before']->add( new HookMethod($methodName, $before->priority()), ); } if ($metadata->isPreCondition()->isNotEmpty()) { $preCondition = $metadata->isPreCondition()->asArray()[0]; assert($preCondition instanceof PreCondition); self::$hookMethods[$className]['preCondition']->add( new HookMethod($methodName, $preCondition->priority()), ); } if ($metadata->isPostCondition()->isNotEmpty()) { $postCondition = $metadata->isPostCondition()->asArray()[0]; assert($postCondition instanceof PostCondition); self::$hookMethods[$className]['postCondition']->add( new HookMethod($methodName, $postCondition->priority()), ); } if ($metadata->isAfter()->isNotEmpty()) { $after = $metadata->isAfter()->asArray()[0]; assert($after instanceof After); self::$hookMethods[$className]['after']->add( new HookMethod($methodName, $after->priority()), ); } } return self::$hookMethods[$className]; } /** * @return array{beforeClass: HookMethodCollection, before: HookMethodCollection, preCondition: HookMethodCollection, postCondition: HookMethodCollection, after: HookMethodCollection, afterClass: HookMethodCollection} */ private function emptyHookMethodsArray(): array { return [ 'beforeClass' => HookMethodCollection::defaultBeforeClass(), 'before' => HookMethodCollection::defaultBefore(), 'preCondition' => HookMethodCollection::defaultPreCondition(), 'postCondition' => HookMethodCollection::defaultPostCondition(), 'after' => HookMethodCollection::defaultAfter(), 'afterClass' => HookMethodCollection::defaultAfterClass(), ]; } } phpunit/src/Metadata/IgnoreDeprecations.php 0000644 00000001053 15253321353 0015040 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class IgnoreDeprecations extends Metadata { public function isIgnoreDeprecations(): true { return true; } } phpunit/src/Metadata/RunTestsInSeparateProcesses.php 0000644 00000001075 15253321353 0016712 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class RunTestsInSeparateProcesses extends Metadata { public function isRunTestsInSeparateProcesses(): true { return true; } } phpunit/src/Metadata/UsesDefaultClass.php 0000644 00000001746 15253321353 0014477 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class UsesDefaultClass extends Metadata { /** * @var class-string */ private string $className; /** * @param 0|1 $level * @param class-string $className */ protected function __construct(int $level, string $className) { parent::__construct($level); $this->className = $className; } public function isUsesDefaultClass(): true { return true; } /** * @return class-string */ public function className(): string { return $this->className; } } phpunit/src/Metadata/UsesTrait.php 0000644 00000002317 15253321353 0013203 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class UsesTrait extends Metadata { /** * @var trait-string */ private string $traitName; /** * @param 0|1 $level * @param trait-string $traitName */ protected function __construct(int $level, string $traitName) { parent::__construct($level); $this->traitName = $traitName; } public function isUsesTrait(): true { return true; } /** * @return trait-string */ public function traitName(): string { return $this->traitName; } /** * @return trait-string * * @internal This method is not covered by the backward compatibility promise for PHPUnit */ public function asStringForCodeUnitMapper(): string { return $this->traitName; } } phpunit/src/Metadata/Uses.php 0000644 00000001711 15253321353 0012174 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Uses extends Metadata { /** * @var non-empty-string */ private string $target; /** * @param 0|1 $level * @param non-empty-string $target */ protected function __construct(int $level, string $target) { parent::__construct($level); $this->target = $target; } public function isUses(): true { return true; } /** * @return non-empty-string */ public function target(): string { return $this->target; } } phpunit/src/Metadata/DoesNotPerformAssertions.php 0000644 00000001067 15253321353 0016242 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class DoesNotPerformAssertions extends Metadata { public function isDoesNotPerformAssertions(): true { return true; } } phpunit/src/Metadata/PreserveGlobalState.php 0000644 00000001526 15253321353 0015176 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class PreserveGlobalState extends Metadata { private bool $enabled; /** * @param 0|1 $level */ protected function __construct(int $level, bool $enabled) { parent::__construct($level); $this->enabled = $enabled; } public function isPreserveGlobalState(): true { return true; } public function enabled(): bool { return $this->enabled; } } phpunit/src/Metadata/Test.php 0000644 00000001017 15253321353 0012173 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Metadata; /** * @immutable * * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit */ final readonly class Test extends Metadata { public function isTest(): true { return true; } } phpunit/phpunit.xsd 0000644 00000044272 15253321353 0010455 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 11.3 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="deprecationTrigger" type="deprecationTriggerType" minOccurs="0"/> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSelfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDirectDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreIndirectDeprecations" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="testdoxSummary" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> <xs:attribute name="shortenArraysForExportThreshold" type="xs:integer" default="0"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="deprecationTriggerType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="function" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="method" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> </xs:schema> phpunit/composer.json 0000644 00000004710 15253321353 0010761 0 ustar 00 { "name": "phpunit/phpunit", "description": "The PHP Unit Testing framework.", "type": "library", "keywords": [ "phpunit", "xunit", "testing" ], "homepage": "https://phpunit.de/", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy" }, "prefer-stable": true, "require": { "php": ">=8.2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.12.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "phpunit/php-code-coverage": "^11.0.5", "phpunit/php-file-iterator": "^5.0.1", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.1", "sebastian/comparator": "^6.0.2", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", "sebastian/exporter": "^6.1.3", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.0.1", "sebastian/version": "^5.0.1" }, "config": { "platform": { "php": "8.2.0" }, "optimize-autoloader": true, "sort-packages": true }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" ], "autoload": { "classmap": [ "src/" ], "files": [ "src/Framework/Assert/Functions.php" ] }, "autoload-dev": { "classmap": [ "tests/" ], "files": [ "tests/_files/deprecation-trigger/trigger_deprecation.php", "tests/_files/CoverageNamespacedFunctionTest.php", "tests/_files/CoveredFunction.php", "tests/_files/Generator.php", "tests/_files/NamespaceCoveredFunction.php" ] }, "extra": { "branch-alias": { "dev-main": "11.3-dev" } } } phpunit/schema/10.5.xsd 0000644 00000043107 15253321353 0010605 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.5 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/10.0.xsd 0000644 00000036404 15253321353 0010602 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.0 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="coverageType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/11.1.xsd 0000644 00000044256 15253321353 0010610 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 11.1 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="deprecationTrigger" type="deprecationTriggerType" minOccurs="0"/> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSelfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDirectDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreIndirectDeprecations" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="deprecationTriggerType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="function" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="method" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> </xs:schema> phpunit/schema/10.1.xsd 0000644 00000041253 15253321353 0010601 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.1 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/11.2.xsd 0000644 00000044256 15253321353 0010611 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 11.2 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="deprecationTrigger" type="deprecationTriggerType" minOccurs="0"/> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSelfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDirectDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreIndirectDeprecations" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="deprecationTriggerType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="function" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="method" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> </xs:schema> phpunit/schema/9.5.xsd 0000644 00000043104 15253321353 0010532 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.5 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="coverageType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="false"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxXml" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="logToFileType" minOccurs="0"/> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/9.2.xsd 0000644 00000041334 15253321353 0010532 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.2 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="filtersType"> <xs:sequence> <xs:element name="whitelist" type="whiteListType" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="filterType"> <xs:sequence> <xs:choice maxOccurs="unbounded" minOccurs="0"> <xs:group ref="pathGroup"/> <xs:element name="exclude"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="whiteListType"> <xs:complexContent> <xs:extension base="filterType"> <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/> <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:complexType name="loggersType"> <xs:sequence> <xs:element name="log" type="loggerType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="loggerType"> <xs:attribute name="type"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="coverage-html"/> <xs:enumeration value="coverage-text"/> <xs:enumeration value="coverage-clover"/> <xs:enumeration value="coverage-crap4j"/> <xs:enumeration value="coverage-xml"/> <xs:enumeration value="coverage-php"/> <xs:enumeration value="plain"/> <xs:enumeration value="teamcity"/> <xs:enumeration value="junit"/> <xs:enumeration value="testdox-html"/> <xs:enumeration value="testdox-text"/> <xs:enumeration value="testdox-xml"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="target" type="xs:anyURI"/> <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="50"/> <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="90"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/> </xs:complexType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:string"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="filter" type="filtersType" minOccurs="0"/> <xs:element name="logging" type="loggersType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> </xs:schema> phpunit/schema/8.5.xsd 0000644 00000041323 15253321353 0010532 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 8.5 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="filtersType"> <xs:sequence> <xs:element name="whitelist" type="whiteListType" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="filterType"> <xs:sequence> <xs:choice maxOccurs="unbounded" minOccurs="0"> <xs:group ref="pathGroup"/> <xs:element name="exclude"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="whiteListType"> <xs:complexContent> <xs:extension base="filterType"> <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/> <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:complexType name="loggersType"> <xs:sequence> <xs:element name="log" type="loggerType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="loggerType"> <xs:attribute name="type"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="coverage-html"/> <xs:enumeration value="coverage-text"/> <xs:enumeration value="coverage-clover"/> <xs:enumeration value="coverage-crap4j"/> <xs:enumeration value="coverage-xml"/> <xs:enumeration value="coverage-php"/> <xs:enumeration value="json"/> <xs:enumeration value="plain"/> <xs:enumeration value="tap"/> <xs:enumeration value="teamcity"/> <xs:enumeration value="junit"/> <xs:enumeration value="testdox-html"/> <xs:enumeration value="testdox-text"/> <xs:enumeration value="testdox-xml"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="target" type="xs:anyURI"/> <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="50"/> <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="90"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/> </xs:complexType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="false"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="filter" type="filtersType" minOccurs="0"/> <xs:element name="logging" type="loggersType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> </xs:schema> phpunit/schema/10.4.xsd 0000644 00000043107 15253321353 0010604 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.4 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/9.1.xsd 0000644 00000041325 15253321353 0010531 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.0 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="filtersType"> <xs:sequence> <xs:element name="whitelist" type="whiteListType" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="filterType"> <xs:sequence> <xs:choice maxOccurs="unbounded" minOccurs="0"> <xs:group ref="pathGroup"/> <xs:element name="exclude"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="whiteListType"> <xs:complexContent> <xs:extension base="filterType"> <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/> <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:complexType name="loggersType"> <xs:sequence> <xs:element name="log" type="loggerType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="loggerType"> <xs:attribute name="type"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="coverage-html"/> <xs:enumeration value="coverage-text"/> <xs:enumeration value="coverage-clover"/> <xs:enumeration value="coverage-crap4j"/> <xs:enumeration value="coverage-xml"/> <xs:enumeration value="coverage-php"/> <xs:enumeration value="plain"/> <xs:enumeration value="teamcity"/> <xs:enumeration value="junit"/> <xs:enumeration value="testdox-html"/> <xs:enumeration value="testdox-text"/> <xs:enumeration value="testdox-xml"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="target" type="xs:anyURI"/> <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="35"/> <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="70"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/> </xs:complexType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:string"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="filter" type="filtersType" minOccurs="0"/> <xs:element name="logging" type="loggersType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> </xs:schema> phpunit/schema/9.0.xsd 0000644 00000041064 15253321353 0010530 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.0 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="filtersType"> <xs:sequence> <xs:element name="whitelist" type="whiteListType" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="filterType"> <xs:sequence> <xs:choice maxOccurs="unbounded" minOccurs="0"> <xs:group ref="pathGroup"/> <xs:element name="exclude"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="whiteListType"> <xs:complexContent> <xs:extension base="filterType"> <xs:attribute name="addUncoveredFilesFromWhitelist" default="true" type="xs:boolean"/> <xs:attribute name="processUncoveredFilesFromWhitelist" default="false" type="xs:boolean"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:complexType name="loggersType"> <xs:sequence> <xs:element name="log" type="loggerType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="loggerType"> <xs:attribute name="type"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="coverage-html"/> <xs:enumeration value="coverage-text"/> <xs:enumeration value="coverage-clover"/> <xs:enumeration value="coverage-crap4j"/> <xs:enumeration value="coverage-xml"/> <xs:enumeration value="coverage-php"/> <xs:enumeration value="plain"/> <xs:enumeration value="teamcity"/> <xs:enumeration value="junit"/> <xs:enumeration value="testdox-html"/> <xs:enumeration value="testdox-text"/> <xs:enumeration value="testdox-xml"/> </xs:restriction> </xs:simpleType> </xs:attribute> <xs:attribute name="target" type="xs:anyURI"/> <xs:attribute name="lowUpperBound" type="xs:nonNegativeInteger" default="35"/> <xs:attribute name="highLowerBound" type="xs:nonNegativeInteger" default="70"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> <xs:attribute name="threshold" type="xs:nonNegativeInteger" default="30"/> </xs:complexType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="cacheTokens" type="xs:boolean" default="false"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\ResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnitsFromCodeCoverage" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:string"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="filter" type="filtersType" minOccurs="0"/> <xs:element name="logging" type="loggersType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> </xs:schema> phpunit/schema/9.3.xsd 0000644 00000042674 15253321353 0010543 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.3 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="coverageType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:string"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxXml" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="logToFileType" minOccurs="0"/> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/9.4.xsd 0000644 00000043012 15253321353 0010527 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 9.4 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="coverageType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="pathGroup"/> </xs:complexType> </xs:element> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="processUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="extension" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="listenersType"> <xs:sequence> <xs:element name="listener" type="objectType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="objectType"> <xs:sequence> <xs:element name="arguments" minOccurs="0"> <xs:complexType> <xs:group ref="argumentsGroup"/> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> <xs:attribute name="file" type="xs:anyURI"/> </xs:complexType> <xs:complexType name="arrayType"> <xs:sequence> <xs:element name="element" type="argumentType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="argumentType"> <xs:group ref="argumentChoice"/> <xs:attribute name="key" use="required"/> </xs:complexType> <xs:group name="argumentsGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="array" type="arrayType" /> <xs:element name="integer" type="xs:integer" /> <xs:element name="string" type="xs:string" /> <xs:element name="double" type="xs:double" /> <xs:element name="null" /> <xs:element name="object" type="objectType" /> <xs:element name="file" type="xs:anyURI" /> <xs:element name="directory" type="xs:anyURI" /> <xs:element name="boolean" type="xs:boolean" /> </xs:choice> </xs:sequence> </xs:group> <xs:group name="argumentChoice"> <xs:choice> <xs:element name="array" type="arrayType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="integer" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="string" type="xs:string" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="double" type="xs:double" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="null" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="object" type="objectType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="file" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="directory" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="boolean" type="xs:boolean" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:group> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:group name="pathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="directoryFilterType"/> <xs:element name="file" type="fileFilterType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="directoryFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="fileFilterType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticAttributes" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertErrorsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertNoticesToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="convertWarningsToExceptions" type="xs:boolean" default="true"/> <xs:attribute name="forceCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="printerClass" type="xs:string" default="PHPUnit\TextUI\DefaultResultPrinter"/> <xs:attribute name="printerFile" type="xs:anyURI"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutResourceUsageDuringSmallTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoversAnnotation" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="testSuiteLoaderClass" type="xs:string" default="PHPUnit\Runner\StandardTestSuiteLoader"/> <xs:attribute name="testSuiteLoaderFile" type="xs:anyURI"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="verbose" type="xs:boolean" default="false"/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:string"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="noInteraction" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="testdoxGroups" type="groupsType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="listeners" type="listenersType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:group ref="pathGroup"/> <xs:element name="exclude" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxXml" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="logToFileType" minOccurs="0"/> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/10.3.xsd 0000644 00000043016 15253321353 0010602 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.3 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/10.2.xsd 0000644 00000042521 15253321353 0010601 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 10.2 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="registerMockObjectsFromTestArgumentsRecursively" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/schema/11.0.xsd 0000644 00000043124 15253321353 0010600 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:annotation> <xs:documentation source="https://phpunit.de/documentation.html"> This Schema file defines the rules by which the XML configuration file of PHPUnit 11.0 may be structured. </xs:documentation> <xs:appinfo source="https://phpunit.de/documentation.html"/> </xs:annotation> <xs:element name="phpunit" type="phpUnitType"> <xs:annotation> <xs:documentation>Root Element</xs:documentation> </xs:annotation> </xs:element> <xs:complexType name="sourceType"> <xs:all> <xs:element name="include" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> <xs:element name="exclude" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="sourcePathGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="baseline" type="xs:anyURI"/> <xs:attribute name="restrictDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="restrictNotices" type="xs:boolean" default="false"/> <xs:attribute name="restrictWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfErrors" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpNotices" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfWarnings" type="xs:boolean" default="false"/> <xs:attribute name="ignoreSuppressionOfPhpWarnings" type="xs:boolean" default="false"/> </xs:complexType> <xs:group name="sourcePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="sourceDirectoryType"/> <xs:element name="file" type="xs:anyURI"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="sourceDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default=".php"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="coverageType"> <xs:all> <xs:element name="report" minOccurs="0" maxOccurs="1"> <xs:complexType> <xs:group ref="coverageReportGroup"/> </xs:complexType> </xs:element> </xs:all> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="pathCoverage" type="xs:boolean" default="false"/> <xs:attribute name="includeUncoveredFiles" type="xs:boolean" default="true"/> <xs:attribute name="ignoreDeprecatedCodeUnits" type="xs:boolean" default="false"/> <xs:attribute name="disableCodeCoverageIgnore" type="xs:boolean" default="false"/> </xs:complexType> <xs:complexType name="loggingType"> <xs:group ref="loggingGroup"/> </xs:complexType> <xs:complexType name="groupsType"> <xs:choice> <xs:sequence> <xs:element name="include" type="groupType"/> <xs:element name="exclude" type="groupType" minOccurs="0"/> </xs:sequence> <xs:sequence> <xs:element name="exclude" type="groupType"/> </xs:sequence> </xs:choice> </xs:complexType> <xs:complexType name="groupType"> <xs:sequence> <xs:element name="group" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="extensionsType"> <xs:sequence> <xs:element name="bootstrap" type="bootstrapType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="bootstrapType"> <xs:sequence> <xs:element name="parameter" type="parameterType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:attribute name="class" type="xs:string" use="required"/> </xs:complexType> <xs:complexType name="parameterType"> <xs:attribute name="name" type="xs:string" use="required"/> <xs:attribute name="value" type="xs:string" use="required"/> </xs:complexType> <xs:simpleType name="columnsType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"/> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="max"/> </xs:restriction> </xs:simpleType> </xs:union> </xs:simpleType> <xs:simpleType name="executionOrderType"> <xs:restriction base="xs:string"> <xs:enumeration value="default"/> <xs:enumeration value="defects"/> <xs:enumeration value="depends"/> <xs:enumeration value="depends,defects"/> <xs:enumeration value="depends,duration"/> <xs:enumeration value="depends,random"/> <xs:enumeration value="depends,reverse"/> <xs:enumeration value="depends,size"/> <xs:enumeration value="duration"/> <xs:enumeration value="no-depends"/> <xs:enumeration value="no-depends,defects"/> <xs:enumeration value="no-depends,duration"/> <xs:enumeration value="no-depends,random"/> <xs:enumeration value="no-depends,reverse"/> <xs:enumeration value="no-depends,size"/> <xs:enumeration value="random"/> <xs:enumeration value="reverse"/> <xs:enumeration value="size"/> </xs:restriction> </xs:simpleType> <xs:complexType name="phpType"> <xs:sequence> <xs:choice maxOccurs="unbounded"> <xs:element name="includePath" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="ini" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="const" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="var" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="env" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="post" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="get" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="cookie" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="server" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="files" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="request" type="namedValueType" minOccurs="0" maxOccurs="unbounded"/> </xs:choice> </xs:sequence> </xs:complexType> <xs:complexType name="namedValueType"> <xs:attribute name="name" use="required" type="xs:string"/> <xs:attribute name="value" use="required" type="xs:anySimpleType"/> <xs:attribute name="verbatim" use="optional" type="xs:boolean"/> <xs:attribute name="force" use="optional" type="xs:boolean"/> </xs:complexType> <xs:complexType name="phpUnitType"> <xs:annotation> <xs:documentation>The main type specifying the document structure</xs:documentation> </xs:annotation> <xs:group ref="configGroup"/> <xs:attributeGroup ref="configAttributeGroup"/> </xs:complexType> <xs:attributeGroup name="configAttributeGroup"> <xs:attribute name="backupGlobals" type="xs:boolean" default="false"/> <xs:attribute name="backupStaticProperties" type="xs:boolean" default="false"/> <xs:attribute name="bootstrap" type="xs:anyURI"/> <xs:attribute name="cacheDirectory" type="xs:anyURI"/> <xs:attribute name="cacheResult" type="xs:boolean" default="true"/> <xs:attribute name="cacheResultFile" type="xs:anyURI"/> <xs:attribute name="colors" type="xs:boolean" default="false"/> <xs:attribute name="columns" type="columnsType" default="80"/> <xs:attribute name="controlGarbageCollector" type="xs:boolean" default="false"/> <xs:attribute name="numberOfTestsBeforeGarbageCollection" type="xs:integer" default="100"/> <xs:attribute name="requireCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="processIsolation" type="xs:boolean" default="false"/> <xs:attribute name="failOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="failOnEmptyTestSuite" type="xs:boolean" default="false"/> <xs:attribute name="failOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="failOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="failOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="failOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="failOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDefect" type="xs:boolean" default="false"/> <xs:attribute name="stopOnDeprecation" type="xs:boolean" default="false"/> <xs:attribute name="stopOnError" type="xs:boolean" default="false"/> <xs:attribute name="stopOnFailure" type="xs:boolean" default="false"/> <xs:attribute name="stopOnIncomplete" type="xs:boolean" default="false"/> <xs:attribute name="stopOnNotice" type="xs:boolean" default="false"/> <xs:attribute name="stopOnRisky" type="xs:boolean" default="false"/> <xs:attribute name="stopOnSkipped" type="xs:boolean" default="false"/> <xs:attribute name="stopOnWarning" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutChangesToGlobalState" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutOutputDuringTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutTestsThatDoNotTestAnything" type="xs:boolean" default="true"/> <xs:attribute name="beStrictAboutTodoAnnotatedTests" type="xs:boolean" default="false"/> <xs:attribute name="beStrictAboutCoverageMetadata" type="xs:boolean" default="false"/> <xs:attribute name="defaultTimeLimit" type="xs:integer" default="0"/> <xs:attribute name="enforceTimeLimit" type="xs:boolean" default="false"/> <xs:attribute name="timeoutForSmallTests" type="xs:integer" default="1"/> <xs:attribute name="timeoutForMediumTests" type="xs:integer" default="10"/> <xs:attribute name="timeoutForLargeTests" type="xs:integer" default="60"/> <xs:attribute name="defaultTestSuite" type="xs:string" default=""/> <xs:attribute name="testdox" type="xs:boolean" default="false"/> <xs:attribute name="stderr" type="xs:boolean" default="false"/> <xs:attribute name="reverseDefectList" type="xs:boolean" default="false"/> <xs:attribute name="extensionsDirectory" type="xs:anyURI"/> <xs:attribute name="executionOrder" type="executionOrderType" default="default"/> <xs:attribute name="resolveDependencies" type="xs:boolean" default="true"/> <xs:attribute name="displayDetailsOnIncompleteTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnSkippedTests" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerDeprecations" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerErrors" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerNotices" type="xs:boolean" default="false"/> <xs:attribute name="displayDetailsOnTestsThatTriggerWarnings" type="xs:boolean" default="false"/> </xs:attributeGroup> <xs:group name="configGroup"> <xs:all> <xs:element ref="testSuiteFacet" minOccurs="0"/> <xs:element name="groups" type="groupsType" minOccurs="0"/> <xs:element name="source" type="sourceType" minOccurs="0"/> <xs:element name="coverage" type="coverageType" minOccurs="0"/> <xs:element name="logging" type="loggingType" minOccurs="0"/> <xs:element name="extensions" type="extensionsType" minOccurs="0"/> <xs:element name="php" type="phpType" minOccurs="0"/> </xs:all> </xs:group> <xs:element name="testSuiteFacet" abstract="true"/> <xs:element name="testsuite" type="testSuiteType" substitutionGroup="testSuiteFacet"/> <xs:element name="testsuites" type="testSuitesType" substitutionGroup="testSuiteFacet"/> <xs:complexType name="testSuitesType"> <xs:sequence> <xs:element name="testsuite" type="testSuiteType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="testSuiteType"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:group ref="testSuitePathGroup"/> <xs:element name="exclude" type="xs:string"/> </xs:choice> </xs:sequence> <xs:attribute name="name" type="xs:string" use="required"/> </xs:complexType> <xs:group name="testSuitePathGroup"> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="directory" type="testSuiteDirectoryType"/> <xs:element name="file" type="testSuiteFileType"/> </xs:choice> </xs:sequence> </xs:group> <xs:complexType name="testSuiteDirectoryType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="prefix" default=""/> <xs:attribute type="xs:string" name="suffix" default="Test.php"/> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:complexType name="testSuiteFileType"> <xs:simpleContent> <xs:extension base="xs:anyURI"> <xs:attributeGroup ref="phpVersionGroup"/> <xs:attribute type="xs:string" name="groups"/> </xs:extension> </xs:simpleContent> </xs:complexType> <xs:attributeGroup name="phpVersionGroup"> <xs:attribute name="phpVersion" type="xs:string" default="5.3.0"/> <xs:attribute name="phpVersionOperator" type="xs:string" default=">="/> </xs:attributeGroup> <xs:group name="coverageReportGroup"> <xs:all> <xs:element name="clover" type="logToFileType" minOccurs="0"/> <xs:element name="cobertura" type="logToFileType" minOccurs="0"/> <xs:element name="crap4j" type="coverageReportCrap4JType" minOccurs="0" /> <xs:element name="html" type="coverageReportHtmlType" minOccurs="0" /> <xs:element name="php" type="logToFileType" minOccurs="0" /> <xs:element name="text" type="coverageReportTextType" minOccurs="0" /> <xs:element name="xml" type="logToDirectoryType" minOccurs="0" /> </xs:all> </xs:group> <xs:group name="loggingGroup"> <xs:all> <xs:element name="junit" type="logToFileType" minOccurs="0" /> <xs:element name="teamcity" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxHtml" type="logToFileType" minOccurs="0" /> <xs:element name="testdoxText" type="logToFileType" minOccurs="0" /> </xs:all> </xs:group> <xs:complexType name="logToFileType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="logToDirectoryType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> </xs:complexType> <xs:complexType name="coverageReportCrap4JType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="threshold" type="xs:integer"/> </xs:complexType> <xs:complexType name="coverageReportHtmlType"> <xs:attribute name="outputDirectory" type="xs:anyURI" use="required"/> <xs:attribute name="lowUpperBound" type="xs:integer" default="50"/> <xs:attribute name="highLowerBound" type="xs:integer" default="90"/> <xs:attribute name="colorSuccessLow" type="xs:string" default="#dff0d8"/> <xs:attribute name="colorSuccessMedium" type="xs:string" default="#c3e3b5"/> <xs:attribute name="colorSuccessHigh" type="xs:string" default="#99cb84"/> <xs:attribute name="colorWarning" type="xs:string" default="#fcf8e3"/> <xs:attribute name="colorDanger" type="xs:string" default="#f2dede"/> <xs:attribute name="customCssFile" type="xs:string"/> </xs:complexType> <xs:complexType name="coverageReportTextType"> <xs:attribute name="outputFile" type="xs:anyURI" use="required"/> <xs:attribute name="showUncoveredFiles" type="xs:boolean" default="false"/> <xs:attribute name="showOnlySummary" type="xs:boolean" default="false"/> </xs:complexType> </xs:schema> phpunit/composer.lock 0000644 00000157015 15253321353 0010747 0 ustar 00 { "_readme": [ "This file locks the dependencies of your project to a known state", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], "content-hash": "61b119645b78ca11c08634201765a3a8", "packages": [ { "name": "myclabs/deep-copy", "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "conflict": { "doctrine/collections": "<1.6.8", "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { "files": [ "src/DeepCopy/deep_copy.php" ], "psr-4": { "DeepCopy\\": "src/DeepCopy/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", "keywords": [ "clone", "copy", "duplicate", "object", "object graph" ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], "time": "2024-06-12T14:39:25+00:00" }, { "name": "nikic/php-parser", "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", "extra": { "branch-alias": { "dev-master": "5.0-dev" } }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", "keywords": [ "parser", "php" ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" }, { "name": "Sebastian Heuer", "email": "sebastian@phpeople.de", "role": "Developer" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "Developer" } ], "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", "source": "https://github.com/phar-io/version/tree/3.2.1" }, "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpunit/php-code-coverage", "version": "11.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/19b6365ab8b59a64438c0c3f4241feeb480c9861", "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^5.0", "php": ">=8.2", "phpunit/php-file-iterator": "^5.0", "phpunit/php-text-template": "^4.0", "sebastian/code-unit-reverse-lookup": "^4.0", "sebastian/complexity": "^4.0", "sebastian/environment": "^7.0", "sebastian/lines-of-code": "^3.0", "sebastian/version": "^5.0", "theseer/tokenizer": "^1.2.0" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { "dev-main": "11.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:05:37+00:00" }, { "name": "phpunit/php-file-iterator", "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6ed896bf50bbbfe4d504a33ed5886278c78e4a26", "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:06:37+00:00" }, { "name": "phpunit/php-invoker", "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ "process" ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "7.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "security": "https://github.com/sebastianbergmann/php-timer/security/policy", "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:09:35+00:00" }, { "name": "sebastian/cli-parser", "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for parsing CLI options", "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", "reference": "6bb7d09d6623567178cf54126afa9c2310114268" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", "reference": "6bb7d09d6623567178cf54126afa9c2310114268", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the PHP code units", "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:44:28+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/450d8f237bd611c45b5acf0733ce43e6bb280f81", "reference": "450d8f237bd611c45b5acf0733ce43e6bb280f81", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", "php": ">=8.2", "sebastian/diff": "^6.0", "sebastian/exporter": "^6.0" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-08-12T06:07:25+00:00" }, { "name": "sebastian/complexity", "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { "nikic/php-parser": "^5.0", "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for calculating the complexity of PHP code units", "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff", "udiff", "unidiff", "unified diff" ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { "dev-main": "7.2-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", "version": "6.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "shasum": "" }, "require": { "ext-mbstring": "*", "php": ">=8.2", "sebastian/recursion-context": "^6.0" }, "require-dev": { "phpunit/phpunit": "^11.2" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.1-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" }, { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:56:19+00:00" }, { "name": "sebastian/global-state", "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { "php": ">=8.2", "sebastian/object-reflector": "^4.0", "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "7.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { "nikic/php-parser": "^5.0", "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library for counting the lines of code in PHP source code", "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { "php": ">=8.2", "sebastian/object-reflector": "^4.0", "sebastian/recursion-context": "^6.0" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "4.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "6.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb6a6566f9589e86661291d13eba708cce5eb4aa", "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", "source": "https://github.com/sebastianbergmann/type/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:11:49+00:00" }, { "name": "sebastian/version", "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", "shasum": "" }, "require": { "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "security": "https://github.com/sebastianbergmann/version/security/policy", "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2024-07-03T05:13:08+00:00" }, { "name": "theseer/tokenizer", "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Arne Blankerts", "email": "arne@blankerts.de", "role": "Developer" } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "time": "2024-03-03T12:36:25+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": ">=8.2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*" }, "platform-dev": [], "platform-overrides": { "php": "8.2.0" }, "plugin-api-version": "2.6.0" } phpunit/LICENSE 0000644 00000002773 15253321353 0007253 0 ustar 00 BSD 3-Clause License Copyright (c) 2001-2024, Sebastian Bergmann All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. phpunit/SECURITY.md 0000644 00000004371 15253321353 0010033 0 ustar 00 # Security Policy If you believe you have found a security vulnerability in PHPUnit, please report it to us through coordinated disclosure. **Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.** Instead, please email `sebastian@phpunit.de`. Please include as much of the information listed below as you can to help us better understand and resolve the issue: * The type of issue * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. ## Web Context PHPUnit is a framework for writing as well as a command-line tool for running tests. Writing and running tests is a development-time activity. There is no reason why PHPUnit should be installed on a webserver and/or in a production environment. **If you upload PHPUnit to a webserver then your deployment process is broken. On a more general note, if your `vendor` directory is publicly accessible on your webserver then your deployment process is also broken.** Please note that if you upload PHPUnit to a webserver "bad things" may happen. [You have been warned.](https://thephp.cc/articles/phpunit-a-security-risk?ref=phpunit) PHPUnit is developed with a focus on development environments and the command-line. No specific testing or hardening with regard to using PHPUnit in an HTTP or web context or with untrusted input data is performed. PHPUnit might also contain functionality that intentionally exposes internal application data for debugging purposes. If PHPUnit is used in a web application, the application developer is responsible for filtering inputs or escaping outputs as necessary and for verifying that the used functionality is safe for use within the intended context. Vulnerabilities specific to the use outside a development context will be fixed as applicable, provided that the fix does not have an averse effect on the primary use case for development purposes. phpunit/phpunit 0000644 00000005325 15253321353 0007654 0 ustar 00 #!/usr/bin/env php <?php declare(strict_types=1); /* * This file is part of PHPUnit. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (!version_compare(PHP_VERSION, PHP_VERSION, '=')) { fwrite( STDERR, sprintf( '%s declares an invalid value for PHP_VERSION.' . PHP_EOL . 'This breaks fundamental functionality such as version_compare().' . PHP_EOL . 'Please use a different PHP interpreter.' . PHP_EOL, PHP_BINARY ) ); die(1); } if (version_compare('8.2.0', PHP_VERSION, '>')) { fwrite( STDERR, sprintf( 'This version of PHPUnit requires PHP >= 8.2.' . PHP_EOL . 'You are using PHP %s (%s).' . PHP_EOL, PHP_VERSION, PHP_BINARY ) ); die(1); } if (!ini_get('date.timezone')) { ini_set('date.timezone', 'UTC'); } if (isset($GLOBALS['_composer_autoload_path'])) { define('PHPUNIT_COMPOSER_INSTALL', $GLOBALS['_composer_autoload_path']); unset($GLOBALS['_composer_autoload_path']); } else { foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) { if (file_exists($file)) { define('PHPUNIT_COMPOSER_INSTALL', $file); break; } } unset($file); } if (!defined('PHPUNIT_COMPOSER_INSTALL')) { fwrite( STDERR, 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . ' composer install' . PHP_EOL . PHP_EOL . 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL ); die(1); } require PHPUNIT_COMPOSER_INSTALL; $requiredExtensions = ['dom', 'json', 'libxml', 'mbstring', 'tokenizer', 'xml', 'xmlwriter']; $unavailableExtensions = array_filter( $requiredExtensions, static function ($extension) { return !extension_loaded($extension); } ); // Workaround for https://github.com/sebastianbergmann/phpunit/issues/5662 if (!function_exists('ctype_alnum')) { $unavailableExtensions[] = 'ctype'; } if ([] !== $unavailableExtensions) { fwrite( STDERR, sprintf( 'PHPUnit requires the "%s" extensions, but the "%s" %s not available.' . PHP_EOL, implode('", "', $requiredExtensions), implode('", "', $unavailableExtensions), count($unavailableExtensions) === 1 ? 'extension is' : 'extensions are' ) ); die(1); } unset($requiredExtensions, $unavailableExtensions); exit((new PHPUnit\TextUI\Application)->run($_SERVER['argv'])); phpunit/DEPRECATIONS.md 0000644 00000023312 15253321353 0010440 0 ustar 00 # Deprecations ## Hard Deprecations This functionality is currently [hard-deprecated](https://phpunit.de/backward-compatibility.html#hard-deprecation): ### Writing Tests #### Assertions, Constraints, and Expectations | Issue | Description | Since | Replacement | |-------------------------------------------------------------------|------------------------------------------------|--------|-------------| | [#5472](https://github.com/sebastianbergmann/phpunit/issues/5472) | `TestCase::assertStringNotMatchesFormat()` | 10.4.0 | | | [#5472](https://github.com/sebastianbergmann/phpunit/issues/5472) | `TestCase::assertStringNotMatchesFormatFile()` | 10.4.0 | | #### Test Double API | Issue | Description | Since | Replacement | |-------------------------------------------------------------------|--------------------------------------------------------------------------------|--------|-----------------------------------------------------------------------------------------| | [#5240](https://github.com/sebastianbergmann/phpunit/issues/5240) | `TestCase::createTestProxy()` | 10.1.0 | | | [#5241](https://github.com/sebastianbergmann/phpunit/issues/5241) | `TestCase::getMockForAbstractClass()` | 10.1.0 | | | [#5242](https://github.com/sebastianbergmann/phpunit/issues/5242) | `TestCase::getMockFromWsdl()` | 10.1.0 | | | [#5243](https://github.com/sebastianbergmann/phpunit/issues/5243) | `TestCase::getMockForTrait()` | 10.1.0 | | | [#5244](https://github.com/sebastianbergmann/phpunit/issues/5244) | `TestCase::getObjectForTrait()` | 10.1.0 | | | [#5305](https://github.com/sebastianbergmann/phpunit/issues/5305) | `MockBuilder::getMockForAbstractClass()` | 10.1.0 | | | [#5306](https://github.com/sebastianbergmann/phpunit/issues/5306) | `MockBuilder::getMockForTrait()` | 10.1.0 | | | [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::disableProxyingToOriginalMethods()` | 10.1.0 | | | [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::enableProxyingToOriginalMethods()` | 10.1.0 | | | [#5307](https://github.com/sebastianbergmann/phpunit/issues/5307) | `MockBuilder::setProxyTarget()` | 10.1.0 | | | [#5308](https://github.com/sebastianbergmann/phpunit/issues/5308) | `MockBuilder::allowMockingUnknownTypes()` | 10.1.0 | | | [#5308](https://github.com/sebastianbergmann/phpunit/issues/5308) | `MockBuilder::disallowMockingUnknownTypes()` | 10.1.0 | | | [#5309](https://github.com/sebastianbergmann/phpunit/issues/5309) | `MockBuilder::disableAutoload()` | 10.1.0 | | | [#5309](https://github.com/sebastianbergmann/phpunit/issues/5309) | `MockBuilder::enableAutoload()` | 10.1.0 | | | [#5315](https://github.com/sebastianbergmann/phpunit/issues/5315) | `MockBuilder::disableArgumentCloning()` | 10.1.0 | | | [#5315](https://github.com/sebastianbergmann/phpunit/issues/5315) | `MockBuilder::enableArgumentCloning()` | 10.1.0 | | | [#5320](https://github.com/sebastianbergmann/phpunit/issues/5320) | `MockBuilder::addMethods()` | 10.1.0 | | | [#5415](https://github.com/sebastianbergmann/phpunit/issues/5415) | Support for doubling interfaces (or classes) that have a method named `method` | 11.0.0 | | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::onConsecutiveCalls()` | 10.3.0 | Use `$double->willReturn()` instead of `$double->will($this->onConsecutiveCalls())` | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnArgument()` | 10.3.0 | Use `$double->willReturnArgument()` instead of `$double->will($this->returnArgument())` | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnCallback()` | 10.3.0 | Use `$double->willReturnCallback()` instead of `$double->will($this->returnCallback())` | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnSelf()` | 10.3.0 | Use `$double->willReturnSelf()` instead of `$double->will($this->returnSelf())` | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnValue()` | 10.3.0 | Use `$double->willReturn()` instead of `$double->will($this->returnValue())` | | [#5423](https://github.com/sebastianbergmann/phpunit/issues/5423) | `TestCase::returnValueMap()` | 10.3.0 | Use `$double->willReturnMap()` instead of `$double->will($this->returnValueMap())` | | [#5535](https://github.com/sebastianbergmann/phpunit/issues/5525) | Configuring expectations using `expects()` on test stubs | 11.0.0 | Create a mock object when you need to configure expectations on a test double | ### Running Tests | Issue | Description | Since | Replacement | |-------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|--------|----------------------------------------------------------------------------------------------------| | [#5689](https://github.com/sebastianbergmann/phpunit/issues/5689) | `restrictDeprecations` attribute on the `<source>` element of the XML configuration file | 11.1.0 | Use `ignoreSelfDeprecations`, `ignoreDirectDeprecations`, and `ignoreIndirectDeprecations` instead | | [#5709](https://github.com/sebastianbergmann/phpunit/issues/5709) | Support for using comma-separated values with the `--group`, `--exclude-group`, `--covers`, `--uses`, and `--test-suffix` CLI options | 11.1.0 | Use `--group foo --group bar` instead of `--group foo,bar`, for example | #### Miscellaneous | Issue | Description | Since | Replacement | |-------------------------------------------------------------------|-----------------------------------------------------------|--------|-------------------------------------| | [#4505](https://github.com/sebastianbergmann/phpunit/issues/4505) | Metadata in doc-comments | 10.3.0 | Metadata in attributes | | [#5214](https://github.com/sebastianbergmann/phpunit/issues/5214) | `TestCase::iniSet()` | 10.3.0 | | | [#5216](https://github.com/sebastianbergmann/phpunit/issues/5216) | `TestCase::setLocale()` | 10.3.0 | | | [#5800](https://github.com/sebastianbergmann/phpunit/issues/5800) | Targeting traits with `#[CoversClass]` and `#[UsesClass]` | 11.2.0 | `#[CoversClass]` and `#[UsesTrait]` | phpunit/README.md 0000644 00000003530 15253321353 0007515 0 ustar 00 # PHPUnit [](https://packagist.org/packages/phpunit/phpunit) [](https://github.com/sebastianbergmann/phpunit/actions) [](https://codecov.io/gh/sebastianbergmann/phpunit) PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. ## Installation We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit bundled in a single file: ```bash $ wget https://phar.phpunit.de/phpunit-X.Y.phar $ php phpunit-X.Y.phar --version ``` Please replace `X.Y` with the version of PHPUnit you are interested in. Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the [documentation](https://phpunit.de/documentation.html) for details on how to install PHPUnit. ## Contribute Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/main/.github/CONTRIBUTING.md) for information on how to contribute to PHPUnit and its related projects. ## List of Contributors Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components: * [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors) * [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) A very special thanks to everyone who has contributed to the [documentation](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors). phpunit/.phpstorm.meta.php 0000644 00000001375 15253321353 0011633 0 ustar 00 <?php namespace PHPSTORM_META { override( \PHPUnit\Framework\TestCase::createStub(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::createConfiguredStub(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::createMock(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::createConfiguredMock(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::createPartialMock(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::createTestProxy(0), map([""=>"$0"]) ); override( \PHPUnit\Framework\TestCase::getMockForAbstractClass(0), map([""=>"$0"]) ); } phpunit/ChangeLog-11.3.md 0000644 00000003274 15253321353 0010774 0 ustar 00 # Changes in PHPUnit 11.3 All notable changes of the PHPUnit 11.3 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles. ## [11.3.1] - 2024-08-13 ### Changed * Improved how objects are handled for some assertion failure messages ## [11.3.0] - 2024-08-09 ### Added * [#5869](https://github.com/sebastianbergmann/phpunit/pull/5869): `shortenArraysForExportThreshold` attribute on the `<phpunit>` element of the XML configuration file to limit the export of arrays to a specified number of elements (default: `0` / do not limit the export of arrays) * [#5885](https://github.com/sebastianbergmann/phpunit/pull/5885): Optionally repeat TestDox output for non-successful tests after the regular TestDox output * [#5890](https://github.com/sebastianbergmann/phpunit/pull/5890): Priority for hook methods * [#5906](https://github.com/sebastianbergmann/phpunit/issues/5906): `--extension` CLI option to register a test runner extension ### Changed * [#5856](https://github.com/sebastianbergmann/phpunit/issues/5856): When the test runner is configured to fail on deprecations, notices, warnings, incomplete tests, or skipped tests then details for tests that triggered deprecations, notices, or warnings as well as tests that were marked as incomplete or skipped are always shown, respectively * [#5869](https://github.com/sebastianbergmann/phpunit/pull/5869): The configuration file generated using `--generate-configuration` now limits the export of arrays to 10 elements in order to improve performance [11.3.1]: https://github.com/sebastianbergmann/phpunit/compare/11.3.0...11.3.1 [11.3.0]: https://github.com/sebastianbergmann/phpunit/compare/11.2.9...11.3.0 php-code-coverage/src/Report/Text.php 0000644 00000026133 15253321353 0013542 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use const PHP_EOL; use function array_map; use function date; use function ksort; use function max; use function sprintf; use function str_pad; use function strlen; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Percentage; final class Text { /** * @var string */ private const COLOR_GREEN = "\x1b[30;42m"; /** * @var string */ private const COLOR_YELLOW = "\x1b[30;43m"; /** * @var string */ private const COLOR_RED = "\x1b[37;41m"; /** * @var string */ private const COLOR_HEADER = "\x1b[1;37;40m"; /** * @var string */ private const COLOR_RESET = "\x1b[0m"; private readonly Thresholds $thresholds; private readonly bool $showUncoveredFiles; private readonly bool $showOnlySummary; public function __construct(Thresholds $thresholds, bool $showUncoveredFiles = false, bool $showOnlySummary = false) { $this->thresholds = $thresholds; $this->showUncoveredFiles = $showUncoveredFiles; $this->showOnlySummary = $showOnlySummary; } public function process(CodeCoverage $coverage, bool $showColors = false): string { $hasBranchCoverage = !empty($coverage->getData(true)->functionCoverage()); $output = PHP_EOL . PHP_EOL; $report = $coverage->getReport(); $colors = [ 'header' => '', 'classes' => '', 'methods' => '', 'lines' => '', 'branches' => '', 'paths' => '', 'reset' => '', ]; if ($showColors) { $colors['classes'] = $this->coverageColor( $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits(), ); $colors['methods'] = $this->coverageColor( $report->numberOfTestedMethods(), $report->numberOfMethods(), ); $colors['lines'] = $this->coverageColor( $report->numberOfExecutedLines(), $report->numberOfExecutableLines(), ); $colors['branches'] = $this->coverageColor( $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches(), ); $colors['paths'] = $this->coverageColor( $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths(), ); $colors['reset'] = self::COLOR_RESET; $colors['header'] = self::COLOR_HEADER; } $classes = sprintf( ' Classes: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits(), )->asString(), $report->numberOfTestedClassesAndTraits(), $report->numberOfClassesAndTraits(), ); $methods = sprintf( ' Methods: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfTestedMethods(), $report->numberOfMethods(), )->asString(), $report->numberOfTestedMethods(), $report->numberOfMethods(), ); $paths = ''; $branches = ''; if ($hasBranchCoverage) { $paths = sprintf( ' Paths: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths(), )->asString(), $report->numberOfExecutedPaths(), $report->numberOfExecutablePaths(), ); $branches = sprintf( ' Branches: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches(), )->asString(), $report->numberOfExecutedBranches(), $report->numberOfExecutableBranches(), ); } $lines = sprintf( ' Lines: %6s (%d/%d)', Percentage::fromFractionAndTotal( $report->numberOfExecutedLines(), $report->numberOfExecutableLines(), )->asString(), $report->numberOfExecutedLines(), $report->numberOfExecutableLines(), ); $padding = max(array_map('strlen', [$classes, $methods, $lines])); if ($this->showOnlySummary) { $title = 'Code Coverage Report Summary:'; $padding = max($padding, strlen($title)); $output .= $this->format($colors['header'], $padding, $title); } else { $date = date(' Y-m-d H:i:s'); $title = 'Code Coverage Report:'; $output .= $this->format($colors['header'], $padding, $title); $output .= $this->format($colors['header'], $padding, $date); $output .= $this->format($colors['header'], $padding, ''); $output .= $this->format($colors['header'], $padding, ' Summary:'); } $output .= $this->format($colors['classes'], $padding, $classes); $output .= $this->format($colors['methods'], $padding, $methods); if ($hasBranchCoverage) { $output .= $this->format($colors['paths'], $padding, $paths); $output .= $this->format($colors['branches'], $padding, $branches); } $output .= $this->format($colors['lines'], $padding, $lines); if ($this->showOnlySummary) { return $output . PHP_EOL; } $classCoverage = []; foreach ($report as $item) { if (!$item instanceof File) { continue; } $classes = $item->classesAndTraits(); foreach ($classes as $className => $class) { $classExecutableLines = 0; $classExecutedLines = 0; $classExecutableBranches = 0; $classExecutedBranches = 0; $classExecutablePaths = 0; $classExecutedPaths = 0; $coveredMethods = 0; $classMethods = 0; foreach ($class['methods'] as $method) { if ($method['executableLines'] == 0) { continue; } $classMethods++; $classExecutableLines += $method['executableLines']; $classExecutedLines += $method['executedLines']; $classExecutableBranches += $method['executableBranches']; $classExecutedBranches += $method['executedBranches']; $classExecutablePaths += $method['executablePaths']; $classExecutedPaths += $method['executedPaths']; if ($method['coverage'] == 100) { $coveredMethods++; } } $classCoverage[$className] = [ 'namespace' => $class['namespace'], 'className' => $className, 'methodsCovered' => $coveredMethods, 'methodCount' => $classMethods, 'statementsCovered' => $classExecutedLines, 'statementCount' => $classExecutableLines, 'branchesCovered' => $classExecutedBranches, 'branchesCount' => $classExecutableBranches, 'pathsCovered' => $classExecutedPaths, 'pathsCount' => $classExecutablePaths, ]; } } ksort($classCoverage); $methodColor = ''; $pathsColor = ''; $branchesColor = ''; $linesColor = ''; $resetColor = ''; foreach ($classCoverage as $fullQualifiedPath => $classInfo) { if ($this->showUncoveredFiles || $classInfo['statementsCovered'] != 0) { if ($showColors) { $methodColor = $this->coverageColor($classInfo['methodsCovered'], $classInfo['methodCount']); $pathsColor = $this->coverageColor($classInfo['pathsCovered'], $classInfo['pathsCount']); $branchesColor = $this->coverageColor($classInfo['branchesCovered'], $classInfo['branchesCount']); $linesColor = $this->coverageColor($classInfo['statementsCovered'], $classInfo['statementCount']); $resetColor = $colors['reset']; } $output .= PHP_EOL . $fullQualifiedPath . PHP_EOL . ' ' . $methodColor . 'Methods: ' . $this->printCoverageCounts($classInfo['methodsCovered'], $classInfo['methodCount'], 2) . $resetColor . ' '; if ($hasBranchCoverage) { $output .= ' ' . $pathsColor . 'Paths: ' . $this->printCoverageCounts($classInfo['pathsCovered'], $classInfo['pathsCount'], 3) . $resetColor . ' ' . ' ' . $branchesColor . 'Branches: ' . $this->printCoverageCounts($classInfo['branchesCovered'], $classInfo['branchesCount'], 3) . $resetColor . ' '; } $output .= ' ' . $linesColor . 'Lines: ' . $this->printCoverageCounts($classInfo['statementsCovered'], $classInfo['statementCount'], 3) . $resetColor; } } return $output . PHP_EOL; } private function coverageColor(int $numberOfCoveredElements, int $totalNumberOfElements): string { $coverage = Percentage::fromFractionAndTotal( $numberOfCoveredElements, $totalNumberOfElements, ); if ($coverage->asFloat() >= $this->thresholds->highLowerBound()) { return self::COLOR_GREEN; } if ($coverage->asFloat() > $this->thresholds->lowUpperBound()) { return self::COLOR_YELLOW; } return self::COLOR_RED; } private function printCoverageCounts(int $numberOfCoveredElements, int $totalNumberOfElements, int $precision): string { $format = '%' . $precision . 's'; return Percentage::fromFractionAndTotal( $numberOfCoveredElements, $totalNumberOfElements, )->asFixedWidthString() . ' (' . sprintf($format, $numberOfCoveredElements) . '/' . sprintf($format, $totalNumberOfElements) . ')'; } private function format(string $color, int $padding, false|string $string): string { if ($color === '') { return (string) $string . PHP_EOL; } return $color . str_pad((string) $string, $padding) . self::COLOR_RESET . PHP_EOL; } } php-code-coverage/src/Report/Cobertura.php 0000644 00000030604 15253321353 0014542 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function basename; use function count; use function dirname; use function file_put_contents; use function preg_match; use function range; use function str_contains; use function str_replace; use function time; use DOMImplementation; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class Cobertura { /** * @throws WriteOperationFailedException */ public function process(CodeCoverage $coverage, ?string $target = null): string { $time = (string) time(); $report = $coverage->getReport(); $implementation = new DOMImplementation; $documentType = $implementation->createDocumentType( 'coverage', '', 'http://cobertura.sourceforge.net/xml/coverage-04.dtd', ); $document = $implementation->createDocument('', '', $documentType); $document->xmlVersion = '1.0'; $document->encoding = 'UTF-8'; $document->formatOutput = true; $coverageElement = $document->createElement('coverage'); $linesValid = $report->numberOfExecutableLines(); $linesCovered = $report->numberOfExecutedLines(); $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); $coverageElement->setAttribute('line-rate', (string) $lineRate); $branchesValid = $report->numberOfExecutableBranches(); $branchesCovered = $report->numberOfExecutedBranches(); $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); $coverageElement->setAttribute('branch-rate', (string) $branchRate); $coverageElement->setAttribute('lines-covered', (string) $report->numberOfExecutedLines()); $coverageElement->setAttribute('lines-valid', (string) $report->numberOfExecutableLines()); $coverageElement->setAttribute('branches-covered', (string) $report->numberOfExecutedBranches()); $coverageElement->setAttribute('branches-valid', (string) $report->numberOfExecutableBranches()); $coverageElement->setAttribute('complexity', ''); $coverageElement->setAttribute('version', '0.4'); $coverageElement->setAttribute('timestamp', $time); $document->appendChild($coverageElement); $sourcesElement = $document->createElement('sources'); $coverageElement->appendChild($sourcesElement); $sourceElement = $document->createElement('source', $report->pathAsString()); $sourcesElement->appendChild($sourceElement); $packagesElement = $document->createElement('packages'); $coverageElement->appendChild($packagesElement); $complexity = 0; foreach ($report as $item) { if (!$item instanceof File) { continue; } $packageElement = $document->createElement('package'); $packageComplexity = 0; $packageElement->setAttribute('name', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); $linesValid = $item->numberOfExecutableLines(); $linesCovered = $item->numberOfExecutedLines(); $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); $packageElement->setAttribute('line-rate', (string) $lineRate); $branchesValid = $item->numberOfExecutableBranches(); $branchesCovered = $item->numberOfExecutedBranches(); $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); $packageElement->setAttribute('branch-rate', (string) $branchRate); $packageElement->setAttribute('complexity', ''); $packagesElement->appendChild($packageElement); $classesElement = $document->createElement('classes'); $packageElement->appendChild($classesElement); $classes = $item->classesAndTraits(); $coverageData = $item->lineCoverageData(); foreach ($classes as $className => $class) { $complexity += $class['ccn']; $packageComplexity += $class['ccn']; $linesValid = $class['executableLines']; $linesCovered = $class['executedLines']; $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); $branchesValid = $class['executableBranches']; $branchesCovered = $class['executedBranches']; $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); $classElement = $document->createElement('class'); $classElement->setAttribute('name', $className); $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); $classElement->setAttribute('line-rate', (string) $lineRate); $classElement->setAttribute('branch-rate', (string) $branchRate); $classElement->setAttribute('complexity', (string) $class['ccn']); $classesElement->appendChild($classElement); $methodsElement = $document->createElement('methods'); $classElement->appendChild($methodsElement); $classLinesElement = $document->createElement('lines'); $classElement->appendChild($classLinesElement); foreach ($class['methods'] as $methodName => $method) { if ($method['executableLines'] === 0) { continue; } preg_match("/\((.*?)\)/", $method['signature'], $signature); $linesValid = $method['executableLines']; $linesCovered = $method['executedLines']; $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); $branchesValid = $method['executableBranches']; $branchesCovered = $method['executedBranches']; $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); $methodElement = $document->createElement('method'); $methodElement->setAttribute('name', $methodName); $methodElement->setAttribute('signature', $signature[1]); $methodElement->setAttribute('line-rate', (string) $lineRate); $methodElement->setAttribute('branch-rate', (string) $branchRate); $methodElement->setAttribute('complexity', (string) $method['ccn']); $methodLinesElement = $document->createElement('lines'); $methodElement->appendChild($methodLinesElement); foreach (range($method['startLine'], $method['endLine']) as $line) { if (!isset($coverageData[$line])) { continue; } $methodLineElement = $document->createElement('line'); $methodLineElement->setAttribute('number', (string) $line); $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); $methodLinesElement->appendChild($methodLineElement); $classLineElement = $methodLineElement->cloneNode(); $classLinesElement->appendChild($classLineElement); } $methodsElement->appendChild($methodElement); } } if ($item->numberOfFunctions() === 0) { $packageElement->setAttribute('complexity', (string) $packageComplexity); continue; } $functionsComplexity = 0; $functionsLinesValid = 0; $functionsLinesCovered = 0; $functionsBranchesValid = 0; $functionsBranchesCovered = 0; $classElement = $document->createElement('class'); $classElement->setAttribute('name', basename($item->pathAsString())); $classElement->setAttribute('filename', str_replace($report->pathAsString() . DIRECTORY_SEPARATOR, '', $item->pathAsString())); $methodsElement = $document->createElement('methods'); $classElement->appendChild($methodsElement); $classLinesElement = $document->createElement('lines'); $classElement->appendChild($classLinesElement); $functions = $item->functions(); foreach ($functions as $functionName => $function) { if ($function['executableLines'] === 0) { continue; } $complexity += $function['ccn']; $packageComplexity += $function['ccn']; $functionsComplexity += $function['ccn']; $linesValid = $function['executableLines']; $linesCovered = $function['executedLines']; $lineRate = $linesValid === 0 ? 0 : ($linesCovered / $linesValid); $functionsLinesValid += $linesValid; $functionsLinesCovered += $linesCovered; $branchesValid = $function['executableBranches']; $branchesCovered = $function['executedBranches']; $branchRate = $branchesValid === 0 ? 0 : ($branchesCovered / $branchesValid); $functionsBranchesValid += $branchesValid; $functionsBranchesCovered += $branchesValid; $methodElement = $document->createElement('method'); $methodElement->setAttribute('name', $functionName); $methodElement->setAttribute('signature', $function['signature']); $methodElement->setAttribute('line-rate', (string) $lineRate); $methodElement->setAttribute('branch-rate', (string) $branchRate); $methodElement->setAttribute('complexity', (string) $function['ccn']); $methodLinesElement = $document->createElement('lines'); $methodElement->appendChild($methodLinesElement); foreach (range($function['startLine'], $function['endLine']) as $line) { if (!isset($coverageData[$line])) { continue; } $methodLineElement = $document->createElement('line'); $methodLineElement->setAttribute('number', (string) $line); $methodLineElement->setAttribute('hits', (string) count($coverageData[$line])); $methodLinesElement->appendChild($methodLineElement); $classLineElement = $methodLineElement->cloneNode(); $classLinesElement->appendChild($classLineElement); } $methodsElement->appendChild($methodElement); } $packageElement->setAttribute('complexity', (string) $packageComplexity); if ($functionsLinesValid === 0) { continue; } $lineRate = $functionsLinesCovered / $functionsLinesValid; $branchRate = $functionsBranchesValid === 0 ? 0 : ($functionsBranchesCovered / $functionsBranchesValid); $classElement->setAttribute('line-rate', (string) $lineRate); $classElement->setAttribute('branch-rate', (string) $branchRate); $classElement->setAttribute('complexity', (string) $functionsComplexity); $classesElement->appendChild($classElement); } $coverageElement->setAttribute('complexity', (string) $complexity); $buffer = $document->saveXML(); if ($target !== null) { if (!str_contains($target, '://')) { Filesystem::createDirectory(dirname($target)); } if (@file_put_contents($target, $buffer) === false) { throw new WriteOperationFailedException($target); } } return $buffer; } } php-code-coverage/src/Report/Xml/Tests.php 0000644 00000002404 15253321353 0014453 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use function assert; use DOMElement; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage * * @phpstan-import-type TestType from \SebastianBergmann\CodeCoverage\CodeCoverage */ final class Tests { private readonly DOMElement $contextNode; public function __construct(DOMElement $context) { $this->contextNode = $context; } /** * @param TestType $result */ public function addTest(string $test, array $result): void { $node = $this->contextNode->appendChild( $this->contextNode->ownerDocument->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'test', ), ); assert($node instanceof DOMElement); $node->setAttribute('name', $test); $node->setAttribute('size', $result['size']); $node->setAttribute('status', $result['status']); } } php-code-coverage/src/Report/Xml/Project.php 0000644 00000004640 15253321353 0014763 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMDocument; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Project extends Node { public function __construct(string $directory) { $this->init(); $this->setProjectSourceDirectory($directory); } public function projectSourceDirectory(): string { return $this->contextNode()->getAttribute('source'); } public function buildInformation(): BuildInformation { $buildNode = $this->dom()->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'build', )->item(0); if (!$buildNode) { $buildNode = $this->dom()->documentElement->appendChild( $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'build', ), ); } return new BuildInformation($buildNode); } public function tests(): Tests { $testsNode = $this->contextNode()->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'tests', )->item(0); if (!$testsNode) { $testsNode = $this->contextNode()->appendChild( $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'tests', ), ); } return new Tests($testsNode); } public function asDom(): DOMDocument { return $this->dom(); } private function init(): void { $dom = new DOMDocument; $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><build/><project/></phpunit>'); $this->setContextNode( $dom->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'project', )->item(0), ); } private function setProjectSourceDirectory(string $name): void { $this->contextNode()->setAttribute('source', $name); } } php-code-coverage/src/Report/Xml/Node.php 0000644 00000004241 15253321353 0014237 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMDocument; use DOMElement; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ abstract class Node { private DOMDocument $dom; private DOMElement $contextNode; public function __construct(DOMElement $context) { $this->setContextNode($context); } public function dom(): DOMDocument { return $this->dom; } public function totals(): Totals { $totalsContainer = $this->contextNode()->firstChild; if (!$totalsContainer) { $totalsContainer = $this->contextNode()->appendChild( $this->dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'totals', ), ); } return new Totals($totalsContainer); } public function addDirectory(string $name): Directory { $dirNode = $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'directory', ); $dirNode->setAttribute('name', $name); $this->contextNode()->appendChild($dirNode); return new Directory($dirNode); } public function addFile(string $name, string $href): File { $fileNode = $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'file', ); $fileNode->setAttribute('name', $name); $fileNode->setAttribute('href', $href); $this->contextNode()->appendChild($fileNode); return new File($fileNode); } protected function setContextNode(DOMElement $context): void { $this->dom = $context->ownerDocument; $this->contextNode = $context; } protected function contextNode(): DOMElement { return $this->contextNode; } } php-code-coverage/src/Report/Xml/Totals.php 0000644 00000010366 15253321353 0014625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use function sprintf; use DOMElement; use DOMNode; use SebastianBergmann\CodeCoverage\Util\Percentage; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Totals { private readonly DOMNode $container; private readonly DOMElement $linesNode; private readonly DOMElement $methodsNode; private readonly DOMElement $functionsNode; private readonly DOMElement $classesNode; private readonly DOMElement $traitsNode; public function __construct(DOMElement $container) { $this->container = $container; $dom = $container->ownerDocument; $this->linesNode = $dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'lines', ); $this->methodsNode = $dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'methods', ); $this->functionsNode = $dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'functions', ); $this->classesNode = $dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'classes', ); $this->traitsNode = $dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'traits', ); $container->appendChild($this->linesNode); $container->appendChild($this->methodsNode); $container->appendChild($this->functionsNode); $container->appendChild($this->classesNode); $container->appendChild($this->traitsNode); } public function container(): DOMNode { return $this->container; } public function setNumLines(int $loc, int $cloc, int $ncloc, int $executable, int $executed): void { $this->linesNode->setAttribute('total', (string) $loc); $this->linesNode->setAttribute('comments', (string) $cloc); $this->linesNode->setAttribute('code', (string) $ncloc); $this->linesNode->setAttribute('executable', (string) $executable); $this->linesNode->setAttribute('executed', (string) $executed); $this->linesNode->setAttribute( 'percent', $executable === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($executed, $executable)->asFloat()), ); } public function setNumClasses(int $count, int $tested): void { $this->classesNode->setAttribute('count', (string) $count); $this->classesNode->setAttribute('tested', (string) $tested); $this->classesNode->setAttribute( 'percent', $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), ); } public function setNumTraits(int $count, int $tested): void { $this->traitsNode->setAttribute('count', (string) $count); $this->traitsNode->setAttribute('tested', (string) $tested); $this->traitsNode->setAttribute( 'percent', $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), ); } public function setNumMethods(int $count, int $tested): void { $this->methodsNode->setAttribute('count', (string) $count); $this->methodsNode->setAttribute('tested', (string) $tested); $this->methodsNode->setAttribute( 'percent', $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), ); } public function setNumFunctions(int $count, int $tested): void { $this->functionsNode->setAttribute('count', (string) $count); $this->functionsNode->setAttribute('tested', (string) $tested); $this->functionsNode->setAttribute( 'percent', $count === 0 ? '0' : sprintf('%01.2F', Percentage::fromFractionAndTotal($tested, $count)->asFloat()), ); } } php-code-coverage/src/Report/Xml/BuildInformation.php 0000644 00000004661 15253321353 0016625 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use function assert; use function phpversion; use DateTimeImmutable; use DOMElement; use SebastianBergmann\Environment\Runtime; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class BuildInformation { private readonly DOMElement $contextNode; public function __construct(DOMElement $contextNode) { $this->contextNode = $contextNode; } public function setRuntimeInformation(Runtime $runtime): void { $runtimeNode = $this->nodeByName('runtime'); $runtimeNode->setAttribute('name', $runtime->getName()); $runtimeNode->setAttribute('version', $runtime->getVersion()); $runtimeNode->setAttribute('url', $runtime->getVendorUrl()); $driverNode = $this->nodeByName('driver'); if ($runtime->hasXdebug()) { $driverNode->setAttribute('name', 'xdebug'); $driverNode->setAttribute('version', phpversion('xdebug')); } if ($runtime->hasPCOV()) { $driverNode->setAttribute('name', 'pcov'); $driverNode->setAttribute('version', phpversion('pcov')); } } public function setBuildTime(DateTimeImmutable $date): void { $this->contextNode->setAttribute('time', $date->format('D M j G:i:s T Y')); } public function setGeneratorVersions(string $phpUnitVersion, string $coverageVersion): void { $this->contextNode->setAttribute('phpunit', $phpUnitVersion); $this->contextNode->setAttribute('coverage', $coverageVersion); } private function nodeByName(string $name): DOMElement { $node = $this->contextNode->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', $name, )->item(0); if (!$node) { $node = $this->contextNode->appendChild( $this->contextNode->ownerDocument->createElementNS( 'https://schema.phpunit.de/coverage/1.0', $name, ), ); } assert($node instanceof DOMElement); return $node; } } php-code-coverage/src/Report/Xml/File.php 0000644 00000004047 15253321353 0014235 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMDocument; use DOMElement; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ class File { private readonly DOMDocument $dom; private readonly DOMElement $contextNode; public function __construct(DOMElement $context) { $this->dom = $context->ownerDocument; $this->contextNode = $context; } public function totals(): Totals { $totalsContainer = $this->contextNode->firstChild; if (!$totalsContainer) { $totalsContainer = $this->contextNode->appendChild( $this->dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'totals', ), ); } return new Totals($totalsContainer); } public function lineCoverage(string $line): Coverage { $coverage = $this->contextNode->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'coverage', )->item(0); if (!$coverage) { $coverage = $this->contextNode->appendChild( $this->dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'coverage', ), ); } $lineNode = $coverage->appendChild( $this->dom->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'line', ), ); return new Coverage($lineNode, $line); } protected function contextNode(): DOMElement { return $this->contextNode; } protected function dom(): DOMDocument { return $this->dom; } } php-code-coverage/src/Report/Xml/Coverage.php 0000644 00000003373 15253321353 0015112 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMElement; use SebastianBergmann\CodeCoverage\ReportAlreadyFinalizedException; use XMLWriter; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Coverage { private readonly XMLWriter $writer; private readonly DOMElement $contextNode; private bool $finalized = false; public function __construct(DOMElement $context, string $line) { $this->contextNode = $context; $this->writer = new XMLWriter; $this->writer->openMemory(); $this->writer->startElementNS(null, $context->nodeName, 'https://schema.phpunit.de/coverage/1.0'); $this->writer->writeAttribute('nr', $line); } /** * @throws ReportAlreadyFinalizedException */ public function addTest(string $test): void { if ($this->finalized) { throw new ReportAlreadyFinalizedException; } $this->writer->startElement('covered'); $this->writer->writeAttribute('by', $test); $this->writer->endElement(); } public function finalize(): void { $this->writer->endElement(); $fragment = $this->contextNode->ownerDocument->createDocumentFragment(); $fragment->appendXML($this->writer->outputMemory()); $this->contextNode->parentNode->replaceChild( $fragment, $this->contextNode, ); $this->finalized = true; } } php-code-coverage/src/Report/Xml/Method.php 0000644 00000003076 15253321353 0014577 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMElement; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Method { private readonly DOMElement $contextNode; public function __construct(DOMElement $context, string $name) { $this->contextNode = $context; $this->setName($name); } public function setSignature(string $signature): void { $this->contextNode->setAttribute('signature', $signature); } public function setLines(string $start, ?string $end = null): void { $this->contextNode->setAttribute('start', $start); if ($end !== null) { $this->contextNode->setAttribute('end', $end); } } public function setTotals(string $executable, string $executed, string $coverage): void { $this->contextNode->setAttribute('executable', $executable); $this->contextNode->setAttribute('executed', $executed); $this->contextNode->setAttribute('coverage', $coverage); } public function setCrap(string $crap): void { $this->contextNode->setAttribute('crap', $crap); } private function setName(string $name): void { $this->contextNode->setAttribute('name', $name); } } php-code-coverage/src/Report/Xml/Unit.php 0000644 00000004220 15253321353 0014266 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use function assert; use DOMElement; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Unit { private readonly DOMElement $contextNode; public function __construct(DOMElement $context, string $name) { $this->contextNode = $context; $this->setName($name); } public function setLines(int $start, int $executable, int $executed): void { $this->contextNode->setAttribute('start', (string) $start); $this->contextNode->setAttribute('executable', (string) $executable); $this->contextNode->setAttribute('executed', (string) $executed); } public function setCrap(float $crap): void { $this->contextNode->setAttribute('crap', (string) $crap); } public function setNamespace(string $namespace): void { $node = $this->contextNode->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'namespace', )->item(0); if (!$node) { $node = $this->contextNode->appendChild( $this->contextNode->ownerDocument->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'namespace', ), ); } assert($node instanceof DOMElement); $node->setAttribute('name', $namespace); } public function addMethod(string $name): Method { $node = $this->contextNode->appendChild( $this->contextNode->ownerDocument->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'method', ), ); return new Method($node, $name); } private function setName(string $name): void { $this->contextNode->setAttribute('name', $name); } } php-code-coverage/src/Report/Xml/Source.php 0000644 00000002165 15253321353 0014615 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use DOMElement; use TheSeer\Tokenizer\NamespaceUri; use TheSeer\Tokenizer\Tokenizer; use TheSeer\Tokenizer\XMLSerializer; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Source { private readonly DOMElement $context; public function __construct(DOMElement $context) { $this->context = $context; } public function setSourceCode(string $source): void { $context = $this->context; $tokens = (new Tokenizer)->parse($source); $srcDom = (new XMLSerializer(new NamespaceUri($context->namespaceURI)))->toDom($tokens); $context->parentNode->replaceChild( $context->ownerDocument->importNode($srcDom->documentElement, true), $context, ); } } php-code-coverage/src/Report/Xml/Directory.php 0000644 00000000737 15253321353 0015324 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Directory extends Node { } php-code-coverage/src/Report/Xml/Facade.php 0000644 00000021516 15253321353 0014521 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use const DIRECTORY_SEPARATOR; use const PHP_EOL; use function count; use function dirname; use function file_get_contents; use function file_put_contents; use function is_array; use function is_dir; use function is_file; use function is_writable; use function libxml_clear_errors; use function libxml_get_errors; use function libxml_use_internal_errors; use function sprintf; use function strlen; use function substr; use DateTimeImmutable; use DOMDocument; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\PathExistsButIsNotDirectoryException; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\AbstractNode; use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\CodeCoverage\Node\File as FileNode; use SebastianBergmann\CodeCoverage\Util\Filesystem as DirectoryUtil; use SebastianBergmann\CodeCoverage\Version; use SebastianBergmann\CodeCoverage\XmlException; use SebastianBergmann\Environment\Runtime; final class Facade { private string $target; private Project $project; private readonly string $phpUnitVersion; public function __construct(string $version) { $this->phpUnitVersion = $version; } /** * @throws XmlException */ public function process(CodeCoverage $coverage, string $target): void { if (substr($target, -1, 1) !== DIRECTORY_SEPARATOR) { $target .= DIRECTORY_SEPARATOR; } $this->target = $target; $this->initTargetDirectory($target); $report = $coverage->getReport(); $this->project = new Project( $coverage->getReport()->name(), ); $this->setBuildInformation(); $this->processTests($coverage->getTests()); $this->processDirectory($report, $this->project); $this->saveDocument($this->project->asDom(), 'index'); } private function setBuildInformation(): void { $buildNode = $this->project->buildInformation(); $buildNode->setRuntimeInformation(new Runtime); $buildNode->setBuildTime(new DateTimeImmutable); $buildNode->setGeneratorVersions($this->phpUnitVersion, Version::id()); } /** * @throws PathExistsButIsNotDirectoryException * @throws WriteOperationFailedException */ private function initTargetDirectory(string $directory): void { if (is_file($directory)) { if (!is_dir($directory)) { throw new PathExistsButIsNotDirectoryException($directory); } if (!is_writable($directory)) { throw new WriteOperationFailedException($directory); } } DirectoryUtil::createDirectory($directory); } /** * @throws XmlException */ private function processDirectory(DirectoryNode $directory, Node $context): void { $directoryName = $directory->name(); if ($this->project->projectSourceDirectory() === $directoryName) { $directoryName = '/'; } $directoryObject = $context->addDirectory($directoryName); $this->setTotals($directory, $directoryObject->totals()); foreach ($directory->directories() as $node) { $this->processDirectory($node, $directoryObject); } foreach ($directory->files() as $node) { $this->processFile($node, $directoryObject); } } /** * @throws XmlException */ private function processFile(FileNode $file, Directory $context): void { $fileObject = $context->addFile( $file->name(), $file->id() . '.xml', ); $this->setTotals($file, $fileObject->totals()); $path = substr( $file->pathAsString(), strlen($this->project->projectSourceDirectory()), ); $fileReport = new Report($path); $this->setTotals($file, $fileReport->totals()); foreach ($file->classesAndTraits() as $unit) { $this->processUnit($unit, $fileReport); } foreach ($file->functions() as $function) { $this->processFunction($function, $fileReport); } foreach ($file->lineCoverageData() as $line => $tests) { if (!is_array($tests) || count($tests) === 0) { continue; } $coverage = $fileReport->lineCoverage((string) $line); foreach ($tests as $test) { $coverage->addTest($test); } $coverage->finalize(); } $fileReport->source()->setSourceCode( file_get_contents($file->pathAsString()), ); $this->saveDocument($fileReport->asDom(), $file->id()); } private function processUnit(array $unit, Report $report): void { if (isset($unit['className'])) { $unitObject = $report->classObject($unit['className']); } else { $unitObject = $report->traitObject($unit['traitName']); } $unitObject->setLines( $unit['startLine'], $unit['executableLines'], $unit['executedLines'], ); $unitObject->setCrap((float) $unit['crap']); $unitObject->setNamespace($unit['namespace']); foreach ($unit['methods'] as $method) { $methodObject = $unitObject->addMethod($method['methodName']); $methodObject->setSignature($method['signature']); $methodObject->setLines((string) $method['startLine'], (string) $method['endLine']); $methodObject->setCrap($method['crap']); $methodObject->setTotals( (string) $method['executableLines'], (string) $method['executedLines'], (string) $method['coverage'], ); } } private function processFunction(array $function, Report $report): void { $functionObject = $report->functionObject($function['functionName']); $functionObject->setSignature($function['signature']); $functionObject->setLines((string) $function['startLine']); $functionObject->setCrap($function['crap']); $functionObject->setTotals((string) $function['executableLines'], (string) $function['executedLines'], (string) $function['coverage']); } private function processTests(array $tests): void { $testsObject = $this->project->tests(); foreach ($tests as $test => $result) { $testsObject->addTest($test, $result); } } private function setTotals(AbstractNode $node, Totals $totals): void { $loc = $node->linesOfCode(); $totals->setNumLines( $loc['linesOfCode'], $loc['commentLinesOfCode'], $loc['nonCommentLinesOfCode'], $node->numberOfExecutableLines(), $node->numberOfExecutedLines(), ); $totals->setNumClasses( $node->numberOfClasses(), $node->numberOfTestedClasses(), ); $totals->setNumTraits( $node->numberOfTraits(), $node->numberOfTestedTraits(), ); $totals->setNumMethods( $node->numberOfMethods(), $node->numberOfTestedMethods(), ); $totals->setNumFunctions( $node->numberOfFunctions(), $node->numberOfTestedFunctions(), ); } private function targetDirectory(): string { return $this->target; } /** * @throws XmlException */ private function saveDocument(DOMDocument $document, string $name): void { $filename = sprintf('%s/%s.xml', $this->targetDirectory(), $name); $document->formatOutput = true; $document->preserveWhiteSpace = false; $this->initTargetDirectory(dirname($filename)); file_put_contents($filename, $this->documentAsString($document)); } /** * @throws XmlException * * @see https://bugs.php.net/bug.php?id=79191 */ private function documentAsString(DOMDocument $document): string { $xmlErrorHandling = libxml_use_internal_errors(true); $xml = $document->saveXML(); if ($xml === false) { $message = 'Unable to generate the XML'; foreach (libxml_get_errors() as $error) { $message .= PHP_EOL . $error->message; } throw new XmlException($message); } libxml_clear_errors(); libxml_use_internal_errors($xmlErrorHandling); return $xml; } } php-code-coverage/src/Report/Xml/Report.php 0000644 00000005070 15253321353 0014626 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Xml; use function basename; use function dirname; use DOMDocument; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Report extends File { public function __construct(string $name) { $dom = new DOMDocument; $dom->loadXML('<?xml version="1.0" ?><phpunit xmlns="https://schema.phpunit.de/coverage/1.0"><file /></phpunit>'); $contextNode = $dom->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'file', )->item(0); parent::__construct($contextNode); $this->setName($name); } public function asDom(): DOMDocument { return $this->dom(); } public function functionObject($name): Method { $node = $this->contextNode()->appendChild( $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'function', ), ); return new Method($node, $name); } public function classObject($name): Unit { return $this->unitObject('class', $name); } public function traitObject($name): Unit { return $this->unitObject('trait', $name); } public function source(): Source { $source = $this->contextNode()->getElementsByTagNameNS( 'https://schema.phpunit.de/coverage/1.0', 'source', )->item(0); if (!$source) { $source = $this->contextNode()->appendChild( $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', 'source', ), ); } return new Source($source); } private function setName(string $name): void { $this->contextNode()->setAttribute('name', basename($name)); $this->contextNode()->setAttribute('path', dirname($name)); } private function unitObject(string $tagName, $name): Unit { $node = $this->contextNode()->appendChild( $this->dom()->createElementNS( 'https://schema.phpunit.de/coverage/1.0', $tagName, ), ); return new Unit($node, $name); } } php-code-coverage/src/Report/Crap4j.php 0000644 00000013113 15253321353 0013733 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function date; use function dirname; use function file_put_contents; use function htmlspecialchars; use function is_string; use function round; use function str_contains; use DOMDocument; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class Crap4j { private readonly int $threshold; public function __construct(int $threshold = 30) { $this->threshold = $threshold; } /** * @throws WriteOperationFailedException */ public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string { $document = new DOMDocument('1.0', 'UTF-8'); $document->formatOutput = true; $root = $document->createElement('crap_result'); $document->appendChild($root); $project = $document->createElement('project', is_string($name) ? $name : ''); $root->appendChild($project); $root->appendChild($document->createElement('timestamp', date('Y-m-d H:i:s'))); $stats = $document->createElement('stats'); $methodsNode = $document->createElement('methods'); $report = $coverage->getReport(); unset($coverage); $fullMethodCount = 0; $fullCrapMethodCount = 0; $fullCrapLoad = 0; $fullCrap = 0; foreach ($report as $item) { $namespace = 'global'; if (!$item instanceof File) { continue; } $file = $document->createElement('file'); $file->setAttribute('name', $item->pathAsString()); $classes = $item->classesAndTraits(); foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { $crapLoad = $this->crapLoad((float) $method['crap'], $method['ccn'], $method['coverage']); $fullCrap += $method['crap']; $fullCrapLoad += $crapLoad; $fullMethodCount++; if ($method['crap'] >= $this->threshold) { $fullCrapMethodCount++; } $methodNode = $document->createElement('method'); if (!empty($class['namespace'])) { $namespace = $class['namespace']; } $methodNode->appendChild($document->createElement('package', $namespace)); $methodNode->appendChild($document->createElement('className', $className)); $methodNode->appendChild($document->createElement('methodName', $methodName)); $methodNode->appendChild($document->createElement('methodSignature', htmlspecialchars($method['signature']))); $methodNode->appendChild($document->createElement('fullMethod', htmlspecialchars($method['signature']))); $methodNode->appendChild($document->createElement('crap', (string) $this->roundValue((float) $method['crap']))); $methodNode->appendChild($document->createElement('complexity', (string) $method['ccn'])); $methodNode->appendChild($document->createElement('coverage', (string) $this->roundValue($method['coverage']))); $methodNode->appendChild($document->createElement('crapLoad', (string) round($crapLoad))); $methodsNode->appendChild($methodNode); } } } $stats->appendChild($document->createElement('name', 'Method Crap Stats')); $stats->appendChild($document->createElement('methodCount', (string) $fullMethodCount)); $stats->appendChild($document->createElement('crapMethodCount', (string) $fullCrapMethodCount)); $stats->appendChild($document->createElement('crapLoad', (string) round($fullCrapLoad))); $stats->appendChild($document->createElement('totalCrap', (string) $fullCrap)); $crapMethodPercent = 0; if ($fullMethodCount > 0) { $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); } $stats->appendChild($document->createElement('crapMethodPercent', (string) $crapMethodPercent)); $root->appendChild($stats); $root->appendChild($methodsNode); $buffer = $document->saveXML(); if ($target !== null) { if (!str_contains($target, '://')) { Filesystem::createDirectory(dirname($target)); } if (@file_put_contents($target, $buffer) === false) { throw new WriteOperationFailedException($target); } } return $buffer; } private function crapLoad(float $crapValue, int $cyclomaticComplexity, float $coveragePercent): float { $crapLoad = 0; if ($crapValue >= $this->threshold) { $crapLoad += $cyclomaticComplexity * (1.0 - $coveragePercent / 100); $crapLoad += $cyclomaticComplexity / $this->threshold; } return $crapLoad; } private function roundValue(float $value): float { return round($value, 2); } } php-code-coverage/src/Report/Thresholds.php 0000644 00000002536 15253321353 0014736 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use SebastianBergmann\CodeCoverage\InvalidArgumentException; /** * @immutable */ final class Thresholds { private readonly int $lowUpperBound; private readonly int $highLowerBound; public static function default(): self { return new self(50, 90); } /** * @throws InvalidArgumentException */ public static function from(int $lowUpperBound, int $highLowerBound): self { if ($lowUpperBound > $highLowerBound) { throw new InvalidArgumentException( '$lowUpperBound must not be larger than $highLowerBound', ); } return new self($lowUpperBound, $highLowerBound); } private function __construct(int $lowUpperBound, int $highLowerBound) { $this->lowUpperBound = $lowUpperBound; $this->highLowerBound = $highLowerBound; } public function lowUpperBound(): int { return $this->lowUpperBound; } public function highLowerBound(): int { return $this->highLowerBound; } } php-code-coverage/src/Report/Clover.php 0000644 00000023405 15253321353 0014047 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report; use function count; use function dirname; use function file_put_contents; use function is_string; use function ksort; use function max; use function range; use function str_contains; use function time; use DOMDocument; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Driver\WriteOperationFailedException; use SebastianBergmann\CodeCoverage\Node\File; use SebastianBergmann\CodeCoverage\Util\Filesystem; final class Clover { /** * @throws WriteOperationFailedException */ public function process(CodeCoverage $coverage, ?string $target = null, ?string $name = null): string { $time = (string) time(); $xmlDocument = new DOMDocument('1.0', 'UTF-8'); $xmlDocument->formatOutput = true; $xmlCoverage = $xmlDocument->createElement('coverage'); $xmlCoverage->setAttribute('generated', $time); $xmlDocument->appendChild($xmlCoverage); $xmlProject = $xmlDocument->createElement('project'); $xmlProject->setAttribute('timestamp', $time); if (is_string($name)) { $xmlProject->setAttribute('name', $name); } $xmlCoverage->appendChild($xmlProject); $packages = []; $report = $coverage->getReport(); foreach ($report as $item) { if (!$item instanceof File) { continue; } /* @var File $item */ $xmlFile = $xmlDocument->createElement('file'); $xmlFile->setAttribute('name', $item->pathAsString()); $classes = $item->classesAndTraits(); $coverageData = $item->lineCoverageData(); $lines = []; $namespace = 'global'; foreach ($classes as $className => $class) { $classStatements = 0; $coveredClassStatements = 0; $coveredMethods = 0; $classMethods = 0; // Assumption: one namespace per file if ($class['namespace'] !== '') { $namespace = $class['namespace']; } foreach ($class['methods'] as $methodName => $method) { if ($method['executableLines'] == 0) { continue; } $classMethods++; $classStatements += $method['executableLines']; $coveredClassStatements += $method['executedLines']; if ($method['coverage'] == 100) { $coveredMethods++; } $methodCount = 0; foreach (range($method['startLine'], $method['endLine']) as $line) { if (isset($coverageData[$line])) { $methodCount = max($methodCount, count($coverageData[$line])); } } $lines[$method['startLine']] = [ 'ccn' => $method['ccn'], 'count' => $methodCount, 'crap' => $method['crap'], 'type' => 'method', 'visibility' => $method['visibility'], 'name' => $methodName, ]; } $xmlClass = $xmlDocument->createElement('class'); $xmlClass->setAttribute('name', $className); $xmlClass->setAttribute('namespace', $namespace); $xmlFile->appendChild($xmlClass); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('complexity', (string) $class['ccn']); $xmlMetrics->setAttribute('methods', (string) $classMethods); $xmlMetrics->setAttribute('coveredmethods', (string) $coveredMethods); $xmlMetrics->setAttribute('conditionals', (string) $class['executableBranches']); $xmlMetrics->setAttribute('coveredconditionals', (string) $class['executedBranches']); $xmlMetrics->setAttribute('statements', (string) $classStatements); $xmlMetrics->setAttribute('coveredstatements', (string) $coveredClassStatements); $xmlMetrics->setAttribute('elements', (string) ($classMethods + $classStatements + $class['executableBranches'])); $xmlMetrics->setAttribute('coveredelements', (string) ($coveredMethods + $coveredClassStatements + $class['executedBranches'])); $xmlClass->appendChild($xmlMetrics); } foreach ($coverageData as $line => $data) { if ($data === null || isset($lines[$line])) { continue; } $lines[$line] = [ 'count' => count($data), 'type' => 'stmt', ]; } ksort($lines); foreach ($lines as $line => $data) { $xmlLine = $xmlDocument->createElement('line'); $xmlLine->setAttribute('num', (string) $line); $xmlLine->setAttribute('type', $data['type']); if (isset($data['name'])) { $xmlLine->setAttribute('name', $data['name']); } if (isset($data['visibility'])) { $xmlLine->setAttribute('visibility', $data['visibility']); } if (isset($data['ccn'])) { $xmlLine->setAttribute('complexity', (string) $data['ccn']); } if (isset($data['crap'])) { $xmlLine->setAttribute('crap', (string) $data['crap']); } $xmlLine->setAttribute('count', (string) $data['count']); $xmlFile->appendChild($xmlLine); } $linesOfCode = $item->linesOfCode(); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); $xmlMetrics->setAttribute('classes', (string) $item->numberOfClassesAndTraits()); $xmlMetrics->setAttribute('methods', (string) $item->numberOfMethods()); $xmlMetrics->setAttribute('coveredmethods', (string) $item->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $item->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $item->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $item->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $item->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($item->numberOfMethods() + $item->numberOfExecutableLines() + $item->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($item->numberOfTestedMethods() + $item->numberOfExecutedLines() + $item->numberOfExecutedBranches())); $xmlFile->appendChild($xmlMetrics); if ($namespace === 'global') { $xmlProject->appendChild($xmlFile); } else { if (!isset($packages[$namespace])) { $packages[$namespace] = $xmlDocument->createElement( 'package', ); $packages[$namespace]->setAttribute('name', $namespace); $xmlProject->appendChild($packages[$namespace]); } $packages[$namespace]->appendChild($xmlFile); } } $linesOfCode = $report->linesOfCode(); $xmlMetrics = $xmlDocument->createElement('metrics'); $xmlMetrics->setAttribute('files', (string) count($report)); $xmlMetrics->setAttribute('loc', (string) $linesOfCode['linesOfCode']); $xmlMetrics->setAttribute('ncloc', (string) $linesOfCode['nonCommentLinesOfCode']); $xmlMetrics->setAttribute('classes', (string) $report->numberOfClassesAndTraits()); $xmlMetrics->setAttribute('methods', (string) $report->numberOfMethods()); $xmlMetrics->setAttribute('coveredmethods', (string) $report->numberOfTestedMethods()); $xmlMetrics->setAttribute('conditionals', (string) $report->numberOfExecutableBranches()); $xmlMetrics->setAttribute('coveredconditionals', (string) $report->numberOfExecutedBranches()); $xmlMetrics->setAttribute('statements', (string) $report->numberOfExecutableLines()); $xmlMetrics->setAttribute('coveredstatements', (string) $report->numberOfExecutedLines()); $xmlMetrics->setAttribute('elements', (string) ($report->numberOfMethods() + $report->numberOfExecutableLines() + $report->numberOfExecutableBranches())); $xmlMetrics->setAttribute('coveredelements', (string) ($report->numberOfTestedMethods() + $report->numberOfExecutedLines() + $report->numberOfExecutedBranches())); $xmlProject->appendChild($xmlMetrics); $buffer = $xmlDocument->saveXML(); if ($target !== null) { if (!str_contains($target, '://')) { Filesystem::createDirectory(dirname($target)); } if (@file_put_contents($target, $buffer) === false) { throw new WriteOperationFailedException($target); } } return $buffer; } } php-code-coverage/src/Report/Html/Colors.php 0000644 00000003312 15253321353 0014755 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; /** * @immutable */ final class Colors { private readonly string $successLow; private readonly string $successMedium; private readonly string $successHigh; private readonly string $warning; private readonly string $danger; public static function default(): self { return new self('#dff0d8', '#c3e3b5', '#99cb84', '#fcf8e3', '#f2dede'); } public static function from(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger): self { return new self($successLow, $successMedium, $successHigh, $warning, $danger); } private function __construct(string $successLow, string $successMedium, string $successHigh, string $warning, string $danger) { $this->successLow = $successLow; $this->successMedium = $successMedium; $this->successHigh = $successHigh; $this->warning = $warning; $this->danger = $danger; } public function successLow(): string { return $this->successLow; } public function successMedium(): string { return $this->successMedium; } public function successHigh(): string { return $this->successHigh; } public function warning(): string { return $this->warning; } public function danger(): string { return $this->danger; } } php-code-coverage/src/Report/Html/Renderer.php 0000644 00000023763 15253321353 0015276 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use function array_pop; use function count; use function sprintf; use function str_repeat; use function substr_count; use SebastianBergmann\CodeCoverage\Node\AbstractNode; use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\CodeCoverage\Node\File as FileNode; use SebastianBergmann\CodeCoverage\Report\Thresholds; use SebastianBergmann\CodeCoverage\Version; use SebastianBergmann\Environment\Runtime; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ abstract class Renderer { protected string $templatePath; protected string $generator; protected string $date; protected Thresholds $thresholds; protected bool $hasBranchCoverage; protected string $version; public function __construct(string $templatePath, string $generator, string $date, Thresholds $thresholds, bool $hasBranchCoverage) { $this->templatePath = $templatePath; $this->generator = $generator; $this->date = $date; $this->thresholds = $thresholds; $this->version = Version::id(); $this->hasBranchCoverage = $hasBranchCoverage; } protected function renderItemTemplate(Template $template, array $data): string { $numSeparator = ' / '; if (isset($data['numClasses']) && $data['numClasses'] > 0) { $classesLevel = $this->colorLevel($data['testedClassesPercent']); $classesNumber = $data['numTestedClasses'] . $numSeparator . $data['numClasses']; $classesBar = $this->coverageBar( $data['testedClassesPercent'], ); } else { $classesLevel = ''; $classesNumber = '0' . $numSeparator . '0'; $classesBar = ''; $data['testedClassesPercentAsString'] = 'n/a'; } if ($data['numMethods'] > 0) { $methodsLevel = $this->colorLevel($data['testedMethodsPercent']); $methodsNumber = $data['numTestedMethods'] . $numSeparator . $data['numMethods']; $methodsBar = $this->coverageBar( $data['testedMethodsPercent'], ); } else { $methodsLevel = ''; $methodsNumber = '0' . $numSeparator . '0'; $methodsBar = ''; $data['testedMethodsPercentAsString'] = 'n/a'; } if ($data['numExecutableLines'] > 0) { $linesLevel = $this->colorLevel($data['linesExecutedPercent']); $linesNumber = $data['numExecutedLines'] . $numSeparator . $data['numExecutableLines']; $linesBar = $this->coverageBar( $data['linesExecutedPercent'], ); } else { $linesLevel = ''; $linesNumber = '0' . $numSeparator . '0'; $linesBar = ''; $data['linesExecutedPercentAsString'] = 'n/a'; } if ($data['numExecutablePaths'] > 0) { $pathsLevel = $this->colorLevel($data['pathsExecutedPercent']); $pathsNumber = $data['numExecutedPaths'] . $numSeparator . $data['numExecutablePaths']; $pathsBar = $this->coverageBar( $data['pathsExecutedPercent'], ); } else { $pathsLevel = ''; $pathsNumber = '0' . $numSeparator . '0'; $pathsBar = ''; $data['pathsExecutedPercentAsString'] = 'n/a'; } if ($data['numExecutableBranches'] > 0) { $branchesLevel = $this->colorLevel($data['branchesExecutedPercent']); $branchesNumber = $data['numExecutedBranches'] . $numSeparator . $data['numExecutableBranches']; $branchesBar = $this->coverageBar( $data['branchesExecutedPercent'], ); } else { $branchesLevel = ''; $branchesNumber = '0' . $numSeparator . '0'; $branchesBar = ''; $data['branchesExecutedPercentAsString'] = 'n/a'; } $template->setVar( [ 'icon' => $data['icon'] ?? '', 'crap' => $data['crap'] ?? '', 'name' => $data['name'], 'lines_bar' => $linesBar, 'lines_executed_percent' => $data['linesExecutedPercentAsString'], 'lines_level' => $linesLevel, 'lines_number' => $linesNumber, 'paths_bar' => $pathsBar, 'paths_executed_percent' => $data['pathsExecutedPercentAsString'], 'paths_level' => $pathsLevel, 'paths_number' => $pathsNumber, 'branches_bar' => $branchesBar, 'branches_executed_percent' => $data['branchesExecutedPercentAsString'], 'branches_level' => $branchesLevel, 'branches_number' => $branchesNumber, 'methods_bar' => $methodsBar, 'methods_tested_percent' => $data['testedMethodsPercentAsString'], 'methods_level' => $methodsLevel, 'methods_number' => $methodsNumber, 'classes_bar' => $classesBar, 'classes_tested_percent' => $data['testedClassesPercentAsString'] ?? '', 'classes_level' => $classesLevel, 'classes_number' => $classesNumber, ], ); return $template->render(); } protected function setCommonTemplateVariables(Template $template, AbstractNode $node): void { $template->setVar( [ 'id' => $node->id(), 'full_path' => $node->pathAsString(), 'path_to_root' => $this->pathToRoot($node), 'breadcrumbs' => $this->breadcrumbs($node), 'date' => $this->date, 'version' => $this->version, 'runtime' => $this->runtimeString(), 'generator' => $this->generator, 'low_upper_bound' => $this->thresholds->lowUpperBound(), 'high_lower_bound' => $this->thresholds->highLowerBound(), ], ); } protected function breadcrumbs(AbstractNode $node): string { $breadcrumbs = ''; $path = $node->pathAsArray(); $pathToRoot = []; $max = count($path); if ($node instanceof FileNode) { $max--; } for ($i = 0; $i < $max; $i++) { $pathToRoot[] = str_repeat('../', $i); } foreach ($path as $step) { if ($step !== $node) { $breadcrumbs .= $this->inactiveBreadcrumb( $step, array_pop($pathToRoot), ); } else { $breadcrumbs .= $this->activeBreadcrumb($step); } } return $breadcrumbs; } protected function activeBreadcrumb(AbstractNode $node): string { $buffer = sprintf( ' <li class="breadcrumb-item active">%s</li>' . "\n", $node->name(), ); if ($node instanceof DirectoryNode) { $buffer .= ' <li class="breadcrumb-item">(<a href="dashboard.html">Dashboard</a>)</li>' . "\n"; } return $buffer; } protected function inactiveBreadcrumb(AbstractNode $node, string $pathToRoot): string { return sprintf( ' <li class="breadcrumb-item"><a href="%sindex.html">%s</a></li>' . "\n", $pathToRoot, $node->name(), ); } protected function pathToRoot(AbstractNode $node): string { $id = $node->id(); $depth = substr_count($id, '/'); if ($id !== 'index' && $node instanceof DirectoryNode) { $depth++; } return str_repeat('../', $depth); } protected function coverageBar(float $percent): string { $level = $this->colorLevel($percent); $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'coverage_bar_branch.html' : 'coverage_bar.html'); $template = new Template( $templateName, '{{', '}}', ); $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]); return $template->render(); } protected function colorLevel(float $percent): string { if ($percent <= $this->thresholds->lowUpperBound()) { return 'danger'; } if ($percent > $this->thresholds->lowUpperBound() && $percent < $this->thresholds->highLowerBound()) { return 'warning'; } return 'success'; } private function runtimeString(): string { $runtime = new Runtime; return sprintf( '<a href="%s" target="_top">%s %s</a>', $runtime->getVendorUrl(), $runtime->getName(), $runtime->getVersion(), ); } } php-code-coverage/src/Report/Html/CustomCssFile.php 0000644 00000002100 15253321353 0016231 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use function is_file; use SebastianBergmann\CodeCoverage\InvalidArgumentException; /** * @immutable */ final class CustomCssFile { private readonly string $path; public static function default(): self { return new self(__DIR__ . '/Renderer/Template/css/custom.css'); } /** * @throws InvalidArgumentException */ public static function from(string $path): self { if (!is_file($path)) { throw new InvalidArgumentException( '$path does not exist', ); } return new self($path); } private function __construct(string $path) { $this->path = $path; } public function path(): string { return $this->path; } } php-code-coverage/src/Report/Html/Renderer/Dashboard.php 0000644 00000023770 15253321353 0017163 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use function array_values; use function arsort; use function asort; use function count; use function explode; use function floor; use function json_encode; use function sprintf; use function str_replace; use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; use SebastianBergmann\CodeCoverage\Node\AbstractNode; use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\Template\Exception; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class Dashboard extends Renderer { public function render(DirectoryNode $node, string $file): void { $classes = $node->classesAndTraits(); $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'dashboard_branch.html' : 'dashboard.html'); $template = new Template( $templateName, '{{', '}}', ); $this->setCommonTemplateVariables($template, $node); $baseLink = $node->id() . '/'; $complexity = $this->complexity($classes, $baseLink); $coverageDistribution = $this->coverageDistribution($classes); $insufficientCoverage = $this->insufficientCoverage($classes, $baseLink); $projectRisks = $this->projectRisks($classes, $baseLink); $template->setVar( [ 'insufficient_coverage_classes' => $insufficientCoverage['class'], 'insufficient_coverage_methods' => $insufficientCoverage['method'], 'project_risks_classes' => $projectRisks['class'], 'project_risks_methods' => $projectRisks['method'], 'complexity_class' => $complexity['class'], 'complexity_method' => $complexity['method'], 'class_coverage_distribution' => $coverageDistribution['class'], 'method_coverage_distribution' => $coverageDistribution['method'], ], ); try { $template->renderTo($file); } catch (Exception $e) { throw new FileCouldNotBeWrittenException( $e->getMessage(), $e->getCode(), $e, ); } } protected function activeBreadcrumb(AbstractNode $node): string { return sprintf( ' <li class="breadcrumb-item"><a href="index.html">%s</a></li>' . "\n" . ' <li class="breadcrumb-item active">(Dashboard)</li>' . "\n", $node->name(), ); } /** * Returns the data for the Class/Method Complexity charts. */ private function complexity(array $classes, string $baseLink): array { $result = ['class' => [], 'method' => []]; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($className !== '*') { $methodName = $className . '::' . $methodName; } $result['method'][] = [ $method['coverage'], $method['ccn'], sprintf( '<a href="%s">%s</a>', str_replace($baseLink, '', $method['link']), $methodName, ), ]; } $result['class'][] = [ $class['coverage'], $class['ccn'], sprintf( '<a href="%s">%s</a>', str_replace($baseLink, '', $class['link']), $className, ), ]; } return [ 'class' => json_encode($result['class']), 'method' => json_encode($result['method']), ]; } /** * Returns the data for the Class / Method Coverage Distribution chart. */ private function coverageDistribution(array $classes): array { $result = [ 'class' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0, ], 'method' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, '20-30%' => 0, '30-40%' => 0, '40-50%' => 0, '50-60%' => 0, '60-70%' => 0, '70-80%' => 0, '80-90%' => 0, '90-100%' => 0, '100%' => 0, ], ]; foreach ($classes as $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] === 0) { $result['method']['0%']++; } elseif ($method['coverage'] === 100) { $result['method']['100%']++; } else { $key = floor($method['coverage'] / 10) * 10; $key = $key . '-' . ($key + 10) . '%'; $result['method'][$key]++; } } if ($class['coverage'] === 0) { $result['class']['0%']++; } elseif ($class['coverage'] === 100) { $result['class']['100%']++; } else { $key = floor($class['coverage'] / 10) * 10; $key = $key . '-' . ($key + 10) . '%'; $result['class'][$key]++; } } return [ 'class' => json_encode(array_values($result['class'])), 'method' => json_encode(array_values($result['method'])), ]; } /** * Returns the classes / methods with insufficient coverage. */ private function insufficientCoverage(array $classes, string $baseLink): array { $leastTestedClasses = []; $leastTestedMethods = []; $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] < $this->thresholds->highLowerBound()) { $key = $methodName; if ($className !== '*') { $key = $className . '::' . $methodName; } $leastTestedMethods[$key] = $method['coverage']; } } if ($class['coverage'] < $this->thresholds->highLowerBound()) { $leastTestedClasses[$className] = $class['coverage']; } } asort($leastTestedClasses); asort($leastTestedMethods); foreach ($leastTestedClasses as $className => $coverage) { $result['class'] .= sprintf( ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d%%</td></tr>' . "\n", str_replace($baseLink, '', $classes[$className]['link']), $className, $coverage, ); } foreach ($leastTestedMethods as $methodName => $coverage) { [$class, $method] = explode('::', $methodName); $result['method'] .= sprintf( ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d%%</td></tr>' . "\n", str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $coverage, ); } return $result; } /** * Returns the project risks according to the CRAP index. */ private function projectRisks(array $classes, string $baseLink): array { $classRisks = []; $methodRisks = []; $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { if ($method['coverage'] < $this->thresholds->highLowerBound() && $method['ccn'] > 1) { $key = $methodName; if ($className !== '*') { $key = $className . '::' . $methodName; } $methodRisks[$key] = $method['crap']; } } if ($class['coverage'] < $this->thresholds->highLowerBound() && $class['ccn'] > count($class['methods'])) { $classRisks[$className] = $class['crap']; } } arsort($classRisks); arsort($methodRisks); foreach ($classRisks as $className => $crap) { $result['class'] .= sprintf( ' <tr><td><a href="%s">%s</a></td><td class="text-right">%d</td></tr>' . "\n", str_replace($baseLink, '', $classes[$className]['link']), $className, $crap, ); } foreach ($methodRisks as $methodName => $crap) { [$class, $method] = explode('::', $methodName); $result['method'] .= sprintf( ' <tr><td><a href="%s"><abbr title="%s">%s</abbr></a></td><td class="text-right">%d</td></tr>' . "\n", str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, $crap, ); } return $result; } } php-code-coverage/src/Report/Html/Renderer/File.php 0000644 00000121063 15253321353 0016145 0 ustar 00 <?php declare(strict_types=1); /* * This file is part of phpunit/php-code-coverage. * * (c) Sebastian Bergmann <sebastian@phpunit.de> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\CodeCoverage\Report\Html; use const ENT_COMPAT; use const ENT_HTML401; use const ENT_SUBSTITUTE; use const T_ABSTRACT; use const T_ARRAY; use const T_AS; use const T_BREAK; use const T_CALLABLE; use const T_CASE; use const T_CATCH; use const T_CLASS; use const T_CLONE; use const T_COMMENT; use const T_CONST; use const T_CONTINUE; use const T_DECLARE; use const T_DEFAULT; use const T_DO; use const T_DOC_COMMENT; use const T_ECHO; use const T_ELSE; use const T_ELSEIF; use const T_EMPTY; use const T_ENDDECLARE; use const T_ENDFOR; use const T_ENDFOREACH; use const T_ENDIF; use const T_ENDSWITCH; use const T_ENDWHILE; use const T_EVAL; use const T_EXIT; use const T_EXTENDS; use const T_FINAL; use const T_FINALLY; use const T_FOR; use const T_FOREACH; use const T_FUNCTION; use const T_GLOBAL; use const T_GOTO; use const T_HALT_COMPILER; use const T_IF; use const T_IMPLEMENTS; use const T_INCLUDE; use const T_INCLUDE_ONCE; use const T_INLINE_HTML; use const T_INSTANCEOF; use const T_INSTEADOF; use const T_INTERFACE; use const T_ISSET; use const T_LIST; use const T_NAMESPACE; use const T_NEW; use const T_PRINT; use const T_PRIVATE; use const T_PROTECTED; use const T_PUBLIC; use const T_REQUIRE; use const T_REQUIRE_ONCE; use const T_RETURN; use const T_STATIC; use const T_SWITCH; use const T_THROW; use const T_TRAIT; use const T_TRY; use const T_UNSET; use const T_USE; use const T_VAR; use const T_WHILE; use const T_YIELD; use const T_YIELD_FROM; use function array_key_exists; use function array_keys; use function array_merge; use function array_pop; use function array_unique; use function count; use function explode; use function file_get_contents; use function htmlspecialchars; use function is_string; use function ksort; use function range; use function sort; use function sprintf; use function str_ends_with; use function str_replace; use function token_get_all; use function trim; use SebastianBergmann\CodeCoverage\FileCouldNotBeWrittenException; use SebastianBergmann\CodeCoverage\Node\File as FileNode; use SebastianBergmann\CodeCoverage\Util\Percentage; use SebastianBergmann\Template\Exception; use SebastianBergmann\Template\Template; /** * @internal This class is not covered by the backward compatibility promise for phpunit/php-code-coverage */ final class File extends Renderer { /** * @var array<int,true> */ private const KEYWORD_TOKENS = [ T_ABSTRACT => true, T_ARRAY => true, T_AS => true, T_BREAK => true, T_CALLABLE => true, T_CASE => true, T_CATCH => true, T_CLASS => true, T_CLONE => true, T_CONST => true, T_CONTINUE => true, T_DECLARE => true, T_DEFAULT => true, T_DO => true, T_ECHO => true, T_ELSE => true, T_ELSEIF => true, T_EMPTY => true, T_ENDDECLARE => true, T_ENDFOR => true, T_ENDFOREACH => true, T_ENDIF => true, T_ENDSWITCH => true, T_ENDWHILE => true, T_ENUM => true, T_EVAL => true, T_EXIT => true, T_EXTENDS => true, T_FINAL => true, T_FINALLY => true, T_FN => true, T_FOR => true, T_FOREACH => true, T_FUNCTION => true, T_GLOBAL => true, T_GOTO => true, T_HALT_COMPILER => true, T_IF => true, T_IMPLEMENTS => true, T_INCLUDE => true, T_INCLUDE_ONCE => true, T_INSTANCEOF => true, T_INSTEADOF => true, T_INTERFACE => true, T_ISSET => true, T_LIST => true, T_MATCH => true, T_NAMESPACE => true, T_NEW => true, T_PRINT => true, T_PRIVATE => true, T_PROTECTED => true, T_PUBLIC => true, T_READONLY => true, T_REQUIRE => true, T_REQUIRE_ONCE => true, T_RETURN => true, T_STATIC => true, T_SWITCH => true, T_THROW => true, T_TRAIT => true, T_TRY => true, T_UNSET => true, T_USE => true, T_VAR => true, T_WHILE => true, T_YIELD => true, T_YIELD_FROM => true, ]; private static array $formattedSourceCache = []; private int $htmlSpecialCharsFlags = ENT_COMPAT | ENT_HTML401 | ENT_SUBSTITUTE; public function render(FileNode $node, string $file): void { $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_branch.html' : 'file.html'); $template = new Template($templateName, '{{', '}}'); $this->setCommonTemplateVariables($template, $node); $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithLineCoverage($node), 'legend' => '<p><span class="legend covered-by-small-tests">Covered by small (and larger) tests</span><span class="legend covered-by-medium-tests">Covered by medium (and large) tests</span><span class="legend covered-by-large-tests">Covered by large tests (and tests of unknown size)</span><span class="legend not-covered">Not covered</span><span class="legend not-coverable">Not coverable</span></p>', 'structure' => '', ], ); try { $template->renderTo($file . '.html'); } catch (Exception $e) { throw new FileCouldNotBeWrittenException( $e->getMessage(), $e->getCode(), $e, ); } if ($this->hasBranchCoverage) { $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithBranchCoverage($node), 'legend' => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>', 'structure' => $this->renderBranchStructure($node), ], ); try { $template->renderTo($file . '_branch.html'); } catch (Exception $e) { throw new FileCouldNotBeWrittenException( $e->getMessage(), $e->getCode(), $e, ); } $template->setVar( [ 'items' => $this->renderItems($node), 'lines' => $this->renderSourceWithPathCoverage($node), 'legend' => '<p><span class="success"><strong>Fully covered</strong></span><span class="warning"><strong>Partially covered</strong></span><span class="danger"><strong>Not covered</strong></span></p>', 'structure' => $this->renderPathStructure($node), ], ); try { $template->renderTo($file . '_path.html'); } catch (Exception $e) { throw new FileCouldNotBeWrittenException( $e->getMessage(), $e->getCode(), $e, ); } } } private function renderItems(FileNode $node): string { $templateName = $this->templatePath . ($this->hasBranchCoverage ? 'file_item_branch.html' : 'file_item.html'); $template = new Template($templateName, '{{', '}}'); $methodTemplateName = $this->templatePath . ($this->hasBranchCoverage ? 'method_item_branch.html' : 'method_item.html'); $methodItemTemplate = new Template( $methodTemplateName, '{{', '}}', ); $items = $this->renderItemTemplate( $template, [ 'name' => 'Total', 'numClasses' => $node->numberOfClassesAndTraits(), 'numTestedClasses' => $node->numberOfTestedClassesAndTraits(), 'numMethods' => $node->numberOfFunctionsAndMethods(), 'numTestedMethods' => $node->numberOfTestedFunctionsAndMethods(), 'linesExecutedPercent' => $node->percentageOfExecutedLines()->asFloat(), 'linesExecutedPercentAsString' => $node->percentageOfExecutedLines()->asString(), 'numExecutedLines' => $node->numberOfExecutedLines(), 'numExecutableLines' => $node->numberOfExecutableLines(), 'branchesExecutedPercent' => $node->percentageOfExecutedBranches()->asFloat(), 'branchesExecutedPercentAsString' => $node->percentageOfExecutedBranches()->asString(), 'numExecutedBranches' => $node->numberOfExecutedBranches(), 'numExecutableBranches' => $node->numberOfExecutableBranches(), 'pathsExecutedPercent' => $node->percentageOfExecutedPaths()->asFloat(), 'pathsExecutedPercentAsString' => $node->percentageOfExecutedPaths()->asString(), 'numExecutedPaths' => $node->numberOfExecutedPaths(), 'numExecutablePaths' => $node->numberOfExecutablePaths(), 'testedMethodsPercent' => $node->percentageOfTestedFunctionsAndMethods()->asFloat(), 'testedMethodsPercentAsString' => $node->percentageOfTestedFunctionsAndMethods()->asString(), 'testedClassesPercent' => $node->percentageOfTestedClassesAndTraits()->asFloat(), 'testedClassesPercentAsString' => $node->percentageOfTestedClassesAndTraits()->asString(), 'crap' => '<abbr title="Change Risk Anti-Patterns (CRAP) Index">CRAP</abbr>', ], ); $items .= $this->renderFunctionItems( $node->functions(), $methodItemTemplate, ); $items .= $this->renderTraitOrClassItems( $node->traits(), $template, $methodItemTemplate, ); $items .= $this->renderTraitOrClassItems( $node->classes(), $template, $methodItemTemplate, ); return $items; } private function renderTraitOrClassItems(array $items, Template $template, Template $methodItemTemplate): string { $buffer = ''; if (empty($items)) { return $buffer; } foreach ($items as $name => $item) { $numMethods = 0; $numTestedMethods = 0; foreach ($item['methods'] as $method) { if ($method['executableLines'] > 0) { $numMethods++; if ($method['executedLines'] === $method['executableLines']) { $numTestedMethods++; } } } if ($item['executableLines'] > 0) { $numClasses = 1; $numTestedClasses = $numTestedMethods === $numMethods ? 1 : 0; $linesExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'], )->asString(); $branchesExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'], )->asString(); $pathsExecutedPercentAsString = Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'], )->asString(); } else { $numClasses = 0; $numTestedClasses = 0; $linesExecutedPercentAsString = 'n/a'; $branchesExecutedPercentAsString = 'n/a'; $pathsExecutedPercentAsString = 'n/a'; } $testedMethodsPercentage = Percentage::fromFractionAndTotal( $numTestedMethods, $numMethods, ); $testedClassesPercentage = Percentage::fromFractionAndTotal( $numTestedMethods === $numMethods ? 1 : 0, 1, ); $buffer .= $this->renderItemTemplate( $template, [ 'name' => $this->abbreviateClassName($name), 'numClasses' => $numClasses, 'numTestedClasses' => $numTestedClasses, 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'], )->asFloat(), 'linesExecutedPercentAsString' => $linesExecutedPercentAsString, 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'branchesExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'], )->asFloat(), 'branchesExecutedPercentAsString' => $branchesExecutedPercentAsString, 'numExecutedBranches' => $item['executedBranches'], 'numExecutableBranches' => $item['executableBranches'], 'pathsExecutedPercent' => Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'], )->asFloat(), 'pathsExecutedPercentAsString' => $pathsExecutedPercentAsString, 'numExecutedPaths' => $item['executedPaths'], 'numExecutablePaths' => $item['executablePaths'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'testedClassesPercent' => $testedClassesPercentage->asFloat(), 'testedClassesPercentAsString' => $testedClassesPercentage->asString(), 'crap' => $item['crap'], ], ); foreach ($item['methods'] as $method) { $buffer .= $this->renderFunctionOrMethodItem( $methodItemTemplate, $method, ' ', ); } } return $buffer; } private function renderFunctionItems(array $functions, Template $template): string { if (empty($functions)) { return ''; } $buffer = ''; foreach ($functions as $function) { $buffer .= $this->renderFunctionOrMethodItem( $template, $function, ); } return $buffer; } private function renderFunctionOrMethodItem(Template $template, array $item, string $indent = ''): string { $numMethods = 0; $numTestedMethods = 0; if ($item['executableLines'] > 0) { $numMethods = 1; if ($item['executedLines'] === $item['executableLines']) { $numTestedMethods = 1; } } $executedLinesPercentage = Percentage::fromFractionAndTotal( $item['executedLines'], $item['executableLines'], ); $executedBranchesPercentage = Percentage::fromFractionAndTotal( $item['executedBranches'], $item['executableBranches'], ); $executedPathsPercentage = Percentage::fromFractionAndTotal( $item['executedPaths'], $item['executablePaths'], ); $testedMethodsPercentage = Percentage::fromFractionAndTotal( $numTestedMethods, 1, ); return $this->renderItemTemplate( $template, [ 'name' => sprintf( '%s<a href="#%d"><abbr title="%s">%s</abbr></a>', $indent, $item['startLine'], htmlspecialchars($item['signature'], $this->htmlSpecialCharsFlags), $item['functionName'] ?? $item['methodName'], ), 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, 'linesExecutedPercent' => $executedLinesPercentage->asFloat(), 'linesExecutedPercentAsString' => $executedLinesPercentage->asString(), 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], 'branchesExecutedPercent' => $executedBranchesPercentage->asFloat(), 'branchesExecutedPercentAsString' => $executedBranchesPercentage->asString(), 'numExecutedBranches' => $item['executedBranches'], 'numExecutableBranches' => $item['executableBranches'], 'pathsExecutedPercent' => $executedPathsPercentage->asFloat(), 'pathsExecutedPercentAsString' => $executedPathsPercentage->asString(), 'numExecutedPaths' => $item['executedPaths'], 'numExecutablePaths' => $item['executablePaths'], 'testedMethodsPercent' => $testedMethodsPercentage->asFloat(), 'testedMethodsPercentAsString' => $testedMethodsPercentage->asString(), 'crap' => $item['crap'], ], ); } private function renderSourceWithLineCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $coverageData = $node->lineCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lines = ''; $i = 1; foreach ($codeLines as $line) { $trClass = ''; $popoverContent = ''; $popoverTitle = ''; if (array_key_exists($i, $coverageData)) { $numTests = ($coverageData[$i] ? count($coverageData[$i]) : 0); if ($coverageData[$i] === null) { $trClass = 'warning'; } elseif ($numTests === 0) { $trClass = 'danger'; } else { if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover line ' . $i; } else { $popoverTitle = '1 test covers line ' . $i; } $lineCss = 'covered-by-large-tests'; $popoverContent = '<ul>'; foreach ($coverageData[$i] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '</ul>'; $trClass = $lineCss . ' popin'; } } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderSourceWithBranchCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $functionCoverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lineData = []; /** @var int $line */ foreach (array_keys($codeLines) as $line) { $lineData[$line + 1] = [ 'includedInBranches' => 0, 'includedInHitBranches' => 0, 'tests' => [], ]; } foreach ($functionCoverageData as $method) { foreach ($method['branches'] as $branch) { foreach (range($branch['line_start'], $branch['line_end']) as $line) { if (!isset($lineData[$line])) { // blank line at end of file is sometimes included here continue; } $lineData[$line]['includedInBranches']++; if ($branch['hit']) { $lineData[$line]['includedInHitBranches']++; $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $branch['hit'])); } } } } $lines = ''; $i = 1; /** @var string $line */ foreach ($codeLines as $line) { $trClass = ''; $popover = ''; if ($lineData[$i]['includedInBranches'] > 0) { $lineCss = 'success'; if ($lineData[$i]['includedInHitBranches'] === 0) { $lineCss = 'danger'; } elseif ($lineData[$i]['includedInHitBranches'] !== $lineData[$i]['includedInBranches']) { $lineCss = 'warning'; } $popoverContent = '<ul>'; if (count($lineData[$i]['tests']) === 1) { $popoverTitle = '1 test covers line ' . $i; } else { $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; } $popoverTitle .= '. These are covering ' . $lineData[$i]['includedInHitBranches'] . ' out of the ' . $lineData[$i]['includedInBranches'] . ' code branches.'; foreach ($lineData[$i]['tests'] as $test) { $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '</ul>'; $trClass = $lineCss . ' popin'; $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderSourceWithPathCoverage(FileNode $node): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $functionCoverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $lineData = []; /** @var int $line */ foreach (array_keys($codeLines) as $line) { $lineData[$line + 1] = [ 'includedInPaths' => [], 'includedInHitPaths' => [], 'tests' => [], ]; } foreach ($functionCoverageData as $method) { foreach ($method['paths'] as $pathId => $path) { foreach ($path['path'] as $branchTaken) { foreach (range($method['branches'][$branchTaken]['line_start'], $method['branches'][$branchTaken]['line_end']) as $line) { if (!isset($lineData[$line])) { continue; } $lineData[$line]['includedInPaths'][] = $pathId; if ($path['hit']) { $lineData[$line]['includedInHitPaths'][] = $pathId; $lineData[$line]['tests'] = array_unique(array_merge($lineData[$line]['tests'], $path['hit'])); } } } } } $lines = ''; $i = 1; /** @var string $line */ foreach ($codeLines as $line) { $trClass = ''; $popover = ''; $includedInPathsCount = count(array_unique($lineData[$i]['includedInPaths'])); $includedInHitPathsCount = count(array_unique($lineData[$i]['includedInHitPaths'])); if ($includedInPathsCount > 0) { $lineCss = 'success'; if ($includedInHitPathsCount === 0) { $lineCss = 'danger'; } elseif ($includedInHitPathsCount !== $includedInPathsCount) { $lineCss = 'warning'; } $popoverContent = '<ul>'; if (count($lineData[$i]['tests']) === 1) { $popoverTitle = '1 test covers line ' . $i; } else { $popoverTitle = count($lineData[$i]['tests']) . ' tests cover line ' . $i; } $popoverTitle .= '. These are covering ' . $includedInHitPathsCount . ' out of the ' . $includedInPathsCount . ' code paths.'; foreach ($lineData[$i]['tests'] as $test) { $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $popoverContent .= '</ul>'; $trClass = $lineCss . ' popin'; $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), ); } $lines .= $this->renderLine($singleLineTemplate, $i, $line, $trClass, $popover); $i++; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderBranchStructure(FileNode $node): string { $branchesTemplate = new Template($this->templatePath . 'branches.html.dist', '{{', '}}'); $coverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $branches = ''; ksort($coverageData); foreach ($coverageData as $methodName => $methodData) { if (!$methodData['branches']) { continue; } $branchStructure = ''; foreach ($methodData['branches'] as $branch) { $branchStructure .= $this->renderBranchLines($branch, $codeLines, $testData); } if ($branchStructure !== '') { // don't show empty branches $branches .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n"; $branches .= $branchStructure; } } $branchesTemplate->setVar(['branches' => $branches]); return $branchesTemplate->render(); } private function renderBranchLines(array $branch, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $lines = ''; $branchLines = range($branch['line_start'], $branch['line_end']); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ foreach ($branchLines as $line) { if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here continue; } $popoverContent = ''; $popoverTitle = ''; $numTests = count($branch['hit']); if ($numTests === 0) { $trClass = 'danger'; } else { $lineCss = 'covered-by-large-tests'; $popoverContent = '<ul>'; if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover this branch'; } else { $popoverTitle = '1 test covers this branch'; } foreach ($branch['hit'] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $trClass = $lineCss . ' popin'; } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), ); } $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); } if ($lines === '') { return ''; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderPathStructure(FileNode $node): string { $pathsTemplate = new Template($this->templatePath . 'paths.html.dist', '{{', '}}'); $coverageData = $node->functionCoverageData(); $testData = $node->testData(); $codeLines = $this->loadFile($node->pathAsString()); $paths = ''; ksort($coverageData); foreach ($coverageData as $methodName => $methodData) { if (!$methodData['paths']) { continue; } $pathStructure = ''; if (count($methodData['paths']) > 100) { $pathStructure .= '<p>' . count($methodData['paths']) . ' is too many paths to sensibly render, consider refactoring your code to bring this number down.</p>'; continue; } foreach ($methodData['paths'] as $path) { $pathStructure .= $this->renderPathLines($path, $methodData['branches'], $codeLines, $testData); } if ($pathStructure !== '') { $paths .= '<h5 class="structure-heading"><a name="' . htmlspecialchars($methodName, $this->htmlSpecialCharsFlags) . '">' . $this->abbreviateMethodName($methodName) . '</a></h5>' . "\n"; $paths .= $pathStructure; } } $pathsTemplate->setVar(['paths' => $paths]); return $pathsTemplate->render(); } private function renderPathLines(array $path, array $branches, array $codeLines, array $testData): string { $linesTemplate = new Template($this->templatePath . 'lines.html.dist', '{{', '}}'); $singleLineTemplate = new Template($this->templatePath . 'line.html.dist', '{{', '}}'); $lines = ''; $first = true; foreach ($path['path'] as $branchId) { if ($first) { $first = false; } else { $lines .= ' <tr><td colspan="2"> </td></tr>' . "\n"; } $branchLines = range($branches[$branchId]['line_start'], $branches[$branchId]['line_end']); sort($branchLines); // sometimes end_line < start_line /** @var int $line */ foreach ($branchLines as $line) { if (!isset($codeLines[$line])) { // blank line at end of file is sometimes included here continue; } $popoverContent = ''; $popoverTitle = ''; $numTests = count($path['hit']); if ($numTests === 0) { $trClass = 'danger'; } else { $lineCss = 'covered-by-large-tests'; $popoverContent = '<ul>'; if ($numTests > 1) { $popoverTitle = $numTests . ' tests cover this path'; } else { $popoverTitle = '1 test covers this path'; } foreach ($path['hit'] as $test) { if ($lineCss === 'covered-by-large-tests' && $testData[$test]['size'] === 'medium') { $lineCss = 'covered-by-medium-tests'; } elseif ($testData[$test]['size'] === 'small') { $lineCss = 'covered-by-small-tests'; } $popoverContent .= $this->createPopoverContentForTest($test, $testData[$test]); } $trClass = $lineCss . ' popin'; } $popover = ''; if (!empty($popoverTitle)) { $popover = sprintf( ' data-title="%s" data-content="%s" data-placement="top" data-html="true"', $popoverTitle, htmlspecialchars($popoverContent, $this->htmlSpecialCharsFlags), ); } $lines .= $this->renderLine($singleLineTemplate, $line, $codeLines[$line - 1], $trClass, $popover); } } if ($lines === '') { return ''; } $linesTemplate->setVar(['lines' => $lines]); return $linesTemplate->render(); } private function renderLine(Template $template, int $lineNumber, string $lineContent, string $class, string $popover): string { $template->setVar( [ 'lineNumber' => $lineNumber, 'lineContent' => $lineContent, 'class' => $class, 'popover' => $popover, ], ); return $template->render(); } private function loadFile(string $file): array { if (isset(self::$formattedSourceCache[$file])) { return self::$formattedSourceCache[$file]; } $buffer = file_get_contents($file); $tokens = token_get_all($buffer); $result = ['']; $i = 0; $stringFlag = false; $fileEndsWithNewLine = str_ends_with($buffer, "\n"); unset($buffer); foreach ($tokens as $j => $token) { if (is_string($token)) { if ($token === '"' && $tokens[$j - 1] !== '\\') { $result[$i] .= sprintf( '<span class="string">%s</span>', htmlspecialchars($token, $this->htmlSpecialCharsFlags), ); $stringFlag = !$stringFlag; } else { $result[$i] .= sprintf( '<span class="keyword">%s</span>', htmlspecialchars($token, $this->htmlSpecialCharsFlags), ); } continue; } [$token, $value] = $token; $value = str_replace( ["\t", ' '], [' ', ' '], htmlspecialchars($value, $this->htmlSpecialCharsFlags), ); if ($value === "\n") { $result[++$i] = ''; } else { $lines = explode("\n", $value); foreach ($lines as $jj => $line) { $line = trim($line); if ($line !== '') { if ($stringFlag) { $colour = 'string'; } else { $colour = 'default'; if ($this->isInlineHtml($token)) { $colour = 'html'; } elseif ($this->isComment($token)) { $colour = 'comment'; } elseif ($this->isKeyword($token)) { $colour = 'keyword'; } } $result[$i] .= sprintf( '<span class="%s">%s</span>', $colour, $line, ); } if (isset($lines[$jj + 1])) { $result[++$i] = ''; } } } } if ($fileEndsWithNewLine) { unset($result[count($result) - 1]); } self::$formattedSourceCache[$file] = $result; return $result; } private function abbreviateClassName(string $className): string { $tmp = explode('\\', $className); if (count($tmp) > 1) { $className = sprintf( '<abbr title="%s">%s</abbr>', $className, array_pop($tmp), ); } return $className; } private function abbreviateMethodName(string $methodName): string { $parts = explode('->', $methodName); if (count($parts) === 2) { return $this->abbreviateClassName($parts[0]) . '->' . $parts[1]; } return $methodName; } private function createPopoverContentForTest(string $test, array $testData): string { $testCSS = ''; switch ($testData['status']) { case 'success': $testCSS = match ($testData['size']) { 'small' => ' class="covered-by-small-tests"', 'medium' => ' class="covered-by-medium-tests"', // no break default => ' class="covered-by-large-tests"', }; break; case 'failure': $testCSS = ' class="danger"'; break; } return sprintf( '<li%s>%s</li>', $testCSS, htmlspecialchars($test, $this->htmlSpecialCharsFlags), ); } private function isComment(int $token): bool { return $token === T_COMMENT || $token === T_DOC_COMMENT; } private function isInlineHtml(int $token): bool { return $token === T_INLINE_HTML; } private function isKeyword(int $token): bool { return isset(self::KEYWORD_TOKENS[$token]); } } php-code-coverage/src/Report/Html/Renderer/Template/file.html.dist 0000644 00000004520 15253321353 0021075 0 ustar 00 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Code Coverage for {{full_path}}</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="{{path_to_root}}_css/bootstrap.min.css?v={{version}}" rel="stylesheet" type="text/css"> <link href="{{path_to_root}}_css/octicons.css?v={{version}}" rel="stylesheet" type="text/css"> <link href="{{path_to_root}}_css/style.css?v={{version}}" rel="stylesheet" type="text/css"> <link href="{{path_to_root}}_css/custom.css" rel="stylesheet" type="text/css"> </head> <body> <header> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <nav aria-label="breadcrumb"> <ol class="breadcrumb"> {{breadcrumbs}} </ol> </nav> </div> </div> </div> </header> <div class="container-fluid"> <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <td> </td> <td colspan="10"><div align="center"><strong>Code Coverage</strong></div></td> </tr> <tr> <td> </td> <td colspan="3"><div align="center"><strong>Lines</strong></div></td> <td colspan="4"><div align="center"><strong>Functions and Methods</strong></div></td> <td colspan="3"><div align="center"><strong>Classes and Traits</strong></div></td> </tr> </thead> <tbody> {{items}} </tbody> </table> </div> {{lines}} {{structure}} <footer> <hr/> <h4>Legend</h4> {{legend}} <p> <small>Generated by <a href="https://github.com/sebastianbergmann/php-code-coverage" target="_top">php-code-coverage {{version}}</a> using {{runtime}}{{generator}} at {{date}}.</small> </p> <a title="Back to the top" id="toplink" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M12 11L6 5l-6 6h12z"/></svg> </a> </footer> </div> <script src="{{path_to_root}}_js/jquery.min.js?v={{version}}" type="text/javascript"></script> <script src="{{path_to_root}}_js/popper.min.js?v={{version}}" type="text/javascript"></script> <script src="{{path_to_root}}_js/bootstrap.min.js?v={{version}}" type="text/javascript"></script> <script src="{{path_to_root}}_js/file.js?v={{version}}" type="text/javascript"></script> </body> </html> php-code-coverage/src/Report/Html/Renderer/Template/directory_item_branch.html.dist 0000644 00000002473 15253321353 0024522 0 ustar 00 <tr> <td class="{{lines_level}}">{{icon}}{{name}}</td> <td class="{{lines_level}} big">{{lines_bar}}</td> <td class="{{lines_level}} small"><div align="right">{{lines_executed_percent}}</div></td> <td class="{{lines_level}} small"><div align="right">{{lines_number}}</div></td> <td class="{{branches_level}} big">{{branches_bar}}</td> <td class="{{branches_level}} small"><div align="right">{{branches_executed_percent}}</div></td> <td class="{{branches_level}} small"><div align="right">{{branches_number}}</div></td> <td class="{{paths_level}} big">{{paths_bar}}</td> <td class="{{paths_level}} small"><div align="right">{{paths_executed_percent}}</div></td> <td class="{{paths_level}} small"><div align="right">{{paths_number}}</div></td> <td class="{{methods_level}} big">{{methods_bar}}</td> <td class="{{methods_level}} small"><div align="right">{{methods_tested_percent}}</div></td> <td class="{{methods_level}} small"><div align="right">{{methods_number}}</div></td> <td class="{{classes_level}} big">{{classes_bar}}</td> <td class="{{classes_level}} small"><div align="right">{{classes_tested_percent}}</div></td> <td class="{{classes_level}} small"><div align="right">{{classes_number}}</div></td> </tr> php-code-coverage/src/Report/Html/Renderer/Template/icons/file-code.svg 0000644 00000000460 15253321353 0022010 0 ustar 00 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM5 6.98L3.5 8.5 5 10l-.5 1L2 8.5 4.5 6l.5.98zM7.5 6L10 8.5 7.5 11l-.5-.98L8.5 8.5 7 7l.5-1z"/></svg>