dep: phpunit 추가

This commit is contained in:
2022-03-02 23:29:09 +09:00
parent f8ab617e4c
commit 923d7f5178
1222 changed files with 121095 additions and 8 deletions
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace PHPSTORM_META {
override(
\PHPUnit\Framework\TestCase::createMock(0),
map([""=>"$0"])
);
override(
\PHPUnit\Framework\TestCase::createStub(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"])
);
}
+234
View File
@@ -0,0 +1,234 @@
# Changes in PHPUnit 8.5
All notable changes of the PHPUnit 8.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
## [8.5.24] - 2022-MM-DD
### Changed
* [#4874](https://github.com/sebastianbergmann/phpunit/pull/4874): `PHP_FLOAT_EPSILON` is now used instead of hardcoded `0.0000000001` in `PHPUnit\Framework\Constraint\IsIdentical`
### Fixed
* When the HTML code coverage report's configured low upper bound is larger than the high lower bound then the default values are used instead
## [8.5.23] - 2022-01-21
### Fixed
* [#4799](https://github.com/sebastianbergmann/phpunit/pull/4799): Memory leaks in `PHPUnit\Framework\TestSuite` class
* [#4857](https://github.com/sebastianbergmann/phpunit/pull/4857): Result of `debug_backtrace()` is not used correctly
## [8.5.22] - 2021-12-25
### Changed
* [#4812](https://github.com/sebastianbergmann/phpunit/issues/4812): Do not enforce time limits when a debugging session through DBGp is active
* [#4835](https://github.com/sebastianbergmann/phpunit/issues/4835): Support for `$GLOBALS['_composer_autoload_path']` introduced in Composer 2.2
### Fixed
* [#4840](https://github.com/sebastianbergmann/phpunit/pull/4840): TestDox prettifying for class names does not correctly handle diacritics
* [#4846](https://github.com/sebastianbergmann/phpunit/pull/4846): Composer proxy script is not ignored
## [8.5.21] - 2021-09-25
### Changed
* PHPUnit no longer converts PHP deprecations to exceptions by default (configure `convertDeprecationsToExceptions="true"` to enable this)
* The PHPUnit XML configuration file generator now configures `convertDeprecationsToExceptions="true"`
### Fixed
* [#4772](https://github.com/sebastianbergmann/phpunit/pull/4772): TestDox HTML report not displayed correctly when browser has custom colour settings
## [8.5.20] - 2021-08-31
### Fixed
* [#4751](https://github.com/sebastianbergmann/phpunit/issues/4751): Configuration validation fails when using brackets in glob pattern
## [8.5.19] - 2021-07-31
### Fixed
* [#4740](https://github.com/sebastianbergmann/phpunit/issues/4740): `phpunit.phar` does not work with PHP 8.1
## [8.5.18] - 2021-07-19
### Fixed
* [#4720](https://github.com/sebastianbergmann/phpunit/issues/4720): PHPUnit does not verify its own PHP extension requirements
## [8.5.17] - 2021-06-23
### Changed
* PHPUnit now errors out on startup when `PHP_VERSION` contains a value that is not compatible with `version_compare()`, for instance `X.Y.Z-(to be removed in future macOS)`
## [8.5.16] - 2021-06-05
### Changed
* The test result cache (the storage for which is implemented in `PHPUnit\Runner\DefaultTestResultCache`) no longer uses PHP's `serialize()` and `unserialize()` functions for persistence. It now uses a versioned JSON format instead that is independent of PHP implementation details (see [#3581](https://github.com/sebastianbergmann/phpunit/issues/3581) and [#4662](https://github.com/sebastianbergmann/phpunit/pull/4662) for examples why this is a problem). When PHPUnit tries to load the test result cache from a file that does not exist, or from a file that does not contain data in JSON format, or from a file that contains data in a JSON format version other than the one used by the currently running PHPUnit version, then this is considered to be a "cache miss". An empty `DefaultTestResultCache` object is created in this case. This should also prevent PHPUnit from crashing when trying to load a test result cache file created by a different version of PHPUnit (see [#4580](https://github.com/sebastianbergmann/phpunit/issues/4580) for example).
### Fixed
* [#4663](https://github.com/sebastianbergmann/phpunit/issues/4663): `TestCase::expectError()` works on PHP 7.3, but not on PHP >= 7.4
* [#4678](https://github.com/sebastianbergmann/phpunit/pull/4678): Stubbed methods with `iterable` return types should return empty array by default
* [#4692](https://github.com/sebastianbergmann/phpunit/issues/4692): Annotations in single-line doc-comments are not handled correctly
* [#4694](https://github.com/sebastianbergmann/phpunit/issues/4694): `TestCase::getMockFromWsdl()` does not work with PHP 8.1-dev
## [8.5.15] - 2021-03-17
### Fixed
* [#4591](https://github.com/sebastianbergmann/phpunit/issues/4591): TeamCity logger logs warnings as test failures
## [8.5.14] - 2021-01-17
### Fixed
* [#4535](https://github.com/sebastianbergmann/phpunit/issues/4535): `getMockFromWsdl()` does not handle methods that do not have parameters correctly
* [#4572](https://github.com/sebastianbergmann/phpunit/issues/4572): Schema validation does not work with `%xx` sequences in path to `phpunit.xsd`
* [#4575](https://github.com/sebastianbergmann/phpunit/issues/4575): PHPUnit 8.5 incompatibility with PHP 8.1
## [8.5.13] - 2020-12-01
### Fixed
* Running tests in isolated processes did not work with PHP 8 on Windows
## [8.5.12] - 2020-11-30
### Changed
* Changed PHP version constraint in `composer.json` from `^7.2` to `>=7.2` to allow the installation of PHPUnit 8.5 on PHP 8. Please note that the code coverage functionality is not available for PHPUnit 8.5 on PHP 8.
### Fixed
* [#4529](https://github.com/sebastianbergmann/phpunit/issues/4529): Debug mode of Xdebug 2 is not disabled for PHPT tests
## [8.5.11] - 2020-11-27
### Changed
* Bumped required version of `phpunit/php-code-coverage`
## [8.5.10] - 2020-11-27
### Added
* Support for Xdebug 3
### Fixed
* [#4516](https://github.com/sebastianbergmann/phpunit/issues/4516): `phpunit/phpunit-selenium` does not work with PHPUnit 8.5.9
## [8.5.9] - 2020-11-10
### Fixed
* [#3965](https://github.com/sebastianbergmann/phpunit/issues/3965): Process Isolation throws exceptions when PHPDBG is used
* [#4470](https://github.com/sebastianbergmann/phpunit/pull/4470): Infinite recursion when `--static-backup --strict-global-state` is used
## [8.5.8] - 2020-06-22
### Fixed
* [#4312](https://github.com/sebastianbergmann/phpunit/issues/4312): Fix for [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299) breaks backward compatibility
## [8.5.7] - 2020-06-21
### Fixed
* [#4299](https://github.com/sebastianbergmann/phpunit/issues/4299): "No tests executed" does not always result in exit code `1`
* [#4306](https://github.com/sebastianbergmann/phpunit/issues/4306): Exceptions during code coverage driver initialization are not handled correctly
## [8.5.6] - 2020-06-15
### Fixed
* [#4211](https://github.com/sebastianbergmann/phpunit/issues/4211): `phpdbg_*()` functions are scoped to `PHPUnit\phpdbg_*()`
## [8.5.5] - 2020-05-22
### Fixed
* [#4033](https://github.com/sebastianbergmann/phpunit/issues/4033): Unexpected behaviour when `$GLOBALS` is deleted
## [8.5.4] - 2020-04-23
### Changed
* Changed how `PHPUnit\TextUI\Command` passes warnings to `PHPUnit\TextUI\TestRunner`
## [8.5.3] - 2020-03-31
### Fixed
* [#4017](https://github.com/sebastianbergmann/phpunit/issues/4017): Do not suggest refactoring to something that is also deprecated
* [#4133](https://github.com/sebastianbergmann/phpunit/issues/4133): `expectExceptionMessageRegExp()` has been removed in PHPUnit 9 without a deprecation warning being given in PHPUnit 8
* [#4139](https://github.com/sebastianbergmann/phpunit/issues/4139): Cannot double interfaces that declare a constructor with PHP 8
* [#4144](https://github.com/sebastianbergmann/phpunit/issues/4144): Empty objects are converted to empty arrays in JSON comparison failure diff
## [8.5.2] - 2020-01-08
### Removed
* `eval-stdin.php` has been removed, it was not used anymore since PHPUnit 7.2.7
## [8.5.1] - 2019-12-25
### Changed
* `eval-stdin.php` can now only be executed with `cli` and `phpdbg`
### Fixed
* [#3983](https://github.com/sebastianbergmann/phpunit/issues/3983): Deprecation warning given too eagerly
## [8.5.0] - 2019-12-06
### Added
* [#3911](https://github.com/sebastianbergmann/phpunit/issues/3911): Support combined use of `addMethods()` and `onlyMethods()`
* [#3949](https://github.com/sebastianbergmann/phpunit/issues/3949): Introduce specialized assertions `assertFileEqualsCanonicalizing()`, `assertFileEqualsIgnoringCase()`, `assertStringEqualsFileCanonicalizing()`, `assertStringEqualsFileIgnoringCase()`, `assertFileNotEqualsCanonicalizing()`, `assertFileNotEqualsIgnoringCase()`, `assertStringNotEqualsFileCanonicalizing()`, and `assertStringNotEqualsFileIgnoringCase()` as alternative to using `assertFileEquals()` etc. with optional parameters
### Changed
* [#3860](https://github.com/sebastianbergmann/phpunit/pull/3860): Deprecate invoking PHPUnit commandline test runner with just a class name
* [#3950](https://github.com/sebastianbergmann/phpunit/issues/3950): Deprecate optional parameters of `assertFileEquals()` etc.
* [#3955](https://github.com/sebastianbergmann/phpunit/issues/3955): Deprecate support for doubling multiple interfaces
### Fixed
* [#3953](https://github.com/sebastianbergmann/phpunit/issues/3953): Code Coverage for test executed in isolation does not work when the PHAR is used
* [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable`
* [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside
[8.5.24]: https://github.com/sebastianbergmann/phpunit/compare/8.5.23...8.5
[8.5.23]: https://github.com/sebastianbergmann/phpunit/compare/8.5.22...8.5.23
[8.5.22]: https://github.com/sebastianbergmann/phpunit/compare/8.5.21...8.5.22
[8.5.21]: https://github.com/sebastianbergmann/phpunit/compare/8.5.20...8.5.21
[8.5.20]: https://github.com/sebastianbergmann/phpunit/compare/8.5.19...8.5.20
[8.5.19]: https://github.com/sebastianbergmann/phpunit/compare/8.5.18...8.5.19
[8.5.18]: https://github.com/sebastianbergmann/phpunit/compare/8.5.17...8.5.18
[8.5.17]: https://github.com/sebastianbergmann/phpunit/compare/8.5.16...8.5.17
[8.5.16]: https://github.com/sebastianbergmann/phpunit/compare/8.5.15...8.5.16
[8.5.15]: https://github.com/sebastianbergmann/phpunit/compare/8.5.14...8.5.15
[8.5.14]: https://github.com/sebastianbergmann/phpunit/compare/8.5.13...8.5.14
[8.5.13]: https://github.com/sebastianbergmann/phpunit/compare/8.5.12...8.5.13
[8.5.12]: https://github.com/sebastianbergmann/phpunit/compare/8.5.11...8.5.12
[8.5.11]: https://github.com/sebastianbergmann/phpunit/compare/8.5.10...8.5.11
[8.5.10]: https://github.com/sebastianbergmann/phpunit/compare/8.5.9...8.5.10
[8.5.9]: https://github.com/sebastianbergmann/phpunit/compare/8.5.8...8.5.9
[8.5.8]: https://github.com/sebastianbergmann/phpunit/compare/8.5.7...8.5.8
[8.5.7]: https://github.com/sebastianbergmann/phpunit/compare/8.5.6...8.5.7
[8.5.6]: https://github.com/sebastianbergmann/phpunit/compare/8.5.5...8.5.6
[8.5.5]: https://github.com/sebastianbergmann/phpunit/compare/8.5.4...8.5.5
[8.5.4]: https://github.com/sebastianbergmann/phpunit/compare/8.5.3...8.5.4
[8.5.3]: https://github.com/sebastianbergmann/phpunit/compare/8.5.2...8.5.3
[8.5.2]: https://github.com/sebastianbergmann/phpunit/compare/8.5.1...8.5.2
[8.5.1]: https://github.com/sebastianbergmann/phpunit/compare/8.5.0...8.5.1
[8.5.0]: https://github.com/sebastianbergmann/phpunit/compare/8.4.3...8.5.0
+153
View File
@@ -0,0 +1,153 @@
# Changes in PHPUnit 9.5
All notable changes of the PHPUnit 9.5 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
## [9.5.16] - 2022-02-23
### Changed
* Reverted sync with API change in (now yanked) phpunit/php-code-coverage 9.2.12
## [9.5.15] - 2022-02-23 [YANKED]
### Fixed
* When the HTML code coverage report's configured low upper bound is larger than the high lower bound then the default values are used instead
## [9.5.14] - 2022-02-18
### Changed
* [#4874](https://github.com/sebastianbergmann/phpunit/pull/4874): `PHP_FLOAT_EPSILON` is now used instead of hardcoded `0.0000000001` in `PHPUnit\Framework\Constraint\IsIdentical`
## [9.5.13] - 2022-01-24
### Fixed
* [#4871](https://github.com/sebastianbergmann/phpunit/issues/4871): Class `SebastianBergmann\CodeCoverage\Filter` is not found during PHPT tests when PHPUnit is used from PHAR
## [9.5.12] - 2022-01-21
### Fixed
* [#4799](https://github.com/sebastianbergmann/phpunit/pull/4799): Memory leaks in `PHPUnit\Framework\TestSuite` class
* [#4857](https://github.com/sebastianbergmann/phpunit/pull/4857): Result of `debug_backtrace()` is not used correctly
## [9.5.11] - 2021-12-25
### Changed
* [#4812](https://github.com/sebastianbergmann/phpunit/issues/4812): Do not enforce time limits when a debugging session through DBGp is active
* [#4835](https://github.com/sebastianbergmann/phpunit/issues/4835): Support for `$GLOBALS['_composer_autoload_path']` introduced in Composer 2.2
### Fixed
* [#4840](https://github.com/sebastianbergmann/phpunit/pull/4840): TestDox prettifying for class names does not correctly handle diacritics
* [#4846](https://github.com/sebastianbergmann/phpunit/pull/4846): Composer proxy script is not ignored
## [9.5.10] - 2021-09-25
### Changed
* PHPUnit no longer converts PHP deprecations to exceptions by default (configure `convertDeprecationsToExceptions="true"` to enable this)
* The PHPUnit XML configuration file generator now configures `convertDeprecationsToExceptions="true"`
### Fixed
* [#4772](https://github.com/sebastianbergmann/phpunit/pull/4772): TestDox HTML report not displayed correctly when browser has custom colour settings
## [9.5.9] - 2021-08-31
### Fixed
* [#4750](https://github.com/sebastianbergmann/phpunit/issues/4750): Automatic return value generation leads to invalid (and superfluous) test double code generation when a stubbed method returns `*|false`
* [#4751](https://github.com/sebastianbergmann/phpunit/issues/4751): Configuration validation fails when using brackets in glob pattern
## [9.5.8] - 2021-07-31
### Fixed
* [#4740](https://github.com/sebastianbergmann/phpunit/issues/4740): `phpunit.phar` does not work with PHP 8.1
## [9.5.7] - 2021-07-19
### Fixed
* [#4720](https://github.com/sebastianbergmann/phpunit/issues/4720): PHPUnit does not verify its own PHP extension requirements
* [#4735](https://github.com/sebastianbergmann/phpunit/issues/4735): Automated return value generation does not work for stubbed methods that return `*|false`
## [9.5.6] - 2021-06-23
### Changed
* PHPUnit now errors out on startup when `PHP_VERSION` contains a value that is not compatible with `version_compare()`, for instance `X.Y.Z-(to be removed in future macOS)`
## [9.5.5] - 2021-06-05
### Changed
* The test result cache (the storage for which is implemented in `PHPUnit\Runner\DefaultTestResultCache`) no longer uses PHP's `serialize()` and `unserialize()` functions for persistence. It now uses a versioned JSON format instead that is independent of PHP implementation details (see [#3581](https://github.com/sebastianbergmann/phpunit/issues/3581) and [#4662](https://github.com/sebastianbergmann/phpunit/pull/4662) for examples why this is a problem). When PHPUnit tries to load the test result cache from a file that does not exist, or from a file that does not contain data in JSON format, or from a file that contains data in a JSON format version other than the one used by the currently running PHPUnit version, then this is considered to be a "cache miss". An empty `DefaultTestResultCache` object is created in this case. This should also prevent PHPUnit from crashing when trying to load a test result cache file created by a different version of PHPUnit (see [#4580](https://github.com/sebastianbergmann/phpunit/issues/4580) for example).
### Fixed
* [#4632](https://github.com/sebastianbergmann/phpunit/issues/4632): TestDox result printer does not handle repeated test execution correctly
* [#4678](https://github.com/sebastianbergmann/phpunit/pull/4678): Stubbed methods with `iterable` return types should return empty array by default
* [#4692](https://github.com/sebastianbergmann/phpunit/issues/4692): Annotations in single-line doc-comments are not handled correctly
* [#4694](https://github.com/sebastianbergmann/phpunit/issues/4694): `TestCase::getMockFromWsdl()` does not work with PHP 8.1-dev
## [9.5.4] - 2021-03-23
### Fixed
* [#4630](https://github.com/sebastianbergmann/phpunit/issues/4630): Empty test case class causes error in TestDox XML logger
## [9.5.3] - 2021-03-17
### Fixed
* [#4591](https://github.com/sebastianbergmann/phpunit/issues/4591): TeamCity logger logs warnings as test failures
* [#4620](https://github.com/sebastianbergmann/phpunit/issues/4620): No useful output when an error occurs in the bootstrap script
## [9.5.2] - 2021-02-02
### Fixed
* [#4573](https://github.com/sebastianbergmann/phpunit/issues/4573): No stack trace printed when PHPUnit is used from PHAR
* [#4590](https://github.com/sebastianbergmann/phpunit/issues/4590): `--coverage-text` CLI option is documented wrong
## [9.5.1] - 2021-01-17
### Fixed
* [#4572](https://github.com/sebastianbergmann/phpunit/issues/4572): Schema validation does not work with `%xx` sequences in path to `phpunit.xsd`
## [9.5.0] - 2020-12-04
### Changed
* [#4490](https://github.com/sebastianbergmann/phpunit/issues/4490): Emit Error instead of Warning when test case class cannot be instantiated
* [#4491](https://github.com/sebastianbergmann/phpunit/issues/4491): Emit Error instead of Warning when data provider does not work correctly
* [#4492](https://github.com/sebastianbergmann/phpunit/issues/4492): Emit Error instead of Warning when test double configuration is invalid
* [#4493](https://github.com/sebastianbergmann/phpunit/issues/4493): Emit error when (configured) test directory does not exist
### Fixed
* [#4535](https://github.com/sebastianbergmann/phpunit/issues/4535): `getMockFromWsdl()` does not handle methods that do not have parameters correctly
[9.5.16]: https://github.com/sebastianbergmann/phpunit/compare/dc738383c519243b0a967f63943a848d3fd861aa...9.5.16
[9.5.15]: https://github.com/sebastianbergmann/phpunit/compare/9.5.14...dc738383c519243b0a967f63943a848d3fd861aa
[9.5.14]: https://github.com/sebastianbergmann/phpunit/compare/9.5.13...9.5.14
[9.5.13]: https://github.com/sebastianbergmann/phpunit/compare/9.5.12...9.5.13
[9.5.12]: https://github.com/sebastianbergmann/phpunit/compare/9.5.11...9.5.12
[9.5.11]: https://github.com/sebastianbergmann/phpunit/compare/9.5.10...9.5.11
[9.5.10]: https://github.com/sebastianbergmann/phpunit/compare/9.5.9...9.5.10
[9.5.9]: https://github.com/sebastianbergmann/phpunit/compare/9.5.8...9.5.9
[9.5.8]: https://github.com/sebastianbergmann/phpunit/compare/9.5.7...9.5.8
[9.5.7]: https://github.com/sebastianbergmann/phpunit/compare/9.5.6...9.5.7
[9.5.6]: https://github.com/sebastianbergmann/phpunit/compare/9.5.5...9.5.6
[9.5.5]: https://github.com/sebastianbergmann/phpunit/compare/9.5.4...9.5.5
[9.5.4]: https://github.com/sebastianbergmann/phpunit/compare/9.5.3...9.5.4
[9.5.3]: https://github.com/sebastianbergmann/phpunit/compare/9.5.2...9.5.3
[9.5.2]: https://github.com/sebastianbergmann/phpunit/compare/9.5.1...9.5.2
[9.5.1]: https://github.com/sebastianbergmann/phpunit/compare/9.5.0...9.5.1
[9.5.0]: https://github.com/sebastianbergmann/phpunit/compare/9.4.4...9.5.0
+33
View File
@@ -0,0 +1,33 @@
PHPUnit
Copyright (c) 2001-2022, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of Sebastian Bergmann nor the names of his
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 OWNER 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.
+43
View File
@@ -0,0 +1,43 @@
# PHPUnit
PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks.
[![Latest Stable Version](https://img.shields.io/packagist/v/phpunit/phpunit.svg?style=flat-square)](https://packagist.org/packages/phpunit/phpunit)
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.3-8892BF.svg?style=flat-square)](https://php.net/)
[![CI Status](https://github.com/sebastianbergmann/phpunit/workflows/CI/badge.svg?branch=9.5&event=push)](https://phpunit.de/build-status.html)
[![Type Coverage](https://shepherd.dev/github/sebastianbergmann/phpunit/coverage.svg)](https://shepherd.dev/github/sebastianbergmann/phpunit)
## 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 "[Getting Started](https://phpunit.de/getting-started-with-phpunit.html)" guide for details on how to install PHPUnit.
## Contribute
Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/.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 and helps maintain the translations:
* [English](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors)
* [Spanish](https://github.com/sebastianbergmann/phpunit-documentation-spanish/graphs/contributors)
* [French](https://github.com/sebastianbergmann/phpunit-documentation-french/graphs/contributors)
* [Japanese](https://github.com/sebastianbergmann/phpunit-documentation-japanese/graphs/contributors)
* [Brazilian Portuguese](https://github.com/sebastianbergmann/phpunit-documentation-brazilian-portuguese/graphs/contributors)
* [Simplified Chinese](https://github.com/sebastianbergmann/phpunit-documentation-chinese/graphs/contributors)
+94
View File
@@ -0,0 +1,94 @@
{
"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"
},
"prefer-stable": true,
"require": {
"php": ">=7.3",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"doctrine/instantiator": "^1.3.1",
"myclabs/deep-copy": "^1.10.1",
"phar-io/manifest": "^2.0.3",
"phar-io/version": "^3.0.2",
"phpspec/prophecy": "^1.12.1",
"phpunit/php-code-coverage": "^9.2.13",
"phpunit/php-file-iterator": "^3.0.5",
"phpunit/php-invoker": "^3.1.1",
"phpunit/php-text-template": "^2.0.3",
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
"sebastian/comparator": "^4.0.5",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
"sebastian/exporter": "^4.0.3",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
"sebastian/type": "^2.3.4",
"sebastian/version": "^3.0.2"
},
"require-dev": {
"ext-PDO": "*",
"phpspec/prophecy-phpunit": "^2.0.1"
},
"config": {
"platform": {
"php": "7.3.0"
},
"optimize-autoloader": true,
"sort-packages": true
},
"suggest": {
"ext-soap": "*",
"ext-xdebug": "*"
},
"bin": [
"phpunit"
],
"autoload": {
"classmap": [
"src/"
],
"files": [
"src/Framework/Assert/Functions.php"
]
},
"autoload-dev": {
"classmap": [
"tests/"
],
"files": [
"tests/_files/CoverageNamespacedFunctionTest.php",
"tests/_files/CoveredFunction.php",
"tests/_files/NamespaceCoveredFunction.php"
]
},
"extra": {
"branch-alias": {
"dev-master": "9.5-dev"
}
}
}
+98
View File
@@ -0,0 +1,98 @@
#!/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('7.3.0', PHP_VERSION, '>')) {
fwrite(
STDERR,
sprintf(
'This version of PHPUnit requires PHP >= 7.3.' . PHP_EOL .
'You are using PHP %s (%s).' . PHP_EOL,
PHP_VERSION,
PHP_BINARY
)
);
die(1);
}
foreach (['dom', 'json', 'libxml', 'mbstring', 'tokenizer', 'xml', 'xmlwriter'] as $extension) {
if (extension_loaded($extension)) {
continue;
}
fwrite(
STDERR,
sprintf(
'PHPUnit requires the "%s" extension.' . PHP_EOL,
$extension
)
);
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);
}
$options = getopt('', array('prepend:'));
if (isset($options['prepend'])) {
require $options['prepend'];
}
unset($options);
require PHPUNIT_COMPOSER_INSTALL;
PHPUnit\TextUI\Command::main();
+328
View File
@@ -0,0 +1,328 @@
<?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="&gt;="/>
</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:group ref="pathGroup"/>
<xs:element name="exclude" type="xs:string" 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>
+317
View File
@@ -0,0 +1,317 @@
<?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="&gt;="/>
</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: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:group ref="pathGroup"/>
<xs:element name="exclude" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
+317
View File
@@ -0,0 +1,317 @@
<?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: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="&gt;="/>
</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: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:group ref="pathGroup"/>
<xs:element name="exclude" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
+19
View File
@@ -0,0 +1,19 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
interface Exception extends Throwable
{
}
+2854
View File
@@ -0,0 +1,2854 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 DEBUG_BACKTRACE_IGNORE_ARGS;
use const PHP_EOL;
use function array_shift;
use function array_unshift;
use function assert;
use function class_exists;
use function count;
use function debug_backtrace;
use function explode;
use function file_get_contents;
use function func_get_args;
use function implode;
use function interface_exists;
use function is_array;
use function is_bool;
use function is_int;
use function is_iterable;
use function is_object;
use function is_string;
use function preg_match;
use function preg_split;
use function sprintf;
use function strpos;
use ArrayAccess;
use Countable;
use DOMAttr;
use DOMDocument;
use DOMElement;
use PHPUnit\Framework\Constraint\ArrayHasKey;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\Constraint\ClassHasAttribute;
use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
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\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\ObjectHasAttribute;
use PHPUnit\Framework\Constraint\RegularExpression;
use PHPUnit\Framework\Constraint\SameSize;
use PHPUnit\Framework\Constraint\StringContains;
use PHPUnit\Framework\Constraint\StringEndsWith;
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\Type;
use PHPUnit\Util\Xml;
use PHPUnit\Util\Xml\Loader as XmlLoader;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
abstract class Assert
{
/**
* @var int
*/
private static $count = 0;
/**
* Asserts that an array has a specified key.
*
* @param int|string $key
* @param array|ArrayAccess $array
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertArrayHasKey($key, $array, string $message = ''): void
{
if (!(is_int($key) || is_string($key))) {
throw InvalidArgumentException::create(
1,
'integer or string'
);
}
if (!(is_array($array) || $array instanceof ArrayAccess)) {
throw InvalidArgumentException::create(
2,
'array or ArrayAccess'
);
}
$constraint = new ArrayHasKey($key);
static::assertThat($array, $constraint, $message);
}
/**
* Asserts that an array does not have a specified key.
*
* @param int|string $key
* @param array|ArrayAccess $array
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertArrayNotHasKey($key, $array, string $message = ''): void
{
if (!(is_int($key) || is_string($key))) {
throw InvalidArgumentException::create(
1,
'integer or string'
);
}
if (!(is_array($array) || $array instanceof ArrayAccess)) {
throw InvalidArgumentException::create(
2,
'array or ArrayAccess'
);
}
$constraint = new LogicalNot(
new ArrayHasKey($key)
);
static::assertThat($array, $constraint, $message);
}
/**
* Asserts that a haystack contains a needle.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertContains($needle, iterable $haystack, string $message = ''): void
{
$constraint = new TraversableContainsIdentical($needle);
static::assertThat($haystack, $constraint, $message);
}
public static function assertContainsEquals($needle, iterable $haystack, string $message = ''): void
{
$constraint = new TraversableContainsEqual($needle);
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that a haystack does not contain a needle.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertNotContains($needle, iterable $haystack, string $message = ''): void
{
$constraint = new LogicalNot(
new TraversableContainsIdentical($needle)
);
static::assertThat($haystack, $constraint, $message);
}
public static function assertNotContainsEquals($needle, iterable $haystack, string $message = ''): void
{
$constraint = new LogicalNot(new TraversableContainsEqual($needle));
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that a haystack contains only values of a given type.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
{
if ($isNativeType === null) {
$isNativeType = Type::isType($type);
}
static::assertThat(
$haystack,
new TraversableContainsOnly(
$type,
$isNativeType
),
$message
);
}
/**
* Asserts that a haystack contains only instances of a given class name.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void
{
static::assertThat(
$haystack,
new TraversableContainsOnly(
$className,
false
),
$message
);
}
/**
* Asserts that a haystack does not contain only values of a given type.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
{
if ($isNativeType === null) {
$isNativeType = Type::isType($type);
}
static::assertThat(
$haystack,
new LogicalNot(
new TraversableContainsOnly(
$type,
$isNativeType
)
),
$message
);
}
/**
* Asserts the number of elements of an array, Countable or Traversable.
*
* @param Countable|iterable $haystack
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertCount(int $expectedCount, $haystack, string $message = ''): void
{
if (!$haystack instanceof Countable && !is_iterable($haystack)) {
throw InvalidArgumentException::create(2, 'countable or iterable');
}
static::assertThat(
$haystack,
new Count($expectedCount),
$message
);
}
/**
* Asserts the number of elements of an array, Countable or Traversable.
*
* @param Countable|iterable $haystack
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertNotCount(int $expectedCount, $haystack, string $message = ''): void
{
if (!$haystack instanceof Countable && !is_iterable($haystack)) {
throw InvalidArgumentException::create(2, 'countable or iterable');
}
$constraint = new LogicalNot(
new Count($expectedCount)
);
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that two variables are equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertEquals($expected, $actual, string $message = ''): void
{
$constraint = new IsEqual($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (canonicalizing).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void
{
$constraint = new IsEqualCanonicalizing($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (ignoring case).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void
{
$constraint = new IsEqualIgnoringCase($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (with delta).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
{
$constraint = new IsEqualWithDelta(
$expected,
$delta
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotEquals($expected, $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqual($expected)
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (canonicalizing).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualCanonicalizing($expected)
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (ignoring case).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualIgnoringCase($expected)
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (with delta).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualWithDelta(
$expected,
$delta
)
);
static::assertThat($actual, $constraint, $message);
}
/**
* @throws ExpectationFailedException
*/
public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void
{
static::assertThat(
$actual,
static::objectEquals($expected, $method),
$message
);
}
/**
* Asserts that a variable is empty.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert empty $actual
*/
public static function assertEmpty($actual, string $message = ''): void
{
static::assertThat($actual, static::isEmpty(), $message);
}
/**
* Asserts that a variable is not empty.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !empty $actual
*/
public static function assertNotEmpty($actual, string $message = ''): void
{
static::assertThat($actual, static::logicalNot(static::isEmpty()), $message);
}
/**
* Asserts that a value is greater than another value.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertGreaterThan($expected, $actual, string $message = ''): void
{
static::assertThat($actual, static::greaterThan($expected), $message);
}
/**
* Asserts that a value is greater than or equal to another value.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void
{
static::assertThat(
$actual,
static::greaterThanOrEqual($expected),
$message
);
}
/**
* Asserts that a value is smaller than another value.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertLessThan($expected, $actual, string $message = ''): void
{
static::assertThat($actual, static::lessThan($expected), $message);
}
/**
* Asserts that a value is smaller than or equal to another value.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertLessThanOrEqual($expected, $actual, string $message = ''): void
{
static::assertThat($actual, static::lessThanOrEqual($expected), $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileEquals(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqual(file_get_contents($expected));
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file (canonicalizing).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqualCanonicalizing(
file_get_contents($expected)
);
static::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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqualIgnoringCase(file_get_contents($expected));
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is not equal to the contents of
* another file.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqual(file_get_contents($expected))
);
static::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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqualCanonicalizing(file_get_contents($expected))
);
static::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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqualIgnoringCase(file_get_contents($expected))
);
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqual(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file (canonicalizing).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file (ignoring case).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqual(file_get_contents($expectedFile))
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file (canonicalizing).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqualCanonicalizing(file_get_contents($expectedFile))
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file (ignoring case).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqualIgnoringCase(file_get_contents($expectedFile))
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that a file/dir is readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertIsReadable(string $filename, string $message = ''): void
{
static::assertThat($filename, new IsReadable, $message);
}
/**
* Asserts that a file/dir exists and is not readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertIsNotReadable(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new IsReadable), $message);
}
/**
* Asserts that a file/dir exists and is not readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4062
*/
public static function assertNotIsReadable(string $filename, string $message = ''): void
{
self::createWarning('assertNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotReadable() instead.');
static::assertThat($filename, new LogicalNot(new IsReadable), $message);
}
/**
* Asserts that a file/dir exists and is writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertIsWritable(string $filename, string $message = ''): void
{
static::assertThat($filename, new IsWritable, $message);
}
/**
* Asserts that a file/dir exists and is not writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertIsNotWritable(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new IsWritable), $message);
}
/**
* Asserts that a file/dir exists and is not writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4065
*/
public static function assertNotIsWritable(string $filename, string $message = ''): void
{
self::createWarning('assertNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertIsNotWritable() instead.');
static::assertThat($filename, new LogicalNot(new IsWritable), $message);
}
/**
* Asserts that a directory exists.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertDirectoryExists(string $directory, string $message = ''): void
{
static::assertThat($directory, new DirectoryExists, $message);
}
/**
* Asserts that a directory does not exist.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
{
static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
}
/**
* Asserts that a directory does not exist.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4068
*/
public static function assertDirectoryNotExists(string $directory, string $message = ''): void
{
self::createWarning('assertDirectoryNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryDoesNotExist() instead.');
static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
}
/**
* Asserts that a directory exists and is readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsNotReadable($directory, $message);
}
/**
* Asserts that a directory exists and is not readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4071
*/
public static function assertDirectoryNotIsReadable(string $directory, string $message = ''): void
{
self::createWarning('assertDirectoryNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotReadable() instead.');
self::assertDirectoryExists($directory, $message);
self::assertIsNotReadable($directory, $message);
}
/**
* Asserts that a directory exists and is writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsNotWritable($directory, $message);
}
/**
* Asserts that a directory exists and is not writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4074
*/
public static function assertDirectoryNotIsWritable(string $directory, string $message = ''): void
{
self::createWarning('assertDirectoryNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDirectoryIsNotWritable() instead.');
self::assertDirectoryExists($directory, $message);
self::assertIsNotWritable($directory, $message);
}
/**
* Asserts that a file exists.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileExists(string $filename, string $message = ''): void
{
static::assertThat($filename, new FileExists, $message);
}
/**
* Asserts that a file does not exist.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileDoesNotExist(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new FileExists), $message);
}
/**
* Asserts that a file does not exist.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4077
*/
public static function assertFileNotExists(string $filename, string $message = ''): void
{
self::createWarning('assertFileNotExists() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileDoesNotExist() instead.');
static::assertThat($filename, new LogicalNot(new FileExists), $message);
}
/**
* Asserts that a file exists and is readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileIsNotReadable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsNotReadable($file, $message);
}
/**
* Asserts that a file exists and is not readable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4080
*/
public static function assertFileNotIsReadable(string $file, string $message = ''): void
{
self::createWarning('assertFileNotIsReadable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotReadable() instead.');
self::assertFileExists($file, $message);
self::assertIsNotReadable($file, $message);
}
/**
* Asserts that a file exists and is writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFileIsNotWritable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsNotWritable($file, $message);
}
/**
* Asserts that a file exists and is not writable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4083
*/
public static function assertFileNotIsWritable(string $file, string $message = ''): void
{
self::createWarning('assertFileNotIsWritable() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertFileIsNotWritable() instead.');
self::assertFileExists($file, $message);
self::assertIsNotWritable($file, $message);
}
/**
* Asserts that a condition is true.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert true $condition
*/
public static function assertTrue($condition, string $message = ''): void
{
static::assertThat($condition, static::isTrue(), $message);
}
/**
* Asserts that a condition is not true.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !true $condition
*/
public static function assertNotTrue($condition, string $message = ''): void
{
static::assertThat($condition, static::logicalNot(static::isTrue()), $message);
}
/**
* Asserts that a condition is false.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert false $condition
*/
public static function assertFalse($condition, string $message = ''): void
{
static::assertThat($condition, static::isFalse(), $message);
}
/**
* Asserts that a condition is not false.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !false $condition
*/
public static function assertNotFalse($condition, string $message = ''): void
{
static::assertThat($condition, static::logicalNot(static::isFalse()), $message);
}
/**
* Asserts that a variable is null.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert null $actual
*/
public static function assertNull($actual, string $message = ''): void
{
static::assertThat($actual, static::isNull(), $message);
}
/**
* Asserts that a variable is not null.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !null $actual
*/
public static function assertNotNull($actual, string $message = ''): void
{
static::assertThat($actual, static::logicalNot(static::isNull()), $message);
}
/**
* Asserts that a variable is finite.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertFinite($actual, string $message = ''): void
{
static::assertThat($actual, static::isFinite(), $message);
}
/**
* Asserts that a variable is infinite.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertInfinite($actual, string $message = ''): void
{
static::assertThat($actual, static::isInfinite(), $message);
}
/**
* Asserts that a variable is nan.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNan($actual, string $message = ''): void
{
static::assertThat($actual, static::isNan(), $message);
}
/**
* Asserts that a class has a specified attribute.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!class_exists($className)) {
throw InvalidArgumentException::create(2, 'class name');
}
static::assertThat($className, new ClassHasAttribute($attributeName), $message);
}
/**
* Asserts that a class does not have a specified attribute.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!class_exists($className)) {
throw InvalidArgumentException::create(2, 'class name');
}
static::assertThat(
$className,
new LogicalNot(
new ClassHasAttribute($attributeName)
),
$message
);
}
/**
* Asserts that a class has a specified static attribute.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!class_exists($className)) {
throw InvalidArgumentException::create(2, 'class name');
}
static::assertThat(
$className,
new ClassHasStaticAttribute($attributeName),
$message
);
}
/**
* Asserts that a class does not have a specified static attribute.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!class_exists($className)) {
throw InvalidArgumentException::create(2, 'class name');
}
static::assertThat(
$className,
new LogicalNot(
new ClassHasStaticAttribute($attributeName)
),
$message
);
}
/**
* Asserts that an object has a specified attribute.
*
* @param object $object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void
{
if (!self::isValidObjectAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!is_object($object)) {
throw InvalidArgumentException::create(2, 'object');
}
static::assertThat(
$object,
new ObjectHasAttribute($attributeName),
$message
);
}
/**
* Asserts that an object does not have a specified attribute.
*
* @param object $object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void
{
if (!self::isValidObjectAttributeName($attributeName)) {
throw InvalidArgumentException::create(1, 'valid attribute name');
}
if (!is_object($object)) {
throw InvalidArgumentException::create(2, 'object');
}
static::assertThat(
$object,
new LogicalNot(
new ObjectHasAttribute($attributeName)
),
$message
);
}
/**
* Asserts that two variables have the same type and value.
* Used on objects, it asserts that two variables reference
* the same object.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-template ExpectedType
* @psalm-param ExpectedType $expected
* @psalm-assert =ExpectedType $actual
*/
public static function assertSame($expected, $actual, string $message = ''): void
{
static::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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertNotSame($expected, $actual, string $message = ''): void
{
if (is_bool($expected) && is_bool($actual)) {
static::assertNotEquals($expected, $actual, $message);
}
static::assertThat(
$actual,
new LogicalNot(
new IsIdentical($expected)
),
$message
);
}
/**
* Asserts that a variable is of a given type.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*
* @psalm-template ExpectedType of object
* @psalm-param class-string<ExpectedType> $expected
* @psalm-assert =ExpectedType $actual
*/
public static function assertInstanceOf(string $expected, $actual, string $message = ''): void
{
if (!class_exists($expected) && !interface_exists($expected)) {
throw InvalidArgumentException::create(1, 'class or interface name');
}
static::assertThat(
$actual,
new IsInstanceOf($expected),
$message
);
}
/**
* Asserts that a variable is not of a given type.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*
* @psalm-template ExpectedType of object
* @psalm-param class-string<ExpectedType> $expected
* @psalm-assert !ExpectedType $actual
*/
public static function assertNotInstanceOf(string $expected, $actual, string $message = ''): void
{
if (!class_exists($expected) && !interface_exists($expected)) {
throw InvalidArgumentException::create(1, 'class or interface name');
}
static::assertThat(
$actual,
new LogicalNot(
new IsInstanceOf($expected)
),
$message
);
}
/**
* Asserts that a variable is of type array.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert array $actual
*/
public static function assertIsArray($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_ARRAY),
$message
);
}
/**
* Asserts that a variable is of type bool.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert bool $actual
*/
public static function assertIsBool($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_BOOL),
$message
);
}
/**
* Asserts that a variable is of type float.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert float $actual
*/
public static function assertIsFloat($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_FLOAT),
$message
);
}
/**
* Asserts that a variable is of type int.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert int $actual
*/
public static function assertIsInt($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_INT),
$message
);
}
/**
* Asserts that a variable is of type numeric.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert numeric $actual
*/
public static function assertIsNumeric($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_NUMERIC),
$message
);
}
/**
* Asserts that a variable is of type object.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert object $actual
*/
public static function assertIsObject($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_OBJECT),
$message
);
}
/**
* Asserts that a variable is of type resource.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert resource $actual
*/
public static function assertIsResource($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_RESOURCE),
$message
);
}
/**
* Asserts that a variable is of type resource and is closed.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert resource $actual
*/
public static function assertIsClosedResource($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_CLOSED_RESOURCE),
$message
);
}
/**
* Asserts that a variable is of type string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert string $actual
*/
public static function assertIsString($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_STRING),
$message
);
}
/**
* Asserts that a variable is of type scalar.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert scalar $actual
*/
public static function assertIsScalar($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_SCALAR),
$message
);
}
/**
* Asserts that a variable is of type callable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert callable $actual
*/
public static function assertIsCallable($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_CALLABLE),
$message
);
}
/**
* Asserts that a variable is of type iterable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert iterable $actual
*/
public static function assertIsIterable($actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsType(IsType::TYPE_ITERABLE),
$message
);
}
/**
* Asserts that a variable is not of type array.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !array $actual
*/
public static function assertIsNotArray($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_ARRAY)),
$message
);
}
/**
* Asserts that a variable is not of type bool.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !bool $actual
*/
public static function assertIsNotBool($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_BOOL)),
$message
);
}
/**
* Asserts that a variable is not of type float.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !float $actual
*/
public static function assertIsNotFloat($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_FLOAT)),
$message
);
}
/**
* Asserts that a variable is not of type int.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !int $actual
*/
public static function assertIsNotInt($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_INT)),
$message
);
}
/**
* Asserts that a variable is not of type numeric.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !numeric $actual
*/
public static function assertIsNotNumeric($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_NUMERIC)),
$message
);
}
/**
* Asserts that a variable is not of type object.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !object $actual
*/
public static function assertIsNotObject($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_OBJECT)),
$message
);
}
/**
* Asserts that a variable is not of type resource.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !resource $actual
*/
public static function assertIsNotResource($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_RESOURCE)),
$message
);
}
/**
* Asserts that a variable is not of type resource.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !resource $actual
*/
public static function assertIsNotClosedResource($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_CLOSED_RESOURCE)),
$message
);
}
/**
* Asserts that a variable is not of type string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !string $actual
*/
public static function assertIsNotString($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_STRING)),
$message
);
}
/**
* Asserts that a variable is not of type scalar.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !scalar $actual
*/
public static function assertIsNotScalar($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_SCALAR)),
$message
);
}
/**
* Asserts that a variable is not of type callable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !callable $actual
*/
public static function assertIsNotCallable($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_CALLABLE)),
$message
);
}
/**
* Asserts that a variable is not of type iterable.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-assert !iterable $actual
*/
public static function assertIsNotIterable($actual, string $message = ''): void
{
static::assertThat(
$actual,
new LogicalNot(new IsType(IsType::TYPE_ITERABLE)),
$message
);
}
/**
* Asserts that a string matches a given regular expression.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void
{
static::assertThat($string, new RegularExpression($pattern), $message);
}
/**
* Asserts that a string matches a given regular expression.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4086
*/
public static function assertRegExp(string $pattern, string $string, string $message = ''): void
{
self::createWarning('assertRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertMatchesRegularExpression() instead.');
static::assertThat($string, new RegularExpression($pattern), $message);
}
/**
* Asserts that a string does not match a given regular expression.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void
{
static::assertThat(
$string,
new LogicalNot(
new RegularExpression($pattern)
),
$message
);
}
/**
* Asserts that a string does not match a given regular expression.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4089
*/
public static function assertNotRegExp(string $pattern, string $string, string $message = ''): void
{
self::createWarning('assertNotRegExp() is deprecated and will be removed in PHPUnit 10. Refactor your code to use assertDoesNotMatchRegularExpression() instead.');
static::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 $expected
* @param Countable|iterable $actual
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertSameSize($expected, $actual, string $message = ''): void
{
if (!$expected instanceof Countable && !is_iterable($expected)) {
throw InvalidArgumentException::create(1, 'countable or iterable');
}
if (!$actual instanceof Countable && !is_iterable($actual)) {
throw InvalidArgumentException::create(2, 'countable or iterable');
}
static::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 $expected
* @param Countable|iterable $actual
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertNotSameSize($expected, $actual, string $message = ''): void
{
if (!$expected instanceof Countable && !is_iterable($expected)) {
throw InvalidArgumentException::create(1, 'countable or iterable');
}
if (!$actual instanceof Countable && !is_iterable($actual)) {
throw InvalidArgumentException::create(2, 'countable or iterable');
}
static::assertThat(
$actual,
new LogicalNot(
new SameSize($expected)
),
$message
);
}
/**
* Asserts that a string matches a given format string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void
{
static::assertThat($string, new StringMatchesFormatDescription($format), $message);
}
/**
* Asserts that a string does not match a given format string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void
{
static::assertThat(
$string,
new LogicalNot(
new StringMatchesFormatDescription($format)
),
$message
);
}
/**
* Asserts that a string matches a given format file.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
{
static::assertFileExists($formatFile, $message);
static::assertThat(
$string,
new StringMatchesFormatDescription(
file_get_contents($formatFile)
),
$message
);
}
/**
* Asserts that a string does not match a given format string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void
{
static::assertFileExists($formatFile, $message);
static::assertThat(
$string,
new LogicalNot(
new StringMatchesFormatDescription(
file_get_contents($formatFile)
)
),
$message
);
}
/**
* Asserts that a string starts with a given prefix.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void
{
static::assertThat($string, new StringStartsWith($prefix), $message);
}
/**
* Asserts that a string starts not with a given prefix.
*
* @param string $prefix
* @param string $string
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringStartsNotWith($prefix, $string, string $message = ''): void
{
static::assertThat(
$string,
new LogicalNot(
new StringStartsWith($prefix)
),
$message
);
}
/**
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void
{
$constraint = new StringContains($needle, false);
static::assertThat($haystack, $constraint, $message);
}
/**
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
{
$constraint = new StringContains($needle, true);
static::assertThat($haystack, $constraint, $message);
}
/**
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void
{
$constraint = new LogicalNot(new StringContains($needle));
static::assertThat($haystack, $constraint, $message);
}
/**
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void
{
$constraint = new LogicalNot(new StringContains($needle, true));
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that a string ends with a given suffix.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void
{
static::assertThat($string, new StringEndsWith($suffix), $message);
}
/**
* Asserts that a string ends not with a given suffix.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void
{
static::assertThat(
$string,
new LogicalNot(
new StringEndsWith($suffix)
),
$message
);
}
/**
* Asserts that two XML files are equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws Exception
* @throws ExpectationFailedException
*/
public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
{
$expected = (new XmlLoader)->loadFile($expectedFile);
$actual = (new XmlLoader)->loadFile($actualFile);
static::assertEquals($expected, $actual, $message);
}
/**
* Asserts that two XML files are not equal.
*
* @throws \PHPUnit\Util\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void
{
$expected = (new XmlLoader)->loadFile($expectedFile);
$actual = (new XmlLoader)->loadFile($actualFile);
static::assertNotEquals($expected, $actual, $message);
}
/**
* Asserts that two XML documents are equal.
*
* @param DOMDocument|string $actualXml
*
* @throws \PHPUnit\Util\Xml\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
{
if (!is_string($actualXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$actual = $actualXml;
} else {
$actual = (new XmlLoader)->load($actualXml);
}
$expected = (new XmlLoader)->loadFile($expectedFile);
static::assertEquals($expected, $actual, $message);
}
/**
* Asserts that two XML documents are not equal.
*
* @param DOMDocument|string $actualXml
*
* @throws \PHPUnit\Util\Xml\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void
{
if (!is_string($actualXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$actual = $actualXml;
} else {
$actual = (new XmlLoader)->load($actualXml);
}
$expected = (new XmlLoader)->loadFile($expectedFile);
static::assertNotEquals($expected, $actual, $message);
}
/**
* Asserts that two XML documents are equal.
*
* @param DOMDocument|string $expectedXml
* @param DOMDocument|string $actualXml
*
* @throws \PHPUnit\Util\Xml\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
{
if (!is_string($expectedXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$expected = $expectedXml;
} else {
$expected = (new XmlLoader)->load($expectedXml);
}
if (!is_string($actualXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$actual = $actualXml;
} else {
$actual = (new XmlLoader)->load($actualXml);
}
static::assertEquals($expected, $actual, $message);
}
/**
* Asserts that two XML documents are not equal.
*
* @param DOMDocument|string $expectedXml
* @param DOMDocument|string $actualXml
*
* @throws \PHPUnit\Util\Xml\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void
{
if (!is_string($expectedXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $expectedXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$expected = $expectedXml;
} else {
$expected = (new XmlLoader)->load($expectedXml);
}
if (!is_string($actualXml)) {
self::createWarning('Passing an argument of type DOMDocument for the $actualXml parameter is deprecated. Support for this will be removed in PHPUnit 10.');
$actual = $actualXml;
} else {
$actual = (new XmlLoader)->load($actualXml);
}
static::assertNotEquals($expected, $actual, $message);
}
/**
* Asserts that a hierarchy of DOMElements matches.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws AssertionFailedError
* @throws ExpectationFailedException
*
* @codeCoverageIgnore
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/4091
*/
public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void
{
self::createWarning('assertEqualXMLStructure() is deprecated and will be removed in PHPUnit 10.');
$expectedElement = Xml::import($expectedElement);
$actualElement = Xml::import($actualElement);
static::assertSame(
$expectedElement->tagName,
$actualElement->tagName,
$message
);
if ($checkAttributes) {
static::assertSame(
$expectedElement->attributes->length,
$actualElement->attributes->length,
sprintf(
'%s%sNumber of attributes on node "%s" does not match',
$message,
!empty($message) ? "\n" : '',
$expectedElement->tagName
)
);
for ($i = 0; $i < $expectedElement->attributes->length; $i++) {
$expectedAttribute = $expectedElement->attributes->item($i);
$actualAttribute = $actualElement->attributes->getNamedItem($expectedAttribute->name);
assert($expectedAttribute instanceof DOMAttr);
if (!$actualAttribute) {
static::fail(
sprintf(
'%s%sCould not find attribute "%s" on node "%s"',
$message,
!empty($message) ? "\n" : '',
$expectedAttribute->name,
$expectedElement->tagName
)
);
}
}
}
Xml::removeCharacterDataNodes($expectedElement);
Xml::removeCharacterDataNodes($actualElement);
static::assertSame(
$expectedElement->childNodes->length,
$actualElement->childNodes->length,
sprintf(
'%s%sNumber of child nodes of "%s" differs',
$message,
!empty($message) ? "\n" : '',
$expectedElement->tagName
)
);
for ($i = 0; $i < $expectedElement->childNodes->length; $i++) {
static::assertEqualXMLStructure(
$expectedElement->childNodes->item($i),
$actualElement->childNodes->item($i),
$checkAttributes,
$message
);
}
}
/**
* Evaluates a PHPUnit\Framework\Constraint matcher object.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertThat($value, Constraint $constraint, string $message = ''): void
{
self::$count += count($constraint);
$constraint->evaluate($value, $message);
}
/**
* Asserts that a string is a valid JSON string.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJson(string $actualJson, string $message = ''): void
{
static::assertThat($actualJson, static::isJson(), $message);
}
/**
* Asserts that two given JSON encoded objects or arrays are equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void
{
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
}
/**
* Asserts that two given JSON encoded objects or arrays are not equal.
*
* @param string $expectedJson
* @param string $actualJson
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void
{
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
static::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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$expectedJson = file_get_contents($expectedFile);
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
static::assertThat($actualJson, new JsonMatches($expectedJson), $message);
}
/**
* Asserts that the generated JSON encoded object and the content of the given file are not equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$expectedJson = file_get_contents($expectedFile);
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
static::assertThat(
$actualJson,
new LogicalNot(
new JsonMatches($expectedJson)
),
$message
);
}
/**
* Asserts that two JSON files are equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
static::assertFileExists($actualFile, $message);
$actualJson = file_get_contents($actualFile);
$expectedJson = file_get_contents($expectedFile);
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
$constraintExpected = new JsonMatches(
$expectedJson
);
$constraintActual = new JsonMatches($actualJson);
static::assertThat($expectedJson, $constraintActual, $message);
static::assertThat($actualJson, $constraintExpected, $message);
}
/**
* Asserts that two JSON files are not equal.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
static::assertFileExists($actualFile, $message);
$actualJson = file_get_contents($actualFile);
$expectedJson = file_get_contents($expectedFile);
static::assertJson($expectedJson, $message);
static::assertJson($actualJson, $message);
$constraintExpected = new JsonMatches(
$expectedJson
);
$constraintActual = new JsonMatches($actualJson);
static::assertThat($expectedJson, new LogicalNot($constraintActual), $message);
static::assertThat($actualJson, new LogicalNot($constraintExpected), $message);
}
/**
* @throws Exception
*/
public static function logicalAnd(): LogicalAnd
{
$constraints = func_get_args();
$constraint = new LogicalAnd;
$constraint->setConstraints($constraints);
return $constraint;
}
public static function logicalOr(): LogicalOr
{
$constraints = func_get_args();
$constraint = new LogicalOr;
$constraint->setConstraints($constraints);
return $constraint;
}
public static function logicalNot(Constraint $constraint): LogicalNot
{
return new LogicalNot($constraint);
}
public static function logicalXor(): LogicalXor
{
$constraints = func_get_args();
$constraint = new LogicalXor;
$constraint->setConstraints($constraints);
return $constraint;
}
public static function anything(): IsAnything
{
return new IsAnything;
}
public static function isTrue(): IsTrue
{
return new IsTrue;
}
/**
* @psalm-template CallbackInput of mixed
*
* @psalm-param callable(CallbackInput $callback): bool $callback
*
* @psalm-return Callback<CallbackInput>
*/
public static function callback(callable $callback): Callback
{
return new Callback($callback);
}
public static function isFalse(): IsFalse
{
return new IsFalse;
}
public static function isJson(): IsJson
{
return new IsJson;
}
public static function isNull(): IsNull
{
return new IsNull;
}
public static function isFinite(): IsFinite
{
return new IsFinite;
}
public static function isInfinite(): IsInfinite
{
return new IsInfinite;
}
public static function isNan(): IsNan
{
return new IsNan;
}
public static function containsEqual($value): TraversableContainsEqual
{
return new TraversableContainsEqual($value);
}
public static function containsIdentical($value): TraversableContainsIdentical
{
return new TraversableContainsIdentical($value);
}
public static function containsOnly(string $type): TraversableContainsOnly
{
return new TraversableContainsOnly($type);
}
public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly
{
return new TraversableContainsOnly($className, false);
}
/**
* @param int|string $key
*/
public static function arrayHasKey($key): ArrayHasKey
{
return new ArrayHasKey($key);
}
public static function equalTo($value): IsEqual
{
return new IsEqual($value, 0.0, false, false);
}
public static function equalToCanonicalizing($value): IsEqualCanonicalizing
{
return new IsEqualCanonicalizing($value);
}
public static function equalToIgnoringCase($value): IsEqualIgnoringCase
{
return new IsEqualIgnoringCase($value);
}
public static function equalToWithDelta($value, float $delta): IsEqualWithDelta
{
return new IsEqualWithDelta($value, $delta);
}
public static function isEmpty(): IsEmpty
{
return new IsEmpty;
}
public static function isWritable(): IsWritable
{
return new IsWritable;
}
public static function isReadable(): IsReadable
{
return new IsReadable;
}
public static function directoryExists(): DirectoryExists
{
return new DirectoryExists;
}
public static function fileExists(): FileExists
{
return new FileExists;
}
public static function greaterThan($value): GreaterThan
{
return new GreaterThan($value);
}
public static function greaterThanOrEqual($value): LogicalOr
{
return static::logicalOr(
new IsEqual($value),
new GreaterThan($value)
);
}
public static function classHasAttribute(string $attributeName): ClassHasAttribute
{
return new ClassHasAttribute($attributeName);
}
public static function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute
{
return new ClassHasStaticAttribute($attributeName);
}
public static function objectHasAttribute($attributeName): ObjectHasAttribute
{
return new ObjectHasAttribute($attributeName);
}
public static function identicalTo($value): IsIdentical
{
return new IsIdentical($value);
}
public static function isInstanceOf(string $className): IsInstanceOf
{
return new IsInstanceOf($className);
}
public static function isType(string $type): IsType
{
return new IsType($type);
}
public static function lessThan($value): LessThan
{
return new LessThan($value);
}
public static function lessThanOrEqual($value): LogicalOr
{
return static::logicalOr(
new IsEqual($value),
new LessThan($value)
);
}
public static function matchesRegularExpression(string $pattern): RegularExpression
{
return new RegularExpression($pattern);
}
public static function matches(string $string): StringMatchesFormatDescription
{
return new StringMatchesFormatDescription($string);
}
public static function stringStartsWith($prefix): StringStartsWith
{
return new StringStartsWith($prefix);
}
public static function stringContains(string $string, bool $case = true): StringContains
{
return new StringContains($string, $case);
}
public static function stringEndsWith(string $suffix): StringEndsWith
{
return new StringEndsWith($suffix);
}
public static function countOf(int $count): Count
{
return new Count($count);
}
public static function objectEquals(object $object, string $method = 'equals'): ObjectEquals
{
return new ObjectEquals($object, $method);
}
/**
* Fails a test with the given message.
*
* @throws AssertionFailedError
*
* @psalm-return never-return
*/
public static function fail(string $message = ''): void
{
self::$count++;
throw new AssertionFailedError($message);
}
/**
* Mark the test as incomplete.
*
* @throws IncompleteTestError
*
* @psalm-return never-return
*/
public static function markTestIncomplete(string $message = ''): void
{
throw new IncompleteTestError($message);
}
/**
* Mark the test as skipped.
*
* @throws SkippedTestError
* @throws SyntheticSkippedError
*
* @psalm-return never-return
*/
public static function markTestSkipped(string $message = ''): void
{
if ($hint = self::detectLocationHint($message)) {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
array_unshift($trace, $hint);
throw new SyntheticSkippedError($hint['message'], 0, $hint['file'], (int) $hint['line'], $trace);
}
throw new SkippedTestError($message);
}
/**
* Return the current assertion count.
*/
public static function getCount(): int
{
return self::$count;
}
/**
* Reset the assertion counter.
*/
public static function resetCount(): void
{
self::$count = 0;
}
private static function detectLocationHint(string $message): ?array
{
$hint = null;
$lines = preg_split('/\r\n|\r|\n/', $message);
while (strpos($lines[0], '__OFFSET') !== false) {
$offset = explode('=', array_shift($lines));
if ($offset[0] === '__OFFSET_FILE') {
$hint['file'] = $offset[1];
}
if ($offset[0] === '__OFFSET_LINE') {
$hint['line'] = $offset[1];
}
}
if ($hint) {
$hint['message'] = implode(PHP_EOL, $lines);
}
return $hint;
}
private static function isValidObjectAttributeName(string $attributeName): bool
{
return (bool) preg_match('/[^\x00-\x1f\x7f-\x9f]+/', $attributeName);
}
private static function isValidClassAttributeName(string $attributeName): bool
{
return (bool) preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName);
}
/**
* @codeCoverageIgnore
*/
private static function createWarning(string $warning): void
{
foreach (debug_backtrace() as $step) {
if (isset($step['object']) && $step['object'] instanceof TestCase) {
assert($step['object'] instanceof TestCase);
$step['object']->addWarning($warning);
break;
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return $other === false;
}
}
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return $other === true;
}
}
@@ -0,0 +1,52 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @psalm-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
*
* @psalm-var callable(CallbackInput $input): bool
*/
private $callback;
/** @psalm-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 mixed $other value or object to evaluate
*
* @psalm-param CallbackInput $other
*/
protected function matches($other): bool
{
return ($this->callback)($other);
}
}
@@ -0,0 +1,142 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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_array;
use function iterator_count;
use function sprintf;
use Countable;
use EmptyIterator;
use Generator;
use Iterator;
use IteratorAggregate;
use PHPUnit\Framework\Exception;
use Traversable;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
class Count extends Constraint
{
/**
* @var int
*/
private $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($other): bool
{
return $this->expectedCount === $this->getCountOf($other);
}
/**
* @throws Exception
*/
protected function getCountOf($other): ?int
{
if ($other instanceof Countable || is_array($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) {
return $this->getCountOfGenerator($iterator);
}
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 total number of iterations from a generator.
* This will fully exhaust the generator.
*/
protected function getCountOfGenerator(Generator $generator): int
{
for ($count = 0; $generator->valid(); $generator->next()) {
$count++;
}
return $count;
}
/**
* 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($other): string
{
return sprintf(
'actual size %d matches expected size %d',
(int) $this->getCountOf($other),
$this->expectedCount
);
}
}
@@ -0,0 +1,50 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 GreaterThan extends Constraint
{
/**
* @var float|int
*/
private $value;
/**
* @param float|int $value
*/
public function __construct($value)
{
$this->value = $value;
}
/**
* Returns a string representation of the constraint.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
return 'is greater than ' . $this->exporter()->export($this->value);
}
/**
* 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($other): bool
{
return $this->value < $other;
}
}
@@ -0,0 +1,70 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strpos;
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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
$type = gettype($other);
return sprintf(
'%s %s %s',
strpos($type, 'a') === 0 || strpos($type, 'o') === 0 ? 'an' : 'a',
$type,
$this->toString()
);
}
}
@@ -0,0 +1,50 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 LessThan extends Constraint
{
/**
* @var float|int
*/
private $value;
/**
* @param float|int $value
*/
public function __construct($value)
{
$this->value = $value;
}
/**
* Returns a string representation of the constraint.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
return 'is less than ' . $this->exporter()->export($this->value);
}
/**
* 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($other): bool
{
return $this->value > $other;
}
}
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 SameSize extends Count
{
public function __construct(iterable $expected)
{
parent::__construct((int) $this->getCountOf($expected));
}
}
@@ -0,0 +1,269 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 Countable;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\SelfDescribing;
use SebastianBergmann\Comparator\ComparisonFailure;
use SebastianBergmann\Exporter\Exporter;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
abstract class Constraint implements Countable, SelfDescribing
{
/**
* @var ?Exporter
*/
private $exporter;
/**
* 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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public function evaluate($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;
}
protected function exporter(): Exporter
{
if ($this->exporter === null) {
$this->exporter = new Exporter;
}
return $this->exporter;
}
/**
* 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.
*
* @param mixed $other value or object to evaluate
* @codeCoverageIgnore
*/
protected function matches($other): bool
{
return false;
}
/**
* Throws an exception for the given compared value and test description.
*
* @param mixed $other evaluated value or object
* @param string $description Additional information about the test
* @param ComparisonFailure $comparisonFailure
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-return never-return
*/
protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void
{
$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
*
* @param mixed $other evaluated value or object
*/
protected function additionalFailureDescription($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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
return $this->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.
*
* @param Operator $operator the $operator of the expression
* @param mixed $role role of $this constraint in the $operator expression
*/
protected function toStringInContext(Operator $operator, $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.
*
* @param Operator $operator the $operator of the expression
* @param mixed $role role of $this constraint in the $operator expression
* @param mixed $other evaluated value or object
*/
protected function failureDescriptionInContext(Operator $operator, $role, $other): string
{
$string = $this->toStringInContext($operator, $role);
if ($string === '') {
return '';
}
return $this->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;
}
}
@@ -0,0 +1,138 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strpos;
use function trim;
use PHPUnit\Framework\ExpectationFailedException;
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
{
/**
* @var mixed
*/
private $value;
/**
* @var float
*/
private $delta;
/**
* @var bool
*/
private $canonicalize;
/**
* @var bool
*/
private $ignoreCase;
public function __construct($value, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false)
{
$this->value = $value;
$this->delta = $delta;
$this->canonicalize = $canonicalize;
$this->ignoreCase = $ignoreCase;
}
/**
* 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
*
* @return bool
*/
public function evaluate($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,
$this->canonicalize,
$this->ignoreCase
);
} 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.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
$delta = '';
if (is_string($this->value)) {
if (strpos($this->value, "\n") !== false) {
return 'is equal to <text>';
}
return sprintf(
"is equal to '%s'",
$this->value
);
}
if ($this->delta != 0) {
$delta = sprintf(
' with delta <%F>',
$this->delta
);
}
return sprintf(
'is equal to %s%s',
$this->exporter()->export($this->value),
$delta
);
}
}
@@ -0,0 +1,108 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strpos;
use function trim;
use PHPUnit\Framework\ExpectationFailedException;
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
{
/**
* @var mixed
*/
private $value;
public function __construct($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($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,
false
);
} 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.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
if (is_string($this->value)) {
if (strpos($this->value, "\n") !== false) {
return 'is equal to <text>';
}
return sprintf(
"is equal to '%s'",
$this->value
);
}
return sprintf(
'is equal to %s',
$this->exporter()->export($this->value)
);
}
}
@@ -0,0 +1,108 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strpos;
use function trim;
use PHPUnit\Framework\ExpectationFailedException;
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
{
/**
* @var mixed
*/
private $value;
public function __construct($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($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.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
if (is_string($this->value)) {
if (strpos($this->value, "\n") !== false) {
return 'is equal to <text>';
}
return sprintf(
"is equal to '%s'",
$this->value
);
}
return sprintf(
'is equal to %s',
$this->exporter()->export($this->value)
);
}
}
@@ -0,0 +1,100 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 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
{
/**
* @var mixed
*/
private $value;
/**
* @var float
*/
private $delta;
public function __construct($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($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.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
return sprintf(
'is equal to %s with delta <%F>>',
$this->exporter()->export($this->value),
$this->delta
);
}
}
@@ -0,0 +1,85 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 get_class;
use function sprintf;
use PHPUnit\Util\Filter;
use Throwable;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class Exception extends Constraint
{
/**
* @var string
*/
private $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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
if ($other !== null) {
$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',
get_class($other),
$this->className,
$message
);
}
return sprintf(
'exception of type "%s" is thrown',
$this->className
);
}
}
@@ -0,0 +1,67 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 Throwable;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ExceptionCode extends Constraint
{
/**
* @var int|string
*/
private $expectedCode;
/**
* @param int|string $expected
*/
public function __construct($expected)
{
$this->expectedCode = $expected;
}
public function toString(): string
{
return 'exception code is ';
}
/**
* Evaluates the constraint for parameter $other. Returns true if the
* constraint is met, false otherwise.
*
* @param Throwable $other
*/
protected function matches($other): bool
{
return (string) $other->getCode() === (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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
return sprintf(
'%s is equal to expected exception code %s',
$this->exporter()->export($other->getCode()),
$this->exporter()->export($this->expectedCode)
);
}
}
@@ -0,0 +1,78 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strpos;
use Throwable;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ExceptionMessage extends Constraint
{
/**
* @var string
*/
private $expectedMessage;
public function __construct(string $expected)
{
$this->expectedMessage = $expected;
}
public function toString(): string
{
if ($this->expectedMessage === '') {
return 'exception message is empty';
}
return 'exception message contains ';
}
/**
* Evaluates the constraint for parameter $other. Returns true if the
* constraint is met, false otherwise.
*
* @param Throwable $other
*/
protected function matches($other): bool
{
if ($this->expectedMessage === '') {
return $other->getMessage() === '';
}
return strpos((string) $other->getMessage(), $this->expectedMessage) !== 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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
if ($this->expectedMessage === '') {
return sprintf(
"exception message is empty but is '%s'",
$other->getMessage()
);
}
return sprintf(
"exception message '%s' contains '%s'",
$other->getMessage(),
$this->expectedMessage
);
}
}
@@ -0,0 +1,74 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 Exception;
use PHPUnit\Util\RegularExpression as RegularExpressionUtil;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ExceptionMessageRegularExpression extends Constraint
{
/**
* @var string
*/
private $expectedMessageRegExp;
public function __construct(string $expected)
{
$this->expectedMessageRegExp = $expected;
}
public function toString(): string
{
return 'exception message matches ';
}
/**
* Evaluates the constraint for parameter $other. Returns true if the
* constraint is met, false otherwise.
*
* @param \PHPUnit\Framework\Exception $other
*
* @throws \PHPUnit\Framework\Exception
* @throws Exception
*/
protected function matches($other): bool
{
$match = RegularExpressionUtil::safeMatch($this->expectedMessageRegExp, $other->getMessage());
if ($match === false) {
throw new \PHPUnit\Framework\Exception(
"Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'"
);
}
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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
return sprintf(
"exception message '%s' matches '%s'",
$other->getMessage(),
$this->expectedMessageRegExp
);
}
}
@@ -0,0 +1,54 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
return sprintf(
'directory "%s" exists',
$other
);
}
}
@@ -0,0 +1,54 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
return sprintf(
'file "%s" exists',
$other
);
}
}
@@ -0,0 +1,54 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
return sprintf(
'"%s" is readable',
$other
);
}
}
@@ -0,0 +1,54 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
*/
protected function failureDescription($other): string
{
return sprintf(
'"%s" is writable',
$other
);
}
}
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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($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;
}
}
@@ -0,0 +1,137 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 PHP_FLOAT_EPSILON;
use function abs;
use function get_class;
use function is_array;
use function is_float;
use function is_infinite;
use function is_nan;
use function is_object;
use function is_string;
use function sprintf;
use PHPUnit\Framework\ExpectationFailedException;
use SebastianBergmann\Comparator\ComparisonFailure;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class IsIdentical extends Constraint
{
/**
* @var mixed
*/
private $value;
public function __construct($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 \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
{
if (is_float($this->value) && is_float($other) &&
!is_infinite($this->value) && !is_infinite($other) &&
!is_nan($this->value) && !is_nan($other)) {
$success = abs($this->value - $other) < PHP_FLOAT_EPSILON;
} else {
$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, make sure a diff is generated
if (is_array($this->value) && is_array($other)) {
$f = new ComparisonFailure(
$this->value,
$other,
$this->exporter()->export($this->value),
$this->exporter()->export($other)
);
}
$this->fail($other, $description, $f);
}
return null;
}
/**
* Returns a string representation of the constraint.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
if (is_object($this->value)) {
return 'is identical to an object of class "' .
get_class($this->value) . '"';
}
return 'is identical to ' . $this->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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
if (is_object($this->value) && is_object($other)) {
return 'two variables reference the same object';
}
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);
}
}
@@ -0,0 +1,109 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\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
{
/**
* @var string
*/
private $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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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.
*
* @param mixed $other evaluated value or object
* @param string $description Additional information about the test
* @param ComparisonFailure $comparisonFailure
*
* @throws \PHPUnit\Framework\Exception
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*
* @psalm-return never-return
*/
protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void
{
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),
false,
'Failed asserting that two json values are equal.'
);
}
parent::fail($other, $description, $comparisonFailure);
}
}
@@ -0,0 +1,72 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strtolower;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class JsonMatchesErrorMessageProvider
{
/**
* Translates JSON error to a human readable string.
*/
public static function determineJsonError(string $error, string $prefix = ''): ?string
{
switch ($error) {
case JSON_ERROR_NONE:
return null;
case JSON_ERROR_DEPTH:
return $prefix . 'Maximum stack depth exceeded';
case JSON_ERROR_STATE_MISMATCH:
return $prefix . 'Underflow or the modes mismatch';
case JSON_ERROR_CTRL_CHAR:
return $prefix . 'Unexpected control character found';
case JSON_ERROR_SYNTAX:
return $prefix . 'Syntax error, malformed JSON';
case JSON_ERROR_UTF8:
return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded';
default:
return $prefix . 'Unknown error';
}
}
/**
* Translates a given type to a human readable message prefix.
*/
public static function translateTypeToPrefix(string $type): string
{
switch (strtolower($type)) {
case 'expected':
$prefix = 'Expected value JSON decode error - ';
break;
case 'actual':
$prefix = 'Actual value JSON decode error - ';
break;
default:
$prefix = '';
break;
}
return $prefix;
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return is_finite($other);
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return is_infinite($other);
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return is_nan($other);
}
}
@@ -0,0 +1,88 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 get_class;
use function is_object;
use function sprintf;
use PHPUnit\Framework\Exception;
use ReflectionClass;
use ReflectionException;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
class ClassHasAttribute extends Constraint
{
/**
* @var string
*/
private $attributeName;
public function __construct(string $attributeName)
{
$this->attributeName = $attributeName;
}
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return sprintf(
'has attribute "%s"',
$this->attributeName
);
}
/**
* 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($other): bool
{
try {
return (new ReflectionClass($other))->hasProperty($this->attributeName);
// @codeCoverageIgnoreStart
} catch (ReflectionException $e) {
throw new Exception(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
}
/**
* 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($other): string
{
return sprintf(
'%sclass "%s" %s',
is_object($other) ? 'object of ' : '',
is_object($other) ? get_class($other) : $other,
$this->toString()
);
}
protected function attributeName(): string
{
return $this->attributeName;
}
}
@@ -0,0 +1,59 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\Framework\Exception;
use ReflectionClass;
use ReflectionException;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ClassHasStaticAttribute extends ClassHasAttribute
{
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return sprintf(
'has static attribute "%s"',
$this->attributeName()
);
}
/**
* 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($other): bool
{
try {
$class = new ReflectionClass($other);
if ($class->hasProperty($this->attributeName())) {
return $class->getProperty($this->attributeName())->isStatic();
}
// @codeCoverageIgnoreStart
} catch (ReflectionException $e) {
throw new Exception(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
// @codeCoverageIgnoreEnd
return false;
}
}
@@ -0,0 +1,151 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 get_class;
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
{
/**
* @var object
*/
private $expected;
/**
* @var string
*/
private $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($other): bool
{
if (!is_object($other)) {
throw new ActualValueIsNotAnObjectException;
}
$object = new ReflectionObject($other);
if (!$object->hasMethod($this->method)) {
throw new ComparisonMethodDoesNotExistException(
get_class($other),
$this->method
);
}
/** @noinspection PhpUnhandledExceptionInspection */
$method = $object->getMethod($this->method);
if (!$method->hasReturnType()) {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
get_class($other),
$this->method
);
}
$returnType = $method->getReturnType();
if (!$returnType instanceof ReflectionNamedType) {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
get_class($other),
$this->method
);
}
if ($returnType->allowsNull()) {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
get_class($other),
$this->method
);
}
if ($returnType->getName() !== 'bool') {
throw new ComparisonMethodDoesNotDeclareBoolReturnTypeException(
get_class($other),
$this->method
);
}
if ($method->getNumberOfParameters() !== 1 || $method->getNumberOfRequiredParameters() !== 1) {
throw new ComparisonMethodDoesNotDeclareExactlyOneParameterException(
get_class($other),
$this->method
);
}
$parameter = $method->getParameters()[0];
if (!$parameter->hasType()) {
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
get_class($other),
$this->method
);
}
$type = $parameter->getType();
if (!$type instanceof ReflectionNamedType) {
throw new ComparisonMethodDoesNotDeclareParameterTypeException(
get_class($other),
$this->method
);
}
$typeName = $type->getName();
if ($typeName === 'self') {
$typeName = get_class($other);
}
if (!$this->expected instanceof $typeName) {
throw new ComparisonMethodDoesNotAcceptParameterTypeException(
get_class($other),
$this->method,
get_class($this->expected)
);
}
return $other->{$this->method}($this->expected);
}
protected function failureDescription($other): string
{
return $this->toString();
}
}
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 ReflectionObject;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ObjectHasAttribute extends ClassHasAttribute
{
/**
* 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($other): bool
{
return (new ReflectionObject($other))->hasProperty($this->attributeName());
}
}
@@ -0,0 +1,148 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 array_values;
use function count;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
abstract class BinaryOperator extends Operator
{
/**
* @var Constraint[]
*/
private $constraints = [];
public static function fromConstraints(Constraint ...$constraints): self
{
$constraint = new static;
$constraint->constraints = $constraints;
return $constraint;
}
/**
* @param mixed[] $constraints
*/
public function setConstraints(array $constraints): void
{
$this->constraints = array_map(function ($constraint): Constraint
{
return $this->checkConstraint($constraint);
}, array_values($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;
}
/**
* Returns the nested constraints.
*/
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.
*
* @param Constraint $constraint operand constraint
* @param int $position position of $constraint in this expression
*/
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;
}
}
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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
{
/**
* 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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
foreach ($this->constraints() as $constraint) {
if (!$constraint->evaluate($other, '', true)) {
return false;
}
}
return [] !== $this->constraints();
}
}
@@ -0,0 +1,136 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @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);
$positives = array_map(static function (string $s)
{
return '/\\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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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();
}
}
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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
{
/**
* 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.
*
* @param mixed $other value or object to evaluate
*/
public function matches($other): bool
{
foreach ($this->constraints() as $constraint) {
if ($constraint->evaluate($other, '', true)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,63 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class LogicalXor extends BinaryOperator
{
/**
* 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.
*
* @param mixed $other value or object to evaluate
*/
public function matches($other): bool
{
$constraints = $this->constraints();
$initial = array_shift($constraints);
if ($initial === null) {
return false;
}
return array_reduce(
$constraints,
static function (bool $matches, Constraint $constraint) use ($other): bool
{
return $matches xor $constraint->evaluate($other, '', true);
},
$initial->evaluate($other, '', true)
);
}
}
@@ -0,0 +1,55 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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($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();
}
}
@@ -0,0 +1,140 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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
{
/**
* @var Constraint
*/
private $constraint;
/**
* @param Constraint|mixed $constraint
*/
public function __construct($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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($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().
*
* @param string $string the string to be transformed
*/
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);
}
}
@@ -0,0 +1,77 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
if ($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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
if ($other === '') {
return 'an empty string is valid JSON';
}
json_decode($other);
$error = (string) JsonMatchesErrorMessageProvider::determineJsonError(
(string) json_last_error()
);
return sprintf(
'%s is valid JSON (%s)',
$this->exporter()->shortenedExport($other),
$error
);
}
}
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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
*/
class RegularExpression extends Constraint
{
/**
* @var string
*/
private $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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return preg_match($this->pattern, $other) > 0;
}
}
@@ -0,0 +1,85 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 mb_stripos;
use function mb_strtolower;
use function sprintf;
use function strpos;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class StringContains extends Constraint
{
/**
* @var string
*/
private $string;
/**
* @var bool
*/
private $ignoreCase;
public function __construct(string $string, bool $ignoreCase = false)
{
$this->string = $string;
$this->ignoreCase = $ignoreCase;
}
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
if ($this->ignoreCase) {
$string = mb_strtolower($this->string, 'UTF-8');
} else {
$string = $this->string;
}
return sprintf(
'contains "%s"',
$string
);
}
/**
* 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($other): bool
{
if ('' === $this->string) {
return true;
}
if ($this->ignoreCase) {
/*
* We must use the multi byte safe version so we can accurately compare non latin upper characters with
* their lowercase equivalents.
*/
return mb_stripos($other, $this->string, 0, 'UTF-8') !== false;
}
/*
* Use the non multi byte 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 strpos($other, $this->string) !== false;
}
}
@@ -0,0 +1,48 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strlen;
use function substr;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class StringEndsWith extends Constraint
{
/**
* @var string
*/
private $suffix;
public function __construct(string $suffix)
{
$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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return substr($other, 0 - strlen($this->suffix)) === $this->suffix;
}
}
@@ -0,0 +1,109 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 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 RegularExpression
{
/**
* @var string
*/
private $string;
public function __construct(string $string)
{
parent::__construct(
$this->createPatternFromFormat(
$this->convertNewlines($string)
)
);
$this->string = $string;
}
/**
* 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($other): bool
{
return parent::matches(
$this->convertNewlines($other)
);
}
protected function failureDescription($other): string
{
return 'string matches format description';
}
protected function additionalFailureDescription($other): string
{
$from = explode("\n", $this->string);
$to = explode("\n", $this->convertNewlines($other));
foreach ($from as $index => $line) {
if (isset($to[$index]) && $line !== $to[$index]) {
$line = $this->createPatternFromFormat($line);
if (preg_match($line, $to[$index]) > 0) {
$from[$index] = $to[$index];
}
}
}
$this->string = implode("\n", $from);
$other = implode("\n", $to);
return (new Differ(new UnifiedDiffOutputBuilder("--- Expected\n+++ Actual\n")))->diff($this->string, $other);
}
private function createPatternFromFormat(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);
}
}
@@ -0,0 +1,53 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 strlen;
use function strpos;
use PHPUnit\Framework\InvalidArgumentException;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class StringStartsWith extends Constraint
{
/**
* @var string
*/
private $prefix;
public function __construct(string $prefix)
{
if (strlen($prefix) === 0) {
throw InvalidArgumentException::create(1, 'non-empty string');
}
$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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return strpos((string) $other, $this->prefix) === 0;
}
}
@@ -0,0 +1,77 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ArrayHasKey extends Constraint
{
/**
* @var int|string
*/
private $key;
/**
* @param int|string $key
*/
public function __construct($key)
{
$this->key = $key;
}
/**
* Returns a string representation of the constraint.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
return 'has the key ' . $this->exporter()->export($this->key);
}
/**
* 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($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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
return 'an array ' . $this->toString();
}
}
@@ -0,0 +1,63 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
abstract class TraversableContains extends Constraint
{
/**
* @var mixed
*/
private $value;
public function __construct($value)
{
$this->value = $value;
}
/**
* Returns a string representation of the constraint.
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function toString(): string
{
return 'contains ' . $this->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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
return sprintf(
'%s %s',
is_array($other) ? 'an array' : 'a traversable',
$this->toString()
);
}
protected function value()
{
return $this->value;
}
}
@@ -0,0 +1,40 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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;
}
}
@@ -0,0 +1,39 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
if ($other instanceof SplObjectStorage) {
return $other->contains($this->value());
}
foreach ($other as $element) {
if ($this->value() === $element) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,91 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
use Traversable;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class TraversableContainsOnly extends Constraint
{
/**
* @var Constraint
*/
private $constraint;
/**
* @var string
*/
private $type;
/**
* @throws \PHPUnit\Framework\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.
*
* @param mixed|Traversable $other
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
* @throws ExpectationFailedException
*/
public function evaluate($other, string $description = '', bool $returnResult = false): ?bool
{
$success = true;
foreach ($other as $item) {
if (!$this->constraint->evaluate($item, '', true)) {
$success = false;
break;
}
}
if ($returnResult) {
return $success;
}
if (!$success) {
$this->fail($other, $description);
}
return null;
}
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return 'contains only values of type "' . $this->type . '"';
}
}
@@ -0,0 +1,87 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 ReflectionClass;
use ReflectionException;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class IsInstanceOf extends Constraint
{
/**
* @var string
*/
private $className;
public function __construct(string $className)
{
$this->className = $className;
}
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return sprintf(
'is instance of %s "%s"',
$this->getType(),
$this->className
);
}
/**
* 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($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.
*
* @param mixed $other evaluated value or object
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
protected function failureDescription($other): string
{
return sprintf(
'%s is an instance of %s "%s"',
$this->exporter()->shortenedExport($other),
$this->getType(),
$this->className
);
}
private function getType(): string
{
try {
$reflection = new ReflectionClass($this->className);
if ($reflection->isInterface()) {
return 'interface';
}
} catch (ReflectionException $e) {
}
return 'class';
}
}
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($other): bool
{
return $other === null;
}
}
@@ -0,0 +1,210 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @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 string
*/
private $type;
/**
* @throws \PHPUnit\Framework\Exception
*/
public function __construct(string $type)
{
if (!isset(self::KNOWN_TYPES[$type])) {
throw new \PHPUnit\Framework\Exception(
sprintf(
'Type specified for PHPUnit\Framework\Constraint\IsType <%s> ' .
'is not a valid type.',
$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.
*
* @param mixed $other value or object to evaluate
*/
protected function matches($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;
}
}
}
@@ -0,0 +1,75 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 explode;
use PHPUnit\Util\Test as TestUtil;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class DataProviderTestSuite extends TestSuite
{
/**
* @var list<ExecutionOrderDependency>
*/
private $dependencies = [];
/**
* @param list<ExecutionOrderDependency> $dependencies
*/
public function setDependencies(array $dependencies): void
{
$this->dependencies = $dependencies;
foreach ($this->tests as $test) {
if (!$test instanceof TestCase) {
// @codeCoverageIgnoreStart
continue;
// @codeCoverageIgnoreStart
}
$test->setDependencies($dependencies);
}
}
/**
* @return list<ExecutionOrderDependency>
*/
public function provides(): array
{
if ($this->providedTests === null) {
$this->providedTests = [new ExecutionOrderDependency($this->getName())];
}
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 the each test created using the data provider(s).
*
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*/
public function getSize(): int
{
[$className, $methodName] = explode('::', $this->getName());
return TestUtil::getSize($className, $methodName);
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\Error;
/**
* @internal
*/
final class Deprecated extends Error
{
}
+26
View File
@@ -0,0 +1,26 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\Error;
use PHPUnit\Framework\Exception;
/**
* @internal
*/
class Error extends Exception
{
public function __construct(string $message, int $code, string $file, int $line, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
$this->file = $file;
$this->line = $line;
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\Error;
/**
* @internal
*/
final class Notice extends Error
{
}
+17
View File
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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\Error;
/**
* @internal
*/
final class Warning extends Error
{
}
+66
View File
@@ -0,0 +1,66 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class ErrorTestCase extends TestCase
{
/**
* @var bool
*/
protected $backupGlobals = false;
/**
* @var bool
*/
protected $backupStaticAttributes = false;
/**
* @var bool
*/
protected $runTestInSeparateProcess = false;
/**
* @var string
*/
private $message;
public function __construct(string $message = '')
{
$this->message = $message;
parent::__construct('Error');
}
public function getMessage(): string
{
return $this->message;
}
/**
* Returns a string representation of the test case.
*/
public function toString(): string
{
return 'Error';
}
/**
* @throws Exception
*
* @psalm-return never-return
*/
protected function runTest(): void
{
throw new Error($this->message);
}
}
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @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',
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @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();
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
class CodeCoverageException extends Exception
{
}
@@ -0,0 +1,38 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 sprintf;
/**
* @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
),
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 sprintf;
/**
* @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
),
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 sprintf;
/**
* @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
),
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 sprintf;
/**
* @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
),
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,37 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 sprintf;
/**
* @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
),
0,
null
);
}
public function __toString(): string
{
return $this->getMessage() . PHP_EOL;
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class CoveredCodeNotExecutedException extends RiskyTestError
{
}
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class Error extends Exception implements SelfDescribing
{
/**
* Wrapper for getMessage() which is declared as final.
*/
public function toString(): string
{
return $this->getMessage();
}
}
@@ -0,0 +1,81 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 PHPUnit\Util\Filter;
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
*
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
class Exception extends RuntimeException implements \PHPUnit\Exception
{
/**
* @var array
*/
protected $serializableTrace;
public function __construct($message = '', $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 __toString(): string
{
$string = TestFailure::exceptionToString($this);
if ($trace = Filter::getFilteredStacktrace($this)) {
$string .= "\n" . $trace;
}
return $string;
}
public function __sleep(): array
{
return array_keys(get_object_vars($this));
}
/**
* Returns the serializable trace (without 'args').
*/
public function getSerializableTrace(): array
{
return $this->serializableTrace;
}
}
@@ -0,0 +1,42 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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.
*
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class ExpectationFailedException extends AssertionFailedError
{
/**
* @var ComparisonFailure
*/
protected $comparisonFailure;
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;
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class IncompleteTestError extends AssertionFailedError implements IncompleteTest
{
}
@@ -0,0 +1,46 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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 debug_backtrace;
use function in_array;
use function lcfirst;
use function sprintf;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class InvalidArgumentException extends Exception
{
public static function create(int $argument, string $type): self
{
$stack = debug_backtrace();
$function = $stack[1]['function'];
if (isset($stack[1]['class'])) {
$function = sprintf('%s::%s', $stack[1]['class'], $stack[1]['function']);
}
return new self(
sprintf(
'Argument #%d of %s() must be %s %s',
$argument,
$function,
in_array(lcfirst($type)[0], ['a', 'e', 'i', 'o', 'u'], true) ? 'an' : 'a',
$type
)
);
}
private function __construct(string $message = '', int $code = 0, \Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class InvalidCoversTargetException extends CodeCoverageException
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class InvalidDataProviderException extends Exception
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class MissingCoversAnnotationException extends RiskyTestError
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class NoChildTestSuiteException extends Exception
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class OutputError extends AssertionFailedError
{
}
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class PHPTAssertionFailedError extends SyntheticError
{
/**
* @var string
*/
private $diff;
public function __construct(string $message, int $code, string $file, int $line, array $trace, string $diff)
{
parent::__construct($message, $code, $file, $line, $trace);
$this->diff = $diff;
}
public function getDiff(): string
{
return $this->diff;
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
class RiskyTestError extends AssertionFailedError
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class SkippedTestError extends AssertionFailedError implements SkippedTest
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest
{
}
@@ -0,0 +1,61 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
class SyntheticError extends AssertionFailedError
{
/**
* The synthetic file.
*
* @var string
*/
protected $syntheticFile = '';
/**
* The synthetic line number.
*
* @var int
*/
protected $syntheticLine = 0;
/**
* The synthetic trace.
*
* @var array
*/
protected $syntheticTrace = [];
public function __construct(string $message, int $code, string $file, int $line, array $trace)
{
parent::__construct($message, $code);
$this->syntheticFile = $file;
$this->syntheticLine = $line;
$this->syntheticTrace = $trace;
}
public function getSyntheticFile(): string
{
return $this->syntheticFile;
}
public function getSyntheticLine(): int
{
return $this->syntheticLine;
}
public function getSyntheticTrace(): array
{
return $this->syntheticTrace;
}
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class SyntheticSkippedError extends SyntheticError implements SkippedTest
{
}
@@ -0,0 +1,17 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class UnintentionallyCoveredCodeError extends RiskyTestError
{
}
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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;
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class Warning extends Exception implements SelfDescribing
{
/**
* Wrapper for getMessage() which is declared as final.
*/
public function toString(): string
{
return $this->getMessage();
}
}
@@ -0,0 +1,122 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <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_class;
use function spl_object_hash;
use PHPUnit\Util\Filter;
use Throwable;
/**
* Wraps Exceptions thrown by code under test.
*
* Re-instantiates Exceptions thrown by user-space code to retain their original
* class names, properties, and stack traces (but without arguments).
*
* Unlike PHPUnit\Framework\Exception, the complete stack of previous Exceptions
* is processed.
*
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class ExceptionWrapper extends Exception
{
/**
* @var string
*/
protected $className;
/**
* @var null|ExceptionWrapper
*/
protected $previous;
public function __construct(Throwable $t)
{
// PDOException::getCode() is a string.
// @see https://php.net/manual/en/class.pdoexception.php#95812
parent::__construct($t->getMessage(), (int) $t->getCode());
$this->setOriginalException($t);
}
public function __toString(): string
{
$string = TestFailure::exceptionToString($this);
if ($trace = Filter::getFilteredStacktrace($this)) {
$string .= "\n" . $trace;
}
if ($this->previous) {
$string .= "\nCaused by\n" . $this->previous;
}
return $string;
}
public function getClassName(): string
{
return $this->className;
}
public function getPreviousWrapped(): ?self
{
return $this->previous;
}
public function setClassName(string $className): void
{
$this->className = $className;
}
public function setOriginalException(Throwable $t): void
{
$this->originalException($t);
$this->className = get_class($t);
$this->file = $t->getFile();
$this->line = $t->getLine();
$this->serializableTrace = $t->getTrace();
foreach (array_keys($this->serializableTrace) as $key) {
unset($this->serializableTrace[$key]['args']);
}
if ($t->getPrevious()) {
$this->previous = new self($t->getPrevious());
}
}
public function getOriginalException(): ?Throwable
{
return $this->originalException();
}
/**
* Method to contain static originalException to exclude it from stacktrace to prevent the stacktrace contents,
* which can be quite big, from being garbage-collected, thus blocking memory until shutdown.
*
* Approach works both for var_dump() and var_export() and print_r().
*/
private function originalException(Throwable $exceptionToStore = null): ?Throwable
{
static $originalExceptions;
$instanceId = spl_object_hash($this);
if ($exceptionToStore) {
$originalExceptions[$instanceId] = $exceptionToStore;
}
return $originalExceptions[$instanceId] ?? null;
}
}

Some files were not shown because too many files have changed in this diff Show More