pax_global_header00006660000000000000000000000064132154074670014523gustar00rootroot0000000000000052 comment=83d27937a310f2984fd575686138597147bdc7df phpunit-6.5.5/000077500000000000000000000000001321540746700132275ustar00rootroot00000000000000phpunit-6.5.5/.editorconfig000066400000000000000000000001631321540746700157040ustar00rootroot00000000000000root = true [*] end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 charset = utf-8 phpunit-6.5.5/.gitattributes000066400000000000000000000000461321540746700161220ustar00rootroot00000000000000/build export-ignore *.php diff=php phpunit-6.5.5/.github/000077500000000000000000000000001321540746700145675ustar00rootroot00000000000000phpunit-6.5.5/.github/CODE_OF_CONDUCT.md000066400000000000000000000045271321540746700173760ustar00rootroot00000000000000# Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainer at sebastian@phpunit.de. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.3.0, available at [http://contributor-covenant.org/version/1/3/0/][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/3/0/ phpunit-6.5.5/.github/CONTRIBUTING.md000066400000000000000000000051451321540746700170250ustar00rootroot00000000000000# Contributing to PHPUnit ## Contributor Code of Conduct Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. ## Workflow * Fork the project. * Make your bug fix or feature addition. * Add tests for it. This is important so we don't break it in a future version unintentionally. * Send a pull request. Bonus points for topic branches. Please make sure that you have [set up your user name and email address](http://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) for use with Git. Strings such as `silly nick name ` look really stupid in the commit history of a project. Pull requests for bug fixes must be based on the current stable branch whereas pull requests for new features must be based on the `master` branch. We are trying to keep backwards compatibility breaks in PHPUnit to an absolute minimum. Please take this into account when proposing changes. Due to time constraints, we are not always able to respond as quickly as we would like. Please do not take delays personal and feel free to remind us if you feel that we forgot to respond. ## Coding Guidelines This project comes with a configuration file for [php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) (`.php_cs`) that you can use to (re)format your sourcecode for compliance with this project's coding guidelines: ```bash $ wget http://cs.sensiolabs.org/download/php-cs-fixer-v2.phar -O php-cs-fixer.phar $ php php-cs-fixer.phar fix ``` ## Using PHPUnit from a Git checkout The following commands can be used to perform the initial checkout of PHPUnit: ```bash $ git clone git://github.com/sebastianbergmann/phpunit.git $ cd phpunit ``` Retrieve PHPUnit's dependencies using [Composer](https://getcomposer.org/): ```bash $ composer install ``` The `phpunit` script can be used to invoke the PHPUnit test runner: ```bash $ ./phpunit --version ``` ## Running PHPUnit's own test suite After following the steps shown above, PHPUnit's own test suite is run like this: ```bash $ ./phpunit ``` ## Reporting issues Please use the most specific issue tracker to search for existing tickets and to open new tickets: * [General problems](https://github.com/sebastianbergmann/phpunit/issues) * [Code Coverage](https://github.com/sebastianbergmann/php-code-coverage/issues) * [Stub and Mock Objects](https://github.com/sebastianbergmann/phpunit-mock-objects/issues) * [Documentation](https://github.com/sebastianbergmann/phpunit-documentation/issues) * [Website](https://github.com/sebastianbergmann/phpunit-website/issues) phpunit-6.5.5/.github/ISSUE_TEMPLATE.md000066400000000000000000000011501321540746700172710ustar00rootroot00000000000000| Q | A | --------------------| --------------- | PHPUnit version | x.y.z | PHP version | x.y.z | Installation Method | Composer / PHAR phpunit-6.5.5/.gitignore000066400000000000000000000004611321540746700152200ustar00rootroot00000000000000/.ant_targets /.idea /build/documentation /build/logfiles /build/phar /build/phpdox /build/*.phar /build/*.phar.asc /build/binary-phar-autoload.php /tests/TextUI/*.diff /tests/TextUI/*.exp /tests/TextUI/*.log /tests/TextUI/*.out /tests/TextUI/*.php /cache.properties /composer.lock /vendor /.php_cs.cache phpunit-6.5.5/.php_cs000066400000000000000000000064161321540746700145130ustar00rootroot00000000000000 For the full copyright and license information, please view the LICENSE file that was distributed with this source code. EOF; return PhpCsFixer\Config::create() ->setRiskyAllowed(true) ->setRules( [ 'array_syntax' => ['syntax' => 'short'], 'binary_operator_spaces' => [ 'align_double_arrow' => true, 'align_equals' => true ], 'blank_line_after_namespace' => true, 'blank_line_before_statement' => [ 'statements' => [ 'break', 'continue', 'return', 'throw', 'try', ], ], 'braces' => true, 'cast_spaces' => true, 'concat_space' => ['spacing' => 'one'], 'elseif' => true, 'encoding' => true, 'full_opening_tag' => true, 'function_declaration' => true, 'header_comment' => ['header' => $header, 'separate' => 'none'], 'indentation_type' => true, 'line_ending' => true, 'lowercase_constants' => true, 'lowercase_keywords' => true, 'method_argument_space' => true, 'native_function_invocation' => true, 'no_alias_functions' => true, 'no_blank_lines_after_class_opening' => true, 'no_blank_lines_after_phpdoc' => true, 'no_closing_tag' => true, 'no_empty_phpdoc' => true, 'no_empty_statement' => true, 'no_extra_consecutive_blank_lines' => true, 'no_leading_namespace_whitespace' => true, 'no_singleline_whitespace_before_semicolons' => true, 'no_spaces_after_function_name' => true, 'no_spaces_inside_parenthesis' => true, 'no_trailing_comma_in_list_call' => true, 'no_trailing_whitespace' => true, 'no_unused_imports' => true, 'no_whitespace_in_blank_line' => true, 'ordered_imports' => true, 'phpdoc_align' => true, 'phpdoc_indent' => true, 'phpdoc_no_access' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_no_package' => true, 'phpdoc_scalar' => true, 'phpdoc_separation' => true, 'phpdoc_to_comment' => true, 'phpdoc_trim' => true, 'phpdoc_types' => true, 'phpdoc_var_without_name' => true, 'self_accessor' => true, 'simplified_null_return' => true, 'single_blank_line_at_eof' => true, 'single_import_per_statement' => true, 'single_line_after_imports' => true, 'single_quote' => true, 'ternary_operator_spaces' => true, 'trim_array_spaces' => true, 'visibility_required' => true, ] ) ->setFinder( PhpCsFixer\Finder::create() ->files() ->in(__DIR__ . '/build') ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests/Framework') ->in(__DIR__ . '/tests/Runner') ->in(__DIR__ . '/tests/Util') ->name('*.php') ); phpunit-6.5.5/.stickler.yml000066400000000000000000000000621321540746700156460ustar00rootroot00000000000000linters: phpcs: standard: 'build/phpcs.xml' phpunit-6.5.5/.travis.yml000066400000000000000000000025371321540746700153470ustar00rootroot00000000000000language: php sudo: false addons: apt: packages: - libxml2-utils php: - 7.0 - 7.1 - 7.2 - master env: matrix: - DEPENDENCIES="high" - DEPENDENCIES="low" global: - DEFAULT_COMPOSER_FLAGS="--no-interaction --no-ansi --no-progress --no-suggest" before_install: - composer self-update - composer clear-cache install: - if [[ "$DEPENDENCIES" = 'high' ]]; then travis_retry composer update $DEFAULT_COMPOSER_FLAGS; fi - if [[ "$DEPENDENCIES" = 'low' ]]; then travis_retry composer update $DEFAULT_COMPOSER_FLAGS --prefer-lowest; fi before_script: - echo 'zend.assertions=1' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - echo 'assert.exception=On' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini script: - ./phpunit --coverage-clover=coverage.xml - ./phpunit --configuration ./build/travis-ci-fail.xml > /dev/null; if [ $? -eq 0 ]; then echo "SHOULD FAIL"; false; else echo "fail checked"; fi; - xmllint --noout --schema phpunit.xsd phpunit.xml - xmllint --noout --schema phpunit.xsd tests/_files/configuration.xml - xmllint --noout --schema phpunit.xsd tests/_files/configuration_empty.xml - xmllint --noout --schema phpunit.xsd tests/_files/configuration_xinclude.xml -xinclude after_success: - bash <(curl -s https://codecov.io/bash) notifications: email: false phpunit-6.5.5/ChangeLog-5.7.md000066400000000000000000000265461321540746700157240ustar00rootroot00000000000000# Changes in PHPUnit 5.7 All notable changes of the PHPUnit 5.7 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [5.7.26] - 2017-12-17 ### Fixed * Fixed [#2472](https://github.com/sebastianbergmann/phpunit/issues/2472): `PHPUnit\Util\Getopt` uses deprecated `each()` function * Fixed [#2833](https://github.com/sebastianbergmann/phpunit/issues/2833): Test class loaded during data provider execution is not discovered * Fixed [#2922](https://github.com/sebastianbergmann/phpunit/issues/2922): Test class is not discovered when there is a test class with `@group` and provider throwing exception in it, tests are run with `--exclude-group` for that group, there is another class called later (after the class from above), and the name of that another class does not match its filename ## [5.7.25] - 2017-11-14 ### Fixed * Fixed [#2859](https://github.com/sebastianbergmann/phpunit/issues/2859): Regression caused by fix for [#2833](https://github.com/sebastianbergmann/phpunit/issues/2833) ## [5.7.24] - 2017-11-14 ### Fixed * Fixed [#2833](https://github.com/sebastianbergmann/phpunit/issues/2833): Test class loaded during data provider execution is not discovered ## [5.7.23] - 2017-10-15 ### Fixed * Fixed [#2731](https://github.com/sebastianbergmann/phpunit/issues/2731): Empty exception message cannot be expected ## [5.7.22] - 2017-09-24 ### Fixed * Fixed [#2769](https://github.com/sebastianbergmann/phpunit/issues/2769): Usage of `setUseErrorHandler()` produces `Undefined variable` error ## [5.7.21] - 2017-06-21 ### Added * Added `PHPUnit\Framework\AssertionFailedError`, `PHPUnit\Framework\Test`, and `PHPUnit\Framework\TestSuite` to the forward compatibility layer for PHPUnit 6 ### Fixed * Fixed [#2705](https://github.com/sebastianbergmann/phpunit/issues/2705): `stderr` parameter in `phpunit.xml` always considered `true` ## [5.7.20] - 2017-05-22 ### Fixed * Fixed [#2563](https://github.com/sebastianbergmann/phpunit/pull/2563): `phpunit --version` does not display version when running unsupported PHP ## [5.7.19] - 2017-04-03 ### Fixed * Fixed [#2638](https://github.com/sebastianbergmann/phpunit/pull/2638): Regression in `PHPUnit\Framework\TestCase:registerMockObjectsFromTestArguments()` ## [5.7.18] - 2017-04-02 ### Fixed * Fixed [#2145](https://github.com/sebastianbergmann/phpunit/issues/2145): `--stop-on-failure` fails to stop on PHP 7 * Fixed [#2572](https://github.com/sebastianbergmann/phpunit/issues/2572): `PHPUnit\Framework\TestCase:registerMockObjectsFromTestArguments()` does not correctly handle arrays that reference themselves ## [5.7.17] - 2017-03-19 ### Fixed * Fixed [#2016](https://github.com/sebastianbergmann/phpunit/issues/2016): `prophesize()` does not work when static attributes are backed up * Fixed [#2568](https://github.com/sebastianbergmann/phpunit/issues/2568): `ArraySubsetConstraint` uses invalid cast to array * Fixed [#2573](https://github.com/sebastianbergmann/phpunit/issues/2573): `getMockFromWsdl()` does not handle URLs with query parameters * `PHPUnit\Util\Test::getDataFromTestWithAnnotation()` raises notice when docblock contains Windows line endings ## [5.7.16] - 2017-03-15 ### Fixed * Fixed [#2547](https://github.com/sebastianbergmann/phpunit/issues/2547): Code Coverage data is collected for test annotated with `@coversNothing` * Fixed [#2558](https://github.com/sebastianbergmann/phpunit/issues/2558): `countOf()` function is missing ## [5.7.15] - 2017-03-02 ### Fixed * Fixed [#1999](https://github.com/sebastianbergmann/phpunit/issues/1999): Handler is inherited from previous custom option with handler * Fixed [#2149](https://github.com/sebastianbergmann/phpunit/issues/2149): `assertCount()` does not handle generators properly * Fixed [#2478](https://github.com/sebastianbergmann/phpunit/issues/2478): Tests that take too long are not reported as risky test ## [5.7.14] - 2017-02-19 ### Fixed * Fixed [#2489](https://github.com/sebastianbergmann/phpunit/issues/2489): `processUncoveredFilesFromWhitelist` is not handled correctly * Fixed default values for `addUncoveredFilesFromWhitelist` and `processUncoveredFilesFromWhitelist` in `phpunit.xsd` ## [5.7.13] - 2017-02-10 ### Fixed * Fixed [#2493](https://github.com/sebastianbergmann/phpunit/issues/2493): Fix for [#2475](https://github.com/sebastianbergmann/phpunit/pull/2475) does not apply to PHPUnit 5.7 ## [5.7.12] - 2017-02-08 ### Fixed * Fixed [#2475](https://github.com/sebastianbergmann/phpunit/pull/2475): Defining a test suite with only one file does not work ## [5.7.11] - 2017-02-05 ### Fixed * Deprecation errors when used with PHP 7.2 ## [5.7.10] - 2017-02-04 ### Fixed * Fixed [#2462](https://github.com/sebastianbergmann/phpunit/issues/2462): Code Coverage whitelist is filled even if no code coverage data is to be collected ## [5.7.9] - 2017-01-28 ### Fixed * Fixed [#2447](https://github.com/sebastianbergmann/phpunit/issues/2447): Reverted backwards incompatible change to handling of boolean environment variable values specified in XML ## [5.7.8] - 2017-01-26 ### Fixed * Fixed [#2446](https://github.com/sebastianbergmann/phpunit/issues/2446): Reverted backwards incompatible change to exit code in case of warnings ## [5.7.7] - 2017-01-25 ### Fixed * Fixed [#1896](https://github.com/sebastianbergmann/phpunit/issues/1896): Wrong test location when `@depends` and `@dataProvider` are combined * Fixed [#1983](https://github.com/sebastianbergmann/phpunit/pull/1983): Tests with `@expectedException` annotation cannot be skipped * Fixed [#2137](https://github.com/sebastianbergmann/phpunit/issues/2137): Warnings for invalid data providers are suppressed when test execution is filtered * Fixed [#2275](https://github.com/sebastianbergmann/phpunit/pull/2275): Invalid UTF-8 characters can lead to missing output * Fixed [#2299](https://github.com/sebastianbergmann/phpunit/issues/2299): `expectExceptionMessage()` and `expectExceptionCode()` do not work without `expectException()` * Fixed [#2328](https://github.com/sebastianbergmann/phpunit/issues/2328): `TestListener` callbacks `startTest()` and `endTest()` are not called when test is skipped due to `@depends` * Fixed [#2331](https://github.com/sebastianbergmann/phpunit/issues/2331): Boolean environment variable values specified in XML get mangled * Fixed [#2333](https://github.com/sebastianbergmann/phpunit/issues/2333): `assertContains()` and `assertNotContains()` do not handle UTF-8 strings correctly * Fixed [#2340](https://github.com/sebastianbergmann/phpunit/pull/2340): Data providers that use `yield` or implement `Iterator` cannot be combined * Fixed [#2349](https://github.com/sebastianbergmann/phpunit/pull/2349): `PHPUnit_TextUI_Command` does not `exit()` when it should * Fixed [#2392](https://github.com/sebastianbergmann/phpunit/issues/2392): Empty (but valid) data provider should skip the test * Fixed [#2431](https://github.com/sebastianbergmann/phpunit/issues/2431): `assertArraySubset()` does not support `ArrayAccess` * Fixed [#2435](https://github.com/sebastianbergmann/phpunit/issues/2435): Empty `@group` annotation causes error on PHP 7.2+ ## [5.7.6] - 2017-01-22 ### Fixed * Fixed [#2424](https://github.com/sebastianbergmann/phpunit/issues/2424): `TestCase::getStatus()` returns `STATUS_PASSED` instead of `STATUS_RISKY` for risky test * Fixed [#2427](https://github.com/sebastianbergmann/phpunit/issues/2427): TestDox group configuration is not handled * Fixed [#2428](https://github.com/sebastianbergmann/phpunit/pull/2428): Nested arrays specificied in XML configuration file are not handled correctly ## [5.7.5] - 2016-12-28 ### Fixed * Fixed [#2404](https://github.com/sebastianbergmann/phpunit/pull/2404): `assertDirectoryNotIsWriteable()` calls itself ## [5.7.4] - 2016-12-13 ### Fixed * Fixed [#2394](https://github.com/sebastianbergmann/phpunit/issues/2394): Do not treat `AssertionError` as assertion failure on PHP 5 ## [5.7.3] - 2016-12-09 ### Fixed * Fixed [#2384](https://github.com/sebastianbergmann/phpunit/pull/2384): Handle `PHPUnit_Framework_Exception` correctly when expecting exceptions ## [5.7.2] - 2016-12-03 ### Fixed * Fixed [#2382](https://github.com/sebastianbergmann/phpunit/issues/2382): Uncloneable test doubles passed via data provider do not work ## [5.7.1] - 2016-12-02 ### Fixed * Fixed [#2380](https://github.com/sebastianbergmann/phpunit/issues/2380): Data Providers cannot be generators anymore ## [5.7.0] - 2016-12-02 ### Added * Merged [#2223](https://github.com/sebastianbergmann/phpunit/pull/2223): Add support for multiple data providers * Added `extensionsDirectory` configuration directive to configure a directory from which all `.phar` files are loaded as PHPUnit extensions * Added `--no-extensions` commandline option to suppress loading of extensions (from configured extension directory) * Added `PHPUnit\Framework\Assert` as an alias for `PHPUnit_Framework_Assert` for forward compatibility * Added `PHPUnit\Framework\BaseTestListener` as an alias for `PHPUnit_Framework_BaseTestListener` for forward compatibility * Added `PHPUnit\Framework\TestListener` as an alias for `PHPUnit_Framework_TestListener` for forward compatibility ### Changed * The `--log-json` commandline option has been deprecated * The `--tap` and `--log-tap` commandline options have been deprecated * The `--self-update` and `--self-upgrade` commandline options have been deprecated (PHAR binary only) [5.7.26]: https://github.com/sebastianbergmann/phpunit/compare/5.7.25...5.7.26 [5.7.25]: https://github.com/sebastianbergmann/phpunit/compare/5.7.24...5.7.25 [5.7.24]: https://github.com/sebastianbergmann/phpunit/compare/5.7.23...5.7.24 [5.7.23]: https://github.com/sebastianbergmann/phpunit/compare/5.7.22...5.7.23 [5.7.22]: https://github.com/sebastianbergmann/phpunit/compare/5.7.21...5.7.22 [5.7.21]: https://github.com/sebastianbergmann/phpunit/compare/5.7.20...5.7.21 [5.7.20]: https://github.com/sebastianbergmann/phpunit/compare/5.7.19...5.7.20 [5.7.19]: https://github.com/sebastianbergmann/phpunit/compare/5.7.18...5.7.19 [5.7.18]: https://github.com/sebastianbergmann/phpunit/compare/5.7.17...5.7.18 [5.7.17]: https://github.com/sebastianbergmann/phpunit/compare/5.7.16...5.7.17 [5.7.16]: https://github.com/sebastianbergmann/phpunit/compare/5.7.15...5.7.16 [5.7.15]: https://github.com/sebastianbergmann/phpunit/compare/5.7.14...5.7.15 [5.7.14]: https://github.com/sebastianbergmann/phpunit/compare/5.7.13...5.7.14 [5.7.13]: https://github.com/sebastianbergmann/phpunit/compare/5.7.12...5.7.13 [5.7.12]: https://github.com/sebastianbergmann/phpunit/compare/5.7.11...5.7.12 [5.7.11]: https://github.com/sebastianbergmann/phpunit/compare/5.7.10...5.7.11 [5.7.10]: https://github.com/sebastianbergmann/phpunit/compare/5.7.9...5.7.10 [5.7.9]: https://github.com/sebastianbergmann/phpunit/compare/5.7.8...5.7.9 [5.7.8]: https://github.com/sebastianbergmann/phpunit/compare/5.7.7...5.7.8 [5.7.7]: https://github.com/sebastianbergmann/phpunit/compare/5.7.6...5.7.7 [5.7.6]: https://github.com/sebastianbergmann/phpunit/compare/5.7.5...5.7.6 [5.7.5]: https://github.com/sebastianbergmann/phpunit/compare/5.7.4...5.7.5 [5.7.4]: https://github.com/sebastianbergmann/phpunit/compare/5.7.3...5.7.4 [5.7.3]: https://github.com/sebastianbergmann/phpunit/compare/5.7.2...5.7.3 [5.7.2]: https://github.com/sebastianbergmann/phpunit/compare/5.7.1...5.7.2 [5.7.1]: https://github.com/sebastianbergmann/phpunit/compare/5.7.0...5.7.1 [5.7.0]: https://github.com/sebastianbergmann/phpunit/compare/5.6...5.7.0 phpunit-6.5.5/ChangeLog-6.5.md000066400000000000000000000043231321540746700157100ustar00rootroot00000000000000# Changes in PHPUnit 6.5 All notable changes of the PHPUnit 6.5 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. ## [6.5.5] - 2017-12-17 ### Fixed * Fixed [#2922](https://github.com/sebastianbergmann/phpunit/issues/2922): Test class is not discovered when there is a test class with `@group` and provider throwing exception in it, tests are run with `--exclude-group` for that group, there is another class called later (after the class from above), and the name of that another class does not match its filename ## [6.5.4] - 2017-12-10 ### Changed * Require version 5.0.5 of `phpunit/phpunit-mock-objects` for [phpunit-mock-objects#394](https://github.com/sebastianbergmann/phpunit-mock-objects/issues/394) ## [6.5.3] - 2017-12-06 ### Fixed * Fixed an issue with PHPT tests when `forceCoversAnnotation="true"` is configured ## [6.5.2] - 2017-12-02 ### Changed * Require version 5.0.4 of `phpunit/phpunit-mock-objects` for [phpunit-mock-objects#388](https://github.com/sebastianbergmann/phpunit-mock-objects/issues/388) ## [6.5.1] - 2017-12-01 * Fixed [#2886](https://github.com/sebastianbergmann/phpunit/pull/2886): Forced environment variables do not affect `getenv()` ## [6.5.0] - 2017-12-01 ### Added * Implemented [#2286](https://github.com/sebastianbergmann/phpunit/issues/2286): Optional `$exit` parameter for `PHPUnit\TextUI\TestRunner::run()` * Implemented [#2496](https://github.com/sebastianbergmann/phpunit/issues/2496): Allow shallow copy of dependencies ### Fixed * Fixed [#2654](https://github.com/sebastianbergmann/phpunit/issues/2654): Problems with `assertJsonStringEqualsJsonString()` * Fixed [#2810](https://github.com/sebastianbergmann/phpunit/pull/2810): Code Coverage for PHPT tests does not work [6.5.5]: https://github.com/sebastianbergmann/phpunit/compare/6.5.4...6.5.5 [6.5.4]: https://github.com/sebastianbergmann/phpunit/compare/6.5.3...6.5.4 [6.5.3]: https://github.com/sebastianbergmann/phpunit/compare/6.5.2...6.5.3 [6.5.2]: https://github.com/sebastianbergmann/phpunit/compare/6.5.1...6.5.2 [6.5.1]: https://github.com/sebastianbergmann/phpunit/compare/6.5.0...6.5.1 [6.5.0]: https://github.com/sebastianbergmann/phpunit/compare/6.4...6.5.0 phpunit-6.5.5/LICENSE000066400000000000000000000030061321540746700142330ustar00rootroot00000000000000PHPUnit Copyright (c) 2001-2017, Sebastian Bergmann . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * 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. phpunit-6.5.5/README.md000066400000000000000000000041531321540746700145110ustar00rootroot00000000000000# 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.0-8892BF.svg?style=flat-square)](https://php.net/) [![Build Status](https://img.shields.io/travis/sebastianbergmann/phpunit/6.5.svg?style=flat-square)](https://phpunit.de/build-status.html) ## 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.phar $ chmod +x phpunit.phar $ mv phpunit.phar /usr/local/bin/phpunit ``` You can also immediately use the PHAR after you have downloaded it, of course: ```bash $ wget https://phar.phpunit.de/phpunit.phar $ php phpunit.phar ``` Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the [documentation](https://phpunit.de/documentation.html) for details on how to do this. ## 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_CodeCoverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) * [PHPUnit_MockObject](https://github.com/sebastianbergmann/phpunit-mock-objects/graphs/contributors) A very special thanks to everyone who has contributed to the documentation and helps maintain the translations: * [PHPUnit Documentation](https://github.com/sebastianbergmann/phpunit-documentation/graphs/contributors) phpunit-6.5.5/appveyor.yml000066400000000000000000000053131321540746700156210ustar00rootroot00000000000000build: false clone_folder: c:\phpunit max_jobs: 3 platform: x86 pull_requests: do_not_increment_build_number: true version: '{build}.{branch}' environment: COMPOSER_ROOT_VERSION: '6.5.x-dev' matrix: - PHP_VERSION: '7.0.25' XDEBUG_VERSION: '2.5.5-7.0' DEPENDENCIES: '--prefer-lowest' - PHP_VERSION: '7.0.25' XDEBUG_VERSION: '2.5.5-7.0' DEPENDENCIES: '' - PHP_VERSION: '7.1.11' XDEBUG_VERSION: '2.5.5-7.1' DEPENDENCIES: '--prefer-lowest' - PHP_VERSION: '7.1.11' XDEBUG_VERSION: '2.5.5-7.1' DEPENDENCIES: '' matrix: fast_finish: true cache: - c:\php -> appveyor.yml - '%LOCALAPPDATA%\Composer\files' init: - SET PATH=c:\php\%PHP_VERSION%;%PATH% install: - IF NOT EXIST c:\php mkdir c:\php - IF NOT EXIST c:\php\%PHP_VERSION% mkdir c:\php\%PHP_VERSION% - cd c:\php\%PHP_VERSION% - IF NOT EXIST php-installed.txt appveyor DownloadFile http://windows.php.net/downloads/releases/archives/php-%PHP_VERSION%-Win32-VC14-x86.zip - IF NOT EXIST php-installed.txt 7z x php-%PHP_VERSION%-Win32-VC14-x86.zip -y >nul - IF NOT EXIST php-installed.txt del /Q *.zip - IF NOT EXIST php-installed.txt copy /Y php.ini-development php.ini - IF NOT EXIST php-installed.txt echo max_execution_time=1200 >> php.ini - IF NOT EXIST php-installed.txt echo date.timezone="UTC" >> php.ini - IF NOT EXIST php-installed.txt echo extension_dir=ext >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_curl.dll >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_openssl.dll >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_mbstring.dll >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_fileinfo.dll >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_mysqli.dll >> php.ini - IF NOT EXIST php-installed.txt echo extension=php_pdo_sqlite.dll >> php.ini - IF NOT EXIST php-installed.txt echo zend.assertions=1 >> php.ini - IF NOT EXIST php-installed.txt echo assert.exception=On >> php.ini - IF NOT EXIST php-installed.txt appveyor DownloadFile https://getcomposer.org/composer.phar - IF NOT EXIST php-installed.txt echo @php %%~dp0composer.phar %%* > composer.bat - IF NOT EXIST php-installed.txt appveyor DownloadFile https://xdebug.org/files/php_xdebug-%XDEBUG_VERSION%-vc14.dll -FileName c:\php\%PHP_VERSION%\ext\php_xdebug-%XDEBUG_VERSION%-vc14.dll - IF NOT EXIST php-installed.txt echo zend_extension=php_xdebug-%XDEBUG_VERSION%-vc14.dll >> php.ini - IF NOT EXIST php-installed.txt type nul >> php-installed.txt - cd c:\phpunit - composer update --no-interaction --no-ansi --no-progress --no-suggest --optimize-autoloader --prefer-stable %DEPENDENCIES% test_script: - cd c:\phpunit - php phpunit phpunit-6.5.5/build.xml000066400000000000000000000457111321540746700150600ustar00rootroot00000000000000 phpunit-6.5.5/composer.json000066400000000000000000000043051321540746700157530ustar00rootroot00000000000000{ "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.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "myclabs/deep-copy": "^1.6.1", "phar-io/manifest": "^1.0.1", "phar-io/version": "^1.0", "phpspec/prophecy": "^1.7", "phpunit/php-code-coverage": "^5.3", "phpunit/php-file-iterator": "^1.4.3", "phpunit/php-text-template": "^1.2.1", "phpunit/php-timer": "^1.0.9", "phpunit/phpunit-mock-objects": "^5.0.5", "sebastian/comparator": "^2.1", "sebastian/diff": "^2.0", "sebastian/environment": "^3.1", "sebastian/exporter": "^3.1", "sebastian/global-state": "^2.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^1.0", "sebastian/version": "^2.0.1" }, "require-dev": { "ext-PDO": "*" }, "conflict": { "phpunit/dbunit": "<3.0", "phpdocumentor/reflection-docblock": "3.0.2" }, "config": { "platform": { "php": "7.0.0" }, "optimize-autoloader": true, "sort-packages": true }, "suggest": { "phpunit/php-invoker": "^1.1", "ext-xdebug": "*" }, "bin": [ "phpunit" ], "autoload": { "classmap": [ "src/" ] }, "autoload-dev": { "classmap": [ "tests/" ], "files": [ "src/Framework/Assert/Functions.php", "tests/_files/CoveredFunction.php" ] }, "extra": { "branch-alias": { "dev-master": "6.5.x-dev" } } } phpunit-6.5.5/phpunit000077500000000000000000000023751321540746700146530ustar00rootroot00000000000000#!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (version_compare('7.0.0', PHP_VERSION, '>')) { fwrite( STDERR, sprintf( 'This version of PHPUnit is supported on PHP 7.0 and PHP 7.1.' . PHP_EOL . 'You are using PHP %s (%s).' . PHP_EOL, PHP_VERSION, PHP_BINARY ) ); die(1); } if (!ini_get('date.timezone')) { ini_set('date.timezone', 'UTC'); } foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) { if (file_exists($file)) { define('PHPUNIT_COMPOSER_INSTALL', $file); break; } } unset($file); if (!defined('PHPUNIT_COMPOSER_INSTALL')) { fwrite( STDERR, 'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL . ' composer install' . PHP_EOL . PHP_EOL . 'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL ); die(1); } require PHPUNIT_COMPOSER_INSTALL; PHPUnit\TextUI\Command::main(); phpunit-6.5.5/phpunit.xml000066400000000000000000000021301321540746700154340ustar00rootroot00000000000000 tests/Framework tests/Runner tests/Util tests/TextUI tests/Regression src src/Framework/Assert/Functions.php src/Util/PHP/eval-stdin.php phpunit-6.5.5/phpunit.xsd000066400000000000000000000322311321540746700154370ustar00rootroot00000000000000 This Schema file defines the rules by which the XML configuration file of PHPUnit 6.5 may be structured. Root Element The main type specifying the document structure phpunit-6.5.5/src/000077500000000000000000000000001321540746700140165ustar00rootroot00000000000000phpunit-6.5.5/src/Exception.php000066400000000000000000000005051321540746700164650ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit; /** * Marker interface for PHPUnit exceptions. */ interface Exception { } phpunit-6.5.5/src/Framework/000077500000000000000000000000001321540746700157535ustar00rootroot00000000000000phpunit-6.5.5/src/Framework/Assert.php000066400000000000000000002406711321540746700177370ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use ArrayAccess; use Countable; use DOMDocument; use DOMElement; use PHPUnit\Framework\Constraint\ArrayHasKey; use PHPUnit\Framework\Constraint\ArraySubset; use PHPUnit\Framework\Constraint\Attribute; 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\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\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\TraversableContains; use PHPUnit\Framework\Constraint\TraversableContainsOnly; use PHPUnit\Util\InvalidArgumentHelper; use PHPUnit\Util\Type; use PHPUnit\Util\Xml; use ReflectionClass; use ReflectionException; use ReflectionObject; use ReflectionProperty; use Traversable; /** * A set of assertion methods. */ abstract class Assert { /** * @var int */ private static $count = 0; /** * Asserts that an array has a specified key. * * @param mixed $key * @param array|ArrayAccess $array * @param string $message */ public static function assertArrayHasKey($key, $array, $message = '') { if (!(\is_int($key) || \is_string($key))) { throw InvalidArgumentHelper::factory( 1, 'integer or string' ); } if (!(\is_array($array) || $array instanceof ArrayAccess)) { throw InvalidArgumentHelper::factory( 2, 'array or ArrayAccess' ); } $constraint = new ArrayHasKey($key); static::assertThat($array, $constraint, $message); } /** * Asserts that an array has a specified subset. * * @param array|ArrayAccess $subset * @param array|ArrayAccess $array * @param bool $strict Check for object identity * @param string $message */ public static function assertArraySubset($subset, $array, $strict = false, $message = '') { if (!(\is_array($subset) || $subset instanceof ArrayAccess)) { throw InvalidArgumentHelper::factory( 1, 'array or ArrayAccess' ); } if (!(\is_array($array) || $array instanceof ArrayAccess)) { throw InvalidArgumentHelper::factory( 2, 'array or ArrayAccess' ); } $constraint = new ArraySubset($subset, $strict); static::assertThat($array, $constraint, $message); } /** * Asserts that an array does not have a specified key. * * @param mixed $key * @param array|ArrayAccess $array * @param string $message */ public static function assertArrayNotHasKey($key, $array, $message = '') { if (!(\is_int($key) || \is_string($key))) { throw InvalidArgumentHelper::factory( 1, 'integer or string' ); } if (!(\is_array($array) || $array instanceof ArrayAccess)) { throw InvalidArgumentHelper::factory( 2, 'array or ArrayAccess' ); } $constraint = new LogicalNot( new ArrayHasKey($key) ); static::assertThat($array, $constraint, $message); } /** * Asserts that a haystack contains a needle. * * @param mixed $needle * @param mixed $haystack * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ public static function assertContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { if (\is_array($haystack) || (\is_object($haystack) && $haystack instanceof Traversable)) { $constraint = new TraversableContains( $needle, $checkForObjectIdentity, $checkForNonObjectIdentity ); } elseif (\is_string($haystack)) { if (!\is_string($needle)) { throw InvalidArgumentHelper::factory( 1, 'string' ); } $constraint = new StringContains( $needle, $ignoreCase ); } else { throw InvalidArgumentHelper::factory( 2, 'array, traversable or string' ); } static::assertThat($haystack, $constraint, $message); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object contains a needle. * * @param mixed $needle * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ public static function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { static::assertContains( $needle, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity ); } /** * Asserts that a haystack does not contain a needle. * * @param mixed $needle * @param mixed $haystack * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ public static function assertNotContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { if (\is_array($haystack) || (\is_object($haystack) && $haystack instanceof Traversable)) { $constraint = new LogicalNot( new TraversableContains( $needle, $checkForObjectIdentity, $checkForNonObjectIdentity ) ); } elseif (\is_string($haystack)) { if (!\is_string($needle)) { throw InvalidArgumentHelper::factory( 1, 'string' ); } $constraint = new LogicalNot( new StringContains( $needle, $ignoreCase ) ); } else { throw InvalidArgumentHelper::factory( 2, 'array, traversable or string' ); } static::assertThat($haystack, $constraint, $message); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object does not contain a needle. * * @param mixed $needle * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ public static function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { static::assertNotContains( $needle, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message, $ignoreCase, $checkForObjectIdentity, $checkForNonObjectIdentity ); } /** * Asserts that a haystack contains only values of a given type. * * @param string $type * @param mixed $haystack * @param bool $isNativeType * @param string $message */ public static function assertContainsOnly($type, $haystack, $isNativeType = null, $message = '') { if (!\is_array($haystack) && !(\is_object($haystack) && $haystack instanceof Traversable)) { throw InvalidArgumentHelper::factory( 2, 'array or traversable' ); } 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 classname * * @param string $classname * @param array|\Traversable $haystack * @param string $message */ public static function assertContainsOnlyInstancesOf($classname, $haystack, $message = '') { if (!\is_array($haystack) && !(\is_object($haystack) && $haystack instanceof Traversable)) { throw InvalidArgumentHelper::factory( 2, 'array or traversable' ); } static::assertThat( $haystack, new TraversableContainsOnly( $classname, false ), $message ); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object contains only values of a given type. * * @param string $type * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param bool $isNativeType * @param string $message */ public static function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') { static::assertContainsOnly( $type, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $isNativeType, $message ); } /** * Asserts that a haystack does not contain only values of a given type. * * @param string $type * @param mixed $haystack * @param bool $isNativeType * @param string $message */ public static function assertNotContainsOnly($type, $haystack, $isNativeType = null, $message = '') { if (!\is_array($haystack) && !(\is_object($haystack) && $haystack instanceof Traversable)) { throw InvalidArgumentHelper::factory( 2, 'array or traversable' ); } if ($isNativeType == null) { $isNativeType = Type::isType($type); } static::assertThat( $haystack, new LogicalNot( new TraversableContainsOnly( $type, $isNativeType ) ), $message ); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object does not contain only values of a given * type. * * @param string $type * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param bool $isNativeType * @param string $message */ public static function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') { static::assertNotContainsOnly( $type, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $isNativeType, $message ); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param int $expectedCount * @param mixed $haystack * @param string $message */ public static function assertCount($expectedCount, $haystack, $message = '') { if (!\is_int($expectedCount)) { throw InvalidArgumentHelper::factory(1, 'integer'); } if (!$haystack instanceof Countable && !$haystack instanceof Traversable && !\is_array($haystack)) { throw InvalidArgumentHelper::factory(2, 'countable or traversable'); } static::assertThat( $haystack, new Count($expectedCount), $message ); } /** * Asserts the number of elements of an array, Countable or Traversable * that is stored in an attribute. * * @param int $expectedCount * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message */ public static function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') { static::assertCount( $expectedCount, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message ); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param int $expectedCount * @param mixed $haystack * @param string $message */ public static function assertNotCount($expectedCount, $haystack, $message = '') { if (!\is_int($expectedCount)) { throw InvalidArgumentHelper::factory(1, 'integer'); } if (!$haystack instanceof Countable && !$haystack instanceof Traversable && !\is_array($haystack)) { throw InvalidArgumentHelper::factory(2, 'countable or traversable'); } $constraint = new LogicalNot( new Count($expectedCount) ); static::assertThat($haystack, $constraint, $message); } /** * Asserts the number of elements of an array, Countable or Traversable * that is stored in an attribute. * * @param int $expectedCount * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message */ public static function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') { static::assertNotCount( $expectedCount, static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message ); } /** * Asserts that two variables are equal. * * @param mixed $expected * @param mixed $actual * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { $constraint = new IsEqual( $expected, $delta, $maxDepth, $canonicalize, $ignoreCase ); static::assertThat($actual, $constraint, $message); } /** * Asserts that a variable is equal to an attribute of an object. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { static::assertEquals( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message, $delta, $maxDepth, $canonicalize, $ignoreCase ); } /** * Asserts that two variables are not equal. * * @param mixed $expected * @param mixed $actual * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertNotEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { $constraint = new LogicalNot( new IsEqual( $expected, $delta, $maxDepth, $canonicalize, $ignoreCase ) ); static::assertThat($actual, $constraint, $message); } /** * Asserts that a variable is not equal to an attribute of an object. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { static::assertNotEquals( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message, $delta, $maxDepth, $canonicalize, $ignoreCase ); } /** * Asserts that a variable is empty. * * @param mixed $actual * @param string $message * * @throws AssertionFailedError */ public static function assertEmpty($actual, $message = '') { static::assertThat($actual, static::isEmpty(), $message); } /** * Asserts that a static attribute of a class or an attribute of an object * is empty. * * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message */ public static function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') { static::assertEmpty( static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message ); } /** * Asserts that a variable is not empty. * * @param mixed $actual * @param string $message * * @throws AssertionFailedError */ public static function assertNotEmpty($actual, $message = '') { static::assertThat($actual, static::logicalNot(static::isEmpty()), $message); } /** * Asserts that a static attribute of a class or an attribute of an object * is not empty. * * @param string $haystackAttributeName * @param string|object $haystackClassOrObject * @param string $message */ public static function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') { static::assertNotEmpty( static::readAttribute($haystackClassOrObject, $haystackAttributeName), $message ); } /** * Asserts that a value is greater than another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertGreaterThan($expected, $actual, $message = '') { static::assertThat($actual, static::greaterThan($expected), $message); } /** * Asserts that an attribute is greater than another value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertGreaterThan( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message ); } /** * Asserts that a value is greater than or equal to another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertGreaterThanOrEqual($expected, $actual, $message = '') { static::assertThat( $actual, static::greaterThanOrEqual($expected), $message ); } /** * Asserts that an attribute is greater than or equal to another value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertGreaterThanOrEqual( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message ); } /** * Asserts that a value is smaller than another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertLessThan($expected, $actual, $message = '') { static::assertThat($actual, static::lessThan($expected), $message); } /** * Asserts that an attribute is smaller than another value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertLessThan( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message ); } /** * Asserts that a value is smaller than or equal to another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertLessThanOrEqual($expected, $actual, $message = '') { static::assertThat($actual, static::lessThanOrEqual($expected), $message); } /** * Asserts that an attribute is smaller than or equal to another value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertLessThanOrEqual( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message ); } /** * Asserts that the contents of one file is equal to the contents of another * file. * * @param string $expected * @param string $actual * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertFileEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) { static::assertFileExists($expected, $message); static::assertFileExists($actual, $message); static::assertEquals( \file_get_contents($expected), \file_get_contents($actual), $message, 0, 10, $canonicalize, $ignoreCase ); } /** * Asserts that the contents of one file is not equal to the contents of * another file. * * @param string $expected * @param string $actual * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) { static::assertFileExists($expected, $message); static::assertFileExists($actual, $message); static::assertNotEquals( \file_get_contents($expected), \file_get_contents($actual), $message, 0, 10, $canonicalize, $ignoreCase ); } /** * Asserts that the contents of a string is equal * to the contents of a file. * * @param string $expectedFile * @param string $actualString * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) { static::assertFileExists($expectedFile, $message); static::assertEquals( \file_get_contents($expectedFile), $actualString, $message, 0, 10, $canonicalize, $ignoreCase ); } /** * Asserts that the contents of a string is not equal * to the contents of a file. * * @param string $expectedFile * @param string $actualString * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ public static function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) { static::assertFileExists($expectedFile, $message); static::assertNotEquals( \file_get_contents($expectedFile), $actualString, $message, 0, 10, $canonicalize, $ignoreCase ); } /** * Asserts that a file/dir is readable. * * @param string $filename * @param string $message */ public static function assertIsReadable($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new IsReadable; static::assertThat($filename, $constraint, $message); } /** * Asserts that a file/dir exists and is not readable. * * @param string $filename * @param string $message */ public static function assertNotIsReadable($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new LogicalNot( new IsReadable ); static::assertThat($filename, $constraint, $message); } /** * Asserts that a file/dir exists and is writable. * * @param string $filename * @param string $message */ public static function assertIsWritable($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new IsWritable; static::assertThat($filename, $constraint, $message); } /** * Asserts that a file/dir exists and is not writable. * * @param string $filename * @param string $message */ public static function assertNotIsWritable($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new LogicalNot( new IsWritable ); static::assertThat($filename, $constraint, $message); } /** * Asserts that a directory exists. * * @param string $directory * @param string $message */ public static function assertDirectoryExists($directory, $message = '') { if (!\is_string($directory)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new DirectoryExists; static::assertThat($directory, $constraint, $message); } /** * Asserts that a directory does not exist. * * @param string $directory * @param string $message */ public static function assertDirectoryNotExists($directory, $message = '') { if (!\is_string($directory)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new LogicalNot( new DirectoryExists ); static::assertThat($directory, $constraint, $message); } /** * Asserts that a directory exists and is readable. * * @param string $directory * @param string $message */ public static function assertDirectoryIsReadable($directory, $message = '') { self::assertDirectoryExists($directory, $message); self::assertIsReadable($directory, $message); } /** * Asserts that a directory exists and is not readable. * * @param string $directory * @param string $message */ public static function assertDirectoryNotIsReadable($directory, $message = '') { self::assertDirectoryExists($directory, $message); self::assertNotIsReadable($directory, $message); } /** * Asserts that a directory exists and is writable. * * @param string $directory * @param string $message */ public static function assertDirectoryIsWritable($directory, $message = '') { self::assertDirectoryExists($directory, $message); self::assertIsWritable($directory, $message); } /** * Asserts that a directory exists and is not writable. * * @param string $directory * @param string $message */ public static function assertDirectoryNotIsWritable($directory, $message = '') { self::assertDirectoryExists($directory, $message); self::assertNotIsWritable($directory, $message); } /** * Asserts that a file exists. * * @param string $filename * @param string $message */ public static function assertFileExists($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new FileExists; static::assertThat($filename, $constraint, $message); } /** * Asserts that a file does not exist. * * @param string $filename * @param string $message */ public static function assertFileNotExists($filename, $message = '') { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new LogicalNot( new FileExists ); static::assertThat($filename, $constraint, $message); } /** * Asserts that a file exists and is readable. * * @param string $file * @param string $message */ public static function assertFileIsReadable($file, $message = '') { self::assertFileExists($file, $message); self::assertIsReadable($file, $message); } /** * Asserts that a file exists and is not readable. * * @param string $file * @param string $message */ public static function assertFileNotIsReadable($file, $message = '') { self::assertFileExists($file, $message); self::assertNotIsReadable($file, $message); } /** * Asserts that a file exists and is writable. * * @param string $file * @param string $message */ public static function assertFileIsWritable($file, $message = '') { self::assertFileExists($file, $message); self::assertIsWritable($file, $message); } /** * Asserts that a file exists and is not writable. * * @param string $file * @param string $message */ public static function assertFileNotIsWritable($file, $message = '') { self::assertFileExists($file, $message); self::assertNotIsWritable($file, $message); } /** * Asserts that a condition is true. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ public static function assertTrue($condition, $message = '') { static::assertThat($condition, static::isTrue(), $message); } /** * Asserts that a condition is not true. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ public static function assertNotTrue($condition, $message = '') { static::assertThat($condition, static::logicalNot(static::isTrue()), $message); } /** * Asserts that a condition is false. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ public static function assertFalse($condition, $message = '') { static::assertThat($condition, static::isFalse(), $message); } /** * Asserts that a condition is not false. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ public static function assertNotFalse($condition, $message = '') { static::assertThat($condition, static::logicalNot(static::isFalse()), $message); } /** * Asserts that a variable is null. * * @param mixed $actual * @param string $message */ public static function assertNull($actual, $message = '') { static::assertThat($actual, static::isNull(), $message); } /** * Asserts that a variable is not null. * * @param mixed $actual * @param string $message */ public static function assertNotNull($actual, $message = '') { static::assertThat($actual, static::logicalNot(static::isNull()), $message); } /** * Asserts that a variable is finite. * * @param mixed $actual * @param string $message */ public static function assertFinite($actual, $message = '') { static::assertThat($actual, static::isFinite(), $message); } /** * Asserts that a variable is infinite. * * @param mixed $actual * @param string $message */ public static function assertInfinite($actual, $message = '') { static::assertThat($actual, static::isInfinite(), $message); } /** * Asserts that a variable is nan. * * @param mixed $actual * @param string $message */ public static function assertNan($actual, $message = '') { static::assertThat($actual, static::isNan(), $message); } /** * Asserts that a class has a specified attribute. * * @param string $attributeName * @param string $className * @param string $message */ public static function assertClassHasAttribute($attributeName, $className, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_string($className) || !\class_exists($className)) { throw InvalidArgumentHelper::factory(2, 'class name', $className); } $constraint = new ClassHasAttribute( $attributeName ); static::assertThat($className, $constraint, $message); } /** * Asserts that a class does not have a specified attribute. * * @param string $attributeName * @param string $className * @param string $message */ public static function assertClassNotHasAttribute($attributeName, $className, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_string($className) || !\class_exists($className)) { throw InvalidArgumentHelper::factory(2, 'class name', $className); } $constraint = new LogicalNot( new ClassHasAttribute($attributeName) ); static::assertThat($className, $constraint, $message); } /** * Asserts that a class has a specified static attribute. * * @param string $attributeName * @param string $className * @param string $message */ public static function assertClassHasStaticAttribute($attributeName, $className, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_string($className) || !\class_exists($className)) { throw InvalidArgumentHelper::factory(2, 'class name', $className); } $constraint = new ClassHasStaticAttribute( $attributeName ); static::assertThat($className, $constraint, $message); } /** * Asserts that a class does not have a specified static attribute. * * @param string $attributeName * @param string $className * @param string $message */ public static function assertClassNotHasStaticAttribute($attributeName, $className, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_string($className) || !\class_exists($className)) { throw InvalidArgumentHelper::factory(2, 'class name', $className); } $constraint = new LogicalNot( new ClassHasStaticAttribute( $attributeName ) ); static::assertThat($className, $constraint, $message); } /** * Asserts that an object has a specified attribute. * * @param string $attributeName * @param object $object * @param string $message */ public static function assertObjectHasAttribute($attributeName, $object, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_object($object)) { throw InvalidArgumentHelper::factory(2, 'object'); } $constraint = new ObjectHasAttribute( $attributeName ); static::assertThat($object, $constraint, $message); } /** * Asserts that an object does not have a specified attribute. * * @param string $attributeName * @param object $object * @param string $message */ public static function assertObjectNotHasAttribute($attributeName, $object, $message = '') { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(1, 'valid attribute name'); } if (!\is_object($object)) { throw InvalidArgumentHelper::factory(2, 'object'); } $constraint = new LogicalNot( new ObjectHasAttribute($attributeName) ); static::assertThat($object, $constraint, $message); } /** * Asserts that two variables have the same type and value. * Used on objects, it asserts that two variables reference * the same object. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertSame($expected, $actual, $message = '') { if (\is_bool($expected) && \is_bool($actual)) { static::assertEquals($expected, $actual, $message); } else { $constraint = new IsIdentical( $expected ); static::assertThat($actual, $constraint, $message); } } /** * Asserts that a variable and an attribute of an object have the same type * and value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertSame( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $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. * * @param mixed $expected * @param mixed $actual * @param string $message */ public static function assertNotSame($expected, $actual, $message = '') { if (\is_bool($expected) && \is_bool($actual)) { static::assertNotEquals($expected, $actual, $message); } else { $constraint = new LogicalNot( new IsIdentical($expected) ); static::assertThat($actual, $constraint, $message); } } /** * Asserts that a variable and an attribute of an object do not have the * same type and value. * * @param mixed $expected * @param string $actualAttributeName * @param string|object $actualClassOrObject * @param string $message */ public static function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') { static::assertNotSame( $expected, static::readAttribute($actualClassOrObject, $actualAttributeName), $message ); } /** * Asserts that a variable is of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ public static function assertInstanceOf($expected, $actual, $message = '') { if (!(\is_string($expected) && (\class_exists($expected) || \interface_exists($expected)))) { throw InvalidArgumentHelper::factory(1, 'class or interface name'); } $constraint = new IsInstanceOf( $expected ); static::assertThat($actual, $constraint, $message); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param string|object $classOrObject * @param string $message */ public static function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '') { static::assertInstanceOf( $expected, static::readAttribute($classOrObject, $attributeName), $message ); } /** * Asserts that a variable is not of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ public static function assertNotInstanceOf($expected, $actual, $message = '') { if (!(\is_string($expected) && (\class_exists($expected) || \interface_exists($expected)))) { throw InvalidArgumentHelper::factory(1, 'class or interface name'); } $constraint = new LogicalNot( new IsInstanceOf($expected) ); static::assertThat($actual, $constraint, $message); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param string|object $classOrObject * @param string $message */ public static function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '') { static::assertNotInstanceOf( $expected, static::readAttribute($classOrObject, $attributeName), $message ); } /** * Asserts that a variable is of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ public static function assertInternalType($expected, $actual, $message = '') { if (!\is_string($expected)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new IsType( $expected ); static::assertThat($actual, $constraint, $message); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param string|object $classOrObject * @param string $message */ public static function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '') { static::assertInternalType( $expected, static::readAttribute($classOrObject, $attributeName), $message ); } /** * Asserts that a variable is not of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ public static function assertNotInternalType($expected, $actual, $message = '') { if (!\is_string($expected)) { throw InvalidArgumentHelper::factory(1, 'string'); } $constraint = new LogicalNot( new IsType($expected) ); static::assertThat($actual, $constraint, $message); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param string|object $classOrObject * @param string $message */ public static function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '') { static::assertNotInternalType( $expected, static::readAttribute($classOrObject, $attributeName), $message ); } /** * Asserts that a string matches a given regular expression. * * @param string $pattern * @param string $string * @param string $message */ public static function assertRegExp($pattern, $string, $message = '') { if (!\is_string($pattern)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new RegularExpression($pattern); static::assertThat($string, $constraint, $message); } /** * Asserts that a string does not match a given regular expression. * * @param string $pattern * @param string $string * @param string $message */ public static function assertNotRegExp($pattern, $string, $message = '') { if (!\is_string($pattern)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new LogicalNot( new RegularExpression($pattern) ); static::assertThat($string, $constraint, $message); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is the same. * * @param array|\Countable|\Traversable $expected * @param array|\Countable|\Traversable $actual * @param string $message */ public static function assertSameSize($expected, $actual, $message = '') { if (!$expected instanceof Countable && !$expected instanceof Traversable && !\is_array($expected)) { throw InvalidArgumentHelper::factory(1, 'countable or traversable'); } if (!$actual instanceof Countable && !$actual instanceof Traversable && !\is_array($actual)) { throw InvalidArgumentHelper::factory(2, 'countable or traversable'); } static::assertThat( $actual, new SameSize($expected), $message ); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is not the same. * * @param array|\Countable|\Traversable $expected * @param array|\Countable|\Traversable $actual * @param string $message */ public static function assertNotSameSize($expected, $actual, $message = '') { if (!$expected instanceof Countable && !$expected instanceof Traversable && !\is_array($expected)) { throw InvalidArgumentHelper::factory(1, 'countable or traversable'); } if (!$actual instanceof Countable && !$actual instanceof Traversable && !\is_array($actual)) { throw InvalidArgumentHelper::factory(2, 'countable or traversable'); } $constraint = new LogicalNot( new SameSize($expected) ); static::assertThat($actual, $constraint, $message); } /** * Asserts that a string matches a given format string. * * @param string $format * @param string $string * @param string $message */ public static function assertStringMatchesFormat($format, $string, $message = '') { if (!\is_string($format)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new StringMatchesFormatDescription($format); static::assertThat($string, $constraint, $message); } /** * Asserts that a string does not match a given format string. * * @param string $format * @param string $string * @param string $message */ public static function assertStringNotMatchesFormat($format, $string, $message = '') { if (!\is_string($format)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new LogicalNot( new StringMatchesFormatDescription($format) ); static::assertThat($string, $constraint, $message); } /** * Asserts that a string matches a given format file. * * @param string $formatFile * @param string $string * @param string $message */ public static function assertStringMatchesFormatFile($formatFile, $string, $message = '') { static::assertFileExists($formatFile, $message); if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new StringMatchesFormatDescription( \file_get_contents($formatFile) ); static::assertThat($string, $constraint, $message); } /** * Asserts that a string does not match a given format string. * * @param string $formatFile * @param string $string * @param string $message */ public static function assertStringNotMatchesFormatFile($formatFile, $string, $message = '') { static::assertFileExists($formatFile, $message); if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new LogicalNot( new StringMatchesFormatDescription( \file_get_contents($formatFile) ) ); static::assertThat($string, $constraint, $message); } /** * Asserts that a string starts with a given prefix. * * @param string $prefix * @param string $string * @param string $message */ public static function assertStringStartsWith($prefix, $string, $message = '') { if (!\is_string($prefix)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new StringStartsWith( $prefix ); static::assertThat($string, $constraint, $message); } /** * Asserts that a string starts not with a given prefix. * * @param string $prefix * @param string $string * @param string $message */ public static function assertStringStartsNotWith($prefix, $string, $message = '') { if (!\is_string($prefix)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new LogicalNot( new StringStartsWith($prefix) ); static::assertThat($string, $constraint, $message); } /** * Asserts that a string ends with a given suffix. * * @param string $suffix * @param string $string * @param string $message */ public static function assertStringEndsWith($suffix, $string, $message = '') { if (!\is_string($suffix)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new StringEndsWith($suffix); static::assertThat($string, $constraint, $message); } /** * Asserts that a string ends not with a given suffix. * * @param string $suffix * @param string $string * @param string $message */ public static function assertStringEndsNotWith($suffix, $string, $message = '') { if (!\is_string($suffix)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_string($string)) { throw InvalidArgumentHelper::factory(2, 'string'); } $constraint = new LogicalNot( new StringEndsWith($suffix) ); static::assertThat($string, $constraint, $message); } /** * Asserts that two XML files are equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ public static function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '') { $expected = Xml::loadFile($expectedFile); $actual = Xml::loadFile($actualFile); static::assertEquals($expected, $actual, $message); } /** * Asserts that two XML files are not equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ public static function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '') { $expected = Xml::loadFile($expectedFile); $actual = Xml::loadFile($actualFile); static::assertNotEquals($expected, $actual, $message); } /** * Asserts that two XML documents are equal. * * @param string $expectedFile * @param string|DOMDocument $actualXml * @param string $message */ public static function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '') { $expected = Xml::loadFile($expectedFile); $actual = Xml::load($actualXml); static::assertEquals($expected, $actual, $message); } /** * Asserts that two XML documents are not equal. * * @param string $expectedFile * @param string|DOMDocument $actualXml * @param string $message */ public static function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '') { $expected = Xml::loadFile($expectedFile); $actual = Xml::load($actualXml); static::assertNotEquals($expected, $actual, $message); } /** * Asserts that two XML documents are equal. * * @param string|DOMDocument $expectedXml * @param string|DOMDocument $actualXml * @param string $message */ public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '') { $expected = Xml::load($expectedXml); $actual = Xml::load($actualXml); static::assertEquals($expected, $actual, $message); } /** * Asserts that two XML documents are not equal. * * @param string|DOMDocument $expectedXml * @param string|DOMDocument $actualXml * @param string $message */ public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '') { $expected = Xml::load($expectedXml); $actual = Xml::load($actualXml); static::assertNotEquals($expected, $actual, $message); } /** * Asserts that a hierarchy of DOMElements matches. * * @param DOMElement $expectedElement * @param DOMElement $actualElement * @param bool $checkAttributes * @param string $message */ public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = false, $message = '') { $tmp = new DOMDocument; $expectedElement = $tmp->importNode($expectedElement, true); $tmp = new DOMDocument; $actualElement = $tmp->importNode($actualElement, true); unset($tmp); static::assertEquals( $expectedElement->tagName, $actualElement->tagName, $message ); if ($checkAttributes) { static::assertEquals( $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 ); 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::assertEquals( $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. * * @param mixed $value * @param Constraint $constraint * @param string $message */ public static function assertThat($value, Constraint $constraint, $message = '') { self::$count += \count($constraint); $constraint->evaluate($value, $message); } /** * Asserts that a string is a valid JSON string. * * @param string $actualJson * @param string $message */ public static function assertJson($actualJson, $message = '') { if (!\is_string($actualJson)) { throw InvalidArgumentHelper::factory(1, 'string'); } static::assertThat($actualJson, static::isJson(), $message); } /** * Asserts that two given JSON encoded objects or arrays are equal. * * @param string $expectedJson * @param string $actualJson * @param string $message */ public static function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '') { static::assertJson($expectedJson, $message); static::assertJson($actualJson, $message); $constraint = new JsonMatches( $expectedJson ); static::assertThat($actualJson, $constraint, $message); } /** * Asserts that two given JSON encoded objects or arrays are not equal. * * @param string $expectedJson * @param string $actualJson * @param string $message */ public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '') { static::assertJson($expectedJson, $message); static::assertJson($actualJson, $message); $constraint = new JsonMatches( $expectedJson ); static::assertThat($actualJson, new LogicalNot($constraint), $message); } /** * Asserts that the generated JSON encoded object and the content of the given file are equal. * * @param string $expectedFile * @param string $actualJson * @param string $message */ public static function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '') { static::assertFileExists($expectedFile, $message); $expectedJson = \file_get_contents($expectedFile); static::assertJson($expectedJson, $message); static::assertJson($actualJson, $message); $constraint = new JsonMatches( $expectedJson ); static::assertThat($actualJson, $constraint, $message); } /** * Asserts that the generated JSON encoded object and the content of the given file are not equal. * * @param string $expectedFile * @param string $actualJson * @param string $message */ public static function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '') { static::assertFileExists($expectedFile, $message); $expectedJson = \file_get_contents($expectedFile); static::assertJson($expectedJson, $message); static::assertJson($actualJson, $message); $constraint = new JsonMatches( $expectedJson ); static::assertThat($actualJson, new LogicalNot($constraint), $message); } /** * Asserts that two JSON files are equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ public static function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '') { 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. * * @param string $expectedFile * @param string $actualFile * @param string $message */ public static function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '') { 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); } /** * @return LogicalAnd */ public static function logicalAnd() { $constraints = \func_get_args(); $constraint = new LogicalAnd; $constraint->setConstraints($constraints); return $constraint; } /** * @return LogicalOr */ public static function logicalOr() { $constraints = \func_get_args(); $constraint = new LogicalOr; $constraint->setConstraints($constraints); return $constraint; } /** * @param Constraint $constraint * * @return LogicalNot */ public static function logicalNot(Constraint $constraint) { return new LogicalNot($constraint); } /** * @return LogicalXor */ public static function logicalXor() { $constraints = \func_get_args(); $constraint = new LogicalXor; $constraint->setConstraints($constraints); return $constraint; } /** * @return IsAnything */ public static function anything() { return new IsAnything; } /** * @return IsTrue */ public static function isTrue() { return new IsTrue; } /** * @param callable $callback * * @return Callback */ public static function callback($callback) { return new Callback($callback); } /** * @return IsFalse */ public static function isFalse() { return new IsFalse; } /** * @return IsJson */ public static function isJson() { return new IsJson; } /** * @return IsNull */ public static function isNull() { return new IsNull; } /** * @return IsFinite */ public static function isFinite() { return new IsFinite; } /** * @return IsInfinite */ public static function isInfinite() { return new IsInfinite; } /** * @return IsNan */ public static function isNan() { return new IsNan; } /** * @param Constraint $constraint * @param string $attributeName * * @return Attribute */ public static function attribute(Constraint $constraint, $attributeName) { return new Attribute( $constraint, $attributeName ); } /** * @param mixed $value * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity * * @return TraversableContains */ public static function contains($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return new TraversableContains($value, $checkForObjectIdentity, $checkForNonObjectIdentity); } /** * @param string $type * * @return TraversableContainsOnly */ public static function containsOnly($type) { return new TraversableContainsOnly($type); } /** * @param string $classname * * @return TraversableContainsOnly */ public static function containsOnlyInstancesOf($classname) { return new TraversableContainsOnly($classname, false); } /** * @param mixed $key * * @return ArrayHasKey */ public static function arrayHasKey($key) { return new ArrayHasKey($key); } /** * @param mixed $value * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase * * @return IsEqual */ public static function equalTo($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return new IsEqual( $value, $delta, $maxDepth, $canonicalize, $ignoreCase ); } /** * @param string $attributeName * @param mixed $value * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase * * @return Attribute */ public static function attributeEqualTo($attributeName, $value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return static::attribute( static::equalTo( $value, $delta, $maxDepth, $canonicalize, $ignoreCase ), $attributeName ); } /** * @return IsEmpty */ public static function isEmpty() { return new IsEmpty; } /** * @return IsWritable */ public static function isWritable() { return new IsWritable; } /** * @return IsReadable */ public static function isReadable() { return new IsReadable; } /** * @return DirectoryExists */ public static function directoryExists() { return new DirectoryExists; } /** * @return FileExists */ public static function fileExists() { return new FileExists; } /** * @param mixed $value * * @return GreaterThan */ public static function greaterThan($value) { return new GreaterThan($value); } /** * @param mixed $value * * @return LogicalOr */ public static function greaterThanOrEqual($value) { return static::logicalOr( new IsEqual($value), new GreaterThan($value) ); } /** * @param string $attributeName * * @return ClassHasAttribute */ public static function classHasAttribute($attributeName) { return new ClassHasAttribute( $attributeName ); } /** * @param string $attributeName * * @return ClassHasStaticAttribute */ public static function classHasStaticAttribute($attributeName) { return new ClassHasStaticAttribute( $attributeName ); } /** * @param string $attributeName * * @return ObjectHasAttribute */ public static function objectHasAttribute($attributeName) { return new ObjectHasAttribute( $attributeName ); } /** * @param mixed $value * * @return IsIdentical */ public static function identicalTo($value) { return new IsIdentical($value); } /** * @param string $className * * @return IsInstanceOf */ public static function isInstanceOf($className) { return new IsInstanceOf($className); } /** * @param string $type * * @return IsType */ public static function isType($type) { return new IsType($type); } /** * @param mixed $value * * @return LessThan */ public static function lessThan($value) { return new LessThan($value); } /** * @param mixed $value * * @return LogicalOr */ public static function lessThanOrEqual($value) { return static::logicalOr( new IsEqual($value), new LessThan($value) ); } /** * @param string $pattern * * @return RegularExpression */ public static function matchesRegularExpression($pattern) { return new RegularExpression($pattern); } /** * @param string $string * * @return StringMatchesFormatDescription */ public static function matches($string) { return new StringMatchesFormatDescription($string); } /** * @param mixed $prefix * * @return StringStartsWith */ public static function stringStartsWith($prefix) { return new StringStartsWith($prefix); } /** * @param string $string * @param bool $case * * @return StringContains */ public static function stringContains($string, $case = true) { return new StringContains($string, $case); } /** * @param mixed $suffix * * @return StringEndsWith */ public static function stringEndsWith($suffix) { return new StringEndsWith($suffix); } /** * @param int $count * * @return Count */ public static function countOf($count) { return new Count($count); } /** * Fails a test with the given message. * * @param string $message * * @throws AssertionFailedError */ public static function fail($message = '') { self::$count++; throw new AssertionFailedError($message); } /** * Returns the value of an attribute of a class or an object. * This also works for attributes that are declared protected or private. * * @param string|object $classOrObject * @param string $attributeName * * @return mixed * * @throws Exception */ public static function readAttribute($classOrObject, $attributeName) { if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(2, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(2, 'valid attribute name'); } if (\is_string($classOrObject)) { if (!\class_exists($classOrObject)) { throw InvalidArgumentHelper::factory( 1, 'class name' ); } return static::getStaticAttribute( $classOrObject, $attributeName ); } if (\is_object($classOrObject)) { return static::getObjectAttribute( $classOrObject, $attributeName ); } throw InvalidArgumentHelper::factory( 1, 'class name or object' ); } /** * Returns the value of a static attribute. * This also works for attributes that are declared protected or private. * * @param string $className * @param string $attributeName * * @return mixed * * @throws Exception */ public static function getStaticAttribute($className, $attributeName) { if (!\is_string($className)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\class_exists($className)) { throw InvalidArgumentHelper::factory(1, 'class name'); } if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(2, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(2, 'valid attribute name'); } $class = new ReflectionClass($className); while ($class) { $attributes = $class->getStaticProperties(); if (\array_key_exists($attributeName, $attributes)) { return $attributes[$attributeName]; } $class = $class->getParentClass(); } throw new Exception( \sprintf( 'Attribute "%s" not found in class.', $attributeName ) ); } /** * Returns the value of an object's attribute. * This also works for attributes that are declared protected or private. * * @param object $object * @param string $attributeName * * @return mixed * * @throws Exception */ public static function getObjectAttribute($object, $attributeName) { if (!\is_object($object)) { throw InvalidArgumentHelper::factory(1, 'object'); } if (!\is_string($attributeName)) { throw InvalidArgumentHelper::factory(2, 'string'); } if (!\preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { throw InvalidArgumentHelper::factory(2, 'valid attribute name'); } try { $attribute = new ReflectionProperty($object, $attributeName); } catch (ReflectionException $e) { $reflector = new ReflectionObject($object); while ($reflector = $reflector->getParentClass()) { try { $attribute = $reflector->getProperty($attributeName); break; } catch (ReflectionException $e) { } } } if (isset($attribute)) { if (!$attribute || $attribute->isPublic()) { return $object->$attributeName; } $attribute->setAccessible(true); $value = $attribute->getValue($object); $attribute->setAccessible(false); return $value; } throw new Exception( \sprintf( 'Attribute "%s" not found in object.', $attributeName ) ); } /** * Mark the test as incomplete. * * @param string $message * * @throws IncompleteTestError */ public static function markTestIncomplete($message = '') { throw new IncompleteTestError($message); } /** * Mark the test as skipped. * * @param string $message * * @throws SkippedTestError */ public static function markTestSkipped($message = '') { throw new SkippedTestError($message); } /** * Return the current assertion count. * * @return int */ public static function getCount() { return self::$count; } /** * Reset the assertion counter. */ public static function resetCount() { self::$count = 0; } } phpunit-6.5.5/src/Framework/Assert/000077500000000000000000000000001321540746700172145ustar00rootroot00000000000000phpunit-6.5.5/src/Framework/Assert/Functions.php000066400000000000000000001274631321540746700217120ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use PHPUnit\Framework\Assert; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Constraint\ArrayHasKey; use PHPUnit\Framework\Constraint\Attribute; 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\IsFalse; 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\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\ObjectHasAttribute; use PHPUnit\Framework\Constraint\RegularExpression; use PHPUnit\Framework\Constraint\StringContains; use PHPUnit\Framework\Constraint\StringEndsWith; use PHPUnit\Framework\Constraint\StringMatchesFormatDescription; use PHPUnit\Framework\Constraint\StringStartsWith; use PHPUnit\Framework\Constraint\TraversableContains; use PHPUnit\Framework\Constraint\TraversableContainsOnly; use PHPUnit\Framework\TestCase; /** * Returns a matcher that matches when the method is executed * zero or more times. * * @return PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount */ function any() { return TestCase::any(); } /** * Returns a PHPUnit\Framework\Constraint\IsAnything matcher object. * * @return IsAnything */ function anything() { return Assert::anything(); } /** * Returns a PHPUnit\Framework\Constraint\ArrayHasKey matcher object. * * @param mixed $key * * @return ArrayHasKey */ function arrayHasKey($key) { return Assert::arrayHasKey(...\func_get_args()); } /** * Asserts that an array has a specified key. * * @param mixed $key * @param array|ArrayAccess $array * @param string $message */ function assertArrayHasKey($key, $array, $message = '') { return Assert::assertArrayHasKey(...\func_get_args()); } /** * Asserts that an array has a specified subset. * * @param array|ArrayAccess $subset * @param array|ArrayAccess $array * @param bool $strict Check for object identity * @param string $message */ function assertArraySubset($subset, $array, $strict = false, $message = '') { return Assert::assertArraySubset(...\func_get_args()); } /** * Asserts that an array does not have a specified key. * * @param mixed $key * @param array|ArrayAccess $array * @param string $message */ function assertArrayNotHasKey($key, $array, $message = '') { return Assert::assertArrayNotHasKey(...\func_get_args()); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object contains a needle. * * @param mixed $needle * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return Assert::assertAttributeContains(...\func_get_args()); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object contains only values of a given type. * * @param string $type * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param bool $isNativeType * @param string $message */ function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') { return Assert::assertAttributeContainsOnly(...\func_get_args()); } /** * Asserts the number of elements of an array, Countable or Traversable * that is stored in an attribute. * * @param int $expectedCount * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message */ function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') { return Assert::assertAttributeCount(...\func_get_args()); } /** * Asserts that a static attribute of a class or an attribute of an object * is empty. * * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message */ function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') { return Assert::assertAttributeEmpty(...\func_get_args()); } /** * Asserts that a variable is equal to an attribute of an object. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::assertAttributeEquals(...\func_get_args()); } /** * Asserts that an attribute is greater than another value. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message */ function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeGreaterThan(...\func_get_args()); } /** * Asserts that an attribute is greater than or equal to another value. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message */ function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeGreaterThanOrEqual(...\func_get_args()); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param mixed $classOrObject * @param string $message */ function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '') { return Assert::assertAttributeInstanceOf(...\func_get_args()); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param mixed $classOrObject * @param string $message */ function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '') { return Assert::assertAttributeInternalType(...\func_get_args()); } /** * Asserts that an attribute is smaller than another value. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message */ function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeLessThan(...\func_get_args()); } /** * Asserts that an attribute is smaller than or equal to another value. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message */ function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeLessThanOrEqual(...\func_get_args()); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object does not contain a needle. * * @param mixed $needle * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return Assert::assertAttributeNotContains(...\func_get_args()); } /** * Asserts that a haystack that is stored in a static attribute of a class * or an attribute of an object does not contain only values of a given * type. * * @param string $type * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param bool $isNativeType * @param string $message */ function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') { return Assert::assertAttributeNotContainsOnly(...\func_get_args()); } /** * Asserts the number of elements of an array, Countable or Traversable * that is stored in an attribute. * * @param int $expectedCount * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message */ function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') { return Assert::assertAttributeNotCount(...\func_get_args()); } /** * Asserts that a static attribute of a class or an attribute of an object * is not empty. * * @param string $haystackAttributeName * @param mixed $haystackClassOrObject * @param string $message */ function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') { return Assert::assertAttributeNotEmpty(...\func_get_args()); } /** * Asserts that a variable is not equal to an attribute of an object. * * @param mixed $expected * @param string $actualAttributeName * @param string $actualClassOrObject * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::assertAttributeNotEquals(...\func_get_args()); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param mixed $classOrObject * @param string $message */ function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '') { return Assert::assertAttributeNotInstanceOf(...\func_get_args()); } /** * Asserts that an attribute is of a given type. * * @param string $expected * @param string $attributeName * @param mixed $classOrObject * @param string $message */ function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '') { return Assert::assertAttributeNotInternalType(...\func_get_args()); } /** * Asserts that a variable and an attribute of an object do not have the * same type and value. * * @param mixed $expected * @param string $actualAttributeName * @param object $actualClassOrObject * @param string $message */ function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeNotSame(...\func_get_args()); } /** * Asserts that a variable and an attribute of an object have the same type * and value. * * @param mixed $expected * @param string $actualAttributeName * @param object $actualClassOrObject * @param string $message */ function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') { return Assert::assertAttributeSame(...\func_get_args()); } /** * Asserts that a class has a specified attribute. * * @param string $attributeName * @param string $className * @param string $message */ function assertClassHasAttribute($attributeName, $className, $message = '') { return Assert::assertClassHasAttribute(...\func_get_args()); } /** * Asserts that a class has a specified static attribute. * * @param string $attributeName * @param string $className * @param string $message */ function assertClassHasStaticAttribute($attributeName, $className, $message = '') { return Assert::assertClassHasStaticAttribute(...\func_get_args()); } /** * Asserts that a class does not have a specified attribute. * * @param string $attributeName * @param string $className * @param string $message */ function assertClassNotHasAttribute($attributeName, $className, $message = '') { return Assert::assertClassNotHasAttribute(...\func_get_args()); } /** * Asserts that a class does not have a specified static attribute. * * @param string $attributeName * @param string $className * @param string $message */ function assertClassNotHasStaticAttribute($attributeName, $className, $message = '') { return Assert::assertClassNotHasStaticAttribute(...\func_get_args()); } /** * Asserts that a haystack contains a needle. * * @param mixed $needle * @param mixed $haystack * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ function assertContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return Assert::assertContains(...\func_get_args()); } /** * Asserts that a haystack contains only values of a given type. * * @param string $type * @param mixed $haystack * @param bool $isNativeType * @param string $message */ function assertContainsOnly($type, $haystack, $isNativeType = null, $message = '') { return Assert::assertContainsOnly(...\func_get_args()); } /** * Asserts that a haystack contains only instances of a given classname * * @param string $classname * @param array|\Traversable $haystack * @param string $message */ function assertContainsOnlyInstancesOf($classname, $haystack, $message = '') { return Assert::assertContainsOnlyInstancesOf(...\func_get_args()); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param int $expectedCount * @param mixed $haystack * @param string $message */ function assertCount($expectedCount, $haystack, $message = '') { return Assert::assertCount(...\func_get_args()); } /** * Asserts that a variable is empty. * * @param mixed $actual * @param string $message * * @throws AssertionFailedError */ function assertEmpty($actual, $message = '') { return Assert::assertEmpty(...\func_get_args()); } /** * Asserts that a hierarchy of DOMElements matches. * * @param DOMElement $expectedElement * @param DOMElement $actualElement * @param bool $checkAttributes * @param string $message */ function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = false, $message = '') { return Assert::assertEqualXMLStructure(...\func_get_args()); } /** * Asserts that two variables are equal. * * @param mixed $expected * @param mixed $actual * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ function assertEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::assertEquals(...\func_get_args()); } /** * Asserts that a condition is not true. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ function assertNotTrue($condition, $message = '') { return Assert::assertNotTrue(...\func_get_args()); } /** * Asserts that a condition is false. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ function assertFalse($condition, $message = '') { return Assert::assertFalse(...\func_get_args()); } /** * Asserts that the contents of one file is equal to the contents of another * file. * * @param string $expected * @param string $actual * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ function assertFileEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) { return Assert::assertFileEquals(...\func_get_args()); } /** * Asserts that a file exists. * * @param string $filename * @param string $message */ function assertFileExists($filename, $message = '') { return Assert::assertFileExists(...\func_get_args()); } /** * Asserts that the contents of one file is not equal to the contents of * another file. * * @param string $expected * @param string $actual * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) { return Assert::assertFileNotEquals(...\func_get_args()); } /** * Asserts that a file does not exist. * * @param string $filename * @param string $message */ function assertFileNotExists($filename, $message = '') { return Assert::assertFileNotExists(...\func_get_args()); } /** * Asserts that a value is greater than another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertGreaterThan($expected, $actual, $message = '') { return Assert::assertGreaterThan(...\func_get_args()); } /** * Asserts that a value is greater than or equal to another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertGreaterThanOrEqual($expected, $actual, $message = '') { return Assert::assertGreaterThanOrEqual(...\func_get_args()); } /** * Asserts that a variable is of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ function assertInstanceOf($expected, $actual, $message = '') { return Assert::assertInstanceOf(...\func_get_args()); } /** * Asserts that a variable is of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ function assertInternalType($expected, $actual, $message = '') { return Assert::assertInternalType(...\func_get_args()); } /** * Asserts that a string is a valid JSON string. * * @param string $actualJson * @param string $message */ function assertJson($actualJson, $message = '') { return Assert::assertJson(...\func_get_args()); } /** * Asserts that two JSON files are equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '') { return Assert::assertJsonFileEqualsJsonFile(...\func_get_args()); } /** * Asserts that two JSON files are not equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '') { return Assert::assertJsonFileNotEqualsJsonFile(...\func_get_args()); } /** * Asserts that the generated JSON encoded object and the content of the given file are equal. * * @param string $expectedFile * @param string $actualJson * @param string $message */ function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '') { return Assert::assertJsonStringEqualsJsonFile(...\func_get_args()); } /** * Asserts that two given JSON encoded objects or arrays are equal. * * @param string $expectedJson * @param string $actualJson * @param string $message */ function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '') { return Assert::assertJsonStringEqualsJsonString(...\func_get_args()); } /** * Asserts that the generated JSON encoded object and the content of the given file are not equal. * * @param string $expectedFile * @param string $actualJson * @param string $message */ function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '') { return Assert::assertJsonStringNotEqualsJsonFile(...\func_get_args()); } /** * Asserts that two given JSON encoded objects or arrays are not equal. * * @param string $expectedJson * @param string $actualJson * @param string $message */ function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '') { return Assert::assertJsonStringNotEqualsJsonString(...\func_get_args()); } /** * Asserts that a value is smaller than another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertLessThan($expected, $actual, $message = '') { return Assert::assertLessThan(...\func_get_args()); } /** * Asserts that a value is smaller than or equal to another value. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertLessThanOrEqual($expected, $actual, $message = '') { return Assert::assertLessThanOrEqual(...\func_get_args()); } /** * Asserts that a variable is finite. * * @param mixed $actual * @param string $message */ function assertFinite($actual, $message = '') { return Assert::assertFinite(...\func_get_args()); } /** * Asserts that a variable is infinite. * * @param mixed $actual * @param string $message */ function assertInfinite($actual, $message = '') { return Assert::assertInfinite(...\func_get_args()); } /** * Asserts that a variable is nan. * * @param mixed $actual * @param string $message */ function assertNan($actual, $message = '') { return Assert::assertNan(...\func_get_args()); } /** * Asserts that a haystack does not contain a needle. * * @param mixed $needle * @param mixed $haystack * @param string $message * @param bool $ignoreCase * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity */ function assertNotContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return Assert::assertNotContains(...\func_get_args()); } /** * Asserts that a haystack does not contain only values of a given type. * * @param string $type * @param mixed $haystack * @param bool $isNativeType * @param string $message */ function assertNotContainsOnly($type, $haystack, $isNativeType = null, $message = '') { return Assert::assertNotContainsOnly(...\func_get_args()); } /** * Asserts the number of elements of an array, Countable or Traversable. * * @param int $expectedCount * @param mixed $haystack * @param string $message */ function assertNotCount($expectedCount, $haystack, $message = '') { return Assert::assertNotCount(...\func_get_args()); } /** * Asserts that a variable is not empty. * * @param mixed $actual * @param string $message * * @throws AssertionFailedError */ function assertNotEmpty($actual, $message = '') { return Assert::assertNotEmpty(...\func_get_args()); } /** * Asserts that two variables are not equal. * * @param mixed $expected * @param mixed $actual * @param string $message * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase */ function assertNotEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::assertNotEquals(...\func_get_args()); } /** * Asserts that a variable is not of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ function assertNotInstanceOf($expected, $actual, $message = '') { return Assert::assertNotInstanceOf(...\func_get_args()); } /** * Asserts that a variable is not of a given type. * * @param string $expected * @param mixed $actual * @param string $message */ function assertNotInternalType($expected, $actual, $message = '') { return Assert::assertNotInternalType(...\func_get_args()); } /** * Asserts that a condition is not false. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ function assertNotFalse($condition, $message = '') { return Assert::assertNotFalse(...\func_get_args()); } /** * Asserts that a variable is not null. * * @param mixed $actual * @param string $message */ function assertNotNull($actual, $message = '') { return Assert::assertNotNull(...\func_get_args()); } /** * Asserts that a string does not match a given regular expression. * * @param string $pattern * @param string $string * @param string $message */ function assertNotRegExp($pattern, $string, $message = '') { return Assert::assertNotRegExp(...\func_get_args()); } /** * 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. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertNotSame($expected, $actual, $message = '') { return Assert::assertNotSame(...\func_get_args()); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is not the same. * * @param array|\Countable|\Traversable $expected * @param array|\Countable|\Traversable $actual * @param string $message */ function assertNotSameSize($expected, $actual, $message = '') { return Assert::assertNotSameSize(...\func_get_args()); } /** * Asserts that a variable is null. * * @param mixed $actual * @param string $message */ function assertNull($actual, $message = '') { return Assert::assertNull(...\func_get_args()); } /** * Asserts that an object has a specified attribute. * * @param string $attributeName * @param object $object * @param string $message */ function assertObjectHasAttribute($attributeName, $object, $message = '') { return Assert::assertObjectHasAttribute(...\func_get_args()); } /** * Asserts that an object does not have a specified attribute. * * @param string $attributeName * @param object $object * @param string $message */ function assertObjectNotHasAttribute($attributeName, $object, $message = '') { return Assert::assertObjectNotHasAttribute(...\func_get_args()); } /** * Asserts that a string matches a given regular expression. * * @param string $pattern * @param string $string * @param string $message */ function assertRegExp($pattern, $string, $message = '') { return Assert::assertRegExp(...\func_get_args()); } /** * Asserts that two variables have the same type and value. * Used on objects, it asserts that two variables reference * the same object. * * @param mixed $expected * @param mixed $actual * @param string $message */ function assertSame($expected, $actual, $message = '') { return Assert::assertSame(...\func_get_args()); } /** * Assert that the size of two arrays (or `Countable` or `Traversable` objects) * is the same. * * @param array|\Countable|\Traversable $expected * @param array|\Countable|\Traversable $actual * @param string $message */ function assertSameSize($expected, $actual, $message = '') { return Assert::assertSameSize(...\func_get_args()); } /** * Asserts that a string ends not with a given prefix. * * @param string $suffix * @param string $string * @param string $message */ function assertStringEndsNotWith($suffix, $string, $message = '') { return Assert::assertStringEndsNotWith(...\func_get_args()); } /** * Asserts that a string ends with a given prefix. * * @param string $suffix * @param string $string * @param string $message */ function assertStringEndsWith($suffix, $string, $message = '') { return Assert::assertStringEndsWith(...\func_get_args()); } /** * Asserts that the contents of a string is equal * to the contents of a file. * * @param string $expectedFile * @param string $actualString * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) { return Assert::assertStringEqualsFile(...\func_get_args()); } /** * Asserts that a string matches a given format string. * * @param string $format * @param string $string * @param string $message */ function assertStringMatchesFormat($format, $string, $message = '') { return Assert::assertStringMatchesFormat(...\func_get_args()); } /** * Asserts that a string matches a given format file. * * @param string $formatFile * @param string $string * @param string $message */ function assertStringMatchesFormatFile($formatFile, $string, $message = '') { return Assert::assertStringMatchesFormatFile(...\func_get_args()); } /** * Asserts that the contents of a string is not equal * to the contents of a file. * * @param string $expectedFile * @param string $actualString * @param string $message * @param bool $canonicalize * @param bool $ignoreCase */ function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) { return Assert::assertStringNotEqualsFile(...\func_get_args()); } /** * Asserts that a string does not match a given format string. * * @param string $format * @param string $string * @param string $message */ function assertStringNotMatchesFormat($format, $string, $message = '') { return Assert::assertStringNotMatchesFormat(...\func_get_args()); } /** * Asserts that a string does not match a given format string. * * @param string $formatFile * @param string $string * @param string $message */ function assertStringNotMatchesFormatFile($formatFile, $string, $message = '') { return Assert::assertStringNotMatchesFormatFile(...\func_get_args()); } /** * Asserts that a string starts not with a given prefix. * * @param string $prefix * @param string $string * @param string $message */ function assertStringStartsNotWith($prefix, $string, $message = '') { return Assert::assertStringStartsNotWith(...\func_get_args()); } /** * Asserts that a string starts with a given prefix. * * @param string $prefix * @param string $string * @param string $message */ function assertStringStartsWith($prefix, $string, $message = '') { return Assert::assertStringStartsWith(...\func_get_args()); } /** * Evaluates a PHPUnit\Framework\Constraint matcher object. * * @param mixed $value * @param Constraint $constraint * @param string $message */ function assertThat($value, Constraint $constraint, $message = '') { return Assert::assertThat(...\func_get_args()); } /** * Asserts that a condition is true. * * @param bool $condition * @param string $message * * @throws AssertionFailedError */ function assertTrue($condition, $message = '') { return Assert::assertTrue(...\func_get_args()); } /** * Asserts that two XML files are equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '') { return Assert::assertXmlFileEqualsXmlFile(...\func_get_args()); } /** * Asserts that two XML files are not equal. * * @param string $expectedFile * @param string $actualFile * @param string $message */ function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '') { return Assert::assertXmlFileNotEqualsXmlFile(...\func_get_args()); } /** * Asserts that two XML documents are equal. * * @param string $expectedFile * @param string|DOMDocument $actualXml * @param string $message */ function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '') { return Assert::assertXmlStringEqualsXmlFile(...\func_get_args()); } /** * Asserts that two XML documents are equal. * * @param string|DOMDocument $expectedXml * @param string|DOMDocument $actualXml * @param string $message */ function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '') { return Assert::assertXmlStringEqualsXmlString(...\func_get_args()); } /** * Asserts that two XML documents are not equal. * * @param string $expectedFile * @param string|DOMDocument $actualXml * @param string $message */ function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '') { return Assert::assertXmlStringNotEqualsXmlFile(...\func_get_args()); } /** * Asserts that two XML documents are not equal. * * @param string|DOMDocument $expectedXml * @param string|DOMDocument $actualXml * @param string $message */ function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '') { return Assert::assertXmlStringNotEqualsXmlString(...\func_get_args()); } /** * Returns a matcher that matches when the method is executed * at the given $index. * * @param int $index * * @return PHPUnit\Framework\MockObject\Matcher\InvokedAtIndex */ function at($index) { return TestCase::at(...\func_get_args()); } /** * Returns a matcher that matches when the method is executed at least once. * * @return PHPUnit\Framework\MockObject\Matcher\InvokedAtLeastOnce */ function atLeastOnce() { return TestCase::atLeastOnce(); } /** * Returns a PHPUnit\Framework\Constraint\Attribute matcher object. * * @param Constraint $constraint * @param string $attributeName * * @return Attribute */ function attribute(Constraint $constraint, $attributeName) { return Assert::attribute(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\IsEqual matcher object * that is wrapped in a PHPUnit\Framework\Constraint\Attribute matcher * object. * * @param string $attributeName * @param mixed $value * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase * * @return Attribute */ function attributeEqualTo($attributeName, $value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::attributeEqualTo(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Callback matcher object. * * @param callable $callback * * @return Callback */ function callback($callback) { return Assert::callback(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\ClassHasAttribute matcher object. * * @param string $attributeName * * @return ClassHasAttribute */ function classHasAttribute($attributeName) { return Assert::classHasAttribute(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\ClassHasStaticAttribute matcher * object. * * @param string $attributeName * * @return ClassHasStaticAttribute */ function classHasStaticAttribute($attributeName) { return Assert::classHasStaticAttribute(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\TraversableContains matcher * object. * * @param mixed $value * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity * * @return TraversableContains */ function contains($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { return Assert::contains(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\TraversableContainsOnly matcher * object. * * @param string $type * * @return TraversableContainsOnly */ function containsOnly($type) { return Assert::containsOnly(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\TraversableContainsOnly matcher * object. * * @param string $classname * * @return TraversableContainsOnly */ function containsOnlyInstancesOf($classname) { return Assert::containsOnlyInstancesOf(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Count matcher object. * * @param int $count * * @return Count */ function countOf($count) { return Assert::countOf(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\DirectoryExists matcher object. * * @return DirectoryExists */ function directoryExists() { return Assert::directoryExists(); } /** * Returns a PHPUnit\Framework\Constraint\IsEqual matcher object. * * @param mixed $value * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase * * @return IsEqual */ function equalTo($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { return Assert::equalTo(...\func_get_args()); } /** * Returns a matcher that matches when the method is executed * exactly $count times. * * @param int $count * * @return PHPUnit\Framework\MockObject\Matcher\InvokedCount */ function exactly($count) { return TestCase::exactly(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\FileExists matcher object. * * @return FileExists */ function fileExists() { return Assert::fileExists(); } /** * Returns a PHPUnit\Framework\Constraint\GreaterThan matcher object. * * @param mixed $value * * @return GreaterThan */ function greaterThan($value) { return Assert::greaterThan(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Or matcher object that wraps * a PHPUnit\Framework\Constraint\IsEqual and a * PHPUnit\Framework\Constraint\GreaterThan matcher object. * * @param mixed $value * * @return LogicalOr */ function greaterThanOrEqual($value) { return Assert::greaterThanOrEqual(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\IsIdentical matcher object. * * @param mixed $value * * @return IsIdentical */ function identicalTo($value) { return Assert::identicalTo(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\IsEmpty matcher object. * * @return IsEmpty */ function isEmpty() { return Assert::isEmpty(); } /** * Returns a PHPUnit\Framework\Constraint\IsFalse matcher object. * * @return IsFalse */ function isFalse() { return Assert::isFalse(); } /** * Returns a PHPUnit\Framework\Constraint\IsInfinite matcher object. * * @return IsInfinite */ function isInfinite() { return Assert::isInfinite(); } /** * Returns a PHPUnit\Framework\Constraint\IsInstanceOf matcher object. * * @param string $className * * @return IsInstanceOf */ function isInstanceOf($className) { return Assert::isInstanceOf(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\IsJson matcher object. * * @return IsJson */ function isJson() { return Assert::isJson(); } /** * Returns a PHPUnit\Framework\Constraint\IsNan matcher object. * * @return IsNan */ function isNan() { return Assert::isNan(); } /** * Returns a PHPUnit\Framework\Constraint\IsNull matcher object. * * @return IsNull */ function isNull() { return Assert::isNull(); } /** * Returns a PHPUnit\Framework\Constraint\IsReadable matcher object. * * @return IsReadable */ function isReadable() { return Assert::isReadable(); } /** * Returns a PHPUnit\Framework\Constraint\IsTrue matcher object. * * @return IsTrue */ function isTrue() { return Assert::isTrue(); } /** * Returns a PHPUnit\Framework\Constraint\IsType matcher object. * * @param string $type * * @return IsType */ function isType($type) { return Assert::isType(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\IsWritable matcher object. * * @return IsWritable */ function isWritable() { return Assert::isWritable(); } /** * Returns a PHPUnit\Framework\Constraint\LessThan matcher object. * * @param mixed $value * * @return LessThan */ function lessThan($value) { return Assert::lessThan(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Or matcher object that wraps * a PHPUnit\Framework\Constraint\IsEqual and a * PHPUnit\Framework\Constraint\LessThan matcher object. * * @param mixed $value * * @return LogicalOr */ function lessThanOrEqual($value) { return Assert::lessThanOrEqual(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\And matcher object. * * @return LogicalAnd */ function logicalAnd() { return Assert::logicalAnd(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Not matcher object. * * @param Constraint $constraint * * @return LogicalNot */ function logicalNot(Constraint $constraint) { return Assert::logicalNot(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Or matcher object. * * @return LogicalOr */ function logicalOr() { return Assert::logicalOr(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\Xor matcher object. * * @return LogicalXor */ function logicalXor() { return Assert::logicalXor(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\StringMatches matcher object. * * @param string $string * * @return StringMatchesFormatDescription */ function matches($string) { return Assert::matches(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\PCREMatch matcher object. * * @param string $pattern * * @return RegularExpression */ function matchesRegularExpression($pattern) { return Assert::matchesRegularExpression(...\func_get_args()); } /** * Returns a matcher that matches when the method is never executed. * * @return PHPUnit\Framework\MockObject\Matcher\InvokedCount */ function never() { return TestCase::never(); } /** * Returns a PHPUnit\Framework\Constraint\ObjectHasAttribute matcher object. * * @param string $attributeName * * @return ObjectHasAttribute */ function objectHasAttribute($attributeName) { return Assert::objectHasAttribute(...\func_get_args()); } /** * @param mixed $value, ... * * @return PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls */ function onConsecutiveCalls() { return TestCase::onConsecutiveCalls(...\func_get_args()); } /** * Returns a matcher that matches when the method is executed exactly once. * * @return PHPUnit\Framework\MockObject\Matcher\InvokedCount */ function once() { return TestCase::once(); } /** * @param int $argumentIndex * * @return PHPUnit\Framework\MockObject\Stub\ReturnArgument */ function returnArgument($argumentIndex) { return TestCase::returnArgument(...\func_get_args()); } /** * @param mixed $callback * * @return PHPUnit\Framework\MockObject\Stub\ReturnCallback */ function returnCallback($callback) { return TestCase::returnCallback(...\func_get_args()); } /** * Returns the current object. * * This method is useful when mocking a fluent interface. * * @return PHPUnit\Framework\MockObject\Stub\ReturnSelf */ function returnSelf() { return TestCase::returnSelf(); } /** * @param mixed $value * * @return PHPUnit\Framework\MockObject\Stub\Return */ function returnValue($value) { return TestCase::returnValue(...\func_get_args()); } /** * @param array $valueMap * * @return PHPUnit\Framework\MockObject\Stub\ReturnValueMap */ function returnValueMap(array $valueMap) { return TestCase::returnValueMap(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\StringContains matcher object. * * @param string $string * @param bool $case * * @return StringContains */ function stringContains($string, $case = true) { return Assert::stringContains(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\StringEndsWith matcher object. * * @param mixed $suffix * * @return StringEndsWith */ function stringEndsWith($suffix) { return Assert::stringEndsWith(...\func_get_args()); } /** * Returns a PHPUnit\Framework\Constraint\StringStartsWith matcher object. * * @param mixed $prefix * * @return StringStartsWith */ function stringStartsWith($prefix) { return Assert::stringStartsWith(...\func_get_args()); } /** * @param Exception $exception * * @return PHPUnit\Framework\MockObject\Stub\Exception */ function throwException(Exception $exception) { return TestCase::throwException(...\func_get_args()); } phpunit-6.5.5/src/Framework/AssertionFailedError.php000066400000000000000000000010621321540746700225510ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Thrown when an assertion failed. */ class AssertionFailedError extends Exception implements SelfDescribing { /** * Wrapper for getMessage() which is declared as final. * * @return string */ public function toString() { return $this->getMessage(); } } phpunit-6.5.5/src/Framework/BaseTestListener.php000066400000000000000000000010021321540746700216750ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Implementation of the TestListener interface that does not do anything. * * @deprecated Use TestListenerDefaultImplementation trait instead */ abstract class BaseTestListener implements TestListener { use TestListenerDefaultImplementation; } phpunit-6.5.5/src/Framework/CodeCoverageException.php000066400000000000000000000004651321540746700226760ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class CodeCoverageException extends Exception { } phpunit-6.5.5/src/Framework/Constraint/000077500000000000000000000000001321540746700200775ustar00rootroot00000000000000phpunit-6.5.5/src/Framework/Constraint/ArrayHasKey.php000066400000000000000000000036241321540746700230000ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use ArrayAccess; /** * Constraint that asserts that the array it is evaluated for has a given key. * * Uses array_key_exists() to check if the key is found in the input array, if * not found the evaluation fails. * * The array key is passed in the constructor. */ class ArrayHasKey extends Constraint { /** * @var int|string */ protected $key; /** * @param int|string $key */ public function __construct($key) { parent::__construct(); $this->key = $key; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { if (\is_array($other)) { return \array_key_exists($this->key, $other); } if ($other instanceof ArrayAccess) { return $other->offsetExists($this->key); } return false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'has the key ' . $this->exporter->export($this->key); } /** * 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. * * @return string */ protected function failureDescription($other) { return 'an array ' . $this->toString(); } } phpunit-6.5.5/src/Framework/Constraint/ArraySubset.php000066400000000000000000000072301321540746700230560ustar00rootroot00000000000000 * * 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 SebastianBergmann\Comparator\ComparisonFailure; /** * Constraint that asserts that the array it is evaluated for has a specified subset. * * Uses array_replace_recursive() to check if a key value subset is part of the * subject array. */ class ArraySubset extends Constraint { /** * @var array|\Traversable */ protected $subset; /** * @var bool */ protected $strict; /** * @param array|\Traversable $subset * @param bool $strict Check for object identity */ public function __construct($subset, $strict = false) { parent::__construct(); $this->strict = $strict; $this->subset = $subset; } /** * 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 $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { //type cast $other & $this->subset as an array to allow //support in standard array functions. $other = $this->toArray($other); $this->subset = $this->toArray($this->subset); $patched = \array_replace_recursive($other, $this->subset); if ($this->strict) { $result = $other === $patched; } else { $result = $other == $patched; } if ($returnResult) { return $result; } if (!$result) { $f = new ComparisonFailure( $patched, $other, \print_r($patched, true), \print_r($other, true) ); $this->fail($other, $description, $f); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'has the subset ' . $this->exporter->export($this->subset); } /** * 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. * * @return string */ protected function failureDescription($other) { return 'an array ' . $this->toString(); } /** * @param array|\Traversable $other * * @return array */ private function toArray($other) { if (\is_array($other)) { return $other; } if ($other instanceof \ArrayObject) { return $other->getArrayCopy(); } if ($other instanceof \Traversable) { return \iterator_to_array($other); } // Keep BC even if we know that array would not be the expected one return (array) $other; } } phpunit-6.5.5/src/Framework/Constraint/Attribute.php000066400000000000000000000045061321540746700225600ustar00rootroot00000000000000 * * 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\Assert; use PHPUnit\Framework\ExpectationFailedException; class Attribute extends Composite { /** * @var string */ protected $attributeName; /** * @param Constraint $constraint * @param string $attributeName */ public function __construct(Constraint $constraint, $attributeName) { parent::__construct($constraint); $this->attributeName = $attributeName; } /** * 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 $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { return parent::evaluate( Assert::readAttribute( $other, $this->attributeName ), $description, $returnResult ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'attribute "' . $this->attributeName . '" ' . $this->innerConstraint->toString(); } /** * 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. * * @return string */ protected function failureDescription($other) { return $this->toString(); } } phpunit-6.5.5/src/Framework/Constraint/Callback.php000066400000000000000000000025131321540746700223050ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\InvalidArgumentHelper; /** * Constraint that evaluates against a specified closure. */ class Callback extends Constraint { private $callback; /** * @param callable $callback * * @throws \PHPUnit\Framework\Exception */ public function __construct($callback) { if (!\is_callable($callback)) { throw InvalidArgumentHelper::factory( 1, 'callable' ); } parent::__construct(); $this->callback = $callback; } /** * Evaluates the constraint for parameter $value. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \call_user_func($this->callback, $other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is accepted by specified callback'; } } phpunit-6.5.5/src/Framework/Constraint/ClassHasAttribute.php000066400000000000000000000036461321540746700242060ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use ReflectionClass; /** * Constraint that asserts that the class it is evaluated for has a given * attribute. * * The attribute name is passed in the constructor. */ class ClassHasAttribute extends Constraint { /** * @var string */ protected $attributeName; /** * @param string $attributeName */ public function __construct($attributeName) { parent::__construct(); $this->attributeName = $attributeName; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { $class = new ReflectionClass($other); return $class->hasProperty($this->attributeName); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'has attribute "%s"', $this->attributeName ); } /** * 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '%sclass "%s" %s', \is_object($other) ? 'object of ' : '', \is_object($other) ? \get_class($other) : $other, $this->toString() ); } } phpunit-6.5.5/src/Framework/Constraint/ClassHasStaticAttribute.php000066400000000000000000000024111321540746700253430ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use ReflectionClass; /** * Constraint that asserts that the class it is evaluated for has a given * static attribute. * * The attribute name is passed in the constructor. */ class ClassHasStaticAttribute 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. * * @return bool */ protected function matches($other) { $class = new ReflectionClass($other); if ($class->hasProperty($this->attributeName)) { $attribute = $class->getProperty($this->attributeName); return $attribute->isStatic(); } return false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'has static attribute "%s"', $this->attributeName ); } } phpunit-6.5.5/src/Framework/Constraint/Composite.php000066400000000000000000000035751321540746700225640ustar00rootroot00000000000000 * * 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; abstract class Composite extends Constraint { /** * @var Constraint */ protected $innerConstraint; /** * @param Constraint $innerConstraint */ public function __construct(Constraint $innerConstraint) { parent::__construct(); $this->innerConstraint = $innerConstraint; } /** * 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 $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { try { return $this->innerConstraint->evaluate( $other, $description, $returnResult ); } catch (ExpectationFailedException $e) { $this->fail($other, $description, $e->getComparisonFailure()); } } /** * Counts the number of constraint elements. * * @return int */ public function count() { return \count($this->innerConstraint); } } phpunit-6.5.5/src/Framework/Constraint/Constraint.php000066400000000000000000000102751321540746700227410ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use Countable; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\SelfDescribing; use SebastianBergmann\Comparator\ComparisonFailure; use SebastianBergmann\Exporter\Exporter; /** * Abstract base class for constraints which can be applied to any value. */ abstract class Constraint implements Countable, SelfDescribing { protected $exporter; public function __construct() { $this->exporter = new 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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $success = false; if ($this->matches($other)) { $success = true; } if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } } /** * 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. * * @return bool */ protected function matches($other) { return false; } /** * Counts the number of constraint elements. * * @return int */ public function count() { return 1; } /** * 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 ExpectationFailedException */ protected function fail($other, $description, ComparisonFailure $comparisonFailure = null) { $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. * * @return string */ protected function additionalFailureDescription($other) { 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. * * @return string */ protected function failureDescription($other) { return $this->exporter->export($other) . ' ' . $this->toString(); } } phpunit-6.5.5/src/Framework/Constraint/Count.php000066400000000000000000000062141321540746700217030ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use Countable; use Generator; use Iterator; use IteratorAggregate; use Traversable; class Count extends Constraint { /** * @var int */ protected $expectedCount = 0; /** * @param int $expected */ public function __construct($expected) { parent::__construct(); $this->expectedCount = $expected; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other * * @return bool */ protected function matches($other) { return $this->expectedCount === $this->getCountOf($other); } /** * @param \Countable|\Traversable|array $other * * @return int|null */ protected function getCountOf($other) { if ($other instanceof Countable || \is_array($other)) { return \count($other); } if ($other instanceof Traversable) { while ($other instanceof IteratorAggregate) { $other = $other->getIterator(); } $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; } } /** * Returns the total number of iterations from a generator. * This will fully exhaust the generator. * * @param Generator $generator * * @return int */ protected function getCountOfGenerator(Generator $generator) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( 'actual size %d matches expected size %d', $this->getCountOf($other), $this->expectedCount ); } /** * @return string */ public function toString() { return \sprintf( 'count matches %d', $this->expectedCount ); } } phpunit-6.5.5/src/Framework/Constraint/DirectoryExists.php000066400000000000000000000026141321540746700237570ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that checks if the directory(name) that it is evaluated for exists. * * The file path to check is passed as $other in evaluate(). */ class DirectoryExists extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( 'directory "%s" exists', $other ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'directory exists'; } } phpunit-6.5.5/src/Framework/Constraint/Exception.php000066400000000000000000000041321321540746700225460ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\Filter; use Throwable; class Exception extends Constraint { /** * @var string */ protected $className; /** * @param string $className */ public function __construct($className) { parent::__construct(); $this->className = $className; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { 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 ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'exception of type "%s"', $this->className ); } } phpunit-6.5.5/src/Framework/Constraint/ExceptionCode.php000066400000000000000000000030411321540746700233370ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; class ExceptionCode extends Constraint { /** * @var int */ protected $expectedCode; /** * @param int $expected */ public function __construct($expected) { parent::__construct(); $this->expectedCode = $expected; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param \Throwable $other * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '%s is equal to expected exception code %s', $this->exporter->export($other->getCode()), $this->exporter->export($this->expectedCode) ); } /** * @return string */ public function toString() { return 'exception code is '; } } phpunit-6.5.5/src/Framework/Constraint/ExceptionMessage.php000066400000000000000000000036361321540746700240630ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; class ExceptionMessage extends Constraint { /** * @var int */ protected $expectedMessage; /** * @param string $expected */ public function __construct($expected) { parent::__construct(); $this->expectedMessage = $expected; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param \Throwable $other * * @return bool */ protected function matches($other) { if ($this->expectedMessage === '') { return $other->getMessage() === ''; } return \strpos($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. * * @return string */ protected function failureDescription($other) { 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 ); } /** * @return string */ public function toString() { if ($this->expectedMessage === '') { return 'exception message is empty'; } return 'exception message contains '; } } phpunit-6.5.5/src/Framework/Constraint/ExceptionMessageRegularExpression.php000066400000000000000000000036031321540746700274570ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\RegularExpression as RegularExpressionUtil; class ExceptionMessageRegularExpression extends Constraint { /** * @var string */ protected $expectedMessageRegExp; /** * @param string $expected */ public function __construct($expected) { parent::__construct(); $this->expectedMessageRegExp = $expected; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param \PHPUnit\Framework\Exception $other * * @return bool */ protected function matches($other) { $match = RegularExpressionUtil::safeMatch($this->expectedMessageRegExp, $other->getMessage()); if (false === $match) { throw new \PHPUnit\Framework\Exception( "Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'" ); } return 1 === $match; } /** * 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. * * @return string */ protected function failureDescription($other) { return \sprintf( "exception message '%s' matches '%s'", $other->getMessage(), $this->expectedMessageRegExp ); } /** * @return string */ public function toString() { return 'exception message matches '; } } phpunit-6.5.5/src/Framework/Constraint/FileExists.php000066400000000000000000000025751321540746700227000ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that checks if the file(name) that it is evaluated for exists. * * The file path to check is passed as $other in evaluate(). */ class FileExists extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( 'file "%s" exists', $other ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'file exists'; } } phpunit-6.5.5/src/Framework/Constraint/GreaterThan.php000066400000000000000000000022241321540746700230140ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the value it is evaluated for is greater * than a given value. */ class GreaterThan extends Constraint { /** * @var int|float */ protected $value; /** * @param int|float $value */ public function __construct($value) { parent::__construct(); $this->value = $value; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return $this->value < $other; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is greater than ' . $this->exporter->export($this->value); } } phpunit-6.5.5/src/Framework/Constraint/IsAnything.php000066400000000000000000000030361321540746700226670ustar00rootroot00000000000000 * * 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; /** * Constraint that accepts any input value. */ 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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { return $returnResult ? true : null; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is anything'; } /** * Counts the number of constraint elements. * * @return int */ public function count() { return 0; } } phpunit-6.5.5/src/Framework/Constraint/IsEmpty.php000066400000000000000000000030011321540746700221740ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use Countable; /** * Constraint that checks whether a variable is empty(). */ class IsEmpty extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { if ($other instanceof Countable) { return \count($other) === 0; } return empty($other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is empty'; } /** * 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. * * @return string */ protected function failureDescription($other) { $type = \gettype($other); return \sprintf( '%s %s %s', $type[0] == 'a' || $type[0] == 'o' ? 'an' : 'a', $type, $this->toString() ); } } phpunit-6.5.5/src/Framework/Constraint/IsEqual.php000066400000000000000000000112471321540746700221600ustar00rootroot00000000000000 * * 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 PHPUnit\Util\InvalidArgumentHelper; use SebastianBergmann; /** * Constraint that checks if one value is equal to another. * * Equality is checked with PHP's == operator, the operator is explained in * detail at {@url http://www.php.net/manual/en/types.comparisons.php}. * Two values are equal if they have the same value disregarding type. * * The expected value is passed in the constructor. */ class IsEqual extends Constraint { /** * @var mixed */ protected $value; /** * @var float */ protected $delta = 0.0; /** * @var int */ protected $maxDepth = 10; /** * @var bool */ protected $canonicalize = false; /** * @var bool */ protected $ignoreCase = false; /** * @var SebastianBergmann\Comparator\ComparisonFailure */ protected $lastFailure; /** * @param mixed $value * @param float $delta * @param int $maxDepth * @param bool $canonicalize * @param bool $ignoreCase * * @throws \PHPUnit\Framework\Exception */ public function __construct($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { parent::__construct(); if (!\is_numeric($delta)) { throw InvalidArgumentHelper::factory(2, 'numeric'); } if (!\is_int($maxDepth)) { throw InvalidArgumentHelper::factory(3, 'integer'); } if (!\is_bool($canonicalize)) { throw InvalidArgumentHelper::factory(4, 'boolean'); } if (!\is_bool($ignoreCase)) { throw InvalidArgumentHelper::factory(5, 'boolean'); } $this->value = $value; $this->delta = $delta; $this->maxDepth = $maxDepth; $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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { // 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 = SebastianBergmann\Comparator\Factory::getInstance(); try { $comparator = $comparatorFactory->getComparatorFor( $this->value, $other ); $comparator->assertEquals( $this->value, $other, $this->delta, $this->canonicalize, $this->ignoreCase ); } catch (SebastianBergmann\Comparator\ComparisonFailure $f) { if ($returnResult) { return false; } throw new ExpectationFailedException( \trim($description . "\n" . $f->getMessage()), $f ); } return true; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { $delta = ''; if (\is_string($this->value)) { if (\strpos($this->value, "\n") !== false) { return 'is equal to '; } 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 ); } } phpunit-6.5.5/src/Framework/Constraint/IsFalse.php000066400000000000000000000014751321540746700221450ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts false. */ class IsFalse extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return $other === false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is false'; } } phpunit-6.5.5/src/Framework/Constraint/IsFinite.php000066400000000000000000000015021321540746700223200ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts finite. */ class IsFinite extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \is_finite($other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is finite'; } } phpunit-6.5.5/src/Framework/Constraint/IsIdentical.php000066400000000000000000000073341321540746700230070ustar00rootroot00000000000000 * * 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 SebastianBergmann; /** * Constraint that asserts that one value is identical to another. * * Identical check is performed with PHP's === operator, the operator is * explained in detail at * {@url http://www.php.net/manual/en/types.comparisons.php}. * Two values are identical if they have the same value and are of the same * type. * * The expected value is passed in the constructor. */ class IsIdentical extends Constraint { /** * @var float */ const EPSILON = 0.0000000001; /** * @var mixed */ protected $value; /** * @param mixed $value */ public function __construct($value) { parent::__construct(); $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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { 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) < self::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 SebastianBergmann\Comparator\ComparisonFailure( $this->value, $other, \sprintf("'%s'", $this->value), \sprintf("'%s'", $other) ); } $this->fail($other, $description, $f); } } /** * 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. * * @return string */ protected function failureDescription($other) { 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'; } return parent::failureDescription($other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { 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); } } phpunit-6.5.5/src/Framework/Constraint/IsInfinite.php000066400000000000000000000015121321540746700226500ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts infinite. */ class IsInfinite extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \is_infinite($other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is infinite'; } } phpunit-6.5.5/src/Framework/Constraint/IsInstanceOf.php000066400000000000000000000042671321540746700231460ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use ReflectionClass; use ReflectionException; /** * Constraint that asserts that the object it is evaluated for is an instance * of a given class. * * The expected class name is passed in the constructor. */ class IsInstanceOf extends Constraint { /** * @var string */ protected $className; /** * @param string $className */ public function __construct($className) { parent::__construct(); $this->className = $className; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '%s is an instance of %s "%s"', $this->exporter->shortenedExport($other), $this->getType(), $this->className ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'is instance of %s "%s"', $this->getType(), $this->className ); } private function getType() { try { $reflection = new ReflectionClass($this->className); if ($reflection->isInterface()) { return 'interface'; } } catch (ReflectionException $e) { } return 'class'; } } phpunit-6.5.5/src/Framework/Constraint/IsJson.php000066400000000000000000000033431321540746700220200ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that a string is valid JSON. */ class IsJson extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { if ($other === '') { return 'an empty string is valid JSON'; } \json_decode($other); $error = JsonMatchesErrorMessageProvider::determineJsonError( \json_last_error() ); return \sprintf( '%s is valid JSON (%s)', $this->exporter->shortenedExport($other), $error ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is valid JSON'; } } phpunit-6.5.5/src/Framework/Constraint/IsNan.php000066400000000000000000000014661321540746700216270ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts nan. */ class IsNan extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \is_nan($other); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is nan'; } } phpunit-6.5.5/src/Framework/Constraint/IsNull.php000066400000000000000000000014711321540746700220210ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts null. */ class IsNull extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return $other === null; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is null'; } } phpunit-6.5.5/src/Framework/Constraint/IsReadable.php000066400000000000000000000026061321540746700226070ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that checks if the file/dir(name) that it is evaluated for is readable. * * The file path to check is passed as $other in evaluate(). */ class IsReadable extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '"%s" is readable', $other ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is readable'; } } phpunit-6.5.5/src/Framework/Constraint/IsTrue.php000066400000000000000000000014711321540746700220260ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that accepts true. */ class IsTrue extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return $other === true; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is true'; } } phpunit-6.5.5/src/Framework/Constraint/IsType.php000066400000000000000000000065031321540746700220310ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the value it is evaluated for is of a * specified type. * * The expected value is passed in the constructor. */ class IsType extends Constraint { const TYPE_ARRAY = 'array'; const TYPE_BOOL = 'bool'; const TYPE_FLOAT = 'float'; const TYPE_INT = 'int'; const TYPE_NULL = 'null'; const TYPE_NUMERIC = 'numeric'; const TYPE_OBJECT = 'object'; const TYPE_RESOURCE = 'resource'; const TYPE_STRING = 'string'; const TYPE_SCALAR = 'scalar'; const TYPE_CALLABLE = 'callable'; /** * @var array */ protected $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, 'string' => true, 'scalar' => true, 'callable' => true ]; /** * @var string */ protected $type; /** * @param string $type * * @throws \PHPUnit\Framework\Exception */ public function __construct($type) { parent::__construct(); if (!isset($this->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; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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': return \is_resource($other) || \is_string(@\get_resource_type($other)); case 'scalar': return \is_scalar($other); case 'callable': return \is_callable($other); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'is of type "%s"', $this->type ); } } phpunit-6.5.5/src/Framework/Constraint/IsWritable.php000066400000000000000000000026061321540746700226610ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that checks if the file/dir(name) that it is evaluated for is writable. * * The file path to check is passed as $other in evaluate(). */ class IsWritable extends Constraint { /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '"%s" is writable', $other ); } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is writable'; } } phpunit-6.5.5/src/Framework/Constraint/JsonMatches.php000066400000000000000000000055651321540746700230410ustar00rootroot00000000000000 * * 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 PHPUnit\Util\Json; use SebastianBergmann\Comparator\ComparisonFailure; /** * Asserts whether or not two JSON objects are equal. */ class JsonMatches extends Constraint { /** * @var string */ protected $value; /** * Creates a new constraint. * * @param string $value */ public function __construct($value) { parent::__construct(); $this->value = $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. * * @return bool */ protected function matches($other) { list($error, $recodedOther) = Json::canonicalize($other); if ($error) { return false; } list($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 ExpectationFailedException */ protected function fail($other, $description, ComparisonFailure $comparisonFailure = null) { if ($comparisonFailure === null) { list($error) = Json::canonicalize($other); if ($error) { parent::fail($other, $description); return; } list($error) = Json::canonicalize($this->value); if ($error) { parent::fail($other, $description); return; } $comparisonFailure = new ComparisonFailure( \json_decode($this->value), \json_decode($other), Json::prettify($this->value), Json::prettify($other), false, 'Failed asserting that two json values are equal.' ); } parent::fail($other, $description, $comparisonFailure); } /** * Returns a string representation of the object. * * @return string */ public function toString() { return \sprintf( 'matches JSON string "%s"', $this->value ); } } phpunit-6.5.5/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php000066400000000000000000000036151321540746700270650ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Provides human readable messages for each JSON error. */ class JsonMatchesErrorMessageProvider { /** * Translates JSON error to a human readable string. * * @param string $error * @param string $prefix * * @return string */ public static function determineJsonError($error, $prefix = '') { switch ($error) { case JSON_ERROR_NONE: return; 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. * * @param string $type * * @return string */ public static function translateTypeToPrefix($type) { 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; } } phpunit-6.5.5/src/Framework/Constraint/LessThan.php000066400000000000000000000022131321540746700223270ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the value it is evaluated for is less than * a given value. */ class LessThan extends Constraint { /** * @var int|float */ protected $value; /** * @param int|float $value */ public function __construct($value) { parent::__construct(); $this->value = $value; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return $this->value > $other; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'is less than ' . $this->exporter->export($this->value); } } phpunit-6.5.5/src/Framework/Constraint/LogicalAnd.php000066400000000000000000000061561321540746700226150ustar00rootroot00000000000000 * * 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; /** * Logical AND. */ class LogicalAnd extends Constraint { /** * @var Constraint[] */ protected $constraints = []; /** * @var Constraint */ protected $lastConstraint; public static function fromConstraints(Constraint ...$constraints): self { $constraint = new self; $constraint->constraints = \array_values($constraints); return $constraint; } /** * @param Constraint[] $constraints * * @throws \PHPUnit\Framework\Exception */ public function setConstraints(array $constraints) { $this->constraints = []; foreach ($constraints as $constraint) { if (!($constraint instanceof Constraint)) { throw new \PHPUnit\Framework\Exception( 'All parameters to ' . __CLASS__ . ' must be a constraint object.' ); } $this->constraints[] = $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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $success = true; $constraint = null; foreach ($this->constraints as $constraint) { if (!$constraint->evaluate($other, $description, true)) { $success = false; break; } } if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { $text = ''; foreach ($this->constraints as $key => $constraint) { if ($key > 0) { $text .= ' and '; } $text .= $constraint->toString(); } return $text; } /** * Counts the number of constraint elements. * * @return int */ public function count() { $count = 0; foreach ($this->constraints as $constraint) { $count += \count($constraint); } return $count; } } phpunit-6.5.5/src/Framework/Constraint/LogicalNot.php000066400000000000000000000106571321540746700226540ustar00rootroot00000000000000 * * 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; /** * Logical NOT. */ class LogicalNot extends Constraint { /** * @var Constraint */ protected $constraint; /** * @param Constraint $constraint */ public function __construct($constraint) { parent::__construct(); if (!($constraint instanceof Constraint)) { $constraint = new IsEqual($constraint); } $this->constraint = $constraint; } /** * @param string $string * * @return string */ public static function negate($string) { $positives = [ 'contains ', 'exists', 'has ', 'is ', 'are ', 'matches ', 'starts with ', 'ends with ', 'reference ', 'not not ' ]; $negatives = [ 'does not contain ', 'does not exist', 'does not have ', 'is not ', 'are not ', 'does not match ', 'starts not with ', 'ends not with ', 'don\'t reference ', 'not ' ]; \preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches); if (\count($matches) > 0) { $nonInput = $matches[2]; $negatedString = \str_replace( $nonInput, \str_replace( $positives, $negatives, $nonInput ), $string ); } else { $negatedString = \str_replace( $positives, $negatives, $string ); } return $negatedString; } /** * 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 $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $success = !$this->constraint->evaluate($other, $description, true); if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } } /** * 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. * * @return string */ protected function failureDescription($other) { switch (\get_class($this->constraint)) { case LogicalAnd::class: case self::class: case LogicalOr::class: return 'not( ' . $this->constraint->failureDescription($other) . ' )'; default: return self::negate( $this->constraint->failureDescription($other) ); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { switch (\get_class($this->constraint)) { case LogicalAnd::class: case self::class: case LogicalOr::class: return 'not( ' . $this->constraint->toString() . ' )'; default: return self::negate( $this->constraint->toString() ); } } /** * Counts the number of constraint elements. * * @return int */ public function count() { return \count($this->constraint); } } phpunit-6.5.5/src/Framework/Constraint/LogicalOr.php000066400000000000000000000056301321540746700224670ustar00rootroot00000000000000 * * 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; /** * Logical OR. */ class LogicalOr extends Constraint { /** * @var Constraint[] */ protected $constraints = []; public static function fromConstraints(Constraint ...$constraints): self { $constraint = new self; $constraint->constraints = \array_values($constraints); return $constraint; } /** * @param Constraint[] $constraints */ public function setConstraints(array $constraints) { $this->constraints = []; foreach ($constraints as $constraint) { if (!($constraint instanceof Constraint)) { $constraint = new IsEqual( $constraint ); } $this->constraints[] = $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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $success = false; $constraint = null; foreach ($this->constraints as $constraint) { if ($constraint->evaluate($other, $description, true)) { $success = true; break; } } if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { $text = ''; foreach ($this->constraints as $key => $constraint) { if ($key > 0) { $text .= ' or '; } $text .= $constraint->toString(); } return $text; } /** * Counts the number of constraint elements. * * @return int */ public function count() { $count = 0; foreach ($this->constraints as $constraint) { $count += \count($constraint); } return $count; } } phpunit-6.5.5/src/Framework/Constraint/LogicalXor.php000066400000000000000000000060131321540746700226530ustar00rootroot00000000000000 * * 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; /** * Logical XOR. */ class LogicalXor extends Constraint { /** * @var Constraint[] */ protected $constraints = []; public static function fromConstraints(Constraint ...$constraints): self { $constraint = new self; $constraint->constraints = \array_values($constraints); return $constraint; } /** * @param Constraint[] $constraints */ public function setConstraints(array $constraints) { $this->constraints = []; foreach ($constraints as $constraint) { if (!($constraint instanceof Constraint)) { $constraint = new IsEqual( $constraint ); } $this->constraints[] = $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. * * @param mixed $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $success = true; $lastResult = null; $constraint = null; foreach ($this->constraints as $constraint) { $result = $constraint->evaluate($other, $description, true); if ($result === $lastResult) { $success = false; break; } $lastResult = $result; } if ($returnResult) { return $success; } if (!$success) { $this->fail($other, $description); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { $text = ''; foreach ($this->constraints as $key => $constraint) { if ($key > 0) { $text .= ' xor '; } $text .= $constraint->toString(); } return $text; } /** * Counts the number of constraint elements. * * @return int */ public function count() { $count = 0; foreach ($this->constraints as $constraint) { $count += \count($constraint); } return $count; } } phpunit-6.5.5/src/Framework/Constraint/ObjectHasAttribute.php000066400000000000000000000015611321540746700243410ustar00rootroot00000000000000 * * 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; /** * Constraint that asserts that the object it is evaluated for has a given * attribute. * * The attribute name is passed in the constructor. */ 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. * * @return bool */ protected function matches($other) { $object = new ReflectionObject($other); return $object->hasProperty($this->attributeName); } } phpunit-6.5.5/src/Framework/Constraint/RegularExpression.php000066400000000000000000000026171321540746700242770ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the string it is evaluated for matches * a regular expression. * * Checks a given value using the Perl Compatible Regular Expression extension * in PHP. The pattern is matched by executing preg_match(). * * The pattern string passed in the constructor. */ class RegularExpression extends Constraint { /** * @var string */ protected $pattern; /** * @param string $pattern */ public function __construct($pattern) { parent::__construct(); $this->pattern = $pattern; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \preg_match($this->pattern, $other) > 0; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return \sprintf( 'matches PCRE pattern "%s"', $this->pattern ); } } phpunit-6.5.5/src/Framework/Constraint/SameSize.php000066400000000000000000000010451321540746700223300ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; class SameSize extends Count { /** * @var int */ protected $expectedCount; /** * @param \Countable|\Traversable|array $expected */ public function __construct($expected) { parent::__construct($this->getCountOf($expected)); } } phpunit-6.5.5/src/Framework/Constraint/StringContains.php000066400000000000000000000034761321540746700235670ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the string it is evaluated for contains * a given string. * * Uses mb_strpos() to find the position of the string in the input, if not * found the evaluation fails. * * The sub-string is passed in the constructor. */ class StringContains extends Constraint { /** * @var string */ protected $string; /** * @var bool */ protected $ignoreCase; /** * @param string $string * @param bool $ignoreCase */ public function __construct($string, $ignoreCase = false) { parent::__construct(); $this->string = $string; $this->ignoreCase = $ignoreCase; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { if ('' === $this->string) { return true; } if ($this->ignoreCase) { return \mb_stripos($other, $this->string) !== false; } return \mb_strpos($other, $this->string) !== false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { if ($this->ignoreCase) { $string = \mb_strtolower($this->string); } else { $string = $this->string; } return \sprintf( 'contains "%s"', $string ); } } phpunit-6.5.5/src/Framework/Constraint/StringEndsWith.php000066400000000000000000000022411321540746700235230ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the string it is evaluated for ends with a given * suffix. */ class StringEndsWith extends Constraint { /** * @var string */ protected $suffix; /** * @param string $suffix */ public function __construct($suffix) { parent::__construct(); $this->suffix = $suffix; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \substr($other, 0 - \strlen($this->suffix)) == $this->suffix; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'ends with "' . $this->suffix . '"'; } } phpunit-6.5.5/src/Framework/Constraint/StringMatchesFormatDescription.php000066400000000000000000000045161321540746700267460ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use SebastianBergmann\Diff\Differ; /** * ... */ class StringMatchesFormatDescription extends RegularExpression { /** * @var string */ protected $string; /** * @param string $string */ public function __construct($string) { parent::__construct($string); $this->pattern = $this->createPatternFromFormat( \preg_replace('/\r\n/', "\n", $string) ); $this->string = $string; } protected function failureDescription($other) { return 'string matches format description'; } protected function additionalFailureDescription($other) { $from = \preg_split('(\r\n|\r|\n)', $this->string); $to = \preg_split('(\r\n|\r|\n)', $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); $differ = new Differ("--- Expected\n+++ Actual\n"); return $differ->diff($this->string, $other); } protected function createPatternFromFormat($string) { $string = \str_replace( [ '%e', '%s', '%S', '%a', '%A', '%w', '%i', '%d', '%x', '%f', '%c' ], [ '\\' . DIRECTORY_SEPARATOR, '[^\r\n]+', '[^\r\n]*', '.+', '.*', '\s*', '[+-]?\d+', '\d+', '[0-9a-fA-F]+', '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', '.' ], \preg_quote($string, '/') ); return '/^' . $string . '$/s'; } } phpunit-6.5.5/src/Framework/Constraint/StringStartsWith.php000066400000000000000000000022171321540746700241150ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; /** * Constraint that asserts that the string it is evaluated for begins with a * given prefix. */ class StringStartsWith extends Constraint { /** * @var string */ protected $prefix; /** * @param string $prefix */ public function __construct($prefix) { parent::__construct(); $this->prefix = $prefix; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { return \strpos($other, $this->prefix) === 0; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'starts with "' . $this->prefix . '"'; } } phpunit-6.5.5/src/Framework/Constraint/TraversableContains.php000066400000000000000000000066301321540746700245660ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Constraint; use PHPUnit\Util\InvalidArgumentHelper; use SplObjectStorage; /** * Constraint that asserts that the Traversable it is applied to contains * a given value. */ class TraversableContains extends Constraint { /** * @var bool */ protected $checkForObjectIdentity; /** * @var bool */ protected $checkForNonObjectIdentity; /** * @var mixed */ protected $value; /** * @param mixed $value * @param bool $checkForObjectIdentity * @param bool $checkForNonObjectIdentity * * @throws \PHPUnit\Framework\Exception */ public function __construct($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) { parent::__construct(); if (!\is_bool($checkForObjectIdentity)) { throw InvalidArgumentHelper::factory(2, 'boolean'); } if (!\is_bool($checkForNonObjectIdentity)) { throw InvalidArgumentHelper::factory(3, 'boolean'); } $this->checkForObjectIdentity = $checkForObjectIdentity; $this->checkForNonObjectIdentity = $checkForNonObjectIdentity; $this->value = $value; } /** * Evaluates the constraint for parameter $other. Returns true if the * constraint is met, false otherwise. * * @param mixed $other Value or object to evaluate. * * @return bool */ protected function matches($other) { if ($other instanceof SplObjectStorage) { return $other->contains($this->value); } if (\is_object($this->value)) { foreach ($other as $element) { if ($this->checkForObjectIdentity && $element === $this->value) { return true; } if (!$this->checkForObjectIdentity && $element == $this->value) { return true; } } } else { foreach ($other as $element) { if ($this->checkForNonObjectIdentity && $element === $this->value) { return true; } if (!$this->checkForNonObjectIdentity && $element == $this->value) { return true; } } } return false; } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { if (\is_string($this->value) && \strpos($this->value, "\n") !== false) { return 'contains "' . $this->value . '"'; } 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. * * @return string */ protected function failureDescription($other) { return \sprintf( '%s %s', \is_array($other) ? 'an array' : 'a traversable', $this->toString() ); } } phpunit-6.5.5/src/Framework/Constraint/TraversableContainsOnly.php000066400000000000000000000045131321540746700254260ustar00rootroot00000000000000 * * 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; /** * Constraint that asserts that the Traversable it is applied to contains * only values of a given type. */ class TraversableContainsOnly extends Constraint { /** * @var Constraint */ protected $constraint; /** * @var string */ protected $type; /** * @param string $type * @param bool $isNativeType */ public function __construct($type, $isNativeType = true) { parent::__construct(); 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 $other Value or object to evaluate. * @param string $description Additional information about the test * @param bool $returnResult Whether to return a result or throw an exception * * @return mixed * * @throws ExpectationFailedException */ public function evaluate($other, $description = '', $returnResult = false) { $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); } } /** * Returns a string representation of the constraint. * * @return string */ public function toString() { return 'contains only values of type "' . $this->type . '"'; } } phpunit-6.5.5/src/Framework/CoveredCodeNotExecutedException.php000066400000000000000000000005041321540746700246740ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class CoveredCodeNotExecutedException extends RiskyTestError { } phpunit-6.5.5/src/Framework/DataProviderTestSuite.php000066400000000000000000000011101321540746700227130ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class DataProviderTestSuite extends TestSuite { /** * Sets the dependencies of a TestCase. * * @param string[] $dependencies */ public function setDependencies(array $dependencies) { foreach ($this->tests as $test) { $test->setDependencies($dependencies); } } } phpunit-6.5.5/src/Framework/Error/000077500000000000000000000000001321540746700170445ustar00rootroot00000000000000phpunit-6.5.5/src/Framework/Error/Deprecated.php000066400000000000000000000005161321540746700216170ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Error; class Deprecated extends Error { public static $enabled = true; } phpunit-6.5.5/src/Framework/Error/Error.php000066400000000000000000000014311321540746700206450ustar00rootroot00000000000000 * * 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; /** * Wrapper for PHP errors. */ class Error extends Exception { /** * Constructor. * * @param string $message * @param int $code * @param string $file * @param int $line * @param \Exception $previous */ public function __construct($message, $code, $file, $line, \Exception $previous = null) { parent::__construct($message, $code, $previous); $this->file = $file; $this->line = $line; } } phpunit-6.5.5/src/Framework/Error/Notice.php000066400000000000000000000005121321540746700207740ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Error; class Notice extends Error { public static $enabled = true; } phpunit-6.5.5/src/Framework/Error/Warning.php000066400000000000000000000005131321540746700211610ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework\Error; class Warning extends Error { public static $enabled = true; } phpunit-6.5.5/src/Framework/Exception.php000066400000000000000000000043731321540746700204310ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use PHPUnit\Util\Filter; /** * 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 */ class Exception extends \RuntimeException implements \PHPUnit\Exception { /** * @var array */ protected $serializableTrace; public function __construct($message = '', $code = 0, \Exception $previous = null) { parent::__construct($message, $code, $previous); $this->serializableTrace = $this->getTrace(); foreach ($this->serializableTrace as $i => $call) { unset($this->serializableTrace[$i]['args']); } } /** * Returns the serializable trace (without 'args'). * * @return array */ public function getSerializableTrace() { return $this->serializableTrace; } /** * @return string */ public function __toString() { $string = TestFailure::exceptionToString($this); if ($trace = Filter::getFilteredStacktrace($this)) { $string .= "\n" . $trace; } return $string; } public function __sleep() { return \array_keys(\get_object_vars($this)); } } phpunit-6.5.5/src/Framework/ExceptionWrapper.php000066400000000000000000000041101321540746700217570ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; 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. */ class ExceptionWrapper extends Exception { /** * @var string */ protected $className; /** * @var ExceptionWrapper|null */ protected $previous; /** * @param Throwable $t */ public function __construct(Throwable $t) { // PDOException::getCode() is a string. // @see http://php.net/manual/en/class.pdoexception.php#95812 parent::__construct($t->getMessage(), (int) $t->getCode()); $this->className = \get_class($t); $this->file = $t->getFile(); $this->line = $t->getLine(); $this->serializableTrace = $t->getTrace(); foreach ($this->serializableTrace as $i => $call) { unset($this->serializableTrace[$i]['args']); } if ($t->getPrevious()) { $this->previous = new self($t->getPrevious()); } } /** * @return string */ public function getClassName() { return $this->className; } /** * @return ExceptionWrapper */ public function getPreviousWrapped() { return $this->previous; } /** * @return string */ public function __toString() { $string = TestFailure::exceptionToString($this); if ($trace = Filter::getFilteredStacktrace($this)) { $string .= "\n" . $trace; } if ($this->previous) { $string .= "\nCaused by\n" . $this->previous; } return $string; } } phpunit-6.5.5/src/Framework/ExpectationFailedException.php000066400000000000000000000022741321540746700237400ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; 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. */ class ExpectationFailedException extends AssertionFailedError { protected $comparisonFailure; /** * @param string $message * @param ComparisonFailure|null $comparisonFailure * @param \Exception|null $previous */ public function __construct($message, ComparisonFailure $comparisonFailure = null, \Exception $previous = null) { $this->comparisonFailure = $comparisonFailure; parent::__construct($message, 0, $previous); } /** * @return null|ComparisonFailure */ public function getComparisonFailure() { return $this->comparisonFailure; } } phpunit-6.5.5/src/Framework/IncompleteTest.php000066400000000000000000000006661321540746700214330ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * A marker interface for marking any exception/error as result of an unit * test as incomplete implementation or currently not implemented. */ interface IncompleteTest { } phpunit-6.5.5/src/Framework/IncompleteTestCase.php000066400000000000000000000027531321540746700222260ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * An incomplete test case */ class IncompleteTestCase extends TestCase { /** * @var string */ protected $message = ''; /** * @var bool */ protected $backupGlobals = false; /** * @var bool */ protected $backupStaticAttributes = false; /** * @var bool */ protected $runTestInSeparateProcess = false; /** * @var bool */ protected $useErrorHandler = false; /** * @var bool */ protected $useOutputBuffering = false; /** * @param string $className * @param string $methodName * @param string $message */ public function __construct($className, $methodName, $message = '') { $this->message = $message; parent::__construct($className . '::' . $methodName); } /** * @throws Exception */ protected function runTest() { $this->markTestIncomplete($this->message); } /** * @return string */ public function getMessage() { return $this->message; } /** * Returns a string representation of the test case. * * @return string */ public function toString() { return $this->getName(); } } phpunit-6.5.5/src/Framework/IncompleteTestError.php000066400000000000000000000005271321540746700224410ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class IncompleteTestError extends AssertionFailedError implements IncompleteTest { } phpunit-6.5.5/src/Framework/InvalidCoversTargetException.php000066400000000000000000000005071321540746700242640ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class InvalidCoversTargetException extends CodeCoverageException { } phpunit-6.5.5/src/Framework/MissingCoversAnnotationException.php000066400000000000000000000005051321540746700251710ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class MissingCoversAnnotationException extends RiskyTestError { } phpunit-6.5.5/src/Framework/OutputError.php000066400000000000000000000004651321540746700210030ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class OutputError extends AssertionFailedError { } phpunit-6.5.5/src/Framework/RiskyTest.php000066400000000000000000000004331321540746700204250ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; interface RiskyTest { } phpunit-6.5.5/src/Framework/RiskyTestError.php000066400000000000000000000005151321540746700214400ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class RiskyTestError extends AssertionFailedError implements RiskyTest { } phpunit-6.5.5/src/Framework/SelfDescribing.php000066400000000000000000000007551321540746700213560ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Interface for classes that can return a description of itself. */ interface SelfDescribing { /** * Returns a string representation of the object. * * @return string */ public function toString(); } phpunit-6.5.5/src/Framework/SkippedTest.php000066400000000000000000000004351321540746700207250ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; interface SkippedTest { } phpunit-6.5.5/src/Framework/SkippedTestCase.php000066400000000000000000000026401321540746700215210ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * A skipped test case */ class SkippedTestCase extends TestCase { /** * @var string */ protected $message = ''; /** * @var bool */ protected $backupGlobals = false; /** * @var bool */ protected $backupStaticAttributes = false; /** * @var bool */ protected $runTestInSeparateProcess = false; /** * @var bool */ protected $useErrorHandler = false; /** * @var bool */ protected $useOutputBuffering = false; /** * @param string $message */ public function __construct($className, $methodName, $message = '') { $this->message = $message; parent::__construct($className . '::' . $methodName); } /** * @throws Exception */ protected function runTest() { $this->markTestSkipped($this->message); } /** * @return string */ public function getMessage() { return $this->message; } /** * Returns a string representation of the test case. * * @return string */ public function toString() { return $this->getName(); } } phpunit-6.5.5/src/Framework/SkippedTestError.php000066400000000000000000000005221321540746700217340ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class SkippedTestError extends AssertionFailedError implements SkippedTest { } phpunit-6.5.5/src/Framework/SkippedTestSuiteError.php000066400000000000000000000005271321540746700227530ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; class SkippedTestSuiteError extends AssertionFailedError implements SkippedTest { } phpunit-6.5.5/src/Framework/SyntheticError.php000066400000000000000000000027221321540746700214530ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Creates a synthetic failed assertion. */ 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 = []; /** * Constructor. * * @param string $message * @param int $code * @param string $file * @param int $line * @param array $trace */ public function __construct($message, $code, $file, $line, $trace) { parent::__construct($message, $code); $this->syntheticFile = $file; $this->syntheticLine = $line; $this->syntheticTrace = $trace; } /** * @return string */ public function getSyntheticFile() { return $this->syntheticFile; } /** * @return int */ public function getSyntheticLine() { return $this->syntheticLine; } /** * @return array */ public function getSyntheticTrace() { return $this->syntheticTrace; } } phpunit-6.5.5/src/Framework/Test.php000066400000000000000000000011001321540746700173730ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Countable; /** * A Test can be run and collect its results. */ interface Test extends Countable { /** * Runs a test and collects its result in a TestResult instance. * * @param TestResult $result * * @return TestResult */ public function run(TestResult $result = null); } phpunit-6.5.5/src/Framework/TestCase.php000066400000000000000000002075101321540746700202040ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use DeepCopy\DeepCopy; use PHPUnit\Framework\Constraint\Exception as ExceptionConstraint; use PHPUnit\Framework\Constraint\ExceptionCode; use PHPUnit\Framework\Constraint\ExceptionMessage; use PHPUnit\Framework\Constraint\ExceptionMessageRegularExpression; use PHPUnit\Framework\MockObject\Generator as MockGenerator; use PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount as AnyInvokedCountMatcher; use PHPUnit\Framework\MockObject\Matcher\InvokedAtIndex as InvokedAtIndexMatcher; use PHPUnit\Framework\MockObject\Matcher\InvokedAtLeastCount as InvokedAtLeastCountMatcher; use PHPUnit\Framework\MockObject\Matcher\InvokedAtLeastOnce as InvokedAtLeastOnceMatcher; use PHPUnit\Framework\MockObject\Matcher\InvokedAtMostCount as InvokedAtMostCountMatcher; use PHPUnit\Framework\MockObject\Matcher\InvokedCount as InvokedCountMatcher; use PHPUnit\Framework\MockObject\MockBuilder; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\Stub\ConsecutiveCalls as ConsecutiveCallsStub; use PHPUnit\Framework\MockObject\Stub\Exception as ExceptionStub; use PHPUnit\Framework\MockObject\Stub\ReturnArgument as ReturnArgumentStub; use PHPUnit\Framework\MockObject\Stub\ReturnCallback as ReturnCallbackStub; use PHPUnit\Framework\MockObject\Stub\ReturnSelf as ReturnSelfStub; use PHPUnit\Framework\MockObject\Stub\ReturnStub; use PHPUnit\Framework\MockObject\Stub\ReturnValueMap as ReturnValueMapStub; use PHPUnit\Runner\BaseTestRunner; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Util\GlobalState; use PHPUnit\Util\InvalidArgumentHelper; use PHPUnit\Util\PHP\AbstractPhpProcess; use Prophecy; use Prophecy\Exception\Prediction\PredictionException; use Prophecy\Prophet; use ReflectionClass; use ReflectionException; use ReflectionObject; use SebastianBergmann; use SebastianBergmann\Comparator\Comparator; use SebastianBergmann\Comparator\Factory as ComparatorFactory; use SebastianBergmann\Diff\Differ; use SebastianBergmann\Exporter\Exporter; use SebastianBergmann\GlobalState\Blacklist; use SebastianBergmann\GlobalState\Restorer; use SebastianBergmann\GlobalState\Snapshot; use SebastianBergmann\ObjectEnumerator\Enumerator; use Text_Template; use Throwable; /** * A TestCase defines the fixture to run multiple tests. * * To define a TestCase * * 1) Implement a subclass of PHPUnit\Framework\TestCase. * 2) Define instance variables that store the state of the fixture. * 3) Initialize the fixture state by overriding setUp(). * 4) Clean-up after a test by overriding tearDown(). * * Each test runs in its own fixture so there can be no side effects * among test runs. * * Here is an example: * * * value1 = 2; * $this->value2 = 3; * } * } * ?> * * * For each test implement a method which interacts with the fixture. * Verify the expected results with assertions specified by calling * assert with a boolean. * * * assertTrue($this->value1 + $this->value2 == 5); * } * ?> * */ abstract class TestCase extends Assert implements Test, SelfDescribing { /** * Enable or disable the backup and restoration of the $GLOBALS array. * Overwrite this attribute in a child class of TestCase. * Setting this attribute in setUp() has no effect! * * @var bool */ protected $backupGlobals; /** * @var array */ protected $backupGlobalsBlacklist = []; /** * Enable or disable the backup and restoration of static attributes. * Overwrite this attribute in a child class of TestCase. * Setting this attribute in setUp() has no effect! * * @var bool */ protected $backupStaticAttributes; /** * @var array */ protected $backupStaticAttributesBlacklist = []; /** * Whether or not this test is to be run in a separate PHP process. * * @var bool */ protected $runTestInSeparateProcess; /** * Whether or not this class is to be run in a separate PHP process. * * @var bool */ private $runClassInSeparateProcess; /** * Whether or not this test should preserve the global state when * running in a separate PHP process. * * @var bool */ protected $preserveGlobalState = true; /** * Whether or not this test is running in a separate PHP process. * * @var bool */ private $inIsolation = false; /** * @var array */ private $data; /** * @var string */ private $dataName; /** * @var bool */ private $useErrorHandler; /** * The name of the expected Exception. * * @var null|string */ private $expectedException; /** * The message of the expected Exception. * * @var string */ private $expectedExceptionMessage; /** * The regex pattern to validate the expected Exception message. * * @var string */ private $expectedExceptionMessageRegExp; /** * The code of the expected Exception. * * @var null|int|string */ private $expectedExceptionCode; /** * The name of the test case. * * @var string */ private $name; /** * @var string[] */ private $dependencies = []; /** * @var array */ private $dependencyInput = []; /** * @var array */ private $iniSettings = []; /** * @var array */ private $locale = []; /** * @var array */ private $mockObjects = []; /** * @var array */ private $mockObjectGenerator; /** * @var int */ private $status; /** * @var string */ private $statusMessage = ''; /** * @var int */ private $numAssertions = 0; /** * @var TestResult */ private $result; /** * @var mixed */ private $testResult; /** * @var string */ private $output = ''; /** * @var string */ private $outputExpectedRegex; /** * @var string */ private $outputExpectedString; /** * @var mixed */ private $outputCallback = false; /** * @var bool */ private $outputBufferingActive = false; /** * @var int */ private $outputBufferingLevel; /** * @var SebastianBergmann\GlobalState\Snapshot */ private $snapshot; /** * @var Prophecy\Prophet */ private $prophet; /** * @var bool */ private $beStrictAboutChangesToGlobalState = false; /** * @var bool */ private $registerMockObjectsFromTestArgumentsRecursively = false; /** * @var string[] */ private $warnings = []; /** * @var array */ private $groups = []; /** * @var bool */ private $doesNotPerformAssertions = false; /** * @var Comparator[] */ private $customComparators = []; /** * Constructs a test case with the given name. * * @param string $name * @param array $data * @param string $dataName */ public function __construct($name = null, array $data = [], $dataName = '') { if ($name !== null) { $this->setName($name); } $this->data = $data; $this->dataName = $dataName; } /** * Returns a string representation of the test case. * * @return string */ public function toString() { $class = new ReflectionClass($this); $buffer = \sprintf( '%s::%s', $class->name, $this->getName(false) ); return $buffer . $this->getDataSetAsString(); } /** * Counts the number of test cases executed by run(TestResult result). * * @return int */ public function count() { return 1; } public function getGroups() { return $this->groups; } /** * @param array $groups */ public function setGroups(array $groups) { $this->groups = $groups; } /** * Returns the annotations for this test. * * @return array */ public function getAnnotations() { return \PHPUnit\Util\Test::parseTestMethodAnnotations( \get_class($this), $this->name ); } /** * Gets the name of a TestCase. * * @param bool $withDataSet * * @return string */ public function getName($withDataSet = true) { if ($withDataSet) { return $this->name . $this->getDataSetAsString(false); } return $this->name; } /** * Returns the size of the test. * * @return int */ public function getSize() { return \PHPUnit\Util\Test::getSize( \get_class($this), $this->getName(false) ); } /** * @return bool */ public function hasSize() { return $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN; } /** * @return bool */ public function isSmall() { return $this->getSize() === \PHPUnit\Util\Test::SMALL; } /** * @return bool */ public function isMedium() { return $this->getSize() === \PHPUnit\Util\Test::MEDIUM; } /** * @return bool */ public function isLarge() { return $this->getSize() === \PHPUnit\Util\Test::LARGE; } /** * @return string */ public function getActualOutput() { if (!$this->outputBufferingActive) { return $this->output; } return \ob_get_contents(); } /** * @return bool */ public function hasOutput() { if (\strlen($this->output) === 0) { return false; } if ($this->hasExpectationOnOutput()) { return false; } return true; } /** * @return bool */ public function doesNotPerformAssertions() { return $this->doesNotPerformAssertions; } /** * @param string $expectedRegex * * @throws Exception */ public function expectOutputRegex($expectedRegex) { if ($this->outputExpectedString !== null) { throw new Exception; } if (\is_string($expectedRegex) || null === $expectedRegex) { $this->outputExpectedRegex = $expectedRegex; } } /** * @param string $expectedString */ public function expectOutputString($expectedString) { if ($this->outputExpectedRegex !== null) { throw new Exception; } if (\is_string($expectedString) || null === $expectedString) { $this->outputExpectedString = $expectedString; } } /** * @return bool */ public function hasExpectationOnOutput() { return \is_string($this->outputExpectedString) || \is_string($this->outputExpectedRegex); } /** * @return null|string */ public function getExpectedException() { return $this->expectedException; } /** * @return null|int|string */ public function getExpectedExceptionCode() { return $this->expectedExceptionCode; } /** * @return string */ public function getExpectedExceptionMessage() { return $this->expectedExceptionMessage; } /** * @return string */ public function getExpectedExceptionMessageRegExp() { return $this->expectedExceptionMessageRegExp; } /** * @param string $exception */ public function expectException($exception) { if (!\is_string($exception)) { throw InvalidArgumentHelper::factory(1, 'string'); } $this->expectedException = $exception; } /** * @param int|string $code * * @throws Exception */ public function expectExceptionCode($code) { if (!\is_int($code) && !\is_string($code)) { throw InvalidArgumentHelper::factory(1, 'integer or string'); } $this->expectedExceptionCode = $code; } /** * @param string $message * * @throws Exception */ public function expectExceptionMessage($message) { if (!\is_string($message)) { throw InvalidArgumentHelper::factory(1, 'string'); } $this->expectedExceptionMessage = $message; } /** * @param string $messageRegExp * * @throws Exception */ public function expectExceptionMessageRegExp($messageRegExp) { if (!\is_string($messageRegExp)) { throw InvalidArgumentHelper::factory(1, 'string'); } $this->expectedExceptionMessageRegExp = $messageRegExp; } /** * Sets up an expectation for an exception to be raised by the code under test. * Information for expected exception class, expected exception message, and * expected exception code are retrieved from a given Exception object. */ public function expectExceptionObject(\Exception $exception) { $this->expectException(\get_class($exception)); $this->expectExceptionMessage($exception->getMessage()); $this->expectExceptionCode($exception->getCode()); } /** * @param bool $flag */ public function setRegisterMockObjectsFromTestArgumentsRecursively($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->registerMockObjectsFromTestArgumentsRecursively = $flag; } protected function setExpectedExceptionFromAnnotation() { try { $expectedException = \PHPUnit\Util\Test::getExpectedException( \get_class($this), $this->name ); if ($expectedException !== false) { $this->expectException($expectedException['class']); if ($expectedException['code'] !== null) { $this->expectExceptionCode($expectedException['code']); } if ($expectedException['message'] !== '') { $this->expectExceptionMessage($expectedException['message']); } elseif ($expectedException['message_regex'] !== '') { $this->expectExceptionMessageRegExp($expectedException['message_regex']); } } } catch (ReflectionException $e) { } } /** * @param bool $useErrorHandler */ public function setUseErrorHandler($useErrorHandler) { $this->useErrorHandler = $useErrorHandler; } protected function setUseErrorHandlerFromAnnotation() { try { $useErrorHandler = \PHPUnit\Util\Test::getErrorHandlerSettings( \get_class($this), $this->name ); if ($useErrorHandler !== null) { $this->setUseErrorHandler($useErrorHandler); } } catch (ReflectionException $e) { } } protected function checkRequirements() { if (!$this->name || !\method_exists($this, $this->name)) { return; } $missingRequirements = \PHPUnit\Util\Test::getMissingRequirements( \get_class($this), $this->name ); if (!empty($missingRequirements)) { $this->markTestSkipped(\implode(PHP_EOL, $missingRequirements)); } } /** * Returns the status of this test. * * @return int */ public function getStatus() { return $this->status; } public function markAsRisky() { $this->status = BaseTestRunner::STATUS_RISKY; } /** * Returns the status message of this test. * * @return string */ public function getStatusMessage() { return $this->statusMessage; } /** * Returns whether or not this test has failed. * * @return bool */ public function hasFailed() { $status = $this->getStatus(); return $status == BaseTestRunner::STATUS_FAILURE || $status == BaseTestRunner::STATUS_ERROR; } /** * Runs the test case and collects the results in a TestResult object. * If no TestResult object is passed a new one will be created. * * @param TestResult $result * * @return TestResult|null * * @throws Exception */ public function run(TestResult $result = null) { if ($result === null) { $result = $this->createResult(); } if (!$this instanceof WarningTestCase) { $this->setTestResultObject($result); $this->setUseErrorHandlerFromAnnotation(); } if ($this->useErrorHandler !== null) { $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions(); $result->convertErrorsToExceptions($this->useErrorHandler); } if (!$this instanceof WarningTestCase && !$this instanceof SkippedTestCase && !$this->handleDependencies()) { return; } $runEntireClass = $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess; if (($this->runTestInSeparateProcess === true || $this->runClassInSeparateProcess === true) && $this->inIsolation !== true && !$this instanceof PhptTestCase) { $class = new ReflectionClass($this); if ($runEntireClass) { $template = new Text_Template( __DIR__ . '/../Util/PHP/Template/TestCaseClass.tpl' ); } else { $template = new Text_Template( __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl' ); } if ($this->preserveGlobalState) { $constants = GlobalState::getConstantsAsString(); $globals = GlobalState::getGlobalsAsString(); $includedFiles = GlobalState::getIncludedFilesAsString(); $iniSettings = GlobalState::getIniSettingsAsString(); } else { $constants = ''; if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n"; } else { $globals = ''; } $includedFiles = ''; $iniSettings = ''; } $coverage = $result->getCollectCodeCoverageInformation() ? 'true' : 'false'; $isStrictAboutTestsThatDoNotTestAnything = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false'; $isStrictAboutOutputDuringTests = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false'; $enforcesTimeLimit = $result->enforcesTimeLimit() ? 'true' : 'false'; $isStrictAboutTodoAnnotatedTests = $result->isStrictAboutTodoAnnotatedTests() ? 'true' : 'false'; $isStrictAboutResourceUsageDuringSmallTests = $result->isStrictAboutResourceUsageDuringSmallTests() ? 'true' : 'false'; if (\defined('PHPUNIT_COMPOSER_INSTALL')) { $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, true); } else { $composerAutoload = '\'\''; } if (\defined('__PHPUNIT_PHAR__')) { $phar = \var_export(__PHPUNIT_PHAR__, true); } else { $phar = '\'\''; } if ($result->getCodeCoverage()) { $codeCoverageFilter = $result->getCodeCoverage()->filter(); } else { $codeCoverageFilter = null; } $data = \var_export(\serialize($this->data), true); $dataName = \var_export($this->dataName, true); $dependencyInput = \var_export(\serialize($this->dependencyInput), true); $includePath = \var_export(\get_include_path(), true); $codeCoverageFilter = \var_export(\serialize($codeCoverageFilter), true); // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences $data = "'." . $data . ".'"; $dataName = "'.(" . $dataName . ").'"; $dependencyInput = "'." . $dependencyInput . ".'"; $includePath = "'." . $includePath . ".'"; $codeCoverageFilter = "'." . $codeCoverageFilter . ".'"; $configurationFilePath = $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] ?? ''; $var = [ 'composerAutoload' => $composerAutoload, 'phar' => $phar, 'filename' => $class->getFileName(), 'className' => $class->getName(), 'collectCodeCoverageInformation' => $coverage, 'data' => $data, 'dataName' => $dataName, 'dependencyInput' => $dependencyInput, 'constants' => $constants, 'globals' => $globals, 'include_path' => $includePath, 'included_files' => $includedFiles, 'iniSettings' => $iniSettings, 'isStrictAboutTestsThatDoNotTestAnything' => $isStrictAboutTestsThatDoNotTestAnything, 'isStrictAboutOutputDuringTests' => $isStrictAboutOutputDuringTests, 'enforcesTimeLimit' => $enforcesTimeLimit, 'isStrictAboutTodoAnnotatedTests' => $isStrictAboutTodoAnnotatedTests, 'isStrictAboutResourceUsageDuringSmallTests' => $isStrictAboutResourceUsageDuringSmallTests, 'codeCoverageFilter' => $codeCoverageFilter, 'configurationFilePath' => $configurationFilePath ]; if (!$runEntireClass) { $var['methodName'] = $this->name; } $template->setVar( $var ); $this->prepareTemplate($template); $php = AbstractPhpProcess::factory(); $php->runTestJob($template->render(), $this, $result); } else { $result->run($this); } if (isset($oldErrorHandlerSetting)) { $result->convertErrorsToExceptions($oldErrorHandlerSetting); } $this->result = null; return $result; } /** * Runs the bare test sequence. */ public function runBare() { $this->numAssertions = 0; $this->snapshotGlobalState(); $this->startOutputBuffering(); \clearstatcache(); $currentWorkingDirectory = \getcwd(); $hookMethods = \PHPUnit\Util\Test::getHookMethods(\get_class($this)); try { $hasMetRequirements = false; $this->checkRequirements(); $hasMetRequirements = true; if ($this->inIsolation) { foreach ($hookMethods['beforeClass'] as $method) { $this->$method(); } } $this->setExpectedExceptionFromAnnotation(); $this->setDoesNotPerformAssertionsFromAnnotation(); foreach ($hookMethods['before'] as $method) { $this->$method(); } $this->assertPreConditions(); $this->testResult = $this->runTest(); $this->verifyMockObjects(); $this->assertPostConditions(); if (!empty($this->warnings)) { throw new Warning( \implode( "\n", \array_unique($this->warnings) ) ); } $this->status = BaseTestRunner::STATUS_PASSED; } catch (IncompleteTest $e) { $this->status = BaseTestRunner::STATUS_INCOMPLETE; $this->statusMessage = $e->getMessage(); } catch (SkippedTest $e) { $this->status = BaseTestRunner::STATUS_SKIPPED; $this->statusMessage = $e->getMessage(); } catch (Warning $e) { $this->status = BaseTestRunner::STATUS_WARNING; $this->statusMessage = $e->getMessage(); } catch (AssertionFailedError $e) { $this->status = BaseTestRunner::STATUS_FAILURE; $this->statusMessage = $e->getMessage(); } catch (PredictionException $e) { $this->status = BaseTestRunner::STATUS_FAILURE; $this->statusMessage = $e->getMessage(); } catch (Throwable $_e) { $e = $_e; } if (isset($_e)) { $this->status = BaseTestRunner::STATUS_ERROR; $this->statusMessage = $_e->getMessage(); } // Clean up the mock objects. $this->mockObjects = []; $this->prophet = null; // Tear down the fixture. An exception raised in tearDown() will be // caught and passed on when no exception was raised before. try { if ($hasMetRequirements) { foreach ($hookMethods['after'] as $method) { $this->$method(); } if ($this->inIsolation) { foreach ($hookMethods['afterClass'] as $method) { $this->$method(); } } } } catch (Throwable $_e) { if (!isset($e)) { $e = $_e; } } try { $this->stopOutputBuffering(); } catch (RiskyTestError $_e) { if (!isset($e)) { $e = $_e; } } \clearstatcache(); if ($currentWorkingDirectory != \getcwd()) { \chdir($currentWorkingDirectory); } $this->restoreGlobalState(); $this->unregisterCustomComparators(); $this->cleanupIniSettings(); $this->cleanupLocaleSettings(); // Perform assertion on output. if (!isset($e)) { try { if ($this->outputExpectedRegex !== null) { $this->assertRegExp($this->outputExpectedRegex, $this->output); } elseif ($this->outputExpectedString !== null) { $this->assertEquals($this->outputExpectedString, $this->output); } } catch (Throwable $_e) { $e = $_e; } } // Workaround for missing "finally". if (isset($e)) { if ($e instanceof PredictionException) { $e = new AssertionFailedError($e->getMessage()); } $this->onNotSuccessfulTest($e); } } /** * Override to run the test and assert its state. * * @return mixed * * @throws Exception|Exception * @throws Exception */ protected function runTest() { if ($this->name === null) { throw new Exception( 'PHPUnit\Framework\TestCase::$name must not be null.' ); } try { $class = new ReflectionClass($this); $method = $class->getMethod($this->name); } catch (ReflectionException $e) { $this->fail($e->getMessage()); } $testArguments = \array_merge($this->data, $this->dependencyInput); $this->registerMockObjectsFromTestArguments($testArguments); try { $testResult = $method->invokeArgs($this, $testArguments); } catch (Throwable $t) { $exception = $t; } if (isset($exception)) { if ($this->checkExceptionExpectations($exception)) { if ($this->expectedException !== null) { $this->assertThat( $exception, new ExceptionConstraint( $this->expectedException ) ); } if ($this->expectedExceptionMessage !== null) { $this->assertThat( $exception, new ExceptionMessage( $this->expectedExceptionMessage ) ); } if ($this->expectedExceptionMessageRegExp !== null) { $this->assertThat( $exception, new ExceptionMessageRegularExpression( $this->expectedExceptionMessageRegExp ) ); } if ($this->expectedExceptionCode !== null) { $this->assertThat( $exception, new ExceptionCode( $this->expectedExceptionCode ) ); } return; } throw $exception; } if ($this->expectedException !== null) { $this->assertThat( null, new ExceptionConstraint( $this->expectedException ) ); } elseif ($this->expectedExceptionMessage !== null) { $this->numAssertions++; throw new AssertionFailedError( \sprintf( 'Failed asserting that exception with message "%s" is thrown', $this->expectedExceptionMessage ) ); } elseif ($this->expectedExceptionMessageRegExp !== null) { $this->numAssertions++; throw new AssertionFailedError( \sprintf( 'Failed asserting that exception with message matching "%s" is thrown', $this->expectedExceptionMessageRegExp ) ); } elseif ($this->expectedExceptionCode !== null) { $this->numAssertions++; throw new AssertionFailedError( \sprintf( 'Failed asserting that exception with code "%s" is thrown', $this->expectedExceptionCode ) ); } return $testResult; } /** * Verifies the mock object expectations. */ protected function verifyMockObjects() { foreach ($this->mockObjects as $mockObject) { if ($mockObject->__phpunit_hasMatchers()) { $this->numAssertions++; } $mockObject->__phpunit_verify( $this->shouldInvocationMockerBeReset($mockObject) ); } if ($this->prophet !== null) { try { $this->prophet->checkPredictions(); } catch (Throwable $t) { /* Intentionally left empty */ } foreach ($this->prophet->getProphecies() as $objectProphecy) { foreach ($objectProphecy->getMethodProphecies() as $methodProphecies) { foreach ($methodProphecies as $methodProphecy) { $this->numAssertions += \count($methodProphecy->getCheckedPredictions()); } } } if (isset($t)) { throw $t; } } } /** * Sets the name of a TestCase. * * @param string */ public function setName($name) { $this->name = $name; } /** * Sets the dependencies of a TestCase. * * @param string[] $dependencies */ public function setDependencies(array $dependencies) { $this->dependencies = $dependencies; } /** * Returns true if the tests has dependencies * * @return bool */ public function hasDependencies() { return \count($this->dependencies) > 0; } /** * Sets * * @param array $dependencyInput */ public function setDependencyInput(array $dependencyInput) { $this->dependencyInput = $dependencyInput; } /** * @param bool $beStrictAboutChangesToGlobalState */ public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState) { $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; } /** * Calling this method in setUp() has no effect! * * @param bool $backupGlobals */ public function setBackupGlobals($backupGlobals) { if (null === $this->backupGlobals && \is_bool($backupGlobals)) { $this->backupGlobals = $backupGlobals; } } /** * Calling this method in setUp() has no effect! * * @param bool $backupStaticAttributes */ public function setBackupStaticAttributes($backupStaticAttributes) { if (null === $this->backupStaticAttributes && \is_bool($backupStaticAttributes)) { $this->backupStaticAttributes = $backupStaticAttributes; } } /** * @param bool $runTestInSeparateProcess * * @throws Exception */ public function setRunTestInSeparateProcess($runTestInSeparateProcess) { if (\is_bool($runTestInSeparateProcess)) { if ($this->runTestInSeparateProcess === null) { $this->runTestInSeparateProcess = $runTestInSeparateProcess; } } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } /** * @param bool $runClassInSeparateProcess * * @throws Exception */ public function setRunClassInSeparateProcess($runClassInSeparateProcess) { if (\is_bool($runClassInSeparateProcess)) { if ($this->runClassInSeparateProcess === null) { $this->runClassInSeparateProcess = $runClassInSeparateProcess; } } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } /** * @param bool $preserveGlobalState * * @throws Exception */ public function setPreserveGlobalState($preserveGlobalState) { if (\is_bool($preserveGlobalState)) { $this->preserveGlobalState = $preserveGlobalState; } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } /** * @param bool $inIsolation * * @throws Exception */ public function setInIsolation($inIsolation) { if (\is_bool($inIsolation)) { $this->inIsolation = $inIsolation; } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } /** * @return bool */ public function isInIsolation() { return $this->inIsolation; } /** * @return mixed */ public function getResult() { return $this->testResult; } /** * @param mixed $result */ public function setResult($result) { $this->testResult = $result; } /** * @param callable $callback * * @throws Exception */ public function setOutputCallback($callback) { if (!\is_callable($callback)) { throw InvalidArgumentHelper::factory(1, 'callback'); } $this->outputCallback = $callback; } /** * @return TestResult */ public function getTestResultObject() { return $this->result; } /** * @param TestResult $result */ public function setTestResultObject(TestResult $result) { $this->result = $result; } /** * @param MockObject $mockObject */ public function registerMockObject(MockObject $mockObject) { $this->mockObjects[] = $mockObject; } /** * This method is a wrapper for the ini_set() function that automatically * resets the modified php.ini setting to its original value after the * test is run. * * @param string $varName * @param string $newValue * * @throws Exception */ protected function iniSet($varName, $newValue) { if (!\is_string($varName)) { throw InvalidArgumentHelper::factory(1, 'string'); } $currentValue = \ini_set($varName, $newValue); if ($currentValue !== false) { $this->iniSettings[$varName] = $currentValue; } else { throw new Exception( \sprintf( 'INI setting "%s" could not be set to "%s".', $varName, $newValue ) ); } } /** * This method is a wrapper for the setlocale() function that automatically * resets the locale to its original value after the test is run. * * @param int $category * @param string $locale * * @throws Exception */ protected function setLocale() { $args = \func_get_args(); if (\count($args) < 2) { throw new Exception; } list($category, $locale) = $args; $categories = [ LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME ]; if (\defined('LC_MESSAGES')) { $categories[] = LC_MESSAGES; } if (!\in_array($category, $categories)) { throw new Exception; } if (!\is_array($locale) && !\is_string($locale)) { throw new Exception; } $this->locale[$category] = \setlocale($category, 0); $result = \call_user_func_array('setlocale', $args); if ($result === false) { throw new Exception( 'The locale functionality is not implemented on your platform, ' . 'the specified locale does not exist or the category name is ' . 'invalid.' ); } } /** * Returns a builder object to create mock objects using a fluent interface. * * @param string|string[] $className * * @return MockBuilder */ public function getMockBuilder($className) { return new MockBuilder($this, $className); } /** * Returns a test double for the specified class. * * @param string $originalClassName * * @return MockObject * * @throws Exception */ protected function createMock($originalClassName) { return $this->getMockBuilder($originalClassName) ->disableOriginalConstructor() ->disableOriginalClone() ->disableArgumentCloning() ->disallowMockingUnknownTypes() ->getMock(); } /** * Returns a configured test double for the specified class. * * @param string $originalClassName * @param array $configuration * * @return MockObject * * @throws Exception */ protected function createConfiguredMock($originalClassName, array $configuration) { $o = $this->createMock($originalClassName); foreach ($configuration as $method => $return) { $o->method($method)->willReturn($return); } return $o; } /** * Returns a partial test double for the specified class. * * @param string $originalClassName * @param string[] $methods * * @return MockObject * * @throws Exception */ protected function createPartialMock($originalClassName, array $methods) { return $this->getMockBuilder($originalClassName) ->disableOriginalConstructor() ->disableOriginalClone() ->disableArgumentCloning() ->disallowMockingUnknownTypes() ->setMethods(empty($methods) ? null : $methods) ->getMock(); } /** * Returns a test proxy for the specified class. * * @param string $originalClassName * @param array $constructorArguments * * @return MockObject * * @throws Exception */ protected function createTestProxy($originalClassName, array $constructorArguments = []) { return $this->getMockBuilder($originalClassName) ->setConstructorArgs($constructorArguments) ->enableProxyingToOriginalMethods() ->getMock(); } /** * Mocks the specified class and returns the name of the mocked class. * * @param string $originalClassName * @param array $methods * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param bool $cloneArguments * * @return string * * @throws Exception */ protected function getMockClass($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false) { $mock = $this->getMockObjectGenerator()->getMock( $originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments ); return \get_class($mock); } /** * Returns a mock object for the specified abstract class with all abstract * methods of the class mocked. Concrete methods are not mocked by default. * To mock concrete methods, use the 7th parameter ($mockedMethods). * * @param string $originalClassName * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments * * @return MockObject * * @throws Exception */ protected function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false) { $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass( $originalClassName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments ); $this->registerMockObject($mockObject); return $mockObject; } /** * Returns a mock object based on the given WSDL file. * * @param string $wsdlFile * @param string $originalClassName * @param string $mockClassName * @param array $methods * @param bool $callOriginalConstructor * @param array $options An array of options passed to SOAPClient::_construct * * @return MockObject */ protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = [], $callOriginalConstructor = true, array $options = []) { if ($originalClassName === '') { $originalClassName = \pathinfo(\basename(\parse_url($wsdlFile)['path']), PATHINFO_FILENAME); } if (!\class_exists($originalClassName)) { eval( $this->getMockObjectGenerator()->generateClassFromWsdl( $wsdlFile, $originalClassName, $methods, $options ) ); } $mockObject = $this->getMockObjectGenerator()->getMock( $originalClassName, $methods, ['', $options], $mockClassName, $callOriginalConstructor, false, false ); $this->registerMockObject($mockObject); return $mockObject; } /** * Returns a mock object for the specified trait with all abstract methods * of the trait mocked. Concrete methods to mock can be specified with the * `$mockedMethods` parameter. * * @param string $traitName * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments * * @return MockObject * * @throws Exception */ protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false) { $mockObject = $this->getMockObjectGenerator()->getMockForTrait( $traitName, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments ); $this->registerMockObject($mockObject); return $mockObject; } /** * Returns an object for the specified trait. * * @param string $traitName * @param array $arguments * @param string $traitClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * * @return object * * @throws Exception */ protected function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true) { return $this->getMockObjectGenerator()->getObjectForTrait( $traitName, $arguments, $traitClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload ); } /** * @param string|null $classOrInterface * * @return \Prophecy\Prophecy\ObjectProphecy * * @throws \LogicException */ protected function prophesize($classOrInterface = null) { return $this->getProphet()->prophesize($classOrInterface); } /** * Adds a value to the assertion counter. * * @param int $count */ public function addToAssertionCount($count) { $this->numAssertions += $count; } /** * Returns the number of assertions performed by this test. * * @return int */ public function getNumAssertions() { return $this->numAssertions; } /** * Returns a matcher that matches when the method is executed * zero or more times. * * @return AnyInvokedCountMatcher */ public static function any() { return new AnyInvokedCountMatcher; } /** * Returns a matcher that matches when the method is never executed. * * @return InvokedCountMatcher */ public static function never() { return new InvokedCountMatcher(0); } /** * Returns a matcher that matches when the method is executed * at least N times. * * @param int $requiredInvocations * * @return InvokedAtLeastCountMatcher */ public static function atLeast($requiredInvocations) { return new InvokedAtLeastCountMatcher( $requiredInvocations ); } /** * Returns a matcher that matches when the method is executed at least once. * * @return InvokedAtLeastOnceMatcher */ public static function atLeastOnce() { return new InvokedAtLeastOnceMatcher; } /** * Returns a matcher that matches when the method is executed exactly once. * * @return InvokedCountMatcher */ public static function once() { return new InvokedCountMatcher(1); } /** * Returns a matcher that matches when the method is executed * exactly $count times. * * @param int $count * * @return InvokedCountMatcher */ public static function exactly($count) { return new InvokedCountMatcher($count); } /** * Returns a matcher that matches when the method is executed * at most N times. * * @param int $allowedInvocations * * @return InvokedAtMostCountMatcher */ public static function atMost($allowedInvocations) { return new InvokedAtMostCountMatcher($allowedInvocations); } /** * Returns a matcher that matches when the method is executed * at the given index. * * @param int $index * * @return InvokedAtIndexMatcher */ public static function at($index) { return new InvokedAtIndexMatcher($index); } /** * @param mixed $value * * @return ReturnStub */ public static function returnValue($value) { return new ReturnStub($value); } /** * @param array $valueMap * * @return ReturnValueMapStub */ public static function returnValueMap(array $valueMap) { return new ReturnValueMapStub($valueMap); } /** * @param int $argumentIndex * * @return ReturnArgumentStub */ public static function returnArgument($argumentIndex) { return new ReturnArgumentStub($argumentIndex); } /** * @param mixed $callback * * @return ReturnCallbackStub */ public static function returnCallback($callback) { return new ReturnCallbackStub($callback); } /** * Returns the current object. * * This method is useful when mocking a fluent interface. * * @return ReturnSelfStub */ public static function returnSelf() { return new ReturnSelfStub; } /** * @param Throwable $exception * * @return ExceptionStub */ public static function throwException(Throwable $exception) { return new ExceptionStub($exception); } /** * @param mixed $value , ... * * @return ConsecutiveCallsStub */ public static function onConsecutiveCalls() { $args = \func_get_args(); return new ConsecutiveCallsStub($args); } /** * @return bool */ public function usesDataProvider() { return !empty($this->data); } /** * @return string */ public function dataDescription() { return \is_string($this->dataName) ? $this->dataName : ''; } /** * @return int|string */ public function dataName() { return $this->dataName; } public function registerComparator(Comparator $comparator) { ComparatorFactory::getInstance()->register($comparator); $this->customComparators[] = $comparator; } /** * Gets the data set description of a TestCase. * * @param bool $includeData * * @return string */ public function getDataSetAsString($includeData = true) { $buffer = ''; if (!empty($this->data)) { if (\is_int($this->dataName)) { $buffer .= \sprintf(' with data set #%d', $this->dataName); } else { $buffer .= \sprintf(' with data set "%s"', $this->dataName); } $exporter = new Exporter; if ($includeData) { $buffer .= \sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data)); } } return $buffer; } /** * Gets the data set of a TestCase. * * @return array */ protected function getProvidedData() { return $this->data; } /** * Creates a default TestResult object. * * @return TestResult */ protected function createResult() { return new TestResult; } protected function handleDependencies() { if (!empty($this->dependencies) && !$this->inIsolation) { $className = \get_class($this); $passed = $this->result->passed(); $passedKeys = \array_keys($passed); $numKeys = \count($passedKeys); for ($i = 0; $i < $numKeys; $i++) { $pos = \strpos($passedKeys[$i], ' with data set'); if ($pos !== false) { $passedKeys[$i] = \substr($passedKeys[$i], 0, $pos); } } $passedKeys = \array_flip(\array_unique($passedKeys)); foreach ($this->dependencies as $dependency) { $deepClone = false; $shallowClone = false; if (\strpos($dependency, 'clone ') === 0) { $deepClone = true; $dependency = \substr($dependency, \strlen('clone ')); } elseif (\strpos($dependency, '!clone ') === 0) { $deepClone = false; $dependency = \substr($dependency, \strlen('!clone ')); } if (\strpos($dependency, 'shallowClone ') === 0) { $shallowClone = true; $dependency = \substr($dependency, \strlen('shallowClone ')); } elseif (\strpos($dependency, '!shallowClone ') === 0) { $shallowClone = false; $dependency = \substr($dependency, \strlen('!shallowClone ')); } if (\strpos($dependency, '::') === false) { $dependency = $className . '::' . $dependency; } if (!isset($passedKeys[$dependency])) { $this->result->startTest($this); $this->result->addError( $this, new SkippedTestError( \sprintf( 'This test depends on "%s" to pass.', $dependency ) ), 0 ); $this->result->endTest($this, 0); return false; } if (isset($passed[$dependency])) { if ($passed[$dependency]['size'] != \PHPUnit\Util\Test::UNKNOWN && $this->getSize() != \PHPUnit\Util\Test::UNKNOWN && $passed[$dependency]['size'] > $this->getSize()) { $this->result->addError( $this, new SkippedTestError( 'This test depends on a test that is larger than itself.' ), 0 ); return false; } if ($deepClone) { $deepCopy = new DeepCopy; $deepCopy->skipUncloneable(false); $this->dependencyInput[$dependency] = $deepCopy->copy($passed[$dependency]['result']); } elseif ($shallowClone) { $this->dependencyInput[$dependency] = clone $passed[$dependency]['result']; } else { $this->dependencyInput[$dependency] = $passed[$dependency]['result']; } } else { $this->dependencyInput[$dependency] = null; } } } return true; } /** * This method is called before the first test of this test class is run. */ public static function setUpBeforeClass() { } /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. */ protected function setUp() { } /** * Performs assertions shared by all tests of a test case. * * This method is called before the execution of a test starts * and after setUp() is called. */ protected function assertPreConditions() { } /** * Performs assertions shared by all tests of a test case. * * This method is called after the execution of a test ends * and before tearDown() is called. */ protected function assertPostConditions() { } /** * Tears down the fixture, for example, close a network connection. * This method is called after a test is executed. */ protected function tearDown() { } /** * This method is called after the last test of this test class is run. */ public static function tearDownAfterClass() { } /** * This method is called when a test method did not execute successfully. * * @param Throwable $t * * @throws Throwable */ protected function onNotSuccessfulTest(Throwable $t) { throw $t; } /** * Performs custom preparations on the process isolation template. * * @param Text_Template $template */ protected function prepareTemplate(Text_Template $template) { } /** * Get the mock object generator, creating it if it doesn't exist. * * @return MockGenerator */ private function getMockObjectGenerator() { if (null === $this->mockObjectGenerator) { $this->mockObjectGenerator = new MockGenerator; } return $this->mockObjectGenerator; } private function startOutputBuffering() { \ob_start(); $this->outputBufferingActive = true; $this->outputBufferingLevel = \ob_get_level(); } private function stopOutputBuffering() { if (\ob_get_level() != $this->outputBufferingLevel) { while (\ob_get_level() >= $this->outputBufferingLevel) { \ob_end_clean(); } throw new RiskyTestError( 'Test code or tested code did not (only) close its own output buffers' ); } $output = \ob_get_contents(); if ($this->outputCallback === false) { $this->output = $output; } else { $this->output = \call_user_func_array( $this->outputCallback, [$output] ); } \ob_end_clean(); $this->outputBufferingActive = false; $this->outputBufferingLevel = \ob_get_level(); } private function snapshotGlobalState() { if ($this->runTestInSeparateProcess || $this->inIsolation || (!$this->backupGlobals === true && !$this->backupStaticAttributes)) { return; } $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true); } private function restoreGlobalState() { if (!$this->snapshot instanceof Snapshot) { return; } if ($this->beStrictAboutChangesToGlobalState) { try { $this->compareGlobalStateSnapshots( $this->snapshot, $this->createGlobalStateSnapshot($this->backupGlobals === true) ); } catch (RiskyTestError $rte) { // Intentionally left empty } } $restorer = new Restorer; if ($this->backupGlobals === true) { $restorer->restoreGlobalVariables($this->snapshot); } if ($this->backupStaticAttributes) { $restorer->restoreStaticAttributes($this->snapshot); } $this->snapshot = null; if (isset($rte)) { throw $rte; } } /** * @param bool $backupGlobals * * @return Snapshot */ private function createGlobalStateSnapshot($backupGlobals) { $blacklist = new Blacklist; foreach ($this->backupGlobalsBlacklist as $globalVariable) { $blacklist->addGlobalVariable($globalVariable); } if (!\defined('PHPUNIT_TESTSUITE')) { $blacklist->addClassNamePrefix('PHPUnit'); $blacklist->addClassNamePrefix('File_Iterator'); $blacklist->addClassNamePrefix('SebastianBergmann\CodeCoverage'); $blacklist->addClassNamePrefix('PHP_Invoker'); $blacklist->addClassNamePrefix('PHP_Timer'); $blacklist->addClassNamePrefix('PHP_Token'); $blacklist->addClassNamePrefix('Symfony'); $blacklist->addClassNamePrefix('Text_Template'); $blacklist->addClassNamePrefix('Doctrine\Instantiator'); $blacklist->addClassNamePrefix('Prophecy'); foreach ($this->backupStaticAttributesBlacklist as $class => $attributes) { foreach ($attributes as $attribute) { $blacklist->addStaticAttribute($class, $attribute); } } } return new Snapshot( $blacklist, $backupGlobals, (bool) $this->backupStaticAttributes, false, false, false, false, false, false, false ); } /** * @param Snapshot $before * @param Snapshot $after * * @throws RiskyTestError */ private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after) { $backupGlobals = $this->backupGlobals === null || $this->backupGlobals === true; if ($backupGlobals) { $this->compareGlobalStateSnapshotPart( $before->globalVariables(), $after->globalVariables(), "--- Global variables before the test\n+++ Global variables after the test\n" ); $this->compareGlobalStateSnapshotPart( $before->superGlobalVariables(), $after->superGlobalVariables(), "--- Super-global variables before the test\n+++ Super-global variables after the test\n" ); } if ($this->backupStaticAttributes) { $this->compareGlobalStateSnapshotPart( $before->staticAttributes(), $after->staticAttributes(), "--- Static attributes before the test\n+++ Static attributes after the test\n" ); } } /** * @param array $before * @param array $after * @param string $header * * @throws RiskyTestError */ private function compareGlobalStateSnapshotPart(array $before, array $after, $header) { if ($before != $after) { $differ = new Differ($header); $exporter = new Exporter; $diff = $differ->diff( $exporter->export($before), $exporter->export($after) ); throw new RiskyTestError( $diff ); } } /** * @return Prophecy\Prophet */ private function getProphet() { if ($this->prophet === null) { $this->prophet = new Prophet; } return $this->prophet; } /** * @param MockObject $mock * * @return bool */ private function shouldInvocationMockerBeReset(MockObject $mock) { $enumerator = new Enumerator; foreach ($enumerator->enumerate($this->dependencyInput) as $object) { if ($mock === $object) { return false; } } if (!\is_array($this->testResult) && !\is_object($this->testResult)) { return true; } foreach ($enumerator->enumerate($this->testResult) as $object) { if ($mock === $object) { return false; } } return true; } /** * @param array $testArguments * @param array $visited */ private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []) { if ($this->registerMockObjectsFromTestArgumentsRecursively) { $enumerator = new Enumerator; foreach ($enumerator->enumerate($testArguments) as $object) { if ($object instanceof MockObject) { $this->registerMockObject($object); } } } else { foreach ($testArguments as $testArgument) { if ($testArgument instanceof MockObject) { if ($this->isCloneable($testArgument)) { $testArgument = clone $testArgument; } $this->registerMockObject($testArgument); } elseif (\is_array($testArgument) && !\in_array($testArgument, $visited, true)) { $visited[] = $testArgument; $this->registerMockObjectsFromTestArguments( $testArgument, $visited ); } } } } private function setDoesNotPerformAssertionsFromAnnotation() { $annotations = $this->getAnnotations(); if (isset($annotations['method']['doesNotPerformAssertions'])) { $this->doesNotPerformAssertions = true; } } /** * @param MockObject $testArgument * * @return bool */ private function isCloneable(MockObject $testArgument) { $reflector = new ReflectionObject($testArgument); if (!$reflector->isCloneable()) { return false; } if ($reflector->hasMethod('__clone') && $reflector->getMethod('__clone')->isPublic()) { return true; } return false; } private function unregisterCustomComparators() { $factory = ComparatorFactory::getInstance(); foreach ($this->customComparators as $comparator) { $factory->unregister($comparator); } $this->customComparators = []; } private function cleanupIniSettings() { foreach ($this->iniSettings as $varName => $oldValue) { \ini_set($varName, $oldValue); } $this->iniSettings = []; } private function cleanupLocaleSettings() { foreach ($this->locale as $category => $locale) { \setlocale($category, $locale); } $this->locale = []; } private function checkExceptionExpectations(Throwable $throwable): bool { $result = false; if ($this->expectedException !== null || $this->expectedExceptionCode !== null || $this->expectedExceptionMessage !== null || $this->expectedExceptionMessageRegExp !== null) { $result = true; } if ($throwable instanceof Exception) { $result = false; } if (\is_string($this->expectedException)) { $reflector = new ReflectionClass($this->expectedException); if ($this->expectedException === 'PHPUnit\Framework\Exception' || $this->expectedException === '\PHPUnit\Framework\Exception' || $reflector->isSubclassOf('PHPUnit\Framework\Exception')) { $result = true; } } return $result; } } phpunit-6.5.5/src/Framework/TestFailure.php000066400000000000000000000071211321540746700207140ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use PHPUnit\Framework\Error\Error; use Throwable; /** * A TestFailure collects a failed test together with the caught exception. */ class TestFailure { /** * @var string */ private $testName; /** * @var Test|null */ protected $failedTest; /** * @var Throwable */ protected $thrownException; /** * Constructs a TestFailure with the given test and exception. * * @param Test $failedTest * @param Throwable $t */ public function __construct(Test $failedTest, $t) { if ($failedTest instanceof SelfDescribing) { $this->testName = $failedTest->toString(); } else { $this->testName = \get_class($failedTest); } if (!$failedTest instanceof TestCase || !$failedTest->isInIsolation()) { $this->failedTest = $failedTest; } $this->thrownException = $t; } /** * Returns a short description of the failure. * * @return string */ public function toString() { return \sprintf( '%s: %s', $this->testName, $this->thrownException->getMessage() ); } /** * Returns a description for the thrown exception. * * @return string */ public function getExceptionAsString() { return self::exceptionToString($this->thrownException); } /** * Returns a description for an exception. * * @param Throwable $e * * @return string */ public static function exceptionToString(Throwable $e) { if ($e instanceof SelfDescribing) { $buffer = $e->toString(); if ($e instanceof ExpectationFailedException && $e->getComparisonFailure()) { $buffer .= $e->getComparisonFailure()->getDiff(); } if (!empty($buffer)) { $buffer = \trim($buffer) . "\n"; } return $buffer; } if ($e instanceof Error) { return $e->getMessage() . "\n"; } if ($e instanceof ExceptionWrapper) { return $e->getClassName() . ': ' . $e->getMessage() . "\n"; } return \get_class($e) . ': ' . $e->getMessage() . "\n"; } /** * Returns the name of the failing test (including data set, if any). * * @return string */ public function getTestName() { return $this->testName; } /** * Returns the failing test. * * Note: The test object is not set when the test is executed in process * isolation. * * @see Exception * * @return Test|null */ public function failedTest() { return $this->failedTest; } /** * Gets the thrown exception. * * @return Throwable */ public function thrownException() { return $this->thrownException; } /** * Returns the exception's message. * * @return string */ public function exceptionMessage() { return $this->thrownException()->getMessage(); } /** * Returns true if the thrown exception * is of type AssertionFailedError. * * @return bool */ public function isFailure() { return ($this->thrownException() instanceof AssertionFailedError); } } phpunit-6.5.5/src/Framework/TestListener.php000066400000000000000000000041101321540746700211050ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * A Listener for test progress. */ interface TestListener { /** * An error occurred. * * @param Test $test * @param \Exception $e * @param float $time */ public function addError(Test $test, \Exception $e, $time); /** * A warning occurred. * * @param Test $test * @param Warning $e * @param float $time */ public function addWarning(Test $test, Warning $e, $time); /** * A failure occurred. * * @param Test $test * @param AssertionFailedError $e * @param float $time */ public function addFailure(Test $test, AssertionFailedError $e, $time); /** * Incomplete test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addIncompleteTest(Test $test, \Exception $e, $time); /** * Risky test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addRiskyTest(Test $test, \Exception $e, $time); /** * Skipped test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addSkippedTest(Test $test, \Exception $e, $time); /** * A test suite started. * * @param TestSuite $suite */ public function startTestSuite(TestSuite $suite); /** * A test suite ended. * * @param TestSuite $suite */ public function endTestSuite(TestSuite $suite); /** * A test started. * * @param Test $test */ public function startTest(Test $test); /** * A test ended. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time); } phpunit-6.5.5/src/Framework/TestListenerDefaultImplementation.php000066400000000000000000000020101321540746700253150ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; trait TestListenerDefaultImplementation { public function addError(Test $test, \Exception $e, $time) { } public function addWarning(Test $test, Warning $e, $time) { } public function addFailure(Test $test, AssertionFailedError $e, $time) { } public function addIncompleteTest(Test $test, \Exception $e, $time) { } public function addRiskyTest(Test $test, \Exception $e, $time) { } public function addSkippedTest(Test $test, \Exception $e, $time) { } public function startTestSuite(TestSuite $suite) { } public function endTestSuite(TestSuite $suite) { } public function startTest(Test $test) { } public function endTest(Test $test, $time) { } } phpunit-6.5.5/src/Framework/TestResult.php000066400000000000000000000753321321540746700206140ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use AssertionError; use Countable; use Error; use PHP_Invoker; use PHP_Invoker_TimeoutException; use PHP_Timer; use PHPUnit\Framework\MockObject\Exception as MockObjectException; use PHPUnit\Util\Blacklist; use PHPUnit\Util\InvalidArgumentHelper; use PHPUnit\Util\Printer; use ReflectionClass; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException as OriginalCoveredCodeNotExecutedException; use SebastianBergmann\CodeCoverage\Exception as OriginalCodeCoverageException; use SebastianBergmann\CodeCoverage\MissingCoversAnnotationException as OriginalMissingCoversAnnotationException; use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException; use SebastianBergmann\ResourceOperations\ResourceOperations; use Throwable; /** * A TestResult collects the results of executing a test case. */ class TestResult implements Countable { /** * @var array */ protected $passed = []; /** * @var array */ protected $errors = []; /** * @var array */ protected $failures = []; /** * @var array */ protected $warnings = []; /** * @var array */ protected $notImplemented = []; /** * @var array */ protected $risky = []; /** * @var array */ protected $skipped = []; /** * @var array */ protected $listeners = []; /** * @var int */ protected $runTests = 0; /** * @var float */ protected $time = 0; /** * @var TestSuite */ protected $topTestSuite; /** * Code Coverage information. * * @var CodeCoverage */ protected $codeCoverage; /** * @var bool */ protected $convertErrorsToExceptions = true; /** * @var bool */ protected $stop = false; /** * @var bool */ protected $stopOnError = false; /** * @var bool */ protected $stopOnFailure = false; /** * @var bool */ protected $stopOnWarning = false; /** * @var bool */ protected $beStrictAboutTestsThatDoNotTestAnything = true; /** * @var bool */ protected $beStrictAboutOutputDuringTests = false; /** * @var bool */ protected $beStrictAboutTodoAnnotatedTests = false; /** * @var bool */ protected $beStrictAboutResourceUsageDuringSmallTests = false; /** * @var bool */ protected $enforceTimeLimit = false; /** * @var int */ protected $timeoutForSmallTests = 1; /** * @var int */ protected $timeoutForMediumTests = 10; /** * @var int */ protected $timeoutForLargeTests = 60; /** * @var bool */ protected $stopOnRisky = false; /** * @var bool */ protected $stopOnIncomplete = false; /** * @var bool */ protected $stopOnSkipped = false; /** * @var bool */ protected $lastTestFailed = false; /** * @var bool */ private $registerMockObjectsFromTestArgumentsRecursively = false; /** * Registers a TestListener. * * @param TestListener $listener */ public function addListener(TestListener $listener) { $this->listeners[] = $listener; } /** * Unregisters a TestListener. * * @param TestListener $listener */ public function removeListener(TestListener $listener) { foreach ($this->listeners as $key => $_listener) { if ($listener === $_listener) { unset($this->listeners[$key]); } } } /** * Flushes all flushable TestListeners. */ public function flushListeners() { foreach ($this->listeners as $listener) { if ($listener instanceof Printer) { $listener->flush(); } } } /** * Adds an error to the list of errors. * * @param Test $test * @param Throwable $t * @param float $time */ public function addError(Test $test, Throwable $t, $time) { if ($t instanceof RiskyTest) { $this->risky[] = new TestFailure($test, $t); $notifyMethod = 'addRiskyTest'; if ($test instanceof TestCase) { $test->markAsRisky(); } if ($this->stopOnRisky) { $this->stop(); } } elseif ($t instanceof IncompleteTest) { $this->notImplemented[] = new TestFailure($test, $t); $notifyMethod = 'addIncompleteTest'; if ($this->stopOnIncomplete) { $this->stop(); } } elseif ($t instanceof SkippedTest) { $this->skipped[] = new TestFailure($test, $t); $notifyMethod = 'addSkippedTest'; if ($this->stopOnSkipped) { $this->stop(); } } else { $this->errors[] = new TestFailure($test, $t); $notifyMethod = 'addError'; if ($this->stopOnError || $this->stopOnFailure) { $this->stop(); } } // @see https://github.com/sebastianbergmann/phpunit/issues/1953 if ($t instanceof Error) { $t = new ExceptionWrapper($t); } foreach ($this->listeners as $listener) { $listener->$notifyMethod($test, $t, $time); } $this->lastTestFailed = true; $this->time += $time; } /** * Adds a warning to the list of warnings. * The passed in exception caused the warning. * * @param Test $test * @param Warning $e * @param float $time */ public function addWarning(Test $test, Warning $e, $time) { if ($this->stopOnWarning) { $this->stop(); } $this->warnings[] = new TestFailure($test, $e); foreach ($this->listeners as $listener) { $listener->addWarning($test, $e, $time); } $this->time += $time; } /** * Adds a failure to the list of failures. * The passed in exception caused the failure. * * @param Test $test * @param AssertionFailedError $e * @param float $time */ public function addFailure(Test $test, AssertionFailedError $e, $time) { if ($e instanceof RiskyTest || $e instanceof OutputError) { $this->risky[] = new TestFailure($test, $e); $notifyMethod = 'addRiskyTest'; if ($test instanceof TestCase) { $test->markAsRisky(); } if ($this->stopOnRisky) { $this->stop(); } } elseif ($e instanceof IncompleteTest) { $this->notImplemented[] = new TestFailure($test, $e); $notifyMethod = 'addIncompleteTest'; if ($this->stopOnIncomplete) { $this->stop(); } } elseif ($e instanceof SkippedTest) { $this->skipped[] = new TestFailure($test, $e); $notifyMethod = 'addSkippedTest'; if ($this->stopOnSkipped) { $this->stop(); } } else { $this->failures[] = new TestFailure($test, $e); $notifyMethod = 'addFailure'; if ($this->stopOnFailure) { $this->stop(); } } foreach ($this->listeners as $listener) { $listener->$notifyMethod($test, $e, $time); } $this->lastTestFailed = true; $this->time += $time; } /** * Informs the result that a testsuite will be started. * * @param TestSuite $suite */ public function startTestSuite(TestSuite $suite) { if ($this->topTestSuite === null) { $this->topTestSuite = $suite; } foreach ($this->listeners as $listener) { $listener->startTestSuite($suite); } } /** * Informs the result that a testsuite was completed. * * @param TestSuite $suite */ public function endTestSuite(TestSuite $suite) { foreach ($this->listeners as $listener) { $listener->endTestSuite($suite); } } /** * Informs the result that a test will be started. * * @param Test $test */ public function startTest(Test $test) { $this->lastTestFailed = false; $this->runTests += \count($test); foreach ($this->listeners as $listener) { $listener->startTest($test); } } /** * Informs the result that a test was completed. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time) { foreach ($this->listeners as $listener) { $listener->endTest($test, $time); } if (!$this->lastTestFailed && $test instanceof TestCase) { $class = \get_class($test); $key = $class . '::' . $test->getName(); $this->passed[$key] = [ 'result' => $test->getResult(), 'size' => \PHPUnit\Util\Test::getSize( $class, $test->getName(false) ) ]; $this->time += $time; } } /** * Returns true if no risky test occurred. * * @return bool */ public function allHarmless() { return $this->riskyCount() == 0; } /** * Gets the number of risky tests. * * @return int */ public function riskyCount() { return \count($this->risky); } /** * Returns true if no incomplete test occurred. * * @return bool */ public function allCompletelyImplemented() { return $this->notImplementedCount() == 0; } /** * Gets the number of incomplete tests. * * @return int */ public function notImplementedCount() { return \count($this->notImplemented); } /** * Returns an Enumeration for the risky tests. * * @return array */ public function risky() { return $this->risky; } /** * Returns an Enumeration for the incomplete tests. * * @return array */ public function notImplemented() { return $this->notImplemented; } /** * Returns true if no test has been skipped. * * @return bool */ public function noneSkipped() { return $this->skippedCount() == 0; } /** * Gets the number of skipped tests. * * @return int */ public function skippedCount() { return \count($this->skipped); } /** * Returns an Enumeration for the skipped tests. * * @return array */ public function skipped() { return $this->skipped; } /** * Gets the number of detected errors. * * @return int */ public function errorCount() { return \count($this->errors); } /** * Returns an Enumeration for the errors. * * @return array */ public function errors() { return $this->errors; } /** * Gets the number of detected failures. * * @return int */ public function failureCount() { return \count($this->failures); } /** * Returns an Enumeration for the failures. * * @return array */ public function failures() { return $this->failures; } /** * Gets the number of detected warnings. * * @return int */ public function warningCount() { return \count($this->warnings); } /** * Returns an Enumeration for the warnings. * * @return array */ public function warnings() { return $this->warnings; } /** * Returns the names of the tests that have passed. * * @return array */ public function passed() { return $this->passed; } /** * Returns the (top) test suite. * * @return TestSuite */ public function topTestSuite() { return $this->topTestSuite; } /** * Returns whether code coverage information should be collected. * * @return bool If code coverage should be collected */ public function getCollectCodeCoverageInformation() { return $this->codeCoverage !== null; } /** * Runs a TestCase. * * @param Test $test */ public function run(Test $test) { Assert::resetCount(); $coversNothing = false; if ($test instanceof TestCase) { $test->setRegisterMockObjectsFromTestArgumentsRecursively( $this->registerMockObjectsFromTestArgumentsRecursively ); $annotations = $test->getAnnotations(); if (isset($annotations['class']['coversNothing']) || isset($annotations['method']['coversNothing'])) { $coversNothing = true; } } $error = false; $failure = false; $warning = false; $incomplete = false; $risky = false; $skipped = false; $this->startTest($test); $errorHandlerSet = false; if ($this->convertErrorsToExceptions) { $oldErrorHandler = \set_error_handler( [\PHPUnit\Util\ErrorHandler::class, 'handleError'], E_ALL | E_STRICT ); if ($oldErrorHandler === null) { $errorHandlerSet = true; } else { \restore_error_handler(); } } $collectCodeCoverage = $this->codeCoverage !== null && !$test instanceof WarningTestCase && !$coversNothing; if ($collectCodeCoverage) { $this->codeCoverage->start($test); } $monitorFunctions = $this->beStrictAboutResourceUsageDuringSmallTests && !$test instanceof WarningTestCase && $test->getSize() == \PHPUnit\Util\Test::SMALL && \function_exists('xdebug_start_function_monitor'); if ($monitorFunctions) { \xdebug_start_function_monitor(ResourceOperations::getFunctions()); } PHP_Timer::start(); try { if (!$test instanceof WarningTestCase && $test->getSize() != \PHPUnit\Util\Test::UNKNOWN && $this->enforceTimeLimit && \extension_loaded('pcntl') && \class_exists('PHP_Invoker')) { switch ($test->getSize()) { case \PHPUnit\Util\Test::SMALL: $_timeout = $this->timeoutForSmallTests; break; case \PHPUnit\Util\Test::MEDIUM: $_timeout = $this->timeoutForMediumTests; break; case \PHPUnit\Util\Test::LARGE: $_timeout = $this->timeoutForLargeTests; break; } $invoker = new PHP_Invoker; $invoker->invoke([$test, 'runBare'], [], $_timeout); } else { $test->runBare(); } } catch (PHP_Invoker_TimeoutException $e) { $this->addFailure( $test, new RiskyTestError( $e->getMessage() ), $_timeout ); $risky = true; } catch (MockObjectException $e) { $e = new Warning( $e->getMessage() ); $warning = true; } catch (AssertionFailedError $e) { $failure = true; if ($e instanceof RiskyTestError) { $risky = true; } elseif ($e instanceof IncompleteTestError) { $incomplete = true; } elseif ($e instanceof SkippedTestError) { $skipped = true; } } catch (AssertionError $e) { $test->addToAssertionCount(1); $failure = true; $frame = $e->getTrace()[0]; $e = new AssertionFailedError( \sprintf( '%s in %s:%s', $e->getMessage(), $frame['file'], $frame['line'] ) ); } catch (Warning $e) { $warning = true; } catch (Exception $e) { $error = true; } catch (Throwable $e) { $e = new ExceptionWrapper($e); $error = true; } $time = PHP_Timer::stop(); $test->addToAssertionCount(Assert::getCount()); if ($monitorFunctions) { $blacklist = new Blacklist; $functions = \xdebug_get_monitored_functions(); \xdebug_stop_function_monitor(); foreach ($functions as $function) { if (!$blacklist->isBlacklisted($function['filename'])) { $this->addFailure( $test, new RiskyTestError( \sprintf( '%s() used in %s:%s', $function['function'], $function['filename'], $function['lineno'] ) ), $time ); } } } if ($this->beStrictAboutTestsThatDoNotTestAnything && $test->getNumAssertions() == 0) { $risky = true; } if ($collectCodeCoverage) { $append = !$risky && !$incomplete && !$skipped; $linesToBeCovered = []; $linesToBeUsed = []; if ($append && $test instanceof TestCase) { try { $linesToBeCovered = \PHPUnit\Util\Test::getLinesToBeCovered( \get_class($test), $test->getName(false) ); $linesToBeUsed = \PHPUnit\Util\Test::getLinesToBeUsed( \get_class($test), $test->getName(false) ); } catch (InvalidCoversTargetException $cce) { $this->addWarning( $test, new Warning( $cce->getMessage() ), $time ); } } try { $this->codeCoverage->stop( $append, $linesToBeCovered, $linesToBeUsed ); } catch (UnintentionallyCoveredCodeException $cce) { $this->addFailure( $test, new UnintentionallyCoveredCodeError( 'This test executed code that is not listed as code to be covered or used:' . PHP_EOL . $cce->getMessage() ), $time ); } catch (OriginalCoveredCodeNotExecutedException $cce) { $this->addFailure( $test, new CoveredCodeNotExecutedException( 'This test did not execute all the code that is listed as code to be covered:' . PHP_EOL . $cce->getMessage() ), $time ); } catch (OriginalMissingCoversAnnotationException $cce) { if ($linesToBeCovered !== false) { $this->addFailure( $test, new MissingCoversAnnotationException( 'This test does not have a @covers annotation but is expected to have one' ), $time ); } } catch (OriginalCodeCoverageException $cce) { $error = true; if (!isset($e)) { $e = $cce; } } } if ($errorHandlerSet === true) { \restore_error_handler(); } if ($error === true) { $this->addError($test, $e, $time); } elseif ($failure === true) { $this->addFailure($test, $e, $time); } elseif ($warning === true) { $this->addWarning($test, $e, $time); } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && !$test->doesNotPerformAssertions() && $test->getNumAssertions() == 0) { $this->addFailure( $test, new RiskyTestError( 'This test did not perform any assertions' ), $time ); } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) { $this->addFailure( $test, new OutputError( \sprintf( 'This test printed output: %s', $test->getActualOutput() ) ), $time ); } elseif ($this->beStrictAboutTodoAnnotatedTests && $test instanceof TestCase) { $annotations = $test->getAnnotations(); if (isset($annotations['method']['todo'])) { $this->addFailure( $test, new RiskyTestError( 'Test method is annotated with @todo' ), $time ); } } $this->endTest($test, $time); } /** * Gets the number of run tests. * * @return int */ public function count() { return $this->runTests; } /** * Checks whether the test run should stop. * * @return bool */ public function shouldStop() { return $this->stop; } /** * Marks that the test run should stop. */ public function stop() { $this->stop = true; } /** * Returns the code coverage object. * * @return CodeCoverage */ public function getCodeCoverage() { return $this->codeCoverage; } /** * Sets the code coverage object. * * @param CodeCoverage $codeCoverage */ public function setCodeCoverage(CodeCoverage $codeCoverage) { $this->codeCoverage = $codeCoverage; } /** * Enables or disables the error-to-exception conversion. * * @param bool $flag * * @throws Exception */ public function convertErrorsToExceptions($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->convertErrorsToExceptions = $flag; } /** * Returns the error-to-exception conversion setting. * * @return bool */ public function getConvertErrorsToExceptions() { return $this->convertErrorsToExceptions; } /** * Enables or disables the stopping when an error occurs. * * @param bool $flag * * @throws Exception */ public function stopOnError($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnError = $flag; } /** * Enables or disables the stopping when a failure occurs. * * @param bool $flag * * @throws Exception */ public function stopOnFailure($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnFailure = $flag; } /** * Enables or disables the stopping when a warning occurs. * * @param bool $flag * * @throws Exception */ public function stopOnWarning($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnWarning = $flag; } /** * @param bool $flag * * @throws Exception */ public function beStrictAboutTestsThatDoNotTestAnything($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->beStrictAboutTestsThatDoNotTestAnything = $flag; } /** * @return bool */ public function isStrictAboutTestsThatDoNotTestAnything() { return $this->beStrictAboutTestsThatDoNotTestAnything; } /** * @param bool $flag * * @throws Exception */ public function beStrictAboutOutputDuringTests($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->beStrictAboutOutputDuringTests = $flag; } /** * @return bool */ public function isStrictAboutOutputDuringTests() { return $this->beStrictAboutOutputDuringTests; } /** * @param bool $flag * * @throws Exception */ public function beStrictAboutResourceUsageDuringSmallTests($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->beStrictAboutResourceUsageDuringSmallTests = $flag; } /** * @return bool */ public function isStrictAboutResourceUsageDuringSmallTests() { return $this->beStrictAboutResourceUsageDuringSmallTests; } /** * @param bool $flag * * @throws Exception */ public function enforceTimeLimit($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->enforceTimeLimit = $flag; } /** * @return bool */ public function enforcesTimeLimit() { return $this->enforceTimeLimit; } /** * @param bool $flag * * @throws Exception */ public function beStrictAboutTodoAnnotatedTests($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->beStrictAboutTodoAnnotatedTests = $flag; } /** * @return bool */ public function isStrictAboutTodoAnnotatedTests() { return $this->beStrictAboutTodoAnnotatedTests; } /** * Enables or disables the stopping for risky tests. * * @param bool $flag * * @throws Exception */ public function stopOnRisky($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnRisky = $flag; } /** * Enables or disables the stopping for incomplete tests. * * @param bool $flag * * @throws Exception */ public function stopOnIncomplete($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnIncomplete = $flag; } /** * Enables or disables the stopping for skipped tests. * * @param bool $flag * * @throws Exception */ public function stopOnSkipped($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stopOnSkipped = $flag; } /** * Returns the time spent running the tests. * * @return float */ public function time() { return $this->time; } /** * Returns whether the entire test was successful or not. * * @return bool */ public function wasSuccessful() { return empty($this->errors) && empty($this->failures) && empty($this->warnings); } /** * Sets the timeout for small tests. * * @param int $timeout * * @throws Exception */ public function setTimeoutForSmallTests($timeout) { if (!\is_int($timeout)) { throw InvalidArgumentHelper::factory(1, 'integer'); } $this->timeoutForSmallTests = $timeout; } /** * Sets the timeout for medium tests. * * @param int $timeout * * @throws Exception */ public function setTimeoutForMediumTests($timeout) { if (!\is_int($timeout)) { throw InvalidArgumentHelper::factory(1, 'integer'); } $this->timeoutForMediumTests = $timeout; } /** * Sets the timeout for large tests. * * @param int $timeout * * @throws Exception */ public function setTimeoutForLargeTests($timeout) { if (!\is_int($timeout)) { throw InvalidArgumentHelper::factory(1, 'integer'); } $this->timeoutForLargeTests = $timeout; } /** * Returns the set timeout for large tests. * * @return int */ public function getTimeoutForLargeTests() { return $this->timeoutForLargeTests; } /** * @param bool $flag */ public function setRegisterMockObjectsFromTestArgumentsRecursively($flag) { if (!\is_bool($flag)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->registerMockObjectsFromTestArgumentsRecursively = $flag; } /** * Returns the class hierarchy for a given class. * * @param string $className * @param bool $asReflectionObjects * * @return array */ protected function getHierarchy($className, $asReflectionObjects = false) { if ($asReflectionObjects) { $classes = [new ReflectionClass($className)]; } else { $classes = [$className]; } $done = false; while (!$done) { if ($asReflectionObjects) { $class = new ReflectionClass( $classes[\count($classes) - 1]->getName() ); } else { $class = new ReflectionClass($classes[\count($classes) - 1]); } $parent = $class->getParentClass(); if ($parent !== false) { if ($asReflectionObjects) { $classes[] = $parent; } else { $classes[] = $parent->getName(); } } else { $done = true; } } return $classes; } } phpunit-6.5.5/src/Framework/TestSuite.php000066400000000000000000000665121321540746700204270ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use Iterator; use IteratorAggregate; use PHPUnit\Runner\BaseTestRunner; use PHPUnit\Runner\Filter\Factory; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Util\Fileloader; use PHPUnit\Util\InvalidArgumentHelper; use ReflectionClass; use ReflectionMethod; use Throwable; /** * A TestSuite is a composite of Tests. It runs a collection of test cases. */ class TestSuite implements Test, SelfDescribing, IteratorAggregate { /** * Last count of tests in this suite. * * @var int|null */ private $cachedNumTests; /** * Enable or disable the backup and restoration of the $GLOBALS array. * * @var bool */ protected $backupGlobals; /** * Enable or disable the backup and restoration of static attributes. * * @var bool */ protected $backupStaticAttributes; /** * @var bool */ private $beStrictAboutChangesToGlobalState; /** * @var bool */ protected $runTestInSeparateProcess = false; /** * The name of the test suite. * * @var string */ protected $name = ''; /** * The test groups of the test suite. * * @var array */ protected $groups = []; /** * The tests in the test suite. * * @var TestCase[] */ protected $tests = []; /** * The number of tests in the test suite. * * @var int */ protected $numTests = -1; /** * @var bool */ protected $testCase = false; /** * @var array */ protected $foundClasses = []; /** * @var Factory */ private $iteratorFilter; /** * @var string[] */ private $declaredClasses; /** * Constructs a new TestSuite: * * - PHPUnit\Framework\TestSuite() constructs an empty TestSuite. * * - PHPUnit\Framework\TestSuite(ReflectionClass) constructs a * TestSuite from the given class. * * - PHPUnit\Framework\TestSuite(ReflectionClass, String) * constructs a TestSuite from the given class with the given * name. * * - PHPUnit\Framework\TestSuite(String) either constructs a * TestSuite from the given class (if the passed string is the * name of an existing class) or constructs an empty TestSuite * with the given name. * * @param mixed $theClass * @param string $name * * @throws Exception */ public function __construct($theClass = '', $name = '') { $this->declaredClasses = \get_declared_classes(); $argumentsValid = false; if (\is_object($theClass) && $theClass instanceof ReflectionClass) { $argumentsValid = true; } elseif (\is_string($theClass) && $theClass !== '' && \class_exists($theClass, false)) { $argumentsValid = true; if ($name == '') { $name = $theClass; } $theClass = new ReflectionClass($theClass); } elseif (\is_string($theClass)) { $this->setName($theClass); return; } if (!$argumentsValid) { throw new Exception; } if (!$theClass->isSubclassOf(TestCase::class)) { throw new Exception( 'Class "' . $theClass->name . '" does not extend PHPUnit\Framework\TestCase.' ); } if ($name != '') { $this->setName($name); } else { $this->setName($theClass->getName()); } $constructor = $theClass->getConstructor(); if ($constructor !== null && !$constructor->isPublic()) { $this->addTest( self::warning( \sprintf( 'Class "%s" has no public constructor.', $theClass->getName() ) ) ); return; } foreach ($theClass->getMethods() as $method) { $this->addTestMethod($theClass, $method); } if (empty($this->tests)) { $this->addTest( self::warning( \sprintf( 'No tests found in class "%s".', $theClass->getName() ) ) ); } $this->testCase = true; } /** * Returns a string representation of the test suite. * * @return string */ public function toString() { return $this->getName(); } /** * Adds a test to the suite. * * @param Test $test * @param array $groups */ public function addTest(Test $test, $groups = []) { $class = new ReflectionClass($test); if (!$class->isAbstract()) { $this->tests[] = $test; $this->numTests = -1; if ($test instanceof self && empty($groups)) { $groups = $test->getGroups(); } if (empty($groups)) { $groups = ['default']; } foreach ($groups as $group) { if (!isset($this->groups[$group])) { $this->groups[$group] = [$test]; } else { $this->groups[$group][] = $test; } } if ($test instanceof TestCase) { $test->setGroups($groups); } } } /** * Adds the tests from the given class to the suite. * * @param mixed $testClass * * @throws Exception */ public function addTestSuite($testClass) { if (\is_string($testClass) && \class_exists($testClass)) { $testClass = new ReflectionClass($testClass); } if (!\is_object($testClass)) { throw InvalidArgumentHelper::factory( 1, 'class name or object' ); } if ($testClass instanceof self) { $this->addTest($testClass); } elseif ($testClass instanceof ReflectionClass) { $suiteMethod = false; if (!$testClass->isAbstract() && $testClass->hasMethod(BaseTestRunner::SUITE_METHODNAME)) { $method = $testClass->getMethod( BaseTestRunner::SUITE_METHODNAME ); if ($method->isStatic()) { $this->addTest( $method->invoke(null, $testClass->getName()) ); $suiteMethod = true; } } if (!$suiteMethod && !$testClass->isAbstract()) { $this->addTest(new self($testClass)); } } else { throw new Exception; } } /** * Wraps both addTest() and addTestSuite * as well as the separate import statements for the user's convenience. * * If the named file cannot be read or there are no new tests that can be * added, a PHPUnit\Framework\WarningTestCase will be created instead, * leaving the current test run untouched. * * @param string $filename * * @throws Exception */ public function addTestFile($filename) { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (\file_exists($filename) && \substr($filename, -5) == '.phpt') { $this->addTest( new PhptTestCase($filename) ); return; } // The given file may contain further stub classes in addition to the // test class itself. Figure out the actual test class. $filename = Fileloader::checkAndLoad($filename); $newClasses = \array_diff(\get_declared_classes(), $this->declaredClasses); // The diff is empty in case a parent class (with test methods) is added // AFTER a child class that inherited from it. To account for that case, // accumulate all discovered classes, so the parent class may be found in // a later invocation. if (!empty($newClasses)) { // On the assumption that test classes are defined first in files, // process discovered classes in approximate LIFO order, so as to // avoid unnecessary reflection. $this->foundClasses = \array_merge($newClasses, $this->foundClasses); $this->declaredClasses = \get_declared_classes(); } // The test class's name must match the filename, either in full, or as // a PEAR/PSR-0 prefixed shortname ('NameSpace_ShortName'), or as a // PSR-1 local shortname ('NameSpace\ShortName'). The comparison must be // anchored to prevent false-positive matches (e.g., 'OtherShortName'). $shortname = \basename($filename, '.php'); $shortnameRegEx = '/(?:^|_|\\\\)' . \preg_quote($shortname, '/') . '$/'; foreach ($this->foundClasses as $i => $className) { if (\preg_match($shortnameRegEx, $className)) { $class = new ReflectionClass($className); if ($class->getFileName() == $filename) { $newClasses = [$className]; unset($this->foundClasses[$i]); break; } } } foreach ($newClasses as $className) { $class = new ReflectionClass($className); if (dirname($class->getFileName()) === __DIR__) { continue; } if (!$class->isAbstract()) { if ($class->hasMethod(BaseTestRunner::SUITE_METHODNAME)) { $method = $class->getMethod( BaseTestRunner::SUITE_METHODNAME ); if ($method->isStatic()) { $this->addTest($method->invoke(null, $className)); } } elseif ($class->implementsInterface(Test::class)) { $this->addTestSuite($class); } } } $this->numTests = -1; } /** * Wrapper for addTestFile() that adds multiple test files. * * @param array|Iterator $filenames * * @throws Exception */ public function addTestFiles($filenames) { if (!(\is_array($filenames) || (\is_object($filenames) && $filenames instanceof Iterator))) { throw InvalidArgumentHelper::factory( 1, 'array or iterator' ); } foreach ($filenames as $filename) { $this->addTestFile((string) $filename); } } /** * Counts the number of test cases that will be run by this test. * * @param bool $preferCache Indicates if cache is preferred. * * @return int */ public function count($preferCache = false) { if ($preferCache && $this->cachedNumTests !== null) { return $this->cachedNumTests; } $numTests = 0; foreach ($this as $test) { $numTests += \count($test); } $this->cachedNumTests = $numTests; return $numTests; } /** * @param ReflectionClass $theClass * @param string $name * * @return Test * * @throws Exception */ public static function createTest(ReflectionClass $theClass, $name) { $className = $theClass->getName(); if (!$theClass->isInstantiable()) { return self::warning( \sprintf('Cannot instantiate class "%s".', $className) ); } $backupSettings = \PHPUnit\Util\Test::getBackupSettings( $className, $name ); $preserveGlobalState = \PHPUnit\Util\Test::getPreserveGlobalStateSettings( $className, $name ); $runTestInSeparateProcess = \PHPUnit\Util\Test::getProcessIsolationSettings( $className, $name ); $runClassInSeparateProcess = \PHPUnit\Util\Test::getClassProcessIsolationSettings( $className, $name ); $constructor = $theClass->getConstructor(); if ($constructor !== null) { $parameters = $constructor->getParameters(); // TestCase() or TestCase($name) if (\count($parameters) < 2) { $test = new $className; } // TestCase($name, $data) else { try { $data = \PHPUnit\Util\Test::getProvidedData( $className, $name ); } catch (IncompleteTestError $e) { $message = \sprintf( 'Test for %s::%s marked incomplete by data provider', $className, $name ); $_message = $e->getMessage(); if (!empty($_message)) { $message .= "\n" . $_message; } $data = self::incompleteTest($className, $name, $message); } catch (SkippedTestError $e) { $message = \sprintf( 'Test for %s::%s skipped by data provider', $className, $name ); $_message = $e->getMessage(); if (!empty($_message)) { $message .= "\n" . $_message; } $data = self::skipTest($className, $name, $message); } catch (Throwable $_t) { $t = $_t; } catch (Exception $_t) { $t = $_t; } if (isset($t)) { $message = \sprintf( 'The data provider specified for %s::%s is invalid.', $className, $name ); $_message = $t->getMessage(); if (!empty($_message)) { $message .= "\n" . $_message; } $data = self::warning($message); } // Test method with @dataProvider. if (isset($data)) { $test = new DataProviderTestSuite( $className . '::' . $name ); if (empty($data)) { $data = self::warning( \sprintf( 'No tests found in suite "%s".', $test->getName() ) ); } $groups = \PHPUnit\Util\Test::getGroups($className, $name); if ($data instanceof WarningTestCase || $data instanceof SkippedTestCase || $data instanceof IncompleteTestCase) { $test->addTest($data, $groups); } else { foreach ($data as $_dataName => $_data) { $_test = new $className($name, $_data, $_dataName); if ($runTestInSeparateProcess) { $_test->setRunTestInSeparateProcess(true); if ($preserveGlobalState !== null) { $_test->setPreserveGlobalState($preserveGlobalState); } } if ($runClassInSeparateProcess) { $_test->setRunClassInSeparateProcess(true); if ($preserveGlobalState !== null) { $_test->setPreserveGlobalState($preserveGlobalState); } } if ($backupSettings['backupGlobals'] !== null) { $_test->setBackupGlobals( $backupSettings['backupGlobals'] ); } if ($backupSettings['backupStaticAttributes'] !== null) { $_test->setBackupStaticAttributes( $backupSettings['backupStaticAttributes'] ); } $test->addTest($_test, $groups); } } } else { $test = new $className; } } } if (!isset($test)) { throw new Exception('No valid test provided.'); } if ($test instanceof TestCase) { $test->setName($name); if ($runTestInSeparateProcess) { $test->setRunTestInSeparateProcess(true); if ($preserveGlobalState !== null) { $test->setPreserveGlobalState($preserveGlobalState); } } if ($backupSettings['backupGlobals'] !== null) { $test->setBackupGlobals($backupSettings['backupGlobals']); } if ($backupSettings['backupStaticAttributes'] !== null) { $test->setBackupStaticAttributes( $backupSettings['backupStaticAttributes'] ); } } return $test; } /** * Creates a default TestResult object. * * @return TestResult */ protected function createResult() { return new TestResult; } /** * Returns the name of the suite. * * @return string */ public function getName() { return $this->name; } /** * Returns the test groups of the suite. * * @return array */ public function getGroups() { return \array_keys($this->groups); } public function getGroupDetails() { return $this->groups; } /** * Set tests groups of the test case * * @param array $groups */ public function setGroupDetails(array $groups) { $this->groups = $groups; } /** * Runs the tests and collects their result in a TestResult. * * @param TestResult $result * * @return TestResult */ public function run(TestResult $result = null) { if ($result === null) { $result = $this->createResult(); } if (\count($this) == 0) { return $result; } $hookMethods = \PHPUnit\Util\Test::getHookMethods($this->name); $result->startTestSuite($this); try { $this->setUp(); foreach ($hookMethods['beforeClass'] as $beforeClassMethod) { if ($this->testCase === true && \class_exists($this->name, false) && \method_exists($this->name, $beforeClassMethod)) { if ($missingRequirements = \PHPUnit\Util\Test::getMissingRequirements($this->name, $beforeClassMethod)) { $this->markTestSuiteSkipped(\implode(PHP_EOL, $missingRequirements)); } \call_user_func([$this->name, $beforeClassMethod]); } } } catch (SkippedTestSuiteError $e) { $numTests = \count($this); for ($i = 0; $i < $numTests; $i++) { $result->startTest($this); $result->addFailure($this, $e, 0); $result->endTest($this, 0); } $this->tearDown(); $result->endTestSuite($this); return $result; } catch (Throwable $_t) { $t = $_t; } catch (Exception $_t) { $t = $_t; } if (isset($t)) { $numTests = \count($this); for ($i = 0; $i < $numTests; $i++) { if ($result->shouldStop()) { break; } $result->startTest($this); $result->addError($this, $t, 0); $result->endTest($this, 0); } $this->tearDown(); $result->endTestSuite($this); return $result; } foreach ($this as $test) { if ($result->shouldStop()) { break; } if ($test instanceof TestCase || $test instanceof self) { $test->setBeStrictAboutChangesToGlobalState($this->beStrictAboutChangesToGlobalState); $test->setBackupGlobals($this->backupGlobals); $test->setBackupStaticAttributes($this->backupStaticAttributes); $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess); } $test->run($result); } foreach ($hookMethods['afterClass'] as $afterClassMethod) { if ($this->testCase === true && \class_exists($this->name, false) && \method_exists($this->name, $afterClassMethod)) { \call_user_func([$this->name, $afterClassMethod]); } } $this->tearDown(); $result->endTestSuite($this); return $result; } /** * @param bool $runTestInSeparateProcess * * @throws Exception */ public function setRunTestInSeparateProcess($runTestInSeparateProcess) { if (\is_bool($runTestInSeparateProcess)) { $this->runTestInSeparateProcess = $runTestInSeparateProcess; } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } /** * Runs a test. * * @deprecated * * @param Test $test * @param TestResult $result */ public function runTest(Test $test, TestResult $result) { $test->run($result); } /** * Sets the name of the suite. * * @param string */ public function setName($name) { $this->name = $name; } /** * Returns the test at the given index. * * @param int|false * * @return Test|false */ public function testAt($index) { if (isset($this->tests[$index])) { return $this->tests[$index]; } return false; } /** * Returns the tests as an enumeration. * * @return array */ public function tests() { return $this->tests; } /** * Set tests of the test suite * * @param array $tests */ public function setTests(array $tests) { $this->tests = $tests; } /** * Mark the test suite as skipped. * * @param string $message * * @throws SkippedTestSuiteError */ public function markTestSuiteSkipped($message = '') { throw new SkippedTestSuiteError($message); } /** * @param ReflectionClass $class * @param ReflectionMethod $method */ protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method) { if (!$this->isTestMethod($method)) { return; } $name = $method->getName(); if (!$method->isPublic()) { $this->addTest( self::warning( \sprintf( 'Test method "%s" in test class "%s" is not public.', $name, $class->getName() ) ) ); return; } $test = self::createTest($class, $name); if ($test instanceof TestCase || $test instanceof DataProviderTestSuite) { $test->setDependencies( \PHPUnit\Util\Test::getDependencies($class->getName(), $name) ); } $this->addTest( $test, \PHPUnit\Util\Test::getGroups($class->getName(), $name) ); } /** * @param ReflectionMethod $method * * @return bool */ public static function isTestMethod(ReflectionMethod $method) { if (\strpos($method->name, 'test') === 0) { return true; } // @scenario on TestCase::testMethod() // @test on TestCase::testMethod() $docComment = $method->getDocComment(); return \strpos($docComment, '@test') !== false || \strpos($docComment, '@scenario') !== false; } /** * @param string $message * * @return WarningTestCase */ protected static function warning($message) { return new WarningTestCase($message); } /** * @param string $class * @param string $methodName * @param string $message * * @return SkippedTestCase */ protected static function skipTest($class, $methodName, $message) { return new SkippedTestCase($class, $methodName, $message); } /** * @param string $class * @param string $methodName * @param string $message * * @return IncompleteTestCase */ protected static function incompleteTest($class, $methodName, $message) { return new IncompleteTestCase($class, $methodName, $message); } /** * @param bool $beStrictAboutChangesToGlobalState */ public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState) { if (null === $this->beStrictAboutChangesToGlobalState && \is_bool($beStrictAboutChangesToGlobalState)) { $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; } } /** * @param bool $backupGlobals */ public function setBackupGlobals($backupGlobals) { if (null === $this->backupGlobals && \is_bool($backupGlobals)) { $this->backupGlobals = $backupGlobals; } } /** * @param bool $backupStaticAttributes */ public function setBackupStaticAttributes($backupStaticAttributes) { if (null === $this->backupStaticAttributes && \is_bool($backupStaticAttributes)) { $this->backupStaticAttributes = $backupStaticAttributes; } } /** * Returns an iterator for this test suite. * * @return TestSuiteIterator */ public function getIterator() { $iterator = new TestSuiteIterator($this); if ($this->iteratorFilter !== null) { $iterator = $this->iteratorFilter->factory($iterator, $this); } return $iterator; } public function injectFilter(Factory $filter) { $this->iteratorFilter = $filter; foreach ($this as $test) { if ($test instanceof self) { $test->injectFilter($filter); } } } /** * Template Method that is called before the tests * of this test suite are run. */ protected function setUp() { } /** * Template Method that is called after the tests * of this test suite have finished running. */ protected function tearDown() { } } phpunit-6.5.5/src/Framework/TestSuiteIterator.php000066400000000000000000000036141321540746700221330ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; use RecursiveIterator; /** * Iterator for test suites. */ class TestSuiteIterator implements RecursiveIterator { /** * @var int */ protected $position; /** * @var Test[] */ protected $tests; /** * @param TestSuite $testSuite */ public function __construct(TestSuite $testSuite) { $this->tests = $testSuite->tests(); } /** * Rewinds the Iterator to the first element. */ public function rewind() { $this->position = 0; } /** * Checks if there is a current element after calls to rewind() or next(). * * @return bool */ public function valid() { return $this->position < \count($this->tests); } /** * Returns the key of the current element. * * @return int */ public function key() { return $this->position; } /** * Returns the current element. * * @return Test */ public function current() { return $this->valid() ? $this->tests[$this->position] : null; } /** * Moves forward to next element. */ public function next() { $this->position++; } /** * Returns the sub iterator for the current element. * * @return TestSuiteIterator */ public function getChildren() { return new self( $this->tests[$this->position] ); } /** * Checks whether the current element has children. * * @return bool */ public function hasChildren() { return $this->tests[$this->position] instanceof TestSuite; } } phpunit-6.5.5/src/Framework/UnintentionallyCoveredCodeError.php000066400000000000000000000007121321540746700247750ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Extension to PHPUnit\Framework\AssertionFailedError to mark the special * case of a test that unintentionally covers code. */ class UnintentionallyCoveredCodeError extends RiskyTestError { } phpunit-6.5.5/src/Framework/Warning.php000066400000000000000000000010431321540746700200670ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * Thrown when there is a warning. */ class Warning extends Exception implements SelfDescribing { /** * Wrapper for getMessage() which is declared as final. * * @return string */ public function toString() { return $this->getMessage(); } } phpunit-6.5.5/src/Framework/WarningTestCase.php000066400000000000000000000024171321540746700215310ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Framework; /** * A warning. */ class WarningTestCase extends TestCase { /** * @var string */ protected $message = ''; /** * @var bool */ protected $backupGlobals = false; /** * @var bool */ protected $backupStaticAttributes = false; /** * @var bool */ protected $runTestInSeparateProcess = false; /** * @var bool */ protected $useErrorHandler = false; /** * @param string $message */ public function __construct($message = '') { $this->message = $message; parent::__construct('Warning'); } /** * @throws Exception */ protected function runTest() { throw new Warning($this->message); } /** * @return string */ public function getMessage() { return $this->message; } /** * Returns a string representation of the test case. * * @return string */ public function toString() { return 'Warning'; } } phpunit-6.5.5/src/Runner/000077500000000000000000000000001321540746700152675ustar00rootroot00000000000000phpunit-6.5.5/src/Runner/BaseTestRunner.php000066400000000000000000000071721321540746700207130ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use File_Iterator_Facade; use PHPUnit\Framework\Exception; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestSuite; use ReflectionClass; use ReflectionException; /** * Base class for all test runners. */ abstract class BaseTestRunner { const STATUS_PASSED = 0; const STATUS_SKIPPED = 1; const STATUS_INCOMPLETE = 2; const STATUS_FAILURE = 3; const STATUS_ERROR = 4; const STATUS_RISKY = 5; const STATUS_WARNING = 6; const SUITE_METHODNAME = 'suite'; /** * Returns the loader to be used. * * @return TestSuiteLoader */ public function getLoader() { return new StandardTestSuiteLoader; } /** * Returns the Test corresponding to the given suite. * This is a template method, subclasses override * the runFailed() and clearStatus() methods. * * @param string $suiteClassName * @param string $suiteClassFile * @param mixed $suffixes * * @return Test|null */ public function getTest($suiteClassName, $suiteClassFile = '', $suffixes = '') { if (\is_dir($suiteClassName) && !\is_file($suiteClassName . '.php') && empty($suiteClassFile)) { $facade = new File_Iterator_Facade; $files = $facade->getFilesAsArray( $suiteClassName, $suffixes ); $suite = new TestSuite($suiteClassName); $suite->addTestFiles($files); return $suite; } try { $testClass = $this->loadSuiteClass( $suiteClassName, $suiteClassFile ); } catch (Exception $e) { $this->runFailed($e->getMessage()); return; } try { $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME); if (!$suiteMethod->isStatic()) { $this->runFailed( 'suite() method must be static.' ); return; } try { $test = $suiteMethod->invoke(null, $testClass->getName()); } catch (ReflectionException $e) { $this->runFailed( \sprintf( "Failed to invoke suite() method.\n%s", $e->getMessage() ) ); return; } } catch (ReflectionException $e) { try { $test = new TestSuite($testClass); } catch (Exception $e) { $test = new TestSuite; $test->setName($suiteClassName); } } $this->clearStatus(); return $test; } /** * Returns the loaded ReflectionClass for a suite name. * * @param string $suiteClassName * @param string $suiteClassFile * * @return ReflectionClass */ protected function loadSuiteClass($suiteClassName, $suiteClassFile = '') { $loader = $this->getLoader(); return $loader->load($suiteClassName, $suiteClassFile); } /** * Clears the status message. */ protected function clearStatus() { } /** * Override to define how to handle a failed loading of * a test suite. * * @param string $message */ abstract protected function runFailed($message); } phpunit-6.5.5/src/Runner/Exception.php000066400000000000000000000005131321540746700177350ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; class Exception extends \RuntimeException implements \PHPUnit\Exception { } phpunit-6.5.5/src/Runner/Filter/000077500000000000000000000000001321540746700165145ustar00rootroot00000000000000phpunit-6.5.5/src/Runner/Filter/ExcludeGroupFilterIterator.php000066400000000000000000000007651321540746700245230ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; class ExcludeGroupFilterIterator extends GroupFilterIterator { /** * @param string $hash * * @return bool */ protected function doAccept($hash) { return !\in_array($hash, $this->groupTests); } } phpunit-6.5.5/src/Runner/Filter/Factory.php000066400000000000000000000024231321540746700206350ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use FilterIterator; use InvalidArgumentException; use Iterator; use PHPUnit\Framework\TestSuite; use ReflectionClass; class Factory { /** * @var array */ private $filters = []; /** * @param ReflectionClass $filter * @param mixed $args */ public function addFilter(ReflectionClass $filter, $args) { if (!$filter->isSubclassOf(\RecursiveFilterIterator::class)) { throw new InvalidArgumentException( \sprintf( 'Class "%s" does not extend RecursiveFilterIterator', $filter->name ) ); } $this->filters[] = [$filter, $args]; } /** * @return FilterIterator */ public function factory(Iterator $iterator, TestSuite $suite) { foreach ($this->filters as $filter) { list($class, $args) = $filter; $iterator = $class->newInstance($iterator, $args, $suite); } return $iterator; } } phpunit-6.5.5/src/Runner/Filter/GroupFilterIterator.php000066400000000000000000000027511321540746700232060ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use PHPUnit\Framework\TestSuite; use RecursiveFilterIterator; use RecursiveIterator; abstract class GroupFilterIterator extends RecursiveFilterIterator { /** * @var array */ protected $groupTests = []; /** * @param RecursiveIterator $iterator * @param array $groups * @param TestSuite $suite */ public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite) { parent::__construct($iterator); foreach ($suite->getGroupDetails() as $group => $tests) { if (\in_array($group, $groups)) { $testHashes = \array_map( function ($test) { return \spl_object_hash($test); }, $tests ); $this->groupTests = \array_merge($this->groupTests, $testHashes); } } } /** * @return bool */ public function accept() { $test = $this->getInnerIterator()->current(); if ($test instanceof TestSuite) { return true; } return $this->doAccept(\spl_object_hash($test)); } abstract protected function doAccept($hash); } phpunit-6.5.5/src/Runner/Filter/IncludeGroupFilterIterator.php000066400000000000000000000007641321540746700245140ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; class IncludeGroupFilterIterator extends GroupFilterIterator { /** * @param string $hash * * @return bool */ protected function doAccept($hash) { return \in_array($hash, $this->groupTests); } } phpunit-6.5.5/src/Runner/Filter/NameFilterIterator.php000066400000000000000000000064021321540746700227670ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner\Filter; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\WarningTestCase; use PHPUnit\Util\RegularExpression; use RecursiveFilterIterator; use RecursiveIterator; class NameFilterIterator extends RecursiveFilterIterator { /** * @var string */ protected $filter; /** * @var int */ protected $filterMin; /** * @var int */ protected $filterMax; /** * @param RecursiveIterator $iterator * @param string $filter */ public function __construct(RecursiveIterator $iterator, $filter) { parent::__construct($iterator); $this->setFilter($filter); } /** * @param string $filter */ protected function setFilter($filter) { if (RegularExpression::safeMatch($filter, '') === false) { // Handles: // * testAssertEqualsSucceeds#4 // * testAssertEqualsSucceeds#4-8 if (\preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { if (isset($matches[3]) && $matches[2] < $matches[3]) { $filter = \sprintf( '%s.*with data set #(\d+)$', $matches[1] ); $this->filterMin = $matches[2]; $this->filterMax = $matches[3]; } else { $filter = \sprintf( '%s.*with data set #%s$', $matches[1], $matches[2] ); } } // Handles: // * testDetermineJsonError@JSON_ERROR_NONE // * testDetermineJsonError@JSON.* elseif (\preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { $filter = \sprintf( '%s.*with data set "%s"$', $matches[1], $matches[2] ); } // Escape delimiters in regular expression. Do NOT use preg_quote, // to keep magic characters. $filter = \sprintf('/%s/', \str_replace( '/', '\\/', $filter )); } $this->filter = $filter; } /** * @return bool */ public function accept() { $test = $this->getInnerIterator()->current(); if ($test instanceof TestSuite) { return true; } $tmp = \PHPUnit\Util\Test::describe($test, false); if ($test instanceof WarningTestCase) { $name = $test->getMessage(); } else { if ($tmp[0] != '') { $name = \implode('::', $tmp); } else { $name = $tmp[1]; } } $accepted = @\preg_match($this->filter, $name, $matches); if ($accepted && isset($this->filterMax)) { $set = \end($matches); $accepted = $set >= $this->filterMin && $set <= $this->filterMax; } return $accepted; } } phpunit-6.5.5/src/Runner/PhptTestCase.php000066400000000000000000000366131321540746700203600ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use PHP_Timer; use PHPUnit\Framework\Assert; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\IncompleteTestError; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Framework\SkippedTestError; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestResult; use PHPUnit\Util\InvalidArgumentHelper; use PHPUnit\Util\PHP\AbstractPhpProcess; use Text_Template; use Throwable; /** * Runner for PHPT test cases. */ class PhptTestCase implements Test, SelfDescribing { /** * @var string */ private $filename; /** * @var AbstractPhpProcess */ private $phpUtil; /** * @var array */ private $settings = [ 'allow_url_fopen=1', 'auto_append_file=', 'auto_prepend_file=', 'disable_functions=', 'display_errors=1', 'docref_root=', 'docref_ext=.html', 'error_append_string=', 'error_prepend_string=', 'error_reporting=-1', 'html_errors=0', 'log_errors=0', 'magic_quotes_runtime=0', 'output_handler=', 'open_basedir=', 'output_buffering=Off', 'report_memleaks=0', 'report_zend_debug=0', 'safe_mode=0', 'xdebug.default_enable=0' ]; /** * Constructs a test case with the given filename. * * @param string $filename * @param AbstractPhpProcess $phpUtil * * @throws Exception */ public function __construct($filename, $phpUtil = null) { if (!\is_string($filename)) { throw InvalidArgumentHelper::factory(1, 'string'); } if (!\is_file($filename)) { throw new Exception( \sprintf( 'File "%s" does not exist.', $filename ) ); } $this->filename = $filename; $this->phpUtil = $phpUtil ?: AbstractPhpProcess::factory(); } /** * Counts the number of test cases executed by run(TestResult result). * * @return int */ public function count() { return 1; } /** * @param array $sections * @param string $output * * @throws Exception */ private function assertPhptExpectation(array $sections, $output) { $assertions = [ 'EXPECT' => 'assertEquals', 'EXPECTF' => 'assertStringMatchesFormat', 'EXPECTREGEX' => 'assertRegExp', ]; $actual = \preg_replace('/\r\n/', "\n", \trim($output)); foreach ($assertions as $sectionName => $sectionAssertion) { if (isset($sections[$sectionName])) { $sectionContent = \preg_replace('/\r\n/', "\n", \trim($sections[$sectionName])); $assertion = $sectionAssertion; $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent; break; } } if (!isset($assertion)) { throw new Exception('No PHPT assertion found'); } if (!isset($expected)) { throw new Exception('No PHPT expectation found'); } Assert::$assertion($expected, $actual); } /** * Runs a test and collects its result in a TestResult instance. * * @param TestResult $result * * @return TestResult */ public function run(TestResult $result = null) { $sections = $this->parse(); $code = $this->render($sections['FILE']); if ($result === null) { $result = new TestResult; } $xfail = false; $settings = $this->parseIniSection($this->settings); $result->startTest($this); if (isset($sections['INI'])) { $settings = $this->parseIniSection($sections['INI'], $settings); } if (isset($sections['ENV'])) { $env = $this->parseEnvSection($sections['ENV']); $this->phpUtil->setEnv($env); } $this->phpUtil->setUseStderrRedirection(true); if ($result->enforcesTimeLimit()) { $this->phpUtil->setTimeout($result->getTimeoutForLargeTests()); } $skip = $this->runSkip($sections, $result, $settings); if ($skip) { return $result; } if (isset($sections['XFAIL'])) { $xfail = \trim($sections['XFAIL']); } if (isset($sections['STDIN'])) { $this->phpUtil->setStdin($sections['STDIN']); } if (isset($sections['ARGS'])) { $this->phpUtil->setArgs($sections['ARGS']); } if ($result->getCollectCodeCoverageInformation()) { $this->renderForCoverage($settings); } PHP_Timer::start(); $jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings)); $time = PHP_Timer::stop(); if ($result->getCollectCodeCoverageInformation() && ($coverage = $this->cleanupForCoverage())) { $result->getCodeCoverage()->append($coverage, $this, true, [], [], true); } try { $this->assertPhptExpectation($sections, $jobResult['stdout']); } catch (AssertionFailedError $e) { $failure = $e; if ($xfail !== false) { $failure = new IncompleteTestError($xfail, 0, $e); } $result->addFailure($this, $failure, $time); } catch (Throwable $t) { $result->addError($this, $t, $time); } if ($result->allCompletelyImplemented() && $xfail !== false) { $result->addFailure($this, new IncompleteTestError('XFAIL section but test passes'), $time); } $this->runClean($sections); $result->endTest($this, $time); return $result; } /** * @param array $sections * @param TestResult $result * @param array $settings * * @return bool */ private function runSkip(&$sections, TestResult $result, $settings) { if (!isset($sections['SKIPIF'])) { return false; } $skipif = $this->render($sections['SKIPIF']); $jobResult = $this->phpUtil->runJob($skipif, $this->stringifyIni($settings)); if (!\strncasecmp('skip', \ltrim($jobResult['stdout']), 4)) { $message = ''; if (\preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult['stdout'], $skipMatch)) { $message = \substr($skipMatch[1], 2); } $result->addFailure($this, new SkippedTestError($message), 0); $result->endTest($this, 0); return true; } return false; } /** * @param array $sections */ private function runClean(&$sections) { $this->phpUtil->setStdin(''); $this->phpUtil->setArgs(''); if (isset($sections['CLEAN'])) { $cleanCode = $this->render($sections['CLEAN']); $this->phpUtil->runJob($cleanCode, $this->settings); } } /** * Returns the name of the test case. * * @return string */ public function getName() { return $this->toString(); } /** * Returns a string representation of the test case. * * @return string */ public function toString() { return $this->filename; } /** * @return array * * @throws Exception */ private function parse() { $sections = []; $section = ''; $unsupportedSections = [ 'REDIRECTTEST', 'REQUEST', 'POST', 'PUT', 'POST_RAW', 'GZIP_POST', 'DEFLATE_POST', 'GET', 'COOKIE', 'HEADERS', 'CGI', 'EXPECTHEADERS', 'EXTENSIONS', 'PHPDBG' ]; foreach (\file($this->filename) as $line) { if (\preg_match('/^--([_A-Z]+)--/', $line, $result)) { $section = $result[1]; $sections[$section] = ''; continue; } elseif (empty($section)) { throw new Exception('Invalid PHPT file'); } $sections[$section] .= $line; } if (isset($sections['FILEEOF'])) { $sections['FILE'] = \rtrim($sections['FILEEOF'], "\r\n"); unset($sections['FILEEOF']); } $this->parseExtenal($sections); if (!$this->validate($sections)) { throw new Exception('Invalid PHPT file'); } foreach ($unsupportedSections as $section) { if (isset($sections[$section])) { throw new Exception( 'PHPUnit does not support this PHPT file' ); } } return $sections; } /** * @param array $sections */ private function parseExtenal(&$sections) { $allowSections = [ 'FILE', 'EXPECT', 'EXPECTF', 'EXPECTREGEX' ]; $testDirectory = \dirname($this->filename) . DIRECTORY_SEPARATOR; foreach ($allowSections as $section) { if (isset($sections[$section . '_EXTERNAL'])) { $externalFilename = \trim($sections[$section . '_EXTERNAL']); if (!\is_file($testDirectory . $externalFilename) || !\is_readable($testDirectory . $externalFilename)) { throw new Exception( \sprintf( 'Could not load --%s-- %s for PHPT file', $section . '_EXTERNAL', $testDirectory . $externalFilename ) ); } $sections[$section] = \file_get_contents($testDirectory . $externalFilename); unset($sections[$section . '_EXTERNAL']); } } } /** * @param array $sections * * @return bool */ private function validate(&$sections) { $requiredSections = [ 'FILE', [ 'EXPECT', 'EXPECTF', 'EXPECTREGEX' ] ]; foreach ($requiredSections as $section) { if (\is_array($section)) { $foundSection = false; foreach ($section as $anySection) { if (isset($sections[$anySection])) { $foundSection = true; break; } } if (!$foundSection) { return false; } continue; } if (!isset($sections[$section])) { return false; } } return true; } /** * @param string $code * * @return string */ private function render($code) { return \str_replace( [ '__DIR__', '__FILE__' ], [ "'" . \dirname($this->filename) . "'", "'" . $this->filename . "'" ], $code ); } /** * @return array */ private function getCoverageFiles() { $baseDir = \dirname($this->filename) . DIRECTORY_SEPARATOR; $basename = \basename($this->filename, 'phpt'); return [ 'coverage' => $baseDir . $basename . 'coverage', 'job' => $baseDir . $basename . 'php' ]; } /** * @param array $settings * * @return string */ private function renderForCoverage(&$settings) { $files = $this->getCoverageFiles(); $template = new Text_Template( __DIR__ . '/../Util/PHP/Template/PhptTestCase.tpl' ); $composerAutoload = '\'\''; if (\defined('PHPUNIT_COMPOSER_INSTALL') && !\defined('PHPUNIT_TESTSUITE')) { $composerAutoload = \var_export(PHPUNIT_COMPOSER_INSTALL, true); } $phar = '\'\''; if (\defined('__PHPUNIT_PHAR__')) { $phar = \var_export(__PHPUNIT_PHAR__, true); } $globals = ''; if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { $globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n"; } $template->setVar( [ 'composerAutoload' => $composerAutoload, 'phar' => $phar, 'globals' => $globals, 'job' => $files['job'], 'coverageFile' => $files['coverage'], 'autoPrependFile' => \var_export( !empty($settings['auto_prepend_file']) ? $settings['auto_prepend_file'] : false, true ) ] ); \file_put_contents($files['job'], $template->render()); $settings['auto_prepend_file'] = $files['job']; } /** * @return array */ private function cleanupForCoverage() { $files = $this->getCoverageFiles(); $coverage = @\unserialize(\file_get_contents($files['coverage'])); foreach ($files as $file) { @\unlink($file); } return $coverage; } /** * @param array $ini * * @return array */ private function stringifyIni($ini) { $settings = []; foreach ($ini as $key => $value) { if (\is_array($value)) { foreach ($value as $val) { $settings[] = $key . '=' . $val; } continue; } $settings[] = $key . '=' . $value; } return $settings; } /** * Parse --INI-- section key value pairs and return as array. * * @param string|array * * @return array */ protected function parseIniSection($content, $ini = []) { if (\is_string($content)) { $content = \explode("\n", \trim($content)); } foreach ($content as $setting) { if (\strpos($setting, '=') === false) { continue; } $setting = \explode('=', $setting, 2); $name = \trim($setting[0]); $value = \trim($setting[1]); if ($name === 'extension' || $name === 'zend_extension') { if (!isset($ini[$name])) { $ini[$name] = []; } $ini[$name][] = $value; continue; } $ini[$name] = $value; } return $ini; } /** * @param string $content * * @return array */ protected function parseEnvSection($content) { $env = []; foreach (\explode("\n", \trim($content)) as $e) { $e = \explode('=', \trim($e), 2); if (!empty($e[0]) && isset($e[1])) { $env[$e[0]] = $e[1]; } } return $env; } } phpunit-6.5.5/src/Runner/StandardTestSuiteLoader.php000066400000000000000000000066101321540746700225440ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use PHPUnit\Framework\TestCase; use PHPUnit\Util\Fileloader; use PHPUnit\Util\Filesystem; use ReflectionClass; /** * The standard test suite loader. */ class StandardTestSuiteLoader implements TestSuiteLoader { /** * @param string $suiteClassName * @param string $suiteClassFile * * @return ReflectionClass * * @throws Exception */ public function load($suiteClassName, $suiteClassFile = '') { $suiteClassName = \str_replace('.php', '', $suiteClassName); if (empty($suiteClassFile)) { $suiteClassFile = Filesystem::classNameToFilename( $suiteClassName ); } if (!\class_exists($suiteClassName, false)) { $loadedClasses = \get_declared_classes(); $filename = Fileloader::checkAndLoad($suiteClassFile); $loadedClasses = \array_values( \array_diff(\get_declared_classes(), $loadedClasses) ); } if (!\class_exists($suiteClassName, false) && !empty($loadedClasses)) { $offset = 0 - \strlen($suiteClassName); foreach ($loadedClasses as $loadedClass) { $class = new ReflectionClass($loadedClass); if (\substr($loadedClass, $offset) === $suiteClassName && $class->getFileName() == $filename) { $suiteClassName = $loadedClass; break; } } } if (!\class_exists($suiteClassName, false) && !empty($loadedClasses)) { $testCaseClass = TestCase::class; foreach ($loadedClasses as $loadedClass) { $class = new ReflectionClass($loadedClass); $classFile = $class->getFileName(); if ($class->isSubclassOf($testCaseClass) && !$class->isAbstract()) { $suiteClassName = $loadedClass; $testCaseClass = $loadedClass; if ($classFile == \realpath($suiteClassFile)) { break; } } if ($class->hasMethod('suite')) { $method = $class->getMethod('suite'); if (!$method->isAbstract() && $method->isPublic() && $method->isStatic()) { $suiteClassName = $loadedClass; if ($classFile == \realpath($suiteClassFile)) { break; } } } } } if (\class_exists($suiteClassName, false)) { $class = new ReflectionClass($suiteClassName); if ($class->getFileName() == \realpath($suiteClassFile)) { return $class; } } throw new Exception( \sprintf( "Class '%s' could not be found in '%s'.", $suiteClassName, $suiteClassFile ) ); } /** * @param ReflectionClass $aClass * * @return ReflectionClass */ public function reload(ReflectionClass $aClass) { return $aClass; } } phpunit-6.5.5/src/Runner/TestSuiteLoader.php000066400000000000000000000013141321540746700210570ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use ReflectionClass; /** * An interface to define how a test suite should be loaded. */ interface TestSuiteLoader { /** * @param string $suiteClassName * @param string $suiteClassFile * * @return ReflectionClass */ public function load($suiteClassName, $suiteClassFile = ''); /** * @param ReflectionClass $aClass * * @return ReflectionClass */ public function reload(ReflectionClass $aClass); } phpunit-6.5.5/src/Runner/Version.php000066400000000000000000000031371321540746700174310ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Runner; use SebastianBergmann\Version as VersionId; /** * This class defines the current version of PHPUnit. */ class Version { private static $pharVersion; private static $version; /** * Returns the current version of PHPUnit. * * @return string */ public static function id() { if (self::$pharVersion !== null) { return self::$pharVersion; } if (self::$version === null) { $version = new VersionId('6.5.5', \dirname(\dirname(__DIR__))); self::$version = $version->getVersion(); } return self::$version; } /** * @return string */ public static function series() { if (\strpos(self::id(), '-')) { $version = \explode('-', self::id())[0]; } else { $version = self::id(); } return \implode('.', \array_slice(\explode('.', $version), 0, 2)); } /** * @return string */ public static function getVersionString() { return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.'; } /** * @return string */ public static function getReleaseChannel() { if (\strpos(self::$pharVersion, '-') !== false) { return '-nightly'; } return ''; } } phpunit-6.5.5/src/TextUI/000077500000000000000000000000001321540746700152005ustar00rootroot00000000000000phpunit-6.5.5/src/TextUI/Command.php000066400000000000000000001177661321540746700173110ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use File_Iterator_Facade; use PharIo\Manifest\ApplicationName; use PharIo\Manifest\Exception as ManifestException; use PharIo\Manifest\ManifestLoader; use PharIo\Version\Version as PharIoVersion; use PHPUnit\Framework\Exception; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListener; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Runner\StandardTestSuiteLoader; use PHPUnit\Runner\TestSuiteLoader; use PHPUnit\Runner\Version; use PHPUnit\Util\Configuration; use PHPUnit\Util\ConfigurationGenerator; use PHPUnit\Util\Fileloader; use PHPUnit\Util\Filesystem; use PHPUnit\Util\Getopt; use PHPUnit\Util\Log\TeamCity; use PHPUnit\Util\Printer; use PHPUnit\Util\TestDox\TextResultPrinter; use PHPUnit\Util\TextTestListRenderer; use PHPUnit\Util\XmlTestListRenderer; use ReflectionClass; use SebastianBergmann\CodeCoverage\Report\PHP; use Throwable; /** * A TestRunner for the Command Line Interface (CLI) * PHP SAPI Module. */ class Command { /** * @var array */ protected $arguments = [ 'listGroups' => false, 'listSuites' => false, 'listTests' => false, 'listTestsXml' => false, 'loader' => null, 'useDefaultConfiguration' => true, 'loadedExtensions' => [], 'notLoadedExtensions' => [] ]; /** * @var array */ protected $options = []; /** * @var array */ protected $longOptions = [ 'atleast-version=' => null, 'bootstrap=' => null, 'check-version' => null, 'colors==' => null, 'columns=' => null, 'configuration=' => null, 'coverage-clover=' => null, 'coverage-crap4j=' => null, 'coverage-html=' => null, 'coverage-php=' => null, 'coverage-text==' => null, 'coverage-xml=' => null, 'debug' => null, 'disallow-test-output' => null, 'disallow-resource-usage' => null, 'disallow-todo-tests' => null, 'enforce-time-limit' => null, 'exclude-group=' => null, 'filter=' => null, 'generate-configuration' => null, 'globals-backup' => null, 'group=' => null, 'help' => null, 'include-path=' => null, 'list-groups' => null, 'list-suites' => null, 'list-tests' => null, 'list-tests-xml=' => null, 'loader=' => null, 'log-junit=' => null, 'log-teamcity=' => null, 'no-configuration' => null, 'no-coverage' => null, 'no-logging' => null, 'no-extensions' => null, 'printer=' => null, 'process-isolation' => null, 'repeat=' => null, 'dont-report-useless-tests' => null, 'reverse-list' => null, 'static-backup' => null, 'stderr' => null, 'stop-on-error' => null, 'stop-on-failure' => null, 'stop-on-warning' => null, 'stop-on-incomplete' => null, 'stop-on-risky' => null, 'stop-on-skipped' => null, 'fail-on-warning' => null, 'fail-on-risky' => null, 'strict-coverage' => null, 'disable-coverage-ignore' => null, 'strict-global-state' => null, 'teamcity' => null, 'testdox' => null, 'testdox-group=' => null, 'testdox-exclude-group=' => null, 'testdox-html=' => null, 'testdox-text=' => null, 'testdox-xml=' => null, 'test-suffix=' => null, 'testsuite=' => null, 'verbose' => null, 'version' => null, 'whitelist=' => null ]; /** * @var bool */ private $versionStringPrinted = false; /** * @param bool $exit */ public static function main($exit = true) { $command = new static; return $command->run($_SERVER['argv'], $exit); } /** * @param array $argv * @param bool $exit * * @return int */ public function run(array $argv, $exit = true) { $this->handleArguments($argv); $runner = $this->createRunner(); if ($this->arguments['test'] instanceof Test) { $suite = $this->arguments['test']; } else { $suite = $runner->getTest( $this->arguments['test'], $this->arguments['testFile'], $this->arguments['testSuffixes'] ); } if ($this->arguments['listGroups']) { return $this->handleListGroups($suite, $exit); } if ($this->arguments['listSuites']) { return $this->handleListSuites($exit); } if ($this->arguments['listTests']) { return $this->handleListTests($suite, $exit); } if ($this->arguments['listTestsXml']) { return $this->handleListTestsXml($suite, $this->arguments['listTestsXml'], $exit); } unset( $this->arguments['test'], $this->arguments['testFile'] ); try { $result = $runner->doRun($suite, $this->arguments, $exit); } catch (Exception $e) { print $e->getMessage() . PHP_EOL; } $return = TestRunner::FAILURE_EXIT; if (isset($result) && $result->wasSuccessful()) { $return = TestRunner::SUCCESS_EXIT; } elseif (!isset($result) || $result->errorCount() > 0) { $return = TestRunner::EXCEPTION_EXIT; } if ($exit) { exit($return); } return $return; } /** * Create a TestRunner, override in subclasses. * * @return TestRunner */ protected function createRunner() { return new TestRunner($this->arguments['loader']); } /** * Handles the command-line arguments. * * A child class of PHPUnit\TextUI\Command can hook into the argument * parsing by adding the switch(es) to the $longOptions array and point to a * callback method that handles the switch(es) in the child class like this * * * longOptions['my-switch'] = 'myHandler'; * // my-secondswitch will accept a value - note the equals sign * $this->longOptions['my-secondswitch='] = 'myOtherHandler'; * } * * // --my-switch -> myHandler() * protected function myHandler() * { * } * * // --my-secondswitch foo -> myOtherHandler('foo') * protected function myOtherHandler ($value) * { * } * * // You will also need this - the static keyword in the * // PHPUnit\TextUI\Command will mean that it'll be * // PHPUnit\TextUI\Command that gets instantiated, * // not MyCommand * public static function main($exit = true) * { * $command = new static; * * return $command->run($_SERVER['argv'], $exit); * } * * } * * * @param array $argv */ protected function handleArguments(array $argv) { try { $this->options = Getopt::getopt( $argv, 'd:c:hv', \array_keys($this->longOptions) ); } catch (Exception $t) { $this->exitWithErrorMessage($t->getMessage()); } foreach ($this->options[0] as $option) { switch ($option[0]) { case '--colors': $this->arguments['colors'] = $option[1] ?: ResultPrinter::COLOR_AUTO; break; case '--bootstrap': $this->arguments['bootstrap'] = $option[1]; break; case '--columns': if (\is_numeric($option[1])) { $this->arguments['columns'] = (int) $option[1]; } elseif ($option[1] === 'max') { $this->arguments['columns'] = 'max'; } break; case 'c': case '--configuration': $this->arguments['configuration'] = $option[1]; break; case '--coverage-clover': $this->arguments['coverageClover'] = $option[1]; break; case '--coverage-crap4j': $this->arguments['coverageCrap4J'] = $option[1]; break; case '--coverage-html': $this->arguments['coverageHtml'] = $option[1]; break; case '--coverage-php': $this->arguments['coveragePHP'] = $option[1]; break; case '--coverage-text': if ($option[1] === null) { $option[1] = 'php://stdout'; } $this->arguments['coverageText'] = $option[1]; $this->arguments['coverageTextShowUncoveredFiles'] = false; $this->arguments['coverageTextShowOnlySummary'] = false; break; case '--coverage-xml': $this->arguments['coverageXml'] = $option[1]; break; case 'd': $ini = \explode('=', $option[1]); if (isset($ini[0])) { if (isset($ini[1])) { \ini_set($ini[0], $ini[1]); } else { \ini_set($ini[0], true); } } break; case '--debug': $this->arguments['debug'] = true; break; case 'h': case '--help': $this->showHelp(); exit(TestRunner::SUCCESS_EXIT); break; case '--filter': $this->arguments['filter'] = $option[1]; break; case '--testsuite': $this->arguments['testsuite'] = $option[1]; break; case '--generate-configuration': $this->printVersionString(); print 'Generating phpunit.xml in ' . \getcwd() . PHP_EOL . PHP_EOL; print 'Bootstrap script (relative to path shown above; default: vendor/autoload.php): '; $bootstrapScript = \trim(\fgets(STDIN)); print 'Tests directory (relative to path shown above; default: tests): '; $testsDirectory = \trim(\fgets(STDIN)); print 'Source directory (relative to path shown above; default: src): '; $src = \trim(\fgets(STDIN)); if ($bootstrapScript === '') { $bootstrapScript = 'vendor/autoload.php'; } if ($testsDirectory === '') { $testsDirectory = 'tests'; } if ($src === '') { $src = 'src'; } $generator = new ConfigurationGenerator; \file_put_contents( 'phpunit.xml', $generator->generateDefaultConfiguration( Version::series(), $bootstrapScript, $testsDirectory, $src ) ); print PHP_EOL . 'Generated phpunit.xml in ' . \getcwd() . PHP_EOL; exit(TestRunner::SUCCESS_EXIT); break; case '--group': $this->arguments['groups'] = \explode(',', $option[1]); break; case '--exclude-group': $this->arguments['excludeGroups'] = \explode( ',', $option[1] ); break; case '--test-suffix': $this->arguments['testSuffixes'] = \explode( ',', $option[1] ); break; case '--include-path': $includePath = $option[1]; break; case '--list-groups': $this->arguments['listGroups'] = true; break; case '--list-suites': $this->arguments['listSuites'] = true; break; case '--list-tests': $this->arguments['listTests'] = true; break; case '--list-tests-xml': $this->arguments['listTestsXml'] = $option[1]; break; case '--printer': $this->arguments['printer'] = $option[1]; break; case '--loader': $this->arguments['loader'] = $option[1]; break; case '--log-junit': $this->arguments['junitLogfile'] = $option[1]; break; case '--log-teamcity': $this->arguments['teamcityLogfile'] = $option[1]; break; case '--process-isolation': $this->arguments['processIsolation'] = true; break; case '--repeat': $this->arguments['repeat'] = (int) $option[1]; break; case '--stderr': $this->arguments['stderr'] = true; break; case '--stop-on-error': $this->arguments['stopOnError'] = true; break; case '--stop-on-failure': $this->arguments['stopOnFailure'] = true; break; case '--stop-on-warning': $this->arguments['stopOnWarning'] = true; break; case '--stop-on-incomplete': $this->arguments['stopOnIncomplete'] = true; break; case '--stop-on-risky': $this->arguments['stopOnRisky'] = true; break; case '--stop-on-skipped': $this->arguments['stopOnSkipped'] = true; break; case '--fail-on-warning': $this->arguments['failOnWarning'] = true; break; case '--fail-on-risky': $this->arguments['failOnRisky'] = true; break; case '--teamcity': $this->arguments['printer'] = TeamCity::class; break; case '--testdox': $this->arguments['printer'] = TextResultPrinter::class; break; case '--testdox-group': $this->arguments['testdoxGroups'] = \explode( ',', $option[1] ); break; case '--testdox-exclude-group': $this->arguments['testdoxExcludeGroups'] = \explode( ',', $option[1] ); break; case '--testdox-html': $this->arguments['testdoxHTMLFile'] = $option[1]; break; case '--testdox-text': $this->arguments['testdoxTextFile'] = $option[1]; break; case '--testdox-xml': $this->arguments['testdoxXMLFile'] = $option[1]; break; case '--no-configuration': $this->arguments['useDefaultConfiguration'] = false; break; case '--no-extensions': $this->arguments['noExtensions'] = true; break; case '--no-coverage': $this->arguments['noCoverage'] = true; break; case '--no-logging': $this->arguments['noLogging'] = true; break; case '--globals-backup': $this->arguments['backupGlobals'] = true; break; case '--static-backup': $this->arguments['backupStaticAttributes'] = true; break; case 'v': case '--verbose': $this->arguments['verbose'] = true; break; case '--atleast-version': if (\version_compare(Version::id(), $option[1], '>=')) { exit(TestRunner::SUCCESS_EXIT); } exit(TestRunner::FAILURE_EXIT); break; case '--version': $this->printVersionString(); exit(TestRunner::SUCCESS_EXIT); break; case '--dont-report-useless-tests': $this->arguments['reportUselessTests'] = false; break; case '--strict-coverage': $this->arguments['strictCoverage'] = true; break; case '--disable-coverage-ignore': $this->arguments['disableCodeCoverageIgnore'] = true; break; case '--strict-global-state': $this->arguments['beStrictAboutChangesToGlobalState'] = true; break; case '--disallow-test-output': $this->arguments['disallowTestOutput'] = true; break; case '--disallow-resource-usage': $this->arguments['beStrictAboutResourceUsageDuringSmallTests'] = true; break; case '--enforce-time-limit': $this->arguments['enforceTimeLimit'] = true; break; case '--disallow-todo-tests': $this->arguments['disallowTodoAnnotatedTests'] = true; break; case '--reverse-list': $this->arguments['reverseList'] = true; break; case '--check-version': $this->handleVersionCheck(); break; case '--whitelist': $this->arguments['whitelist'] = $option[1]; break; default: $optionName = \str_replace('--', '', $option[0]); $handler = null; if (isset($this->longOptions[$optionName])) { $handler = $this->longOptions[$optionName]; } elseif (isset($this->longOptions[$optionName . '='])) { $handler = $this->longOptions[$optionName . '=']; } if (isset($handler) && \is_callable([$this, $handler])) { $this->$handler($option[1]); } } } $this->handleCustomTestSuite(); if (!isset($this->arguments['test'])) { if (isset($this->options[1][0])) { $this->arguments['test'] = $this->options[1][0]; } if (isset($this->options[1][1])) { $this->arguments['testFile'] = \realpath($this->options[1][1]); } else { $this->arguments['testFile'] = ''; } if (isset($this->arguments['test']) && \is_file($this->arguments['test']) && \substr($this->arguments['test'], -5, 5) != '.phpt') { $this->arguments['testFile'] = \realpath($this->arguments['test']); $this->arguments['test'] = \substr($this->arguments['test'], 0, \strrpos($this->arguments['test'], '.')); } } if (!isset($this->arguments['testSuffixes'])) { $this->arguments['testSuffixes'] = ['Test.php', '.phpt']; } if (isset($includePath)) { \ini_set( 'include_path', $includePath . PATH_SEPARATOR . \ini_get('include_path') ); } if ($this->arguments['loader'] !== null) { $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']); } if (isset($this->arguments['configuration']) && \is_dir($this->arguments['configuration'])) { $configurationFile = $this->arguments['configuration'] . '/phpunit.xml'; if (\file_exists($configurationFile)) { $this->arguments['configuration'] = \realpath( $configurationFile ); } elseif (\file_exists($configurationFile . '.dist')) { $this->arguments['configuration'] = \realpath( $configurationFile . '.dist' ); } } elseif (!isset($this->arguments['configuration']) && $this->arguments['useDefaultConfiguration']) { if (\file_exists('phpunit.xml')) { $this->arguments['configuration'] = \realpath('phpunit.xml'); } elseif (\file_exists('phpunit.xml.dist')) { $this->arguments['configuration'] = \realpath( 'phpunit.xml.dist' ); } } if (isset($this->arguments['configuration'])) { try { $configuration = Configuration::getInstance( $this->arguments['configuration'] ); } catch (Throwable $t) { print $t->getMessage() . PHP_EOL; exit(TestRunner::FAILURE_EXIT); } $phpunitConfiguration = $configuration->getPHPUnitConfiguration(); $configuration->handlePHPConfiguration(); /* * Issue #1216 */ if (isset($this->arguments['bootstrap'])) { $this->handleBootstrap($this->arguments['bootstrap']); } elseif (isset($phpunitConfiguration['bootstrap'])) { $this->handleBootstrap($phpunitConfiguration['bootstrap']); } /* * Issue #657 */ if (isset($phpunitConfiguration['stderr']) && !isset($this->arguments['stderr'])) { $this->arguments['stderr'] = $phpunitConfiguration['stderr']; } if (isset($phpunitConfiguration['extensionsDirectory']) && !isset($this->arguments['noExtensions']) && \extension_loaded('phar')) { $this->handleExtensions($phpunitConfiguration['extensionsDirectory']); } if (isset($phpunitConfiguration['columns']) && !isset($this->arguments['columns'])) { $this->arguments['columns'] = $phpunitConfiguration['columns']; } if (!isset($this->arguments['printer']) && isset($phpunitConfiguration['printerClass'])) { if (isset($phpunitConfiguration['printerFile'])) { $file = $phpunitConfiguration['printerFile']; } else { $file = ''; } $this->arguments['printer'] = $this->handlePrinter( $phpunitConfiguration['printerClass'], $file ); } if (isset($phpunitConfiguration['testSuiteLoaderClass'])) { if (isset($phpunitConfiguration['testSuiteLoaderFile'])) { $file = $phpunitConfiguration['testSuiteLoaderFile']; } else { $file = ''; } $this->arguments['loader'] = $this->handleLoader( $phpunitConfiguration['testSuiteLoaderClass'], $file ); } if (!isset($this->arguments['testsuite']) && isset($phpunitConfiguration['defaultTestSuite'])) { $this->arguments['testsuite'] = $phpunitConfiguration['defaultTestSuite']; } if (!isset($this->arguments['test'])) { $testSuite = $configuration->getTestSuiteConfiguration($this->arguments['testsuite'] ?? null); if ($testSuite !== null) { $this->arguments['test'] = $testSuite; } } } elseif (isset($this->arguments['bootstrap'])) { $this->handleBootstrap($this->arguments['bootstrap']); } if (isset($this->arguments['printer']) && \is_string($this->arguments['printer'])) { $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']); } if (isset($this->arguments['test']) && \is_string($this->arguments['test']) && \substr($this->arguments['test'], -5, 5) == '.phpt') { $test = new PhptTestCase($this->arguments['test']); $this->arguments['test'] = new TestSuite; $this->arguments['test']->addTest($test); } if (!isset($this->arguments['test'])) { $this->showHelp(); exit(TestRunner::EXCEPTION_EXIT); } } /** * Handles the loading of the PHPUnit\Runner\TestSuiteLoader implementation. * * @param string $loaderClass * @param string $loaderFile * * @return TestSuiteLoader|null */ protected function handleLoader($loaderClass, $loaderFile = '') { if (!\class_exists($loaderClass, false)) { if ($loaderFile == '') { $loaderFile = Filesystem::classNameToFilename( $loaderClass ); } $loaderFile = \stream_resolve_include_path($loaderFile); if ($loaderFile) { require $loaderFile; } } if (\class_exists($loaderClass, false)) { $class = new ReflectionClass($loaderClass); if ($class->implementsInterface(TestSuiteLoader::class) && $class->isInstantiable()) { return $class->newInstance(); } } if ($loaderClass == StandardTestSuiteLoader::class) { return; } $this->exitWithErrorMessage( \sprintf( 'Could not use "%s" as loader.', $loaderClass ) ); } /** * Handles the loading of the PHPUnit\Util\Printer implementation. * * @param string $printerClass * @param string $printerFile * * @return Printer|string|null */ protected function handlePrinter($printerClass, $printerFile = '') { if (!\class_exists($printerClass, false)) { if ($printerFile == '') { $printerFile = Filesystem::classNameToFilename( $printerClass ); } $printerFile = \stream_resolve_include_path($printerFile); if ($printerFile) { require $printerFile; } } if (!\class_exists($printerClass)) { $this->exitWithErrorMessage( \sprintf( 'Could not use "%s" as printer: class does not exist', $printerClass ) ); } $class = new ReflectionClass($printerClass); if (!$class->implementsInterface(TestListener::class)) { $this->exitWithErrorMessage( \sprintf( 'Could not use "%s" as printer: class does not implement %s', $printerClass, TestListener::class ) ); } if (!$class->isSubclassOf(Printer::class)) { $this->exitWithErrorMessage( \sprintf( 'Could not use "%s" as printer: class does not extend %s', $printerClass, Printer::class ) ); } if (!$class->isInstantiable()) { $this->exitWithErrorMessage( \sprintf( 'Could not use "%s" as printer: class cannot be instantiated', $printerClass ) ); } if ($class->isSubclassOf(ResultPrinter::class)) { return $printerClass; } $outputStream = isset($this->arguments['stderr']) ? 'php://stderr' : null; return $class->newInstance($outputStream); } /** * Loads a bootstrap file. * * @param string $filename */ protected function handleBootstrap($filename) { try { Fileloader::checkAndLoad($filename); } catch (Exception $e) { $this->exitWithErrorMessage($e->getMessage()); } } protected function handleVersionCheck() { $this->printVersionString(); $latestVersion = \file_get_contents('https://phar.phpunit.de/latest-version-of/phpunit'); $isOutdated = \version_compare($latestVersion, Version::id(), '>'); if ($isOutdated) { \printf( 'You are not using the latest version of PHPUnit.' . PHP_EOL . 'The latest version is PHPUnit %s.' . PHP_EOL, $latestVersion ); } else { print 'You are using the latest version of PHPUnit.' . PHP_EOL; } exit(TestRunner::SUCCESS_EXIT); } /** * Show the help message. */ protected function showHelp() { $this->printVersionString(); print << Code Coverage Options: --coverage-clover Generate code coverage report in Clover XML format. --coverage-crap4j Generate code coverage report in Crap4J XML format. --coverage-html Generate code coverage report in HTML format. --coverage-php Export PHP_CodeCoverage object to file. --coverage-text= Generate code coverage report in text format. Default: Standard output. --coverage-xml Generate code coverage report in PHPUnit XML format. --whitelist Whitelist for code coverage analysis. --disable-coverage-ignore Disable annotations for ignoring code coverage. Logging Options: --log-junit Log test execution in JUnit XML format to file. --log-teamcity Log test execution in TeamCity format to file. --testdox-html Write agile documentation in HTML format to file. --testdox-text Write agile documentation in Text format to file. --testdox-xml Write agile documentation in XML format to file. --reverse-list Print defects in reverse order Test Selection Options: --filter Filter which tests to run. --testsuite Filter which testsuite to run. --group ... Only runs tests from the specified group(s). --exclude-group ... Exclude tests from the specified group(s). --list-groups List available test groups. --list-suites List available test suites. --list-tests List available tests. --list-tests-xml List available tests in XML format. --test-suffix ... Only search for test in files with specified suffix(es). Default: Test.php,.phpt Test Execution Options: --dont-report-useless-tests Do not report tests that do not test anything. --strict-coverage Be strict about @covers annotation usage. --strict-global-state Be strict about changes to global state --disallow-test-output Be strict about output during tests. --disallow-resource-usage Be strict about resource usage during small tests. --enforce-time-limit Enforce time limit based on test size. --disallow-todo-tests Disallow @todo-annotated tests. --process-isolation Run each test in a separate PHP process. --globals-backup Backup and restore \$GLOBALS for each test. --static-backup Backup and restore static attributes for each test. --colors= Use colors in output ("never", "auto" or "always"). --columns Number of columns to use for progress output. --columns max Use maximum number of columns for progress output. --stderr Write to STDERR instead of STDOUT. --stop-on-error Stop execution upon first error. --stop-on-failure Stop execution upon first error or failure. --stop-on-warning Stop execution upon first warning. --stop-on-risky Stop execution upon first risky test. --stop-on-skipped Stop execution upon first skipped test. --stop-on-incomplete Stop execution upon first incomplete test. --fail-on-warning Treat tests with warnings as failures. --fail-on-risky Treat risky tests as failures. -v|--verbose Output more verbose information. --debug Display debugging information. --loader TestSuiteLoader implementation to use. --repeat Runs the test(s) repeatedly. --teamcity Report test execution progress in TeamCity format. --testdox Report test execution progress in TestDox format. --testdox-group Only include tests from the specified group(s). --testdox-exclude-group Exclude tests from the specified group(s). --printer TestListener implementation to use. Configuration Options: --bootstrap A "bootstrap" PHP file that is run before the tests. -c|--configuration Read configuration from XML file. --no-configuration Ignore default configuration file (phpunit.xml). --no-coverage Ignore code coverage configuration. --no-logging Ignore logging configuration. --no-extensions Do not load PHPUnit extensions. --include-path Prepend PHP's include_path with given path(s). -d key[=value] Sets a php.ini value. --generate-configuration Generate configuration file with suggested settings. Miscellaneous Options: -h|--help Prints this usage information. --version Prints the version and exits. --atleast-version Checks that version is greater than min and exits. --check-version Check whether PHPUnit is the latest version. EOT; } /** * Custom callback for test suite discovery. */ protected function handleCustomTestSuite() { } private function printVersionString() { if ($this->versionStringPrinted) { return; } print Version::getVersionString() . PHP_EOL . PHP_EOL; $this->versionStringPrinted = true; } /** * @param string $message */ private function exitWithErrorMessage($message) { $this->printVersionString(); print $message . PHP_EOL; exit(TestRunner::FAILURE_EXIT); } /** * @param string $directory */ private function handleExtensions($directory) { $facade = new File_Iterator_Facade; foreach ($facade->getFilesAsArray($directory, '.phar') as $file) { if (!\file_exists('phar://' . $file . '/manifest.xml')) { $this->arguments['notLoadedExtensions'][] = $file . ' is not an extension for PHPUnit'; continue; } try { $applicationName = new ApplicationName('phpunit/phpunit'); $version = new PharIoVersion(Version::series()); $manifest = ManifestLoader::fromFile('phar://' . $file . '/manifest.xml'); if (!$manifest->isExtensionFor($applicationName)) { $this->arguments['notLoadedExtensions'][] = $file . ' is not an extension for PHPUnit'; continue; } if (!$manifest->isExtensionFor($applicationName, $version)) { $this->arguments['notLoadedExtensions'][] = $file . ' is not compatible with this version of PHPUnit'; continue; } } catch (ManifestException $e) { $this->arguments['notLoadedExtensions'][] = $file . ': ' . $e->getMessage(); continue; } require $file; $this->arguments['loadedExtensions'][] = $manifest->getName() . ' ' . $manifest->getVersion()->getVersionString(); } } private function handleListGroups(TestSuite $suite, bool $exit): int { $this->printVersionString(); print 'Available test group(s):' . PHP_EOL; $groups = $suite->getGroups(); \sort($groups); foreach ($groups as $group) { \printf( ' - %s' . PHP_EOL, $group ); } if ($exit) { exit(TestRunner::SUCCESS_EXIT); } return TestRunner::SUCCESS_EXIT; } private function handleListSuites(bool $exit): int { $this->printVersionString(); print 'Available test suite(s):' . PHP_EOL; $configuration = Configuration::getInstance( $this->arguments['configuration'] ); $suiteNames = $configuration->getTestSuiteNames(); foreach ($suiteNames as $suiteName) { \printf( ' - %s' . PHP_EOL, $suiteName ); } if ($exit) { exit(TestRunner::SUCCESS_EXIT); } return TestRunner::SUCCESS_EXIT; } private function handleListTests(TestSuite $suite, bool $exit): int { $this->printVersionString(); $renderer = new TextTestListRenderer; print $renderer->render($suite); if ($exit) { exit(TestRunner::SUCCESS_EXIT); } return TestRunner::SUCCESS_EXIT; } private function handleListTestsXml(TestSuite $suite, string $target, bool $exit): int { $this->printVersionString(); $renderer = new XmlTestListRenderer; \file_put_contents($target, $renderer->render($suite)); \printf( 'Wrote list of tests that would have been run to %s' . \PHP_EOL, $target ); if ($exit) { exit(TestRunner::SUCCESS_EXIT); } return TestRunner::SUCCESS_EXIT; } } phpunit-6.5.5/src/TextUI/ResultPrinter.php000066400000000000000000000424161321540746700205420ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use PHP_Timer; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Exception; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestFailure; use PHPUnit\Framework\TestListener; use PHPUnit\Framework\TestResult; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; use PHPUnit\Runner\PhptTestCase; use PHPUnit\Util\InvalidArgumentHelper; use PHPUnit\Util\Printer; use SebastianBergmann\Environment\Console; /** * Prints the result of a TextUI TestRunner run. */ class ResultPrinter extends Printer implements TestListener { const EVENT_TEST_START = 0; const EVENT_TEST_END = 1; const EVENT_TESTSUITE_START = 2; const EVENT_TESTSUITE_END = 3; const COLOR_NEVER = 'never'; const COLOR_AUTO = 'auto'; const COLOR_ALWAYS = 'always'; const COLOR_DEFAULT = self::COLOR_NEVER; /** * @var array */ private static $ansiCodes = [ 'bold' => 1, 'fg-black' => 30, 'fg-red' => 31, 'fg-green' => 32, 'fg-yellow' => 33, 'fg-blue' => 34, 'fg-magenta' => 35, 'fg-cyan' => 36, 'fg-white' => 37, 'bg-black' => 40, 'bg-red' => 41, 'bg-green' => 42, 'bg-yellow' => 43, 'bg-blue' => 44, 'bg-magenta' => 45, 'bg-cyan' => 46, 'bg-white' => 47 ]; /** * @var int */ protected $column = 0; /** * @var int */ protected $maxColumn; /** * @var bool */ protected $lastTestFailed = false; /** * @var int */ protected $numAssertions = 0; /** * @var int */ protected $numTests = -1; /** * @var int */ protected $numTestsRun = 0; /** * @var int */ protected $numTestsWidth; /** * @var bool */ protected $colors = false; /** * @var bool */ protected $debug = false; /** * @var bool */ protected $verbose = false; /** * @var int */ private $numberOfColumns; /** * @var bool */ private $reverse; /** * @var bool */ private $defectListPrinted = false; /** * Constructor. * * @param mixed $out * @param bool $verbose * @param string $colors * @param bool $debug * @param int|string $numberOfColumns * @param bool $reverse * * @throws Exception */ public function __construct($out = null, $verbose = false, $colors = self::COLOR_DEFAULT, $debug = false, $numberOfColumns = 80, $reverse = false) { parent::__construct($out); if (!\is_bool($verbose)) { throw InvalidArgumentHelper::factory(2, 'boolean'); } $availableColors = [self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS]; if (!\in_array($colors, $availableColors)) { throw InvalidArgumentHelper::factory( 3, \vsprintf('value from "%s", "%s" or "%s"', $availableColors) ); } if (!\is_bool($debug)) { throw InvalidArgumentHelper::factory(4, 'boolean'); } if (!\is_int($numberOfColumns) && $numberOfColumns !== 'max') { throw InvalidArgumentHelper::factory(5, 'integer or "max"'); } if (!\is_bool($reverse)) { throw InvalidArgumentHelper::factory(6, 'boolean'); } $console = new Console; $maxNumberOfColumns = $console->getNumberOfColumns(); if ($numberOfColumns === 'max' || ($numberOfColumns !== 80 && $numberOfColumns > $maxNumberOfColumns)) { $numberOfColumns = $maxNumberOfColumns; } $this->numberOfColumns = $numberOfColumns; $this->verbose = $verbose; $this->debug = $debug; $this->reverse = $reverse; if ($colors === self::COLOR_AUTO && $console->hasColorSupport()) { $this->colors = true; } else { $this->colors = (self::COLOR_ALWAYS === $colors); } } /** * @param TestResult $result */ public function printResult(TestResult $result) { $this->printHeader(); $this->printErrors($result); $this->printWarnings($result); $this->printFailures($result); $this->printRisky($result); if ($this->verbose) { $this->printIncompletes($result); $this->printSkipped($result); } $this->printFooter($result); } /** * @param array $defects * @param string $type */ protected function printDefects(array $defects, $type) { $count = \count($defects); if ($count == 0) { return; } if ($this->defectListPrinted) { $this->write("\n--\n\n"); } $this->write( \sprintf( "There %s %d %s%s:\n", ($count == 1) ? 'was' : 'were', $count, $type, ($count == 1) ? '' : 's' ) ); $i = 1; if ($this->reverse) { $defects = \array_reverse($defects); } foreach ($defects as $defect) { $this->printDefect($defect, $i++); } $this->defectListPrinted = true; } /** * @param TestFailure $defect * @param int $count */ protected function printDefect(TestFailure $defect, $count) { $this->printDefectHeader($defect, $count); $this->printDefectTrace($defect); } /** * @param TestFailure $defect * @param int $count */ protected function printDefectHeader(TestFailure $defect, $count) { $this->write( \sprintf( "\n%d) %s\n", $count, $defect->getTestName() ) ); } /** * @param TestFailure $defect */ protected function printDefectTrace(TestFailure $defect) { $e = $defect->thrownException(); $this->write((string) $e); while ($e = $e->getPrevious()) { $this->write("\nCaused by\n" . $e); } } /** * @param TestResult $result */ protected function printErrors(TestResult $result) { $this->printDefects($result->errors(), 'error'); } /** * @param TestResult $result */ protected function printFailures(TestResult $result) { $this->printDefects($result->failures(), 'failure'); } /** * @param TestResult $result */ protected function printWarnings(TestResult $result) { $this->printDefects($result->warnings(), 'warning'); } /** * @param TestResult $result */ protected function printIncompletes(TestResult $result) { $this->printDefects($result->notImplemented(), 'incomplete test'); } /** * @param TestResult $result */ protected function printRisky(TestResult $result) { $this->printDefects($result->risky(), 'risky test'); } /** * @param TestResult $result */ protected function printSkipped(TestResult $result) { $this->printDefects($result->skipped(), 'skipped test'); } protected function printHeader() { $this->write("\n\n" . PHP_Timer::resourceUsage() . "\n\n"); } /** * @param TestResult $result */ protected function printFooter(TestResult $result) { if (\count($result) === 0) { $this->writeWithColor( 'fg-black, bg-yellow', 'No tests executed!' ); return; } if ($result->wasSuccessful() && $result->allHarmless() && $result->allCompletelyImplemented() && $result->noneSkipped()) { $this->writeWithColor( 'fg-black, bg-green', \sprintf( 'OK (%d test%s, %d assertion%s)', \count($result), (\count($result) == 1) ? '' : 's', $this->numAssertions, ($this->numAssertions == 1) ? '' : 's' ) ); } else { if ($result->wasSuccessful()) { $color = 'fg-black, bg-yellow'; if ($this->verbose || !$result->allHarmless()) { $this->write("\n"); } $this->writeWithColor( $color, 'OK, but incomplete, skipped, or risky tests!' ); } else { $this->write("\n"); if ($result->errorCount()) { $color = 'fg-white, bg-red'; $this->writeWithColor( $color, 'ERRORS!' ); } elseif ($result->failureCount()) { $color = 'fg-white, bg-red'; $this->writeWithColor( $color, 'FAILURES!' ); } elseif ($result->warningCount()) { $color = 'fg-black, bg-yellow'; $this->writeWithColor( $color, 'WARNINGS!' ); } } $this->writeCountString(\count($result), 'Tests', $color, true); $this->writeCountString($this->numAssertions, 'Assertions', $color, true); $this->writeCountString($result->errorCount(), 'Errors', $color); $this->writeCountString($result->failureCount(), 'Failures', $color); $this->writeCountString($result->warningCount(), 'Warnings', $color); $this->writeCountString($result->skippedCount(), 'Skipped', $color); $this->writeCountString($result->notImplementedCount(), 'Incomplete', $color); $this->writeCountString($result->riskyCount(), 'Risky', $color); $this->writeWithColor($color, '.', true); } } public function printWaitPrompt() { $this->write("\n to continue\n"); } /** * An error occurred. * * @param Test $test * @param \Exception $e * @param float $time */ public function addError(Test $test, \Exception $e, $time) { $this->writeProgressWithColor('fg-red, bold', 'E'); $this->lastTestFailed = true; } /** * A failure occurred. * * @param Test $test * @param AssertionFailedError $e * @param float $time */ public function addFailure(Test $test, AssertionFailedError $e, $time) { $this->writeProgressWithColor('bg-red, fg-white', 'F'); $this->lastTestFailed = true; } /** * A warning occurred. * * @param Test $test * @param Warning $e * @param float $time */ public function addWarning(Test $test, Warning $e, $time) { $this->writeProgressWithColor('fg-yellow, bold', 'W'); $this->lastTestFailed = true; } /** * Incomplete test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addIncompleteTest(Test $test, \Exception $e, $time) { $this->writeProgressWithColor('fg-yellow, bold', 'I'); $this->lastTestFailed = true; } /** * Risky test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addRiskyTest(Test $test, \Exception $e, $time) { $this->writeProgressWithColor('fg-yellow, bold', 'R'); $this->lastTestFailed = true; } /** * Skipped test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addSkippedTest(Test $test, \Exception $e, $time) { $this->writeProgressWithColor('fg-cyan, bold', 'S'); $this->lastTestFailed = true; } /** * A testsuite started. * * @param TestSuite $suite */ public function startTestSuite(TestSuite $suite) { if ($this->numTests == -1) { $this->numTests = \count($suite); $this->numTestsWidth = \strlen((string) $this->numTests); $this->maxColumn = $this->numberOfColumns - \strlen(' / (XXX%)') - (2 * $this->numTestsWidth); } } /** * A testsuite ended. * * @param TestSuite $suite */ public function endTestSuite(TestSuite $suite) { } /** * A test started. * * @param Test $test */ public function startTest(Test $test) { if ($this->debug) { $this->write( \sprintf( "Test '%s' started\n", \PHPUnit\Util\Test::describe($test) ) ); } } /** * A test ended. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time) { if ($this->debug) { $this->write( \sprintf( "Test '%s' ended\n", \PHPUnit\Util\Test::describe($test) ) ); } if (!$this->lastTestFailed) { $this->writeProgress('.'); } if ($test instanceof TestCase) { $this->numAssertions += $test->getNumAssertions(); } elseif ($test instanceof PhptTestCase) { $this->numAssertions++; } $this->lastTestFailed = false; if ($test instanceof TestCase) { if (!$test->hasExpectationOnOutput()) { $this->write($test->getActualOutput()); } } } /** * @param string $progress */ protected function writeProgress($progress) { if ($this->debug) { return; } $this->write($progress); $this->column++; $this->numTestsRun++; if ($this->column == $this->maxColumn || $this->numTestsRun == $this->numTests) { if ($this->numTestsRun == $this->numTests) { $this->write(\str_repeat(' ', $this->maxColumn - $this->column)); } $this->write( \sprintf( ' %' . $this->numTestsWidth . 'd / %' . $this->numTestsWidth . 'd (%3s%%)', $this->numTestsRun, $this->numTests, \floor(($this->numTestsRun / $this->numTests) * 100) ) ); if ($this->column == $this->maxColumn) { $this->writeNewLine(); } } } protected function writeNewLine() { $this->column = 0; $this->write("\n"); } /** * Formats a buffer with a specified ANSI color sequence if colors are * enabled. * * @param string $color * @param string $buffer * * @return string */ protected function formatWithColor($color, $buffer) { if (!$this->colors) { return $buffer; } $codes = \array_map('trim', \explode(',', $color)); $lines = \explode("\n", $buffer); $padding = \max(\array_map('strlen', $lines)); $styles = []; foreach ($codes as $code) { $styles[] = self::$ansiCodes[$code]; } $style = \sprintf("\x1b[%sm", \implode(';', $styles)); $styledLines = []; foreach ($lines as $line) { $styledLines[] = $style . \str_pad($line, $padding) . "\x1b[0m"; } return \implode("\n", $styledLines); } /** * Writes a buffer out with a color sequence if colors are enabled. * * @param string $color * @param string $buffer * @param bool $lf */ protected function writeWithColor($color, $buffer, $lf = true) { $this->write($this->formatWithColor($color, $buffer)); if ($lf) { $this->write("\n"); } } /** * Writes progress with a color sequence if colors are enabled. * * @param string $color * @param string $buffer */ protected function writeProgressWithColor($color, $buffer) { $buffer = $this->formatWithColor($color, $buffer); $this->writeProgress($buffer); } /** * @param int $count * @param string $name * @param string $color * @param bool $always */ private function writeCountString($count, $name, $color, $always = false) { static $first = true; if ($always || $count > 0) { $this->writeWithColor( $color, \sprintf( '%s%s: %d', !$first ? ', ' : '', $name, $count ), false ); $first = false; } } } phpunit-6.5.5/src/TextUI/TestRunner.php000066400000000000000000001260151321540746700200270ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\TextUI; use PHPUnit\Framework\Error\Deprecated; use PHPUnit\Framework\Error\Notice; use PHPUnit\Framework\Error\Warning; use PHPUnit\Framework\Exception; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestListener; use PHPUnit\Framework\TestResult; use PHPUnit\Framework\TestSuite; use PHPUnit\Runner\BaseTestRunner; use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator; use PHPUnit\Runner\Filter\Factory; use PHPUnit\Runner\Filter\IncludeGroupFilterIterator; use PHPUnit\Runner\Filter\NameFilterIterator; use PHPUnit\Runner\StandardTestSuiteLoader; use PHPUnit\Runner\TestSuiteLoader; use PHPUnit\Runner\Version; use PHPUnit\Util\Configuration; use PHPUnit\Util\Log\JUnit; use PHPUnit\Util\Log\TeamCity; use PHPUnit\Util\Printer; use PHPUnit\Util\TestDox\HtmlResultPrinter; use PHPUnit\Util\TestDox\TextResultPrinter; use PHPUnit\Util\TestDox\XmlResultPrinter; use ReflectionClass; use SebastianBergmann; use SebastianBergmann\CodeCoverage\CodeCoverage; use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException; use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter; use SebastianBergmann\CodeCoverage\Report\Clover as CloverReport; use SebastianBergmann\CodeCoverage\Report\Crap4j as Crap4jReport; use SebastianBergmann\CodeCoverage\Report\Html\Facade as HtmlReport; use SebastianBergmann\CodeCoverage\Report\PHP as PhpReport; use SebastianBergmann\CodeCoverage\Report\Text as TextReport; use SebastianBergmann\CodeCoverage\Report\Xml\Facade as XmlReport; use SebastianBergmann\Environment\Runtime; /** * A TestRunner for the Command Line Interface (CLI) * PHP SAPI Module. */ class TestRunner extends BaseTestRunner { const SUCCESS_EXIT = 0; const FAILURE_EXIT = 1; const EXCEPTION_EXIT = 2; /** * @var CodeCoverageFilter */ protected $codeCoverageFilter; /** * @var TestSuiteLoader */ protected $loader; /** * @var ResultPrinter */ protected $printer; /** * @var bool */ protected static $versionStringPrinted = false; /** * @var Runtime */ private $runtime; /** * @var bool */ private $messagePrinted = false; /** * @param TestSuiteLoader $loader * @param CodeCoverageFilter $filter */ public function __construct(TestSuiteLoader $loader = null, CodeCoverageFilter $filter = null) { if ($filter === null) { $filter = new CodeCoverageFilter; } $this->codeCoverageFilter = $filter; $this->loader = $loader; $this->runtime = new Runtime; } /** * @param Test|ReflectionClass $test * @param array $arguments * @param bool $exit * * @return TestResult * * @throws Exception */ public static function run($test, array $arguments = [], $exit = true) { if ($test instanceof ReflectionClass) { $test = new TestSuite($test); } if ($test instanceof Test) { $aTestRunner = new self; return $aTestRunner->doRun( $test, $arguments, $exit ); } throw new Exception('No test case or test suite found.'); } /** * @return TestResult */ protected function createTestResult() { return new TestResult; } /** * @param TestSuite $suite * @param array $arguments */ private function processSuiteFilters(TestSuite $suite, array $arguments) { if (!$arguments['filter'] && empty($arguments['groups']) && empty($arguments['excludeGroups'])) { return; } $filterFactory = new Factory; if (!empty($arguments['excludeGroups'])) { $filterFactory->addFilter( new ReflectionClass(ExcludeGroupFilterIterator::class), $arguments['excludeGroups'] ); } if (!empty($arguments['groups'])) { $filterFactory->addFilter( new ReflectionClass(IncludeGroupFilterIterator::class), $arguments['groups'] ); } if ($arguments['filter']) { $filterFactory->addFilter( new ReflectionClass(NameFilterIterator::class), $arguments['filter'] ); } $suite->injectFilter($filterFactory); } /** * @param Test $suite * @param array $arguments * @param bool $exit * * @return TestResult */ public function doRun(Test $suite, array $arguments = [], $exit = true) { if (isset($arguments['configuration'])) { $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration']; } $this->handleConfiguration($arguments); $this->processSuiteFilters($suite, $arguments); if (isset($arguments['bootstrap'])) { $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap']; } if ($arguments['backupGlobals'] === true) { $suite->setBackupGlobals(true); } if ($arguments['backupStaticAttributes'] === true) { $suite->setBackupStaticAttributes(true); } if ($arguments['beStrictAboutChangesToGlobalState'] === true) { $suite->setBeStrictAboutChangesToGlobalState(true); } if (\is_int($arguments['repeat']) && $arguments['repeat'] > 0) { $_suite = new TestSuite; foreach (\range(1, $arguments['repeat']) as $step) { $_suite->addTest($suite); } $suite = $_suite; unset($_suite); } $result = $this->createTestResult(); if (!$arguments['convertErrorsToExceptions']) { $result->convertErrorsToExceptions(false); } if (!$arguments['convertDeprecationsToExceptions']) { Deprecated::$enabled = false; } if (!$arguments['convertNoticesToExceptions']) { Notice::$enabled = false; } if (!$arguments['convertWarningsToExceptions']) { Warning::$enabled = false; } if ($arguments['stopOnError']) { $result->stopOnError(true); } if ($arguments['stopOnFailure']) { $result->stopOnFailure(true); } if ($arguments['stopOnWarning']) { $result->stopOnWarning(true); } if ($arguments['stopOnIncomplete']) { $result->stopOnIncomplete(true); } if ($arguments['stopOnRisky']) { $result->stopOnRisky(true); } if ($arguments['stopOnSkipped']) { $result->stopOnSkipped(true); } if ($arguments['registerMockObjectsFromTestArgumentsRecursively']) { $result->setRegisterMockObjectsFromTestArgumentsRecursively(true); } if ($this->printer === null) { if (isset($arguments['printer']) && $arguments['printer'] instanceof Printer) { $this->printer = $arguments['printer']; } else { $printerClass = ResultPrinter::class; if (isset($arguments['printer']) && \is_string($arguments['printer']) && \class_exists($arguments['printer'], false)) { $class = new ReflectionClass($arguments['printer']); if ($class->isSubclassOf(ResultPrinter::class)) { $printerClass = $arguments['printer']; } } $this->printer = new $printerClass( (isset($arguments['stderr']) && $arguments['stderr'] === true) ? 'php://stderr' : null, $arguments['verbose'], $arguments['colors'], $arguments['debug'], $arguments['columns'], $arguments['reverseList'] ); } } $this->printer->write( Version::getVersionString() . "\n" ); self::$versionStringPrinted = true; if ($arguments['verbose']) { $runtime = $this->runtime->getNameWithVersion(); if ($this->runtime->hasXdebug()) { $runtime .= \sprintf( ' with Xdebug %s', \phpversion('xdebug') ); } $this->writeMessage('Runtime', $runtime); if (isset($arguments['configuration'])) { $this->writeMessage( 'Configuration', $arguments['configuration']->getFilename() ); } foreach ($arguments['loadedExtensions'] as $extension) { $this->writeMessage( 'Extension', $extension ); } foreach ($arguments['notLoadedExtensions'] as $extension) { $this->writeMessage( 'Extension', $extension ); } } if ($this->runtime->discardsComments()) { $this->writeMessage('Warning', 'opcache.save_comments=0 set; annotations will not work'); } foreach ($arguments['listeners'] as $listener) { $result->addListener($listener); } $result->addListener($this->printer); $codeCoverageReports = 0; if (!isset($arguments['noLogging'])) { if (isset($arguments['testdoxHTMLFile'])) { $result->addListener( new HtmlResultPrinter( $arguments['testdoxHTMLFile'], $arguments['testdoxGroups'], $arguments['testdoxExcludeGroups'] ) ); } if (isset($arguments['testdoxTextFile'])) { $result->addListener( new TextResultPrinter( $arguments['testdoxTextFile'], $arguments['testdoxGroups'], $arguments['testdoxExcludeGroups'] ) ); } if (isset($arguments['testdoxXMLFile'])) { $result->addListener( new XmlResultPrinter( $arguments['testdoxXMLFile'] ) ); } if (isset($arguments['teamcityLogfile'])) { $result->addListener( new TeamCity($arguments['teamcityLogfile']) ); } if (isset($arguments['junitLogfile'])) { $result->addListener( new JUnit( $arguments['junitLogfile'], $arguments['reportUselessTests'] ) ); } if (isset($arguments['coverageClover'])) { $codeCoverageReports++; } if (isset($arguments['coverageCrap4J'])) { $codeCoverageReports++; } if (isset($arguments['coverageHtml'])) { $codeCoverageReports++; } if (isset($arguments['coveragePHP'])) { $codeCoverageReports++; } if (isset($arguments['coverageText'])) { $codeCoverageReports++; } if (isset($arguments['coverageXml'])) { $codeCoverageReports++; } } if (isset($arguments['noCoverage'])) { $codeCoverageReports = 0; } if ($codeCoverageReports > 0 && !$this->runtime->canCollectCodeCoverage()) { $this->writeMessage('Error', 'No code coverage driver is available'); $codeCoverageReports = 0; } if ($codeCoverageReports > 0) { $codeCoverage = new CodeCoverage( null, $this->codeCoverageFilter ); $codeCoverage->setUnintentionallyCoveredSubclassesWhitelist( [SebastianBergmann\Comparator\Comparator::class] ); $codeCoverage->setCheckForUnintentionallyCoveredCode( $arguments['strictCoverage'] ); $codeCoverage->setCheckForMissingCoversAnnotation( $arguments['strictCoverage'] ); if (isset($arguments['forceCoversAnnotation'])) { $codeCoverage->setForceCoversAnnotation( $arguments['forceCoversAnnotation'] ); } if (isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) { $codeCoverage->setIgnoreDeprecatedCode( $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] ); } if (isset($arguments['disableCodeCoverageIgnore'])) { $codeCoverage->setDisableIgnoredLines(true); } $whitelistFromConfigurationFile = false; $whitelistFromOption = false; if (isset($arguments['whitelist'])) { $this->codeCoverageFilter->addDirectoryToWhitelist($arguments['whitelist']); $whitelistFromOption = true; } if (isset($arguments['configuration'])) { $filterConfiguration = $arguments['configuration']->getFilterConfiguration(); if (!empty($filterConfiguration['whitelist'])) { $whitelistFromConfigurationFile = true; } if (!empty($filterConfiguration['whitelist'])) { $codeCoverage->setAddUncoveredFilesFromWhitelist( $filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist'] ); $codeCoverage->setProcessUncoveredFilesFromWhitelist( $filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist'] ); foreach ($filterConfiguration['whitelist']['include']['directory'] as $dir) { $this->codeCoverageFilter->addDirectoryToWhitelist( $dir['path'], $dir['suffix'], $dir['prefix'] ); } foreach ($filterConfiguration['whitelist']['include']['file'] as $file) { $this->codeCoverageFilter->addFileToWhitelist($file); } foreach ($filterConfiguration['whitelist']['exclude']['directory'] as $dir) { $this->codeCoverageFilter->removeDirectoryFromWhitelist( $dir['path'], $dir['suffix'], $dir['prefix'] ); } foreach ($filterConfiguration['whitelist']['exclude']['file'] as $file) { $this->codeCoverageFilter->removeFileFromWhitelist($file); } } } if (isset($codeCoverage) && !$this->codeCoverageFilter->hasWhitelist()) { if (!$whitelistFromConfigurationFile && !$whitelistFromOption) { $this->writeMessage('Error', 'No whitelist is configured, no code coverage will be generated.'); } else { $this->writeMessage('Error', 'Incorrect whitelist config, no code coverage will be generated.'); } $codeCoverageReports = 0; unset($codeCoverage); } } $this->printer->write("\n"); if (isset($codeCoverage)) { $result->setCodeCoverage($codeCoverage); if ($codeCoverageReports > 1 && isset($arguments['cacheTokens'])) { $codeCoverage->setCacheTokens($arguments['cacheTokens']); } } $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']); $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']); $result->beStrictAboutTodoAnnotatedTests($arguments['disallowTodoAnnotatedTests']); $result->beStrictAboutResourceUsageDuringSmallTests($arguments['beStrictAboutResourceUsageDuringSmallTests']); $result->enforceTimeLimit($arguments['enforceTimeLimit']); $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']); $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']); $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']); if ($suite instanceof TestSuite) { $suite->setRunTestInSeparateProcess($arguments['processIsolation']); } $suite->run($result); unset($suite); $result->flushListeners(); if ($this->printer instanceof ResultPrinter) { $this->printer->printResult($result); } if (isset($codeCoverage)) { if (isset($arguments['coverageClover'])) { $this->printer->write( "\nGenerating code coverage report in Clover XML format ..." ); try { $writer = new CloverReport; $writer->process($codeCoverage, $arguments['coverageClover']); $this->printer->write(" done\n"); unset($writer); } catch (CodeCoverageException $e) { $this->printer->write( " failed\n" . $e->getMessage() . "\n" ); } } if (isset($arguments['coverageCrap4J'])) { $this->printer->write( "\nGenerating Crap4J report XML file ..." ); try { $writer = new Crap4jReport($arguments['crap4jThreshold']); $writer->process($codeCoverage, $arguments['coverageCrap4J']); $this->printer->write(" done\n"); unset($writer); } catch (CodeCoverageException $e) { $this->printer->write( " failed\n" . $e->getMessage() . "\n" ); } } if (isset($arguments['coverageHtml'])) { $this->printer->write( "\nGenerating code coverage report in HTML format ..." ); try { $writer = new HtmlReport( $arguments['reportLowUpperBound'], $arguments['reportHighLowerBound'], \sprintf( ' and PHPUnit %s', Version::id() ) ); $writer->process($codeCoverage, $arguments['coverageHtml']); $this->printer->write(" done\n"); unset($writer); } catch (CodeCoverageException $e) { $this->printer->write( " failed\n" . $e->getMessage() . "\n" ); } } if (isset($arguments['coveragePHP'])) { $this->printer->write( "\nGenerating code coverage report in PHP format ..." ); try { $writer = new PhpReport; $writer->process($codeCoverage, $arguments['coveragePHP']); $this->printer->write(" done\n"); unset($writer); } catch (CodeCoverageException $e) { $this->printer->write( " failed\n" . $e->getMessage() . "\n" ); } } if (isset($arguments['coverageText'])) { if ($arguments['coverageText'] == 'php://stdout') { $outputStream = $this->printer; $colors = $arguments['colors'] && $arguments['colors'] != ResultPrinter::COLOR_NEVER; } else { $outputStream = new Printer($arguments['coverageText']); $colors = false; } $processor = new TextReport( $arguments['reportLowUpperBound'], $arguments['reportHighLowerBound'], $arguments['coverageTextShowUncoveredFiles'], $arguments['coverageTextShowOnlySummary'] ); $outputStream->write( $processor->process($codeCoverage, $colors) ); } if (isset($arguments['coverageXml'])) { $this->printer->write( "\nGenerating code coverage report in PHPUnit XML format ..." ); try { $writer = new XmlReport(Version::id()); $writer->process($codeCoverage, $arguments['coverageXml']); $this->printer->write(" done\n"); unset($writer); } catch (CodeCoverageException $e) { $this->printer->write( " failed\n" . $e->getMessage() . "\n" ); } } } if ($exit) { if ($result->wasSuccessful()) { if ($arguments['failOnRisky'] && !$result->allHarmless()) { exit(self::FAILURE_EXIT); } if ($arguments['failOnWarning'] && $result->warningCount() > 0) { exit(self::FAILURE_EXIT); } exit(self::SUCCESS_EXIT); } if ($result->errorCount() > 0) { exit(self::EXCEPTION_EXIT); } if ($result->failureCount() > 0) { exit(self::FAILURE_EXIT); } } return $result; } /** * @param ResultPrinter $resultPrinter */ public function setPrinter(ResultPrinter $resultPrinter) { $this->printer = $resultPrinter; } /** * Override to define how to handle a failed loading of * a test suite. * * @param string $message */ protected function runFailed($message) { $this->write($message . PHP_EOL); exit(self::FAILURE_EXIT); } /** * @param string $buffer */ protected function write($buffer) { if (PHP_SAPI != 'cli' && PHP_SAPI != 'phpdbg') { $buffer = \htmlspecialchars($buffer); } if ($this->printer !== null) { $this->printer->write($buffer); } else { print $buffer; } } /** * Returns the loader to be used. * * @return TestSuiteLoader */ public function getLoader() { if ($this->loader === null) { $this->loader = new StandardTestSuiteLoader; } return $this->loader; } /** * @param array $arguments */ protected function handleConfiguration(array &$arguments) { if (isset($arguments['configuration']) && !$arguments['configuration'] instanceof Configuration) { $arguments['configuration'] = Configuration::getInstance( $arguments['configuration'] ); } $arguments['debug'] = $arguments['debug'] ?? false; $arguments['filter'] = $arguments['filter'] ?? false; $arguments['listeners'] = $arguments['listeners'] ?? []; if (isset($arguments['configuration'])) { $arguments['configuration']->handlePHPConfiguration(); $phpunitConfiguration = $arguments['configuration']->getPHPUnitConfiguration(); if (isset($phpunitConfiguration['backupGlobals']) && !isset($arguments['backupGlobals'])) { $arguments['backupGlobals'] = $phpunitConfiguration['backupGlobals']; } if (isset($phpunitConfiguration['backupStaticAttributes']) && !isset($arguments['backupStaticAttributes'])) { $arguments['backupStaticAttributes'] = $phpunitConfiguration['backupStaticAttributes']; } if (isset($phpunitConfiguration['beStrictAboutChangesToGlobalState']) && !isset($arguments['beStrictAboutChangesToGlobalState'])) { $arguments['beStrictAboutChangesToGlobalState'] = $phpunitConfiguration['beStrictAboutChangesToGlobalState']; } if (isset($phpunitConfiguration['bootstrap']) && !isset($arguments['bootstrap'])) { $arguments['bootstrap'] = $phpunitConfiguration['bootstrap']; } if (isset($phpunitConfiguration['cacheTokens']) && !isset($arguments['cacheTokens'])) { $arguments['cacheTokens'] = $phpunitConfiguration['cacheTokens']; } if (isset($phpunitConfiguration['colors']) && !isset($arguments['colors'])) { $arguments['colors'] = $phpunitConfiguration['colors']; } if (isset($phpunitConfiguration['convertDeprecationsToExceptions']) && !isset($arguments['convertDeprecationsToExceptions'])) { $arguments['convertDeprecationsToExceptions'] = $phpunitConfiguration['convertDeprecationsToExceptions']; } if (isset($phpunitConfiguration['convertErrorsToExceptions']) && !isset($arguments['convertErrorsToExceptions'])) { $arguments['convertErrorsToExceptions'] = $phpunitConfiguration['convertErrorsToExceptions']; } if (isset($phpunitConfiguration['convertNoticesToExceptions']) && !isset($arguments['convertNoticesToExceptions'])) { $arguments['convertNoticesToExceptions'] = $phpunitConfiguration['convertNoticesToExceptions']; } if (isset($phpunitConfiguration['convertWarningsToExceptions']) && !isset($arguments['convertWarningsToExceptions'])) { $arguments['convertWarningsToExceptions'] = $phpunitConfiguration['convertWarningsToExceptions']; } if (isset($phpunitConfiguration['processIsolation']) && !isset($arguments['processIsolation'])) { $arguments['processIsolation'] = $phpunitConfiguration['processIsolation']; } if (isset($phpunitConfiguration['stopOnError']) && !isset($arguments['stopOnError'])) { $arguments['stopOnError'] = $phpunitConfiguration['stopOnError']; } if (isset($phpunitConfiguration['stopOnFailure']) && !isset($arguments['stopOnFailure'])) { $arguments['stopOnFailure'] = $phpunitConfiguration['stopOnFailure']; } if (isset($phpunitConfiguration['stopOnWarning']) && !isset($arguments['stopOnWarning'])) { $arguments['stopOnWarning'] = $phpunitConfiguration['stopOnWarning']; } if (isset($phpunitConfiguration['stopOnIncomplete']) && !isset($arguments['stopOnIncomplete'])) { $arguments['stopOnIncomplete'] = $phpunitConfiguration['stopOnIncomplete']; } if (isset($phpunitConfiguration['stopOnRisky']) && !isset($arguments['stopOnRisky'])) { $arguments['stopOnRisky'] = $phpunitConfiguration['stopOnRisky']; } if (isset($phpunitConfiguration['stopOnSkipped']) && !isset($arguments['stopOnSkipped'])) { $arguments['stopOnSkipped'] = $phpunitConfiguration['stopOnSkipped']; } if (isset($phpunitConfiguration['failOnWarning']) && !isset($arguments['failOnWarning'])) { $arguments['failOnWarning'] = $phpunitConfiguration['failOnWarning']; } if (isset($phpunitConfiguration['failOnRisky']) && !isset($arguments['failOnRisky'])) { $arguments['failOnRisky'] = $phpunitConfiguration['failOnRisky']; } if (isset($phpunitConfiguration['timeoutForSmallTests']) && !isset($arguments['timeoutForSmallTests'])) { $arguments['timeoutForSmallTests'] = $phpunitConfiguration['timeoutForSmallTests']; } if (isset($phpunitConfiguration['timeoutForMediumTests']) && !isset($arguments['timeoutForMediumTests'])) { $arguments['timeoutForMediumTests'] = $phpunitConfiguration['timeoutForMediumTests']; } if (isset($phpunitConfiguration['timeoutForLargeTests']) && !isset($arguments['timeoutForLargeTests'])) { $arguments['timeoutForLargeTests'] = $phpunitConfiguration['timeoutForLargeTests']; } if (isset($phpunitConfiguration['reportUselessTests']) && !isset($arguments['reportUselessTests'])) { $arguments['reportUselessTests'] = $phpunitConfiguration['reportUselessTests']; } if (isset($phpunitConfiguration['strictCoverage']) && !isset($arguments['strictCoverage'])) { $arguments['strictCoverage'] = $phpunitConfiguration['strictCoverage']; } if (isset($phpunitConfiguration['ignoreDeprecatedCodeUnitsFromCodeCoverage']) && !isset($arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'])) { $arguments['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $phpunitConfiguration['ignoreDeprecatedCodeUnitsFromCodeCoverage']; } if (isset($phpunitConfiguration['disallowTestOutput']) && !isset($arguments['disallowTestOutput'])) { $arguments['disallowTestOutput'] = $phpunitConfiguration['disallowTestOutput']; } if (isset($phpunitConfiguration['enforceTimeLimit']) && !isset($arguments['enforceTimeLimit'])) { $arguments['enforceTimeLimit'] = $phpunitConfiguration['enforceTimeLimit']; } if (isset($phpunitConfiguration['disallowTodoAnnotatedTests']) && !isset($arguments['disallowTodoAnnotatedTests'])) { $arguments['disallowTodoAnnotatedTests'] = $phpunitConfiguration['disallowTodoAnnotatedTests']; } if (isset($phpunitConfiguration['beStrictAboutResourceUsageDuringSmallTests']) && !isset($arguments['beStrictAboutResourceUsageDuringSmallTests'])) { $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $phpunitConfiguration['beStrictAboutResourceUsageDuringSmallTests']; } if (isset($phpunitConfiguration['verbose']) && !isset($arguments['verbose'])) { $arguments['verbose'] = $phpunitConfiguration['verbose']; } if (isset($phpunitConfiguration['reverseDefectList']) && !isset($arguments['reverseList'])) { $arguments['reverseList'] = $phpunitConfiguration['reverseDefectList']; } if (isset($phpunitConfiguration['forceCoversAnnotation']) && !isset($arguments['forceCoversAnnotation'])) { $arguments['forceCoversAnnotation'] = $phpunitConfiguration['forceCoversAnnotation']; } if (isset($phpunitConfiguration['disableCodeCoverageIgnore']) && !isset($arguments['disableCodeCoverageIgnore'])) { $arguments['disableCodeCoverageIgnore'] = $phpunitConfiguration['disableCodeCoverageIgnore']; } if (isset($phpunitConfiguration['registerMockObjectsFromTestArgumentsRecursively']) && !isset($arguments['registerMockObjectsFromTestArgumentsRecursively'])) { $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $phpunitConfiguration['registerMockObjectsFromTestArgumentsRecursively']; } $groupCliArgs = []; if (!empty($arguments['groups'])) { $groupCliArgs = $arguments['groups']; } $groupConfiguration = $arguments['configuration']->getGroupConfiguration(); if (!empty($groupConfiguration['include']) && !isset($arguments['groups'])) { $arguments['groups'] = $groupConfiguration['include']; } if (!empty($groupConfiguration['exclude']) && !isset($arguments['excludeGroups'])) { $arguments['excludeGroups'] = \array_diff($groupConfiguration['exclude'], $groupCliArgs); } foreach ($arguments['configuration']->getListenerConfiguration() as $listener) { if (!\class_exists($listener['class'], false) && $listener['file'] !== '') { require_once $listener['file']; } if (!\class_exists($listener['class'])) { throw new Exception( \sprintf( 'Class "%s" does not exist', $listener['class'] ) ); } $listenerClass = new ReflectionClass($listener['class']); if (!$listenerClass->implementsInterface(TestListener::class)) { throw new Exception( \sprintf( 'Class "%s" does not implement the PHPUnit\Framework\TestListener interface', $listener['class'] ) ); } if (\count($listener['arguments']) == 0) { $listener = new $listener['class']; } else { $listener = $listenerClass->newInstanceArgs( $listener['arguments'] ); } $arguments['listeners'][] = $listener; } $loggingConfiguration = $arguments['configuration']->getLoggingConfiguration(); if (isset($loggingConfiguration['coverage-clover']) && !isset($arguments['coverageClover'])) { $arguments['coverageClover'] = $loggingConfiguration['coverage-clover']; } if (isset($loggingConfiguration['coverage-crap4j']) && !isset($arguments['coverageCrap4J'])) { $arguments['coverageCrap4J'] = $loggingConfiguration['coverage-crap4j']; if (isset($loggingConfiguration['crap4jThreshold']) && !isset($arguments['crap4jThreshold'])) { $arguments['crap4jThreshold'] = $loggingConfiguration['crap4jThreshold']; } } if (isset($loggingConfiguration['coverage-html']) && !isset($arguments['coverageHtml'])) { if (isset($loggingConfiguration['lowUpperBound']) && !isset($arguments['reportLowUpperBound'])) { $arguments['reportLowUpperBound'] = $loggingConfiguration['lowUpperBound']; } if (isset($loggingConfiguration['highLowerBound']) && !isset($arguments['reportHighLowerBound'])) { $arguments['reportHighLowerBound'] = $loggingConfiguration['highLowerBound']; } $arguments['coverageHtml'] = $loggingConfiguration['coverage-html']; } if (isset($loggingConfiguration['coverage-php']) && !isset($arguments['coveragePHP'])) { $arguments['coveragePHP'] = $loggingConfiguration['coverage-php']; } if (isset($loggingConfiguration['coverage-text']) && !isset($arguments['coverageText'])) { $arguments['coverageText'] = $loggingConfiguration['coverage-text']; if (isset($loggingConfiguration['coverageTextShowUncoveredFiles'])) { $arguments['coverageTextShowUncoveredFiles'] = $loggingConfiguration['coverageTextShowUncoveredFiles']; } else { $arguments['coverageTextShowUncoveredFiles'] = false; } if (isset($loggingConfiguration['coverageTextShowOnlySummary'])) { $arguments['coverageTextShowOnlySummary'] = $loggingConfiguration['coverageTextShowOnlySummary']; } else { $arguments['coverageTextShowOnlySummary'] = false; } } if (isset($loggingConfiguration['coverage-xml']) && !isset($arguments['coverageXml'])) { $arguments['coverageXml'] = $loggingConfiguration['coverage-xml']; } if (isset($loggingConfiguration['plain'])) { $arguments['listeners'][] = new ResultPrinter( $loggingConfiguration['plain'], true ); } if (isset($loggingConfiguration['teamcity']) && !isset($arguments['teamcityLogfile'])) { $arguments['teamcityLogfile'] = $loggingConfiguration['teamcity']; } if (isset($loggingConfiguration['junit']) && !isset($arguments['junitLogfile'])) { $arguments['junitLogfile'] = $loggingConfiguration['junit']; } if (isset($loggingConfiguration['testdox-html']) && !isset($arguments['testdoxHTMLFile'])) { $arguments['testdoxHTMLFile'] = $loggingConfiguration['testdox-html']; } if (isset($loggingConfiguration['testdox-text']) && !isset($arguments['testdoxTextFile'])) { $arguments['testdoxTextFile'] = $loggingConfiguration['testdox-text']; } if (isset($loggingConfiguration['testdox-xml']) && !isset($arguments['testdoxXMLFile'])) { $arguments['testdoxXMLFile'] = $loggingConfiguration['testdox-xml']; } $testdoxGroupConfiguration = $arguments['configuration']->getTestdoxGroupConfiguration(); if (isset($testdoxGroupConfiguration['include']) && !isset($arguments['testdoxGroups'])) { $arguments['testdoxGroups'] = $testdoxGroupConfiguration['include']; } if (isset($testdoxGroupConfiguration['exclude']) && !isset($arguments['testdoxExcludeGroups'])) { $arguments['testdoxExcludeGroups'] = $testdoxGroupConfiguration['exclude']; } } $arguments['addUncoveredFilesFromWhitelist'] = $arguments['addUncoveredFilesFromWhitelist'] ?? true; $arguments['backupGlobals'] = $arguments['backupGlobals'] ?? null; $arguments['backupStaticAttributes'] = $arguments['backupStaticAttributes'] ?? null; $arguments['beStrictAboutChangesToGlobalState'] = $arguments['beStrictAboutChangesToGlobalState'] ?? null; $arguments['beStrictAboutResourceUsageDuringSmallTests'] = $arguments['beStrictAboutResourceUsageDuringSmallTests'] ?? false; $arguments['cacheTokens'] = $arguments['cacheTokens'] ?? false; $arguments['colors'] = $arguments['colors'] ?? ResultPrinter::COLOR_DEFAULT; $arguments['columns'] = $arguments['columns'] ?? 80; $arguments['convertDeprecationsToExceptions'] = $arguments['convertDeprecationsToExceptions'] ?? true; $arguments['convertErrorsToExceptions'] = $arguments['convertErrorsToExceptions'] ?? true; $arguments['convertNoticesToExceptions'] = $arguments['convertNoticesToExceptions'] ?? true; $arguments['convertWarningsToExceptions'] = $arguments['convertWarningsToExceptions'] ?? true; $arguments['crap4jThreshold'] = $arguments['crap4jThreshold'] ?? 30; $arguments['disallowTestOutput'] = $arguments['disallowTestOutput'] ?? false; $arguments['disallowTodoAnnotatedTests'] = $arguments['disallowTodoAnnotatedTests'] ?? false; $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? false; $arguments['excludeGroups'] = $arguments['excludeGroups'] ?? []; $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? false; $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? false; $arguments['groups'] = $arguments['groups'] ?? []; $arguments['processIsolation'] = $arguments['processIsolation'] ?? false; $arguments['processUncoveredFilesFromWhitelist'] = $arguments['processUncoveredFilesFromWhitelist'] ?? false; $arguments['registerMockObjectsFromTestArgumentsRecursively'] = $arguments['registerMockObjectsFromTestArgumentsRecursively'] ?? false; $arguments['repeat'] = $arguments['repeat'] ?? false; $arguments['reportHighLowerBound'] = $arguments['reportHighLowerBound'] ?? 90; $arguments['reportLowUpperBound'] = $arguments['reportLowUpperBound'] ?? 50; $arguments['reportUselessTests'] = $arguments['reportUselessTests'] ?? true; $arguments['reverseList'] = $arguments['reverseList'] ?? false; $arguments['stopOnError'] = $arguments['stopOnError'] ?? false; $arguments['stopOnFailure'] = $arguments['stopOnFailure'] ?? false; $arguments['stopOnIncomplete'] = $arguments['stopOnIncomplete'] ?? false; $arguments['stopOnRisky'] = $arguments['stopOnRisky'] ?? false; $arguments['stopOnSkipped'] = $arguments['stopOnSkipped'] ?? false; $arguments['stopOnWarning'] = $arguments['stopOnWarning'] ?? false; $arguments['strictCoverage'] = $arguments['strictCoverage'] ?? false; $arguments['testdoxExcludeGroups'] = $arguments['testdoxExcludeGroups'] ?? []; $arguments['testdoxGroups'] = $arguments['testdoxGroups'] ?? []; $arguments['timeoutForLargeTests'] = $arguments['timeoutForLargeTests'] ?? 60; $arguments['timeoutForMediumTests'] = $arguments['timeoutForMediumTests'] ?? 10; $arguments['timeoutForSmallTests'] = $arguments['timeoutForSmallTests'] ?? 1; $arguments['verbose'] = $arguments['verbose'] ?? false; } /** * @param string $type * @param string $message */ private function writeMessage($type, $message) { if (!$this->messagePrinted) { $this->write("\n"); } $this->write( \sprintf( "%-15s%s\n", $type . ':', $message ) ); $this->messagePrinted = true; } } phpunit-6.5.5/src/Util/000077500000000000000000000000001321540746700147335ustar00rootroot00000000000000phpunit-6.5.5/src/Util/Blacklist.php000066400000000000000000000064671321540746700173710ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use ReflectionClass; /** * Utility class for blacklisting PHPUnit's own source code files. */ class Blacklist { /** * @var array */ public static $blacklistedClassNames = [ 'File_Iterator' => 1, 'PHP_Invoker' => 1, 'PHP_Timer' => 1, 'PHP_Token' => 1, 'PHPUnit\Framework\TestCase' => 2, 'PHPUnit\DbUnit\TestCase' => 2, 'PHPUnit\Framework\MockObject\Generator' => 1, 'Text_Template' => 1, 'Symfony\Component\Yaml\Yaml' => 1, 'SebastianBergmann\CodeCoverage\CodeCoverage' => 1, 'SebastianBergmann\Diff\Diff' => 1, 'SebastianBergmann\Environment\Runtime' => 1, 'SebastianBergmann\Comparator\Comparator' => 1, 'SebastianBergmann\Exporter\Exporter' => 1, 'SebastianBergmann\GlobalState\Snapshot' => 1, 'SebastianBergmann\RecursionContext\Context' => 1, 'SebastianBergmann\Version' => 1, 'Composer\Autoload\ClassLoader' => 1, 'Doctrine\Instantiator\Instantiator' => 1, 'phpDocumentor\Reflection\DocBlock' => 1, 'Prophecy\Prophet' => 1, 'DeepCopy\DeepCopy' => 1 ]; /** * @var string[] */ private static $directories; /** * @return string[] */ public function getBlacklistedDirectories() { $this->initialize(); return self::$directories; } /** * @param string $file * * @return bool */ public function isBlacklisted($file) { if (\defined('PHPUNIT_TESTSUITE')) { return false; } $this->initialize(); foreach (self::$directories as $directory) { if (\strpos($file, $directory) === 0) { return true; } } return false; } private function initialize() { if (self::$directories === null) { self::$directories = []; foreach (self::$blacklistedClassNames as $className => $parent) { if (!\class_exists($className)) { continue; } $reflector = new ReflectionClass($className); $directory = $reflector->getFileName(); for ($i = 0; $i < $parent; $i++) { $directory = \dirname($directory); } self::$directories[] = $directory; } // Hide process isolation workaround on Windows. if (DIRECTORY_SEPARATOR === '\\') { // tempnam() prefix is limited to first 3 chars. // @see http://php.net/manual/en/function.tempnam.php self::$directories[] = \sys_get_temp_dir() . '\\PHP'; } } } } phpunit-6.5.5/src/Util/Configuration.php000066400000000000000000001101671321540746700202610ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use DOMElement; use DOMXPath; use File_Iterator_Facade; use PHPUnit\Framework\Exception; use PHPUnit\Framework\TestSuite; use PHPUnit\TextUI\ResultPrinter; /** * Wrapper for the PHPUnit XML configuration file. * * Example XML configuration file: * * * * * * * /path/to/files * /path/to/MyTest.php * /path/to/files/exclude * * * * * * name * * * name * * * * * * name * * * name * * * * * * /path/to/files * /path/to/file * * /path/to/files * /path/to/file * * * * * * * * * * Sebastian * * * 22 * April * 19.78 * * * MyRelativeFile.php * MyRelativeDir * * * * * * * * * * * * * * * * * * * . * * * * * * * * * * * * * */ class Configuration { const TEST_SUITE_FILTER_SEPARATOR = ','; private static $instances = []; protected $document; protected $xpath; protected $filename; /** * Loads a PHPUnit configuration file. * * @param string $filename */ protected function __construct($filename) { $this->filename = $filename; $this->document = Xml::loadFile($filename, false, true, true); $this->xpath = new DOMXPath($this->document); } final private function __clone() { } /** * Returns a PHPUnit configuration object. * * @param string $filename * * @return Configuration */ public static function getInstance($filename) { $realpath = \realpath($filename); if ($realpath === false) { throw new Exception( \sprintf( 'Could not read "%s".', $filename ) ); } if (!isset(self::$instances[$realpath])) { self::$instances[$realpath] = new self($realpath); } return self::$instances[$realpath]; } /** * Returns the realpath to the configuration file. * * @return string */ public function getFilename() { return $this->filename; } /** * Returns the configuration for SUT filtering. * * @return array */ public function getFilterConfiguration() { $addUncoveredFilesFromWhitelist = true; $processUncoveredFilesFromWhitelist = false; $includeDirectory = []; $includeFile = []; $excludeDirectory = []; $excludeFile = []; $tmp = $this->xpath->query('filter/whitelist'); if ($tmp->length === 1) { if ($tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) { $addUncoveredFilesFromWhitelist = $this->getBoolean( (string) $tmp->item(0)->getAttribute( 'addUncoveredFilesFromWhitelist' ), true ); } if ($tmp->item(0)->hasAttribute('processUncoveredFilesFromWhitelist')) { $processUncoveredFilesFromWhitelist = $this->getBoolean( (string) $tmp->item(0)->getAttribute( 'processUncoveredFilesFromWhitelist' ), false ); } $includeDirectory = $this->readFilterDirectories( 'filter/whitelist/directory' ); $includeFile = $this->readFilterFiles( 'filter/whitelist/file' ); $excludeDirectory = $this->readFilterDirectories( 'filter/whitelist/exclude/directory' ); $excludeFile = $this->readFilterFiles( 'filter/whitelist/exclude/file' ); } return [ 'whitelist' => [ 'addUncoveredFilesFromWhitelist' => $addUncoveredFilesFromWhitelist, 'processUncoveredFilesFromWhitelist' => $processUncoveredFilesFromWhitelist, 'include' => [ 'directory' => $includeDirectory, 'file' => $includeFile ], 'exclude' => [ 'directory' => $excludeDirectory, 'file' => $excludeFile ] ] ]; } /** * Returns the configuration for groups. * * @return array */ public function getGroupConfiguration() { return $this->parseGroupConfiguration('groups'); } /** * Returns the configuration for testdox groups. * * @return array */ public function getTestdoxGroupConfiguration() { return $this->parseGroupConfiguration('testdoxGroups'); } /** * @param string $root * * @return array */ private function parseGroupConfiguration($root) { $groups = [ 'include' => [], 'exclude' => [] ]; foreach ($this->xpath->query($root . '/include/group') as $group) { $groups['include'][] = (string) $group->textContent; } foreach ($this->xpath->query($root . '/exclude/group') as $group) { $groups['exclude'][] = (string) $group->textContent; } return $groups; } /** * Returns the configuration for listeners. * * @return array */ public function getListenerConfiguration() { $result = []; foreach ($this->xpath->query('listeners/listener') as $listener) { $class = (string) $listener->getAttribute('class'); $file = ''; $arguments = []; if ($listener->getAttribute('file')) { $file = $this->toAbsolutePath( (string) $listener->getAttribute('file'), true ); } foreach ($listener->childNodes as $node) { if ($node instanceof DOMElement && $node->tagName == 'arguments') { foreach ($node->childNodes as $argument) { if ($argument instanceof DOMElement) { if ($argument->tagName == 'file' || $argument->tagName == 'directory') { $arguments[] = $this->toAbsolutePath((string) $argument->textContent); } else { $arguments[] = Xml::xmlToVariable($argument); } } } } } $result[] = [ 'class' => $class, 'file' => $file, 'arguments' => $arguments ]; } return $result; } /** * Returns the logging configuration. * * @return array */ public function getLoggingConfiguration() { $result = []; foreach ($this->xpath->query('logging/log') as $log) { $type = (string) $log->getAttribute('type'); $target = (string) $log->getAttribute('target'); if (!$target) { continue; } $target = $this->toAbsolutePath($target); if ($type == 'coverage-html') { if ($log->hasAttribute('lowUpperBound')) { $result['lowUpperBound'] = $this->getInteger( (string) $log->getAttribute('lowUpperBound'), 50 ); } if ($log->hasAttribute('highLowerBound')) { $result['highLowerBound'] = $this->getInteger( (string) $log->getAttribute('highLowerBound'), 90 ); } } elseif ($type == 'coverage-crap4j') { if ($log->hasAttribute('threshold')) { $result['crap4jThreshold'] = $this->getInteger( (string) $log->getAttribute('threshold'), 30 ); } } elseif ($type == 'coverage-text') { if ($log->hasAttribute('showUncoveredFiles')) { $result['coverageTextShowUncoveredFiles'] = $this->getBoolean( (string) $log->getAttribute('showUncoveredFiles'), false ); } if ($log->hasAttribute('showOnlySummary')) { $result['coverageTextShowOnlySummary'] = $this->getBoolean( (string) $log->getAttribute('showOnlySummary'), false ); } } $result[$type] = $target; } return $result; } /** * Returns the PHP configuration. * * @return array */ public function getPHPConfiguration() { $result = [ 'include_path' => [], 'ini' => [], 'const' => [], 'var' => [], 'env' => [], 'post' => [], 'get' => [], 'cookie' => [], 'server' => [], 'files' => [], 'request' => [] ]; foreach ($this->xpath->query('php/includePath') as $includePath) { $path = (string) $includePath->textContent; if ($path) { $result['include_path'][] = $this->toAbsolutePath($path); } } foreach ($this->xpath->query('php/ini') as $ini) { $name = (string) $ini->getAttribute('name'); $value = (string) $ini->getAttribute('value'); $result['ini'][$name]['value'] = $value; } foreach ($this->xpath->query('php/const') as $const) { $name = (string) $const->getAttribute('name'); $value = (string) $const->getAttribute('value'); $result['const'][$name]['value'] = $this->getBoolean($value, $value); } foreach (['var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) { foreach ($this->xpath->query('php/' . $array) as $var) { $name = (string) $var->getAttribute('name'); $value = (string) $var->getAttribute('value'); $verbatim = false; $force = false; if ($var->hasAttribute('verbatim')) { $verbatim = $this->getBoolean($var->getAttribute('verbatim'), false); $result[$array][$name]['verbatim'] = $verbatim; } if ($var->hasAttribute('force')) { $force = $this->getBoolean($var->getAttribute('force'), false); $result[$array][$name]['force'] = $force; } if (!$verbatim) { $value = $this->getBoolean($value, $value); } $result[$array][$name]['value'] = $value; } } return $result; } /** * Handles the PHP configuration. */ public function handlePHPConfiguration() { $configuration = $this->getPHPConfiguration(); if (!empty($configuration['include_path'])) { \ini_set( 'include_path', \implode(PATH_SEPARATOR, $configuration['include_path']) . PATH_SEPARATOR . \ini_get('include_path') ); } foreach ($configuration['ini'] as $name => $data) { $value = $data['value']; if (\defined($value)) { $value = (string) \constant($value); } \ini_set($name, $value); } foreach ($configuration['const'] as $name => $data) { $value = $data['value']; if (!\defined($name)) { \define($name, $value); } } foreach (['var', 'post', 'get', 'cookie', 'server', 'files', 'request'] as $array) { // See https://github.com/sebastianbergmann/phpunit/issues/277 switch ($array) { case 'var': $target = &$GLOBALS; break; case 'server': $target = &$_SERVER; break; default: $target = &$GLOBALS['_' . \strtoupper($array)]; break; } foreach ($configuration[$array] as $name => $data) { $target[$name] = $data['value']; } } foreach ($configuration['env'] as $name => $data) { $value = $data['value']; $force = isset($data['force']) ? $data['force'] : false; if ($force || false === \getenv($name)) { \putenv("{$name}={$value}"); } if (!isset($_ENV[$name])) { $_ENV[$name] = $value; } if (true === $force) { $_ENV[$name] = $value; } } } /** * Returns the PHPUnit configuration. * * @return array */ public function getPHPUnitConfiguration() { $result = []; $root = $this->document->documentElement; if ($root->hasAttribute('cacheTokens')) { $result['cacheTokens'] = $this->getBoolean( (string) $root->getAttribute('cacheTokens'), false ); } if ($root->hasAttribute('columns')) { $columns = (string) $root->getAttribute('columns'); if ($columns == 'max') { $result['columns'] = 'max'; } else { $result['columns'] = $this->getInteger($columns, 80); } } if ($root->hasAttribute('colors')) { /* only allow boolean for compatibility with previous versions 'always' only allowed from command line */ if ($this->getBoolean($root->getAttribute('colors'), false)) { $result['colors'] = ResultPrinter::COLOR_AUTO; } else { $result['colors'] = ResultPrinter::COLOR_NEVER; } } /* * Issue #657 */ if ($root->hasAttribute('stderr')) { $result['stderr'] = $this->getBoolean( (string) $root->getAttribute('stderr'), false ); } if ($root->hasAttribute('backupGlobals')) { $result['backupGlobals'] = $this->getBoolean( (string) $root->getAttribute('backupGlobals'), false ); } if ($root->hasAttribute('backupStaticAttributes')) { $result['backupStaticAttributes'] = $this->getBoolean( (string) $root->getAttribute('backupStaticAttributes'), false ); } if ($root->getAttribute('bootstrap')) { $result['bootstrap'] = $this->toAbsolutePath( (string) $root->getAttribute('bootstrap') ); } if ($root->hasAttribute('convertDeprecationsToExceptions')) { $result['convertDeprecationsToExceptions'] = $this->getBoolean( (string) $root->getAttribute('convertDeprecationsToExceptions'), true ); } if ($root->hasAttribute('convertErrorsToExceptions')) { $result['convertErrorsToExceptions'] = $this->getBoolean( (string) $root->getAttribute('convertErrorsToExceptions'), true ); } if ($root->hasAttribute('convertNoticesToExceptions')) { $result['convertNoticesToExceptions'] = $this->getBoolean( (string) $root->getAttribute('convertNoticesToExceptions'), true ); } if ($root->hasAttribute('convertWarningsToExceptions')) { $result['convertWarningsToExceptions'] = $this->getBoolean( (string) $root->getAttribute('convertWarningsToExceptions'), true ); } if ($root->hasAttribute('forceCoversAnnotation')) { $result['forceCoversAnnotation'] = $this->getBoolean( (string) $root->getAttribute('forceCoversAnnotation'), false ); } if ($root->hasAttribute('disableCodeCoverageIgnore')) { $result['disableCodeCoverageIgnore'] = $this->getBoolean( (string) $root->getAttribute('disableCodeCoverageIgnore'), false ); } if ($root->hasAttribute('processIsolation')) { $result['processIsolation'] = $this->getBoolean( (string) $root->getAttribute('processIsolation'), false ); } if ($root->hasAttribute('stopOnError')) { $result['stopOnError'] = $this->getBoolean( (string) $root->getAttribute('stopOnError'), false ); } if ($root->hasAttribute('stopOnFailure')) { $result['stopOnFailure'] = $this->getBoolean( (string) $root->getAttribute('stopOnFailure'), false ); } if ($root->hasAttribute('stopOnWarning')) { $result['stopOnWarning'] = $this->getBoolean( (string) $root->getAttribute('stopOnWarning'), false ); } if ($root->hasAttribute('stopOnIncomplete')) { $result['stopOnIncomplete'] = $this->getBoolean( (string) $root->getAttribute('stopOnIncomplete'), false ); } if ($root->hasAttribute('stopOnRisky')) { $result['stopOnRisky'] = $this->getBoolean( (string) $root->getAttribute('stopOnRisky'), false ); } if ($root->hasAttribute('stopOnSkipped')) { $result['stopOnSkipped'] = $this->getBoolean( (string) $root->getAttribute('stopOnSkipped'), false ); } if ($root->hasAttribute('failOnWarning')) { $result['failOnWarning'] = $this->getBoolean( (string) $root->getAttribute('failOnWarning'), false ); } if ($root->hasAttribute('failOnRisky')) { $result['failOnRisky'] = $this->getBoolean( (string) $root->getAttribute('failOnRisky'), false ); } if ($root->hasAttribute('testSuiteLoaderClass')) { $result['testSuiteLoaderClass'] = (string) $root->getAttribute( 'testSuiteLoaderClass' ); } if ($root->hasAttribute('defaultTestSuite')) { $result['defaultTestSuite'] = (string) $root->getAttribute( 'defaultTestSuite' ); } if ($root->getAttribute('testSuiteLoaderFile')) { $result['testSuiteLoaderFile'] = $this->toAbsolutePath( (string) $root->getAttribute('testSuiteLoaderFile') ); } if ($root->hasAttribute('printerClass')) { $result['printerClass'] = (string) $root->getAttribute( 'printerClass' ); } if ($root->getAttribute('printerFile')) { $result['printerFile'] = $this->toAbsolutePath( (string) $root->getAttribute('printerFile') ); } if ($root->hasAttribute('beStrictAboutChangesToGlobalState')) { $result['beStrictAboutChangesToGlobalState'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutChangesToGlobalState'), false ); } if ($root->hasAttribute('beStrictAboutOutputDuringTests')) { $result['disallowTestOutput'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutOutputDuringTests'), false ); } if ($root->hasAttribute('beStrictAboutResourceUsageDuringSmallTests')) { $result['beStrictAboutResourceUsageDuringSmallTests'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutResourceUsageDuringSmallTests'), false ); } if ($root->hasAttribute('beStrictAboutTestsThatDoNotTestAnything')) { $result['reportUselessTests'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutTestsThatDoNotTestAnything'), true ); } if ($root->hasAttribute('beStrictAboutTodoAnnotatedTests')) { $result['disallowTodoAnnotatedTests'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutTodoAnnotatedTests'), false ); } if ($root->hasAttribute('beStrictAboutCoversAnnotation')) { $result['strictCoverage'] = $this->getBoolean( (string) $root->getAttribute('beStrictAboutCoversAnnotation'), false ); } if ($root->hasAttribute('enforceTimeLimit')) { $result['enforceTimeLimit'] = $this->getBoolean( (string) $root->getAttribute('enforceTimeLimit'), false ); } if ($root->hasAttribute('ignoreDeprecatedCodeUnitsFromCodeCoverage')) { $result['ignoreDeprecatedCodeUnitsFromCodeCoverage'] = $this->getBoolean( (string) $root->getAttribute('ignoreDeprecatedCodeUnitsFromCodeCoverage'), false ); } if ($root->hasAttribute('timeoutForSmallTests')) { $result['timeoutForSmallTests'] = $this->getInteger( (string) $root->getAttribute('timeoutForSmallTests'), 1 ); } if ($root->hasAttribute('timeoutForMediumTests')) { $result['timeoutForMediumTests'] = $this->getInteger( (string) $root->getAttribute('timeoutForMediumTests'), 10 ); } if ($root->hasAttribute('timeoutForLargeTests')) { $result['timeoutForLargeTests'] = $this->getInteger( (string) $root->getAttribute('timeoutForLargeTests'), 60 ); } if ($root->hasAttribute('reverseDefectList')) { $result['reverseDefectList'] = $this->getBoolean( (string) $root->getAttribute('reverseDefectList'), false ); } if ($root->hasAttribute('verbose')) { $result['verbose'] = $this->getBoolean( (string) $root->getAttribute('verbose'), false ); } if ($root->hasAttribute('registerMockObjectsFromTestArgumentsRecursively')) { $result['registerMockObjectsFromTestArgumentsRecursively'] = $this->getBoolean( (string) $root->getAttribute('registerMockObjectsFromTestArgumentsRecursively'), false ); } if ($root->hasAttribute('extensionsDirectory')) { $result['extensionsDirectory'] = $this->toAbsolutePath( (string) $root->getAttribute( 'extensionsDirectory' ) ); } return $result; } /** * Returns the test suite configuration. * * @param string|null $testSuiteFilter * * @return TestSuite */ public function getTestSuiteConfiguration($testSuiteFilter = null) { $testSuiteNodes = $this->xpath->query('testsuites/testsuite'); if ($testSuiteNodes->length == 0) { $testSuiteNodes = $this->xpath->query('testsuite'); } if ($testSuiteNodes->length == 1) { return $this->getTestSuite($testSuiteNodes->item(0), $testSuiteFilter); } //if ($testSuiteNodes->length > 1) { there cannot be a negative number of Nodes $suite = new TestSuite; foreach ($testSuiteNodes as $testSuiteNode) { $suite->addTestSuite( $this->getTestSuite($testSuiteNode, $testSuiteFilter) ); } return $suite; } /** * Returns the test suite names from the configuration. * * @return array */ public function getTestSuiteNames() { $names = []; $nodes = $this->xpath->query('*/testsuite'); foreach ($nodes as $node) { $names[] = $node->getAttribute('name'); } return $names; } /** * @param DOMElement $testSuiteNode * @param string|null $testSuiteFilter * * @return TestSuite */ protected function getTestSuite(DOMElement $testSuiteNode, $testSuiteFilter = null) { if ($testSuiteNode->hasAttribute('name')) { $suite = new TestSuite( (string) $testSuiteNode->getAttribute('name') ); } else { $suite = new TestSuite; } $exclude = []; foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) { $excludeFile = (string) $excludeNode->textContent; if ($excludeFile) { $exclude[] = $this->toAbsolutePath($excludeFile); } } $fileIteratorFacade = new File_Iterator_Facade; $testSuiteFilter = $testSuiteFilter ? \explode(self::TEST_SUITE_FILTER_SEPARATOR, $testSuiteFilter) : []; foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) { if (!empty($testSuiteFilter) && !\in_array($directoryNode->parentNode->getAttribute('name'), $testSuiteFilter)) { continue; } $directory = (string) $directoryNode->textContent; if (empty($directory)) { continue; } if ($directoryNode->hasAttribute('phpVersion')) { $phpVersion = (string) $directoryNode->getAttribute('phpVersion'); } else { $phpVersion = PHP_VERSION; } if ($directoryNode->hasAttribute('phpVersionOperator')) { $phpVersionOperator = (string) $directoryNode->getAttribute('phpVersionOperator'); } else { $phpVersionOperator = '>='; } if (!\version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) { continue; } if ($directoryNode->hasAttribute('prefix')) { $prefix = (string) $directoryNode->getAttribute('prefix'); } else { $prefix = ''; } if ($directoryNode->hasAttribute('suffix')) { $suffix = (string) $directoryNode->getAttribute('suffix'); } else { $suffix = 'Test.php'; } $files = $fileIteratorFacade->getFilesAsArray( $this->toAbsolutePath($directory), $suffix, $prefix, $exclude ); $suite->addTestFiles($files); } foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) { if (!empty($testSuiteFilter) && !\in_array($fileNode->parentNode->getAttribute('name'), $testSuiteFilter)) { continue; } $file = (string) $fileNode->textContent; if (empty($file)) { continue; } // Get the absolute path to the file $file = $fileIteratorFacade->getFilesAsArray( $this->toAbsolutePath($file) ); if (!isset($file[0])) { continue; } $file = $file[0]; if ($fileNode->hasAttribute('phpVersion')) { $phpVersion = (string) $fileNode->getAttribute('phpVersion'); } else { $phpVersion = PHP_VERSION; } if ($fileNode->hasAttribute('phpVersionOperator')) { $phpVersionOperator = (string) $fileNode->getAttribute('phpVersionOperator'); } else { $phpVersionOperator = '>='; } if (!\version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) { continue; } $suite->addTestFile($file); } return $suite; } /** * if $value is 'false' or 'true', this returns the value that $value represents. * Otherwise, returns $default, which may be a string in rare cases. * See PHPUnit\Util\ConfigurationTest::testPHPConfigurationIsReadCorrectly * * @param string $value * @param string|bool $default * * @return string|bool */ protected function getBoolean($value, $default) { if (\strtolower($value) == 'false') { return false; } if (\strtolower($value) == 'true') { return true; } return $default; } /** * @param string $value * @param int $default * * @return int */ protected function getInteger($value, $default) { if (\is_numeric($value)) { return (int) $value; } return $default; } /** * @param string $query * * @return array */ protected function readFilterDirectories($query) { $directories = []; foreach ($this->xpath->query($query) as $directory) { $directoryPath = (string) $directory->textContent; if (!$directoryPath) { continue; } if ($directory->hasAttribute('prefix')) { $prefix = (string) $directory->getAttribute('prefix'); } else { $prefix = ''; } if ($directory->hasAttribute('suffix')) { $suffix = (string) $directory->getAttribute('suffix'); } else { $suffix = '.php'; } if ($directory->hasAttribute('group')) { $group = (string) $directory->getAttribute('group'); } else { $group = 'DEFAULT'; } $directories[] = [ 'path' => $this->toAbsolutePath($directoryPath), 'prefix' => $prefix, 'suffix' => $suffix, 'group' => $group ]; } return $directories; } /** * @param string $query * * @return array */ protected function readFilterFiles($query) { $files = []; foreach ($this->xpath->query($query) as $file) { $filePath = (string) $file->textContent; if ($filePath) { $files[] = $this->toAbsolutePath($filePath); } } return $files; } /** * @param string $path * @param bool $useIncludePath * * @return string */ protected function toAbsolutePath($path, $useIncludePath = false) { $path = \trim($path); if ($path[0] === '/') { return $path; } // Matches the following on Windows: // - \\NetworkComputer\Path // - \\.\D: // - \\.\c: // - C:\Windows // - C:\windows // - C:/windows // - c:/windows if (\defined('PHP_WINDOWS_VERSION_BUILD') && ($path[0] === '\\' || (\strlen($path) >= 3 && \preg_match('#^[A-Z]\:[/\\\]#i', \substr($path, 0, 3))))) { return $path; } // Stream if (\strpos($path, '://') !== false) { return $path; } $file = \dirname($this->filename) . DIRECTORY_SEPARATOR . $path; if ($useIncludePath && !\file_exists($file)) { $includePathFile = \stream_resolve_include_path($path); if ($includePathFile) { $file = $includePathFile; } } return $file; } } phpunit-6.5.5/src/Util/ConfigurationGenerator.php000066400000000000000000000034611321540746700221260ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; class ConfigurationGenerator { /** * @var string */ private $defaultTemplate = << {tests_directory} {src_directory} EOT; /** * @param string $phpunitVersion * @param string $bootstrapScript * @param string $testsDirectory * @param string $srcDirectory * * @return string */ public function generateDefaultConfiguration($phpunitVersion, $bootstrapScript, $testsDirectory, $srcDirectory) { return \str_replace( [ '{phpunit_version}', '{bootstrap_script}', '{tests_directory}', '{src_directory}' ], [ $phpunitVersion, $bootstrapScript, $testsDirectory, $srcDirectory ], $this->defaultTemplate ); } } phpunit-6.5.5/src/Util/ErrorHandler.php000066400000000000000000000056371321540746700200460ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Error\Deprecated; use PHPUnit\Framework\Error\Error; use PHPUnit\Framework\Error\Notice; use PHPUnit\Framework\Error\Warning; /** * Error handler that converts PHP errors and warnings to exceptions. */ class ErrorHandler { protected static $errorStack = []; /** * Returns the error stack. * * @return array */ public static function getErrorStack() { return self::$errorStack; } /** * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * * @return false * * @throws Error */ public static function handleError($errno, $errstr, $errfile, $errline) { if (!($errno & \error_reporting())) { return false; } self::$errorStack[] = [$errno, $errstr, $errfile, $errline]; $trace = \debug_backtrace(); \array_shift($trace); foreach ($trace as $frame) { if ($frame['function'] == '__toString') { return false; } } if ($errno == E_NOTICE || $errno == E_USER_NOTICE || $errno == E_STRICT) { if (Notice::$enabled !== true) { return false; } $exception = Notice::class; } elseif ($errno == E_WARNING || $errno == E_USER_WARNING) { if (Warning::$enabled !== true) { return false; } $exception = Warning::class; } elseif ($errno == E_DEPRECATED || $errno == E_USER_DEPRECATED) { if (Deprecated::$enabled !== true) { return false; } $exception = Deprecated::class; } else { $exception = Error::class; } throw new $exception($errstr, $errno, $errfile, $errline); } /** * Registers an error handler and returns a function that will restore * the previous handler when invoked * * @param int $severity PHP predefined error constant * * @return \Closure * * @throws \Exception if event of specified severity is emitted */ public static function handleErrorOnce($severity = E_WARNING) { $terminator = function () { static $expired = false; if (!$expired) { $expired = true; // cleans temporary error handler return \restore_error_handler(); } }; \set_error_handler(function ($errno, $errstr) use ($severity) { if ($errno === $severity) { return; } return false; }); return $terminator; } } phpunit-6.5.5/src/Util/Fileloader.php000066400000000000000000000043151321540746700175150ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; /** * Utility methods to load PHP sourcefiles. */ class Fileloader { /** * Checks if a PHP sourcefile is readable. * The sourcefile is loaded through the load() method. * * @param string $filename * * @return string * * @throws Exception */ public static function checkAndLoad($filename) { $includePathFilename = \stream_resolve_include_path($filename); // As a fallback, PHP looks in the directory of the file executing the stream_resolve_include_path function. // We don't want to load the Test.php file here, so skip it if it found that. // PHP prioritizes the include_path setting, so if the current directory is in there, it will first look in the // current working directory. $localFile = __DIR__ . DIRECTORY_SEPARATOR . $filename; // @see https://github.com/sebastianbergmann/phpunit/pull/2751 $isReadable = @\fopen($includePathFilename, 'r') !== false; if (!$includePathFilename || !$isReadable || $includePathFilename === $localFile) { throw new Exception( \sprintf('Cannot open file "%s".' . "\n", $filename) ); } self::load($includePathFilename); return $includePathFilename; } /** * Loads a PHP sourcefile. * * @param string $filename * * @return mixed */ public static function load($filename) { $oldVariableNames = \array_keys(\get_defined_vars()); include_once $filename; $newVariables = \get_defined_vars(); $newVariableNames = \array_diff( \array_keys($newVariables), $oldVariableNames ); foreach ($newVariableNames as $variableName) { if ($variableName != 'oldVariableNames') { $GLOBALS[$variableName] = $newVariables[$variableName]; } } return $filename; } } phpunit-6.5.5/src/Util/Filesystem.php000066400000000000000000000014551321540746700175750ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; /** * Filesystem helpers. */ class Filesystem { /** * @var array */ protected static $buffer = []; /** * Maps class names to source file names: * - PEAR CS: Foo_Bar_Baz -> Foo/Bar/Baz.php * - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php * * @param string $className * * @return string */ public static function classNameToFilename($className) { return \str_replace( ['_', '\\'], DIRECTORY_SEPARATOR, $className ) . '.php'; } } phpunit-6.5.5/src/Util/Filter.php000066400000000000000000000055671321540746700167060ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; use PHPUnit\Framework\SyntheticError; /** * Utility class for code filtering. */ class Filter { /** * Filters stack frames from PHPUnit classes. * * @param \Throwable $e * @param bool $asString * * @return string|string[] */ public static function getFilteredStacktrace($e, $asString = true) { $prefix = false; $script = \realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); if (\defined('__PHPUNIT_PHAR_ROOT__')) { $prefix = __PHPUNIT_PHAR_ROOT__; } if ($asString === true) { $filteredStacktrace = ''; } else { $filteredStacktrace = []; } if ($e instanceof SyntheticError) { $eTrace = $e->getSyntheticTrace(); $eFile = $e->getSyntheticFile(); $eLine = $e->getSyntheticLine(); } elseif ($e instanceof Exception) { $eTrace = $e->getSerializableTrace(); $eFile = $e->getFile(); $eLine = $e->getLine(); } else { if ($e->getPrevious()) { $e = $e->getPrevious(); } $eTrace = $e->getTrace(); $eFile = $e->getFile(); $eLine = $e->getLine(); } if (!self::frameExists($eTrace, $eFile, $eLine)) { \array_unshift( $eTrace, ['file' => $eFile, 'line' => $eLine] ); } $blacklist = new Blacklist; foreach ($eTrace as $frame) { if (isset($frame['file']) && \is_file($frame['file']) && !$blacklist->isBlacklisted($frame['file']) && ($prefix === false || \strpos($frame['file'], $prefix) !== 0) && $frame['file'] !== $script) { if ($asString === true) { $filteredStacktrace .= \sprintf( "%s:%s\n", $frame['file'], $frame['line'] ?? '?' ); } else { $filteredStacktrace[] = $frame; } } } return $filteredStacktrace; } /** * @param array $trace * @param string $file * @param int $line * * @return bool */ private static function frameExists(array $trace, $file, $line) { foreach ($trace as $frame) { if (isset($frame['file']) && $frame['file'] == $file && isset($frame['line']) && $frame['line'] == $line) { return true; } } return false; } } phpunit-6.5.5/src/Util/Getopt.php000066400000000000000000000110041321540746700167020ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; /** * Command-line options parsing class. */ class Getopt { public static function getopt(array $args, $short_options, $long_options = null) { if (empty($args)) { return [[], []]; } $opts = []; $non_opts = []; if ($long_options) { \sort($long_options); } if (isset($args[0][0]) && $args[0][0] != '-') { \array_shift($args); } \reset($args); $args = \array_map('trim', $args); while (false !== $arg = \current($args)) { $i = \key($args); \next($args); if ($arg == '') { continue; } if ($arg == '--') { $non_opts = \array_merge($non_opts, \array_slice($args, $i + 1)); break; } if ($arg[0] != '-' || (\strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) { $non_opts[] = $args[$i]; continue; } elseif (\strlen($arg) > 1 && $arg[1] == '-') { self::parseLongOption( \substr($arg, 2), $long_options, $opts, $args ); } else { self::parseShortOption( \substr($arg, 1), $short_options, $opts, $args ); } } return [$opts, $non_opts]; } protected static function parseShortOption($arg, $short_options, &$opts, &$args) { $argLen = \strlen($arg); for ($i = 0; $i < $argLen; $i++) { $opt = $arg[$i]; $opt_arg = null; if (($spec = \strstr($short_options, $opt)) === false || $arg[$i] == ':') { throw new Exception( "unrecognized option -- $opt" ); } if (\strlen($spec) > 1 && $spec[1] == ':') { if ($i + 1 < $argLen) { $opts[] = [$opt, \substr($arg, $i + 1)]; break; } if (!(\strlen($spec) > 2 && $spec[2] == ':')) { if (false === $opt_arg = \current($args)) { throw new Exception( "option requires an argument -- $opt" ); } \next($args); } } $opts[] = [$opt, $opt_arg]; } } protected static function parseLongOption($arg, $long_options, &$opts, &$args) { $count = \count($long_options); $list = \explode('=', $arg); $opt = $list[0]; $opt_arg = null; if (\count($list) > 1) { $opt_arg = $list[1]; } $opt_len = \strlen($opt); for ($i = 0; $i < $count; $i++) { $long_opt = $long_options[$i]; $opt_start = \substr($long_opt, 0, $opt_len); if ($opt_start != $opt) { continue; } $opt_rest = \substr($long_opt, $opt_len); if ($opt_rest != '' && $opt[0] != '=' && $i + 1 < $count && $opt == \substr($long_options[$i + 1], 0, $opt_len)) { throw new Exception( "option --$opt is ambiguous" ); } if (\substr($long_opt, -1) == '=') { if (\substr($long_opt, -2) != '==') { if (!\strlen($opt_arg)) { if (false === $opt_arg = \current($args)) { throw new Exception( "option --$opt requires an argument" ); } \next($args); } } } elseif ($opt_arg) { throw new Exception( "option --$opt doesn't allow an argument" ); } $full_option = '--' . \preg_replace('/={1,2}$/', '', $long_opt); $opts[] = [$full_option, $opt_arg]; return; } throw new Exception("unrecognized option --$opt"); } } phpunit-6.5.5/src/Util/GlobalState.php000066400000000000000000000121171321540746700176470ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use Closure; class GlobalState { /** * @var string[] */ protected static $superGlobalArrays = [ '_ENV', '_POST', '_GET', '_COOKIE', '_SERVER', '_FILES', '_REQUEST' ]; /** * @return string */ public static function getIncludedFilesAsString() { return static::processIncludedFilesAsString(\get_included_files()); } /** * @param array $files * * @return string */ public static function processIncludedFilesAsString(array $files) { $blacklist = new Blacklist; $prefix = false; $result = ''; if (\defined('__PHPUNIT_PHAR__')) { $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/'; } for ($i = \count($files) - 1; $i > 0; $i--) { $file = $files[$i]; if (!empty($GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST']) && \in_array($file, $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'])) { continue; } if ($prefix !== false && \strpos($file, $prefix) === 0) { continue; } // Skip virtual file system protocols if (\preg_match('/^(vfs|phpvfs[a-z0-9]+):/', $file)) { continue; } if (!$blacklist->isBlacklisted($file) && \is_file($file)) { $result = 'require_once \'' . $file . "';\n" . $result; } } return $result; } /** * @return string */ public static function getIniSettingsAsString() { $result = ''; $iniSettings = \ini_get_all(null, false); foreach ($iniSettings as $key => $value) { $result .= \sprintf( '@ini_set(%s, %s);' . "\n", self::exportVariable($key), self::exportVariable($value) ); } return $result; } /** * @return string */ public static function getConstantsAsString() { $constants = \get_defined_constants(true); $result = ''; if (isset($constants['user'])) { foreach ($constants['user'] as $name => $value) { $result .= \sprintf( 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", $name, $name, self::exportVariable($value) ); } } return $result; } /** * @return string */ public static function getGlobalsAsString() { $result = ''; $superGlobalArrays = self::getSuperGlobalArrays(); foreach ($superGlobalArrays as $superGlobalArray) { if (isset($GLOBALS[$superGlobalArray]) && \is_array($GLOBALS[$superGlobalArray])) { foreach (\array_keys($GLOBALS[$superGlobalArray]) as $key) { if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { continue; } $result .= \sprintf( '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", $superGlobalArray, $key, self::exportVariable($GLOBALS[$superGlobalArray][$key]) ); } } } $blacklist = $superGlobalArrays; $blacklist[] = 'GLOBALS'; foreach (\array_keys($GLOBALS) as $key) { if (!\in_array($key, $blacklist) && !$GLOBALS[$key] instanceof Closure) { $result .= \sprintf( '$GLOBALS[\'%s\'] = %s;' . "\n", $key, self::exportVariable($GLOBALS[$key]) ); } } return $result; } /** * @return string[] */ protected static function getSuperGlobalArrays() { return self::$superGlobalArrays; } protected static function exportVariable($variable) { if (\is_scalar($variable) || null === $variable || (\is_array($variable) && self::arrayOnlyContainsScalars($variable))) { return \var_export($variable, true); } return 'unserialize(' . \var_export(\serialize($variable), true) . ')'; } /** * @param array $array * * @return bool */ protected static function arrayOnlyContainsScalars(array $array) { $result = true; foreach ($array as $element) { if (\is_array($element)) { $result = self::arrayOnlyContainsScalars($element); } elseif (!\is_scalar($element) && null !== $element) { $result = false; } if ($result === false) { break; } } return $result; } } phpunit-6.5.5/src/Util/InvalidArgumentHelper.php000066400000000000000000000020511321540746700216730ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; /** * Factory for PHPUnit\Framework\Exception objects that are used to describe * invalid arguments passed to a function or method. */ class InvalidArgumentHelper { /** * @param int $argument * @param string $type * @param mixed $value * * @return Exception */ public static function factory($argument, $type, $value = null) { $stack = \debug_backtrace(); return new Exception( \sprintf( 'Argument #%d%sof %s::%s() must be a %s', $argument, $value !== null ? ' (' . \gettype($value) . '#' . $value . ')' : ' (No Value) ', $stack[1]['class'], $stack[1]['function'], $type ) ); } } phpunit-6.5.5/src/Util/Json.php000066400000000000000000000036331321540746700163620ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; class Json { /** * Prettify json string * * @param string $json * * @return string * * @throws \PHPUnit\Framework\Exception */ public static function prettify(string $json) { $decodedJson = \json_decode($json, true); if (\json_last_error()) { throw new Exception( 'Cannot prettify invalid json' ); } return \json_encode($decodedJson, JSON_PRETTY_PRINT); } /* * To allow comparison of JSON strings, first process them into a consistent * format so that they can be compared as strings. * @return array ($error, $canonicalized_json) The $error parameter is used * to indicate an error decoding the json. This is used to avoid ambiguity * with JSON strings consisting entirely of 'null' or 'false'. */ public static function canonicalize(string $json) { $decodedJson = \json_decode($json, true); if (\json_last_error()) { return [true, null]; } self::recursiveSort($decodedJson); $reencodedJson = \json_encode($decodedJson); return [false, $reencodedJson]; } /* * JSON object keys are unordered while PHP array keys are ordered. * Sort all array keys to ensure both the expected and actual values have * their keys in the same order. */ private static function recursiveSort(&$json) { if (false === \is_array($json)) { return; } \ksort($json); foreach ($json as $key => &$value) { self::recursiveSort($value); } } } phpunit-6.5.5/src/Util/Log/000077500000000000000000000000001321540746700154545ustar00rootroot00000000000000phpunit-6.5.5/src/Util/Log/JUnit.php000066400000000000000000000272021321540746700172210ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\Log; use DOMDocument; use DOMElement; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExceptionWrapper; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestFailure; use PHPUnit\Framework\TestListener; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; use PHPUnit\Util\Filter; use PHPUnit\Util\Printer; use PHPUnit\Util\Xml; use ReflectionClass; use ReflectionException; /** * A TestListener that generates a logfile of the test execution in XML markup. * * The XML markup used is the same as the one that is used by the JUnit Ant task. */ class JUnit extends Printer implements TestListener { /** * @var DOMDocument */ protected $document; /** * @var DOMElement */ protected $root; /** * @var bool */ protected $reportUselessTests = false; /** * @var bool */ protected $writeDocument = true; /** * @var DOMElement[] */ protected $testSuites = []; /** * @var int[] */ protected $testSuiteTests = [0]; /** * @var int[] */ protected $testSuiteAssertions = [0]; /** * @var int[] */ protected $testSuiteErrors = [0]; /** * @var int[] */ protected $testSuiteFailures = [0]; /** * @var int[] */ protected $testSuiteSkipped = [0]; /** * @var int[] */ protected $testSuiteTimes = [0]; /** * @var int */ protected $testSuiteLevel = 0; /** * @var ?DOMElement */ protected $currentTestCase; /** * Constructor. * * @param mixed $out * @param bool $reportUselessTests */ public function __construct($out = null, $reportUselessTests = false) { $this->document = new DOMDocument('1.0', 'UTF-8'); $this->document->formatOutput = true; $this->root = $this->document->createElement('testsuites'); $this->document->appendChild($this->root); parent::__construct($out); $this->reportUselessTests = $reportUselessTests; } /** * Flush buffer and close output. */ public function flush() { if ($this->writeDocument === true) { $this->write($this->getXML()); } parent::flush(); } /** * An error occurred. * * @param Test $test * @param \Exception $e * @param float $time */ public function addError(Test $test, \Exception $e, $time) { $this->doAddFault($test, $e, $time, 'error'); $this->testSuiteErrors[$this->testSuiteLevel]++; } /** * A warning occurred. * * @param Test $test * @param Warning $e * @param float $time */ public function addWarning(Test $test, Warning $e, $time) { $this->doAddFault($test, $e, $time, 'warning'); $this->testSuiteFailures[$this->testSuiteLevel]++; } /** * A failure occurred. * * @param Test $test * @param AssertionFailedError $e * @param float $time */ public function addFailure(Test $test, AssertionFailedError $e, $time) { $this->doAddFault($test, $e, $time, 'failure'); $this->testSuiteFailures[$this->testSuiteLevel]++; } /** * Incomplete test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addIncompleteTest(Test $test, \Exception $e, $time) { $this->doAddSkipped($test); } /** * Risky test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addRiskyTest(Test $test, \Exception $e, $time) { if (!$this->reportUselessTests || $this->currentTestCase === null) { return; } $error = $this->document->createElement( 'error', Xml::prepareString( "Risky Test\n" . Filter::getFilteredStacktrace($e) ) ); $error->setAttribute('type', \get_class($e)); $this->currentTestCase->appendChild($error); $this->testSuiteErrors[$this->testSuiteLevel]++; } /** * Skipped test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addSkippedTest(Test $test, \Exception $e, $time) { $this->doAddSkipped($test); } /** * A testsuite started. * * @param TestSuite $suite */ public function startTestSuite(TestSuite $suite) { $testSuite = $this->document->createElement('testsuite'); $testSuite->setAttribute('name', $suite->getName()); if (\class_exists($suite->getName(), false)) { try { $class = new ReflectionClass($suite->getName()); $testSuite->setAttribute('file', $class->getFileName()); } catch (ReflectionException $e) { } } if ($this->testSuiteLevel > 0) { $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite); } else { $this->root->appendChild($testSuite); } $this->testSuiteLevel++; $this->testSuites[$this->testSuiteLevel] = $testSuite; $this->testSuiteTests[$this->testSuiteLevel] = 0; $this->testSuiteAssertions[$this->testSuiteLevel] = 0; $this->testSuiteErrors[$this->testSuiteLevel] = 0; $this->testSuiteFailures[$this->testSuiteLevel] = 0; $this->testSuiteSkipped[$this->testSuiteLevel] = 0; $this->testSuiteTimes[$this->testSuiteLevel] = 0; } /** * A testsuite ended. * * @param TestSuite $suite */ public function endTestSuite(TestSuite $suite) { $this->testSuites[$this->testSuiteLevel]->setAttribute( 'tests', $this->testSuiteTests[$this->testSuiteLevel] ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'assertions', $this->testSuiteAssertions[$this->testSuiteLevel] ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'errors', $this->testSuiteErrors[$this->testSuiteLevel] ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'failures', $this->testSuiteFailures[$this->testSuiteLevel] ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'skipped', $this->testSuiteSkipped[$this->testSuiteLevel] ); $this->testSuites[$this->testSuiteLevel]->setAttribute( 'time', \sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]) ); if ($this->testSuiteLevel > 1) { $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel]; $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel]; $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel]; $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel]; $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel]; $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel]; } $this->testSuiteLevel--; } /** * A test started. * * @param Test $test */ public function startTest(Test $test) { $testCase = $this->document->createElement('testcase'); $testCase->setAttribute('name', $test->getName()); if ($test instanceof TestCase) { $class = new ReflectionClass($test); $methodName = $test->getName(!$test->usesDataProvider()); if ($class->hasMethod($methodName)) { $method = $class->getMethod($methodName); $testCase->setAttribute('class', $class->getName()); $testCase->setAttribute('classname', \str_replace('\\', '.', $class->getName())); $testCase->setAttribute('file', $class->getFileName()); $testCase->setAttribute('line', $method->getStartLine()); } } $this->currentTestCase = $testCase; } /** * A test ended. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time) { if ($test instanceof TestCase) { $numAssertions = $test->getNumAssertions(); $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; $this->currentTestCase->setAttribute( 'assertions', $numAssertions ); } $this->currentTestCase->setAttribute( 'time', \sprintf('%F', $time) ); $this->testSuites[$this->testSuiteLevel]->appendChild( $this->currentTestCase ); $this->testSuiteTests[$this->testSuiteLevel]++; $this->testSuiteTimes[$this->testSuiteLevel] += $time; if (\method_exists($test, 'hasOutput') && $test->hasOutput()) { $systemOut = $this->document->createElement('system-out'); $systemOut->appendChild( $this->document->createTextNode($test->getActualOutput()) ); $this->currentTestCase->appendChild($systemOut); } $this->currentTestCase = null; } /** * Returns the XML as a string. * * @return string */ public function getXML() { return $this->document->saveXML(); } /** * Enables or disables the writing of the document * in flush(). * * This is a "hack" needed for the integration of * PHPUnit with Phing. * * @return string */ public function setWriteDocument($flag) { if (\is_bool($flag)) { $this->writeDocument = $flag; } } /** * Method which generalizes addError() and addFailure() * * @param Test $test * @param \Exception $e * @param float $time * @param string $type */ private function doAddFault(Test $test, \Exception $e, $time, $type) { if ($this->currentTestCase === null) { return; } if ($test instanceof SelfDescribing) { $buffer = $test->toString() . "\n"; } else { $buffer = ''; } $buffer .= TestFailure::exceptionToString($e) . "\n" . Filter::getFilteredStacktrace($e); $fault = $this->document->createElement( $type, Xml::prepareString($buffer) ); if ($e instanceof ExceptionWrapper) { $fault->setAttribute('type', $e->getClassName()); } else { $fault->setAttribute('type', \get_class($e)); } $this->currentTestCase->appendChild($fault); } private function doAddSkipped(Test $test) { if ($this->currentTestCase === null) { return; } $skipped = $this->document->createElement('skipped'); $this->currentTestCase->appendChild($skipped); $this->testSuiteSkipped[$this->testSuiteLevel]++; } } phpunit-6.5.5/src/Util/Log/TeamCity.php000066400000000000000000000252741321540746700177160ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\Log; use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\ExceptionWrapper; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestFailure; use PHPUnit\Framework\TestResult; use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; use PHPUnit\TextUI\ResultPrinter; use PHPUnit\Util\Filter; use ReflectionClass; use SebastianBergmann\Comparator\ComparisonFailure; /** * A TestListener that generates a logfile of the test execution using the * TeamCity format (for use with PhpStorm, for instance). */ class TeamCity extends ResultPrinter { /** * @var bool */ private $isSummaryTestCountPrinted = false; /** * @var string */ private $startedTestName; /** * @var int|false */ private $flowId; /** * @param string $progress */ protected function writeProgress($progress) { } /** * @param TestResult $result */ public function printResult(TestResult $result) { $this->printHeader(); $this->printFooter($result); } /** * An error occurred. * * @param Test $test * @param \Exception $e * @param float $time */ public function addError(Test $test, \Exception $e, $time) { $this->printEvent( 'testFailed', [ 'name' => $test->getName(), 'message' => self::getMessage($e), 'details' => self::getDetails($e), ] ); } /** * A warning occurred. * * @param Test $test * @param Warning $e * @param float $time */ public function addWarning(Test $test, Warning $e, $time) { $this->printEvent( 'testFailed', [ 'name' => $test->getName(), 'message' => self::getMessage($e), 'details' => self::getDetails($e) ] ); } /** * A failure occurred. * * @param Test $test * @param AssertionFailedError $e * @param float $time */ public function addFailure(Test $test, AssertionFailedError $e, $time) { $parameters = [ 'name' => $test->getName(), 'message' => self::getMessage($e), 'details' => self::getDetails($e), ]; if ($e instanceof ExpectationFailedException) { $comparisonFailure = $e->getComparisonFailure(); if ($comparisonFailure instanceof ComparisonFailure) { $expectedString = $comparisonFailure->getExpectedAsString(); if (null === $expectedString || empty($expectedString)) { $expectedString = self::getPrimitiveValueAsString($comparisonFailure->getExpected()); } $actualString = $comparisonFailure->getActualAsString(); if (null === $actualString || empty($actualString)) { $actualString = self::getPrimitiveValueAsString($comparisonFailure->getActual()); } if (null !== $actualString && null !== $expectedString) { $parameters['type'] = 'comparisonFailure'; $parameters['actual'] = $actualString; $parameters['expected'] = $expectedString; } } } $this->printEvent('testFailed', $parameters); } /** * Incomplete test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addIncompleteTest(Test $test, \Exception $e, $time) { $this->printIgnoredTest($test->getName(), $e); } /** * Risky test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addRiskyTest(Test $test, \Exception $e, $time) { $this->addError($test, $e, $time); } /** * Skipped test. * * @param Test $test * @param \Exception $e * @param float $time */ public function addSkippedTest(Test $test, \Exception $e, $time) { $testName = $test->getName(); if ($this->startedTestName != $testName) { $this->startTest($test); $this->printIgnoredTest($testName, $e); $this->endTest($test, $time); } else { $this->printIgnoredTest($testName, $e); } } public function printIgnoredTest($testName, \Exception $e) { $this->printEvent( 'testIgnored', [ 'name' => $testName, 'message' => self::getMessage($e), 'details' => self::getDetails($e), ] ); } /** * A testsuite started. * * @param TestSuite $suite */ public function startTestSuite(TestSuite $suite) { if (\stripos(\ini_get('disable_functions'), 'getmypid') === false) { $this->flowId = \getmypid(); } else { $this->flowId = false; } if (!$this->isSummaryTestCountPrinted) { $this->isSummaryTestCountPrinted = true; $this->printEvent( 'testCount', ['count' => \count($suite)] ); } $suiteName = $suite->getName(); if (empty($suiteName)) { return; } $parameters = ['name' => $suiteName]; if (\class_exists($suiteName, false)) { $fileName = self::getFileName($suiteName); $parameters['locationHint'] = "php_qn://$fileName::\\$suiteName"; } else { $split = \preg_split('/::/', $suiteName); if (\count($split) == 2 && \method_exists($split[0], $split[1])) { $fileName = self::getFileName($split[0]); $parameters['locationHint'] = "php_qn://$fileName::\\$suiteName"; $parameters['name'] = $split[1]; } } $this->printEvent('testSuiteStarted', $parameters); } /** * A testsuite ended. * * @param TestSuite $suite */ public function endTestSuite(TestSuite $suite) { $suiteName = $suite->getName(); if (empty($suiteName)) { return; } $parameters = ['name' => $suiteName]; if (!\class_exists($suiteName, false)) { $split = \preg_split('/::/', $suiteName); if (\count($split) == 2 && \method_exists($split[0], $split[1])) { $parameters['name'] = $split[1]; } } $this->printEvent('testSuiteFinished', $parameters); } /** * A test started. * * @param Test $test */ public function startTest(Test $test) { $testName = $test->getName(); $this->startedTestName = $testName; $params = ['name' => $testName]; if ($test instanceof TestCase) { $className = \get_class($test); $fileName = self::getFileName($className); $params['locationHint'] = "php_qn://$fileName::\\$className::$testName"; } $this->printEvent('testStarted', $params); } /** * A test ended. * * @param Test $test * @param float $time */ public function endTest(Test $test, $time) { parent::endTest($test, $time); $this->printEvent( 'testFinished', [ 'name' => $test->getName(), 'duration' => (int) (\round($time, 2) * 1000) ] ); } /** * @param string $eventName * @param array $params */ private function printEvent($eventName, $params = []) { $this->write("\n##teamcity[$eventName"); if ($this->flowId) { $params['flowId'] = $this->flowId; } foreach ($params as $key => $value) { $escapedValue = self::escapeValue($value); $this->write(" $key='$escapedValue'"); } $this->write("]\n"); } /** * @param \Exception $e * * @return string */ private static function getMessage(\Exception $e) { $message = ''; if ($e instanceof ExceptionWrapper) { if (\strlen($e->getClassName()) != 0) { $message .= $e->getClassName(); } if (\strlen($message) != 0 && \strlen($e->getMessage()) != 0) { $message .= ' : '; } } return $message . $e->getMessage(); } /** * @param \Exception $e * * @return string */ private static function getDetails(\Exception $e) { $stackTrace = Filter::getFilteredStacktrace($e); $previous = $e instanceof ExceptionWrapper ? $e->getPreviousWrapped() : $e->getPrevious(); while ($previous) { $stackTrace .= "\nCaused by\n" . TestFailure::exceptionToString($previous) . "\n" . Filter::getFilteredStacktrace($previous); $previous = $previous instanceof ExceptionWrapper ? $previous->getPreviousWrapped() : $previous->getPrevious(); } return ' ' . \str_replace("\n", "\n ", $stackTrace); } /** * @param mixed $value * * @return string */ private static function getPrimitiveValueAsString($value) { if (null === $value) { return 'null'; } if (\is_bool($value)) { return $value == true ? 'true' : 'false'; } if (\is_scalar($value)) { return \print_r($value, true); } } /** * @param $text * * @return string */ private static function escapeValue($text) { $text = \str_replace('|', '||', $text); $text = \str_replace("'", "|'", $text); $text = \str_replace("\n", '|n', $text); $text = \str_replace("\r", '|r', $text); $text = \str_replace(']', '|]', $text); $text = \str_replace('[', '|[', $text); return $text; } /** * @param string $className * * @return string */ private static function getFileName($className) { $reflectionClass = new ReflectionClass($className); return $reflectionClass->getFileName(); } } phpunit-6.5.5/src/Util/PHP/000077500000000000000000000000001321540746700153625ustar00rootroot00000000000000phpunit-6.5.5/src/Util/PHP/AbstractPhpProcess.php000066400000000000000000000246531321540746700216570ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; use __PHP_Incomplete_Class; use ErrorException; use PHPUnit\Framework\Exception; use PHPUnit\Framework\SyntheticError; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestFailure; use PHPUnit\Framework\TestResult; use PHPUnit\Util\InvalidArgumentHelper; use SebastianBergmann\Environment\Runtime; /** * Utility methods for PHP sub-processes. */ abstract class AbstractPhpProcess { /** * @var Runtime */ protected $runtime; /** * @var bool */ protected $stderrRedirection = false; /** * @var string */ protected $stdin = ''; /** * @var string */ protected $args = ''; /** * @var array */ protected $env = []; /** * @var int */ protected $timeout = 0; /** * Creates internal Runtime instance. */ public function __construct() { $this->runtime = new Runtime(); } /** * Defines if should use STDERR redirection or not. * * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT. * * @throws Exception * * @param bool $stderrRedirection */ public function setUseStderrRedirection($stderrRedirection) { if (!\is_bool($stderrRedirection)) { throw InvalidArgumentHelper::factory(1, 'boolean'); } $this->stderrRedirection = $stderrRedirection; } /** * Returns TRUE if uses STDERR redirection or FALSE if not. * * @return bool */ public function useStderrRedirection() { return $this->stderrRedirection; } /** * Sets the input string to be sent via STDIN * * @param string $stdin */ public function setStdin($stdin) { $this->stdin = (string) $stdin; } /** * Returns the input string to be sent via STDIN * * @return string */ public function getStdin() { return $this->stdin; } /** * Sets the string of arguments to pass to the php job * * @param string $args */ public function setArgs($args) { $this->args = (string) $args; } /** * Returns the string of arguments to pass to the php job * * @retrun string */ public function getArgs() { return $this->args; } /** * Sets the array of environment variables to start the child process with * * @param array $env */ public function setEnv(array $env) { $this->env = $env; } /** * Returns the array of environment variables to start the child process with * * @return array */ public function getEnv() { return $this->env; } /** * Sets the amount of seconds to wait before timing out * * @param int $timeout */ public function setTimeout($timeout) { $this->timeout = (int) $timeout; } /** * Returns the amount of seconds to wait before timing out * * @return int */ public function getTimeout() { return $this->timeout; } /** * @return AbstractPhpProcess */ public static function factory() { if (DIRECTORY_SEPARATOR == '\\') { return new WindowsPhpProcess; } return new DefaultPhpProcess; } /** * Runs a single test in a separate PHP process. * * @param string $job * @param Test $test * @param TestResult $result * * @throws Exception */ public function runTestJob($job, Test $test, TestResult $result) { $result->startTest($test); $_result = $this->runJob($job); $this->processChildResult( $test, $result, $_result['stdout'], $_result['stderr'] ); } /** * Returns the command based into the configurations. * * @param array $settings * @param string|null $file * * @return string */ public function getCommand(array $settings, $file = null) { $command = $this->runtime->getBinary(); $command .= $this->settingsToParameters($settings); if ('phpdbg' === PHP_SAPI) { $command .= ' -qrr '; if ($file) { $command .= '-e ' . \escapeshellarg($file); } else { $command .= \escapeshellarg(__DIR__ . '/eval-stdin.php'); } } elseif ($file) { $command .= ' -f ' . \escapeshellarg($file); } if ($this->args) { $command .= ' -- ' . $this->args; } if (true === $this->stderrRedirection) { $command .= ' 2>&1'; } return $command; } /** * Runs a single job (PHP code) using a separate PHP process. * * @param string $job * @param array $settings * * @return array * * @throws Exception */ abstract public function runJob($job, array $settings = []); /** * @param array $settings * * @return string */ protected function settingsToParameters(array $settings) { $buffer = ''; foreach ($settings as $setting) { $buffer .= ' -d ' . \escapeshellarg($setting); } return $buffer; } /** * Processes the TestResult object from an isolated process. * * @param Test $test * @param TestResult $result * @param string $stdout * @param string $stderr */ private function processChildResult(Test $test, TestResult $result, $stdout, $stderr) { $time = 0; if (!empty($stderr)) { $result->addError( $test, new Exception(\trim($stderr)), $time ); } else { \set_error_handler(function ($errno, $errstr, $errfile, $errline) { throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); }); try { if (\strpos($stdout, "#!/usr/bin/env php\n") === 0) { $stdout = \substr($stdout, 19); } $childResult = \unserialize(\str_replace("#!/usr/bin/env php\n", '', $stdout)); \restore_error_handler(); } catch (ErrorException $e) { \restore_error_handler(); $childResult = false; $result->addError( $test, new Exception(\trim($stdout), 0, $e), $time ); } if ($childResult !== false) { if (!empty($childResult['output'])) { $output = $childResult['output']; } $test->setResult($childResult['testResult']); $test->addToAssertionCount($childResult['numAssertions']); /** @var TestResult $childResult */ $childResult = $childResult['result']; if ($result->getCollectCodeCoverageInformation()) { $result->getCodeCoverage()->merge( $childResult->getCodeCoverage() ); } $time = $childResult->time(); $notImplemented = $childResult->notImplemented(); $risky = $childResult->risky(); $skipped = $childResult->skipped(); $errors = $childResult->errors(); $warnings = $childResult->warnings(); $failures = $childResult->failures(); if (!empty($notImplemented)) { $result->addError( $test, $this->getException($notImplemented[0]), $time ); } elseif (!empty($risky)) { $result->addError( $test, $this->getException($risky[0]), $time ); } elseif (!empty($skipped)) { $result->addError( $test, $this->getException($skipped[0]), $time ); } elseif (!empty($errors)) { $result->addError( $test, $this->getException($errors[0]), $time ); } elseif (!empty($warnings)) { $result->addWarning( $test, $this->getException($warnings[0]), $time ); } elseif (!empty($failures)) { $result->addFailure( $test, $this->getException($failures[0]), $time ); } } } $result->endTest($test, $time); if (!empty($output)) { print $output; } } /** * Gets the thrown exception from a PHPUnit\Framework\TestFailure. * * @param TestFailure $error * * @return Exception * * @see https://github.com/sebastianbergmann/phpunit/issues/74 */ private function getException(TestFailure $error) { $exception = $error->thrownException(); if ($exception instanceof __PHP_Incomplete_Class) { $exceptionArray = []; foreach ((array) $exception as $key => $value) { $key = \substr($key, \strrpos($key, "\0") + 1); $exceptionArray[$key] = $value; } $exception = new SyntheticError( \sprintf( '%s: %s', $exceptionArray['_PHP_Incomplete_Class_Name'], $exceptionArray['message'] ), $exceptionArray['code'], $exceptionArray['file'], $exceptionArray['line'], $exceptionArray['trace'] ); } return $exception; } } phpunit-6.5.5/src/Util/PHP/DefaultPhpProcess.php000066400000000000000000000127731321540746700215000ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; use PHPUnit\Framework\Exception; /** * Default utility for PHP sub-processes. */ class DefaultPhpProcess extends AbstractPhpProcess { /** * @var string */ protected $tempFile; /** * @var bool */ protected $useTempFile = false; /** * Runs a single job (PHP code) using a separate PHP process. * * @param string $job * @param array $settings * * @return array * * @throws Exception */ public function runJob($job, array $settings = []) { if ($this->useTempFile || $this->stdin) { if (!($this->tempFile = \tempnam(\sys_get_temp_dir(), 'PHPUnit')) || \file_put_contents($this->tempFile, $job) === false) { throw new Exception( 'Unable to write temporary file' ); } $job = $this->stdin; } return $this->runProcess($job, $settings); } /** * Returns an array of file handles to be used in place of pipes * * @return array */ protected function getHandles() { return []; } /** * Handles creating the child process and returning the STDOUT and STDERR * * @param string $job * @param array $settings * * @return array * * @throws Exception */ protected function runProcess($job, $settings) { $handles = $this->getHandles(); $env = null; if ($this->env) { $env = $_SERVER ?? []; unset($env['argv'], $env['argc']); $env = \array_merge($env, $this->env); foreach ($env as $envKey => $envVar) { if (\is_array($envVar)) { unset($env[$envKey]); } } } $pipeSpec = [ 0 => $handles[0] ?? ['pipe', 'r'], 1 => $handles[1] ?? ['pipe', 'w'], 2 => $handles[2] ?? ['pipe', 'w'], ]; $process = \proc_open( $this->getCommand($settings, $this->tempFile), $pipeSpec, $pipes, null, $env ); if (!\is_resource($process)) { throw new Exception( 'Unable to spawn worker process' ); } if ($job) { $this->process($pipes[0], $job); } \fclose($pipes[0]); if ($this->timeout) { $stderr = $stdout = ''; unset($pipes[0]); while (true) { $r = $pipes; $w = null; $e = null; $n = @\stream_select($r, $w, $e, $this->timeout); if ($n === false) { break; } elseif ($n === 0) { \proc_terminate($process, 9); throw new Exception( \sprintf( 'Job execution aborted after %d seconds', $this->timeout ) ); } elseif ($n > 0) { foreach ($r as $pipe) { $pipeOffset = 0; foreach ($pipes as $i => $origPipe) { if ($pipe == $origPipe) { $pipeOffset = $i; break; } } if (!$pipeOffset) { break; } $line = \fread($pipe, 8192); if (\strlen($line) == 0) { \fclose($pipes[$pipeOffset]); unset($pipes[$pipeOffset]); } else { if ($pipeOffset == 1) { $stdout .= $line; } else { $stderr .= $line; } } } if (empty($pipes)) { break; } } } } else { if (isset($pipes[1])) { $stdout = \stream_get_contents($pipes[1]); \fclose($pipes[1]); } if (isset($pipes[2])) { $stderr = \stream_get_contents($pipes[2]); \fclose($pipes[2]); } } if (isset($handles[1])) { \rewind($handles[1]); $stdout = \stream_get_contents($handles[1]); \fclose($handles[1]); } if (isset($handles[2])) { \rewind($handles[2]); $stderr = \stream_get_contents($handles[2]); \fclose($handles[2]); } \proc_close($process); $this->cleanup(); return ['stdout' => $stdout, 'stderr' => $stderr]; } /** * @param resource $pipe * @param string $job * * @throws Exception */ protected function process($pipe, $job) { \fwrite($pipe, $job); } protected function cleanup() { if ($this->tempFile) { \unlink($this->tempFile); } } } phpunit-6.5.5/src/Util/PHP/Template/000077500000000000000000000000001321540746700171355ustar00rootroot00000000000000phpunit-6.5.5/src/Util/PHP/Template/PhptTestCase.tpl.dist000066400000000000000000000021061321540746700231660ustar00rootroot00000000000000start(__FILE__); } register_shutdown_function(function() use ($coverage, $autoPrependFile) { $output = null; if ($coverage) { $output = $coverage->stop(); } file_put_contents('{coverageFile}', serialize($output)); }); ob_end_clean(); if ($autoPrependFile) { require $autoPrependFile; $includes = get_included_files(); $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'][] = array_pop($includes); unset($includes); } phpunit-6.5.5/src/Util/PHP/Template/TestCaseClass.tpl.dist000066400000000000000000000057631321540746700233340ustar00rootroot00000000000000setCodeCoverage( new CodeCoverage( null, unserialize('{codeCoverageFilter}') ) ); } $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); $result->enforceTimeLimit({enforcesTimeLimit}); $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests}); $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests}); $test = new {className}(null, unserialize('{data}'), '{dataName}'); $test->setDependencyInput(unserialize('{dependencyInput}')); $test->setInIsolation(TRUE); ob_end_clean(); $test->run($result); $output = ''; if (!$test->hasExpectationOnOutput()) { $output = $test->getActualOutput(); } @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */ if ($stdout = stream_get_contents(STDOUT)) { $output = $stdout . $output; $streamMetaData = stream_get_meta_data(STDOUT); if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { @ftruncate(STDOUT, 0); @rewind(STDOUT); } } print serialize( array( 'testResult' => $test->getResult(), 'numAssertions' => $test->getNumAssertions(), 'result' => $result, 'output' => $output ) ); } $configurationFilePath = '{configurationFilePath}'; if ('' !== $configurationFilePath) { $configuration = PHPUnit\Util\Configuration::getInstance($configurationFilePath); $configuration->handlePHPConfiguration(); unset($configuration); } function __phpunit_error_handler($errno, $errstr, $errfile, $errline, $errcontext) { return true; } set_error_handler('__phpunit_error_handler'); {constants} {included_files} {globals} restore_error_handler(); if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { require_once $GLOBALS['__PHPUNIT_BOOTSTRAP']; unset($GLOBALS['__PHPUNIT_BOOTSTRAP']); } __phpunit_run_isolated_test(); phpunit-6.5.5/src/Util/PHP/Template/TestCaseMethod.tpl.dist000066400000000000000000000060741321540746700235030ustar00rootroot00000000000000setCodeCoverage( new CodeCoverage( null, unserialize('{codeCoverageFilter}') ) ); } $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); $result->enforceTimeLimit({enforcesTimeLimit}); $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests}); $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests}); /** @var TestCase $test */ $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}'); $test->setDependencyInput(unserialize('{dependencyInput}')); $test->setInIsolation(TRUE); ob_end_clean(); $test->run($result); $output = ''; if (!$test->hasExpectationOnOutput()) { $output = $test->getActualOutput(); } @rewind(STDOUT); /* @ as not every STDOUT target stream is rewindable */ if ($stdout = stream_get_contents(STDOUT)) { $output = $stdout . $output; $streamMetaData = stream_get_meta_data(STDOUT); if (!empty($streamMetaData['stream_type']) && 'STDIO' === $streamMetaData['stream_type']) { @ftruncate(STDOUT, 0); @rewind(STDOUT); } } print serialize( array( 'testResult' => $test->getResult(), 'numAssertions' => $test->getNumAssertions(), 'result' => $result, 'output' => $output ) ); } $configurationFilePath = '{configurationFilePath}'; if ('' !== $configurationFilePath) { $configuration = PHPUnit\Util\Configuration::getInstance($configurationFilePath); $configuration->handlePHPConfiguration(); unset($configuration); } function __phpunit_error_handler($errno, $errstr, $errfile, $errline, $errcontext) { return true; } set_error_handler('__phpunit_error_handler'); {constants} {included_files} {globals} restore_error_handler(); if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { require_once $GLOBALS['__PHPUNIT_BOOTSTRAP']; unset($GLOBALS['__PHPUNIT_BOOTSTRAP']); } __phpunit_run_isolated_test(); phpunit-6.5.5/src/Util/PHP/WindowsPhpProcess.php000066400000000000000000000020241321540746700215320ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\PHP; use PHPUnit\Framework\Exception; /** * Windows utility for PHP sub-processes. * * Reading from STDOUT or STDERR hangs forever on Windows if the output is * too large. * * @see https://bugs.php.net/bug.php?id=51800 */ class WindowsPhpProcess extends DefaultPhpProcess { protected $useTempFile = true; protected function getHandles() { if (false === $stdout_handle = \tmpfile()) { throw new Exception( 'A temporary file could not be created; verify that your TEMP environment variable is writable' ); } return [ 1 => $stdout_handle ]; } public function getCommand(array $settings, $file = null) { return '"' . parent::getCommand($settings, $file) . '"'; } } phpunit-6.5.5/src/Util/PHP/eval-stdin.php000066400000000000000000000004241321540746700201410ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ eval('?>' . \file_get_contents('php://stdin')); phpunit-6.5.5/src/Util/Printer.php000066400000000000000000000065011321540746700170710ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use PHPUnit\Framework\Exception; /** * Utility class that can print to STDOUT or write to a file. */ class Printer { /** * If true, flush output after every write. * * @var bool */ protected $autoFlush = false; /** * @var resource */ protected $out; /** * @var string */ protected $outTarget; /** * Constructor. * * @param mixed $out * * @throws Exception */ public function __construct($out = null) { if ($out !== null) { if (\is_string($out)) { if (\strpos($out, 'socket://') === 0) { $out = \explode(':', \str_replace('socket://', '', $out)); if (\count($out) != 2) { throw new Exception; } $this->out = \fsockopen($out[0], $out[1]); } else { if (\strpos($out, 'php://') === false && !\is_dir(\dirname($out))) { \mkdir(\dirname($out), 0777, true); } $this->out = \fopen($out, 'wt'); } $this->outTarget = $out; } else { $this->out = $out; } } } /** * Flush buffer and close output if it's not to a PHP stream */ public function flush() { if ($this->out && \strncmp($this->outTarget, 'php://', 6) !== 0) { \fclose($this->out); } } /** * Performs a safe, incremental flush. * * Do not confuse this function with the flush() function of this class, * since the flush() function may close the file being written to, rendering * the current object no longer usable. */ public function incrementalFlush() { if ($this->out) { \fflush($this->out); } else { \flush(); } } /** * @param string $buffer */ public function write($buffer) { if ($this->out) { \fwrite($this->out, $buffer); if ($this->autoFlush) { $this->incrementalFlush(); } } else { if (PHP_SAPI != 'cli' && PHP_SAPI != 'phpdbg') { $buffer = \htmlspecialchars($buffer, ENT_SUBSTITUTE); } print $buffer; if ($this->autoFlush) { $this->incrementalFlush(); } } } /** * Check auto-flush mode. * * @return bool */ public function getAutoFlush() { return $this->autoFlush; } /** * Set auto-flushing mode. * * If set, *incremental* flushes will be done after each write. This should * not be confused with the different effects of this class' flush() method. * * @param bool $autoFlush */ public function setAutoFlush($autoFlush) { if (\is_bool($autoFlush)) { $this->autoFlush = $autoFlush; } else { throw InvalidArgumentHelper::factory(1, 'boolean'); } } } phpunit-6.5.5/src/Util/RegularExpression.php000066400000000000000000000015701321540746700211300ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; /** * Error handler that converts PHP errors and warnings to exceptions. */ class RegularExpression { /** * @param string $pattern * @param string $subject * @param null $matches * @param int $flags * @param int $offset * * @return int */ public static function safeMatch($pattern, $subject, $matches = null, $flags = 0, $offset = 0) { $handler_terminator = ErrorHandler::handleErrorOnce(E_WARNING); $match = \preg_match($pattern, $subject, $matches, $flags, $offset); $handler_terminator(); // cleaning return $match; } } phpunit-6.5.5/src/Util/Test.php000066400000000000000000001131701321540746700163660ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util; use Iterator; use PharIo\Version\VersionConstraintParser; use PHPUnit\Framework\CodeCoverageException; use PHPUnit\Framework\Exception; use PHPUnit\Framework\InvalidCoversTargetException; use PHPUnit\Framework\SelfDescribing; use PHPUnit\Framework\SkippedTestError; use PHPUnit\Framework\TestCase; use PHPUnit\Framework\Warning; use PHPUnit\Runner\Version; use ReflectionClass; use ReflectionException; use ReflectionFunction; use ReflectionMethod; use SebastianBergmann\Environment\OperatingSystem; use Traversable; /** * Test helpers. */ class Test { const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/'; const REGEX_TEST_WITH = '/@testWith\s+/'; const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m'; const REGEX_REQUIRES_VERSION = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[<>=!]{0,2})\s*(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[\d\t -.|~^]+)[ \t]*\r?$/m'; const REGEX_REQUIRES_OS = '/@requires\s+(?POS(?:FAMILY)?)\s+(?P.+?)[ \t]*\r?$/m'; const REGEX_REQUIRES = '/@requires\s+(?Pfunction|extension)\s+(?P([^ ]+?))\s*(?P[<>=!]{0,2})\s*(?P[\d\.-]+[\d\.]?)?[ \t]*\r?$/m'; const UNKNOWN = -1; const SMALL = 0; const MEDIUM = 1; const LARGE = 2; private static $annotationCache = []; private static $hookMethods = []; /** * @param \PHPUnit\Framework\Test $test * @param bool $asString * * @return mixed */ public static function describe(\PHPUnit\Framework\Test $test, $asString = true) { if ($asString) { if ($test instanceof SelfDescribing) { return $test->toString(); } return \get_class($test); } if ($test instanceof TestCase) { return [ \get_class($test), $test->getName() ]; } if ($test instanceof SelfDescribing) { return ['', $test->toString()]; } return ['', \get_class($test)]; } /** * @param string $className * @param string $methodName * * @return array|bool * * @throws CodeCoverageException */ public static function getLinesToBeCovered($className, $methodName) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); if (isset($annotations['class']['coversNothing']) || isset($annotations['method']['coversNothing'])) { return false; } return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers'); } /** * Returns lines of code specified with the @uses annotation. * * @param string $className * @param string $methodName * * @return array */ public static function getLinesToBeUsed($className, $methodName) { return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses'); } /** * @param string $className * @param string $methodName * @param string $mode * * @return array * * @throws CodeCoverageException */ private static function getLinesToBeCoveredOrUsed($className, $methodName, $mode) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); $classShortcut = null; if (!empty($annotations['class'][$mode . 'DefaultClass'])) { if (\count($annotations['class'][$mode . 'DefaultClass']) > 1) { throw new CodeCoverageException( \sprintf( 'More than one @%sClass annotation in class or interface "%s".', $mode, $className ) ); } $classShortcut = $annotations['class'][$mode . 'DefaultClass'][0]; } $list = []; if (isset($annotations['class'][$mode])) { $list = $annotations['class'][$mode]; } if (isset($annotations['method'][$mode])) { $list = \array_merge($list, $annotations['method'][$mode]); } $codeList = []; foreach (\array_unique($list) as $element) { if ($classShortcut && \strncmp($element, '::', 2) === 0) { $element = $classShortcut . $element; } $element = \preg_replace('/[\s()]+$/', '', $element); $element = \explode(' ', $element); $element = $element[0]; $codeList = \array_merge( $codeList, self::resolveElementToReflectionObjects($element) ); } return self::resolveReflectionObjectsToLines($codeList); } /** * Returns the requirements for a test. * * @param string $className * @param string $methodName * * @return array */ public static function getRequirements($className, $methodName) { $reflector = new ReflectionClass($className); $docComment = $reflector->getDocComment(); $reflector = new ReflectionMethod($className, $methodName); $docComment .= "\n" . $reflector->getDocComment(); $requires = []; if ($count = \preg_match_all(self::REGEX_REQUIRES_OS, $docComment, $matches)) { foreach (\range(0, $count - 1) as $i) { $requires[$matches['name'][$i]] = $matches['value'][$i]; } } if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION, $docComment, $matches)) { foreach (\range(0, $count - 1) as $i) { $requires[$matches['name'][$i]] = [ 'version' => $matches['version'][$i], 'operator' => $matches['operator'][$i] ]; } } if ($count = \preg_match_all(self::REGEX_REQUIRES_VERSION_CONSTRAINT, $docComment, $matches)) { foreach (\range(0, $count - 1) as $i) { if (!empty($requires[$matches['name'][$i]])) { continue; } try { $versionConstraintParser = new VersionConstraintParser; $requires[$matches['name'][$i] . '_constraint'] = [ 'constraint' => $versionConstraintParser->parse(\trim($matches['constraint'][$i])) ]; } catch (\PharIo\Version\Exception $e) { throw new Warning($e->getMessage(), $e->getCode(), $e); } } } if ($count = \preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) { foreach (\range(0, $count - 1) as $i) { $name = $matches['name'][$i] . 's'; if (!isset($requires[$name])) { $requires[$name] = []; } $requires[$name][] = $matches['value'][$i]; if (empty($matches['version'][$i]) || $name != 'extensions') { continue; } $requires['extension_versions'][$matches['value'][$i]] = [ 'version' => $matches['version'][$i], 'operator' => $matches['operator'][$i] ]; } } return $requires; } /** * Returns the missing requirements for a test. * * @param string $className * @param string $methodName * * @return string[] */ public static function getMissingRequirements($className, $methodName) { $required = static::getRequirements($className, $methodName); $missing = []; if (!empty($required['PHP'])) { $operator = empty($required['PHP']['operator']) ? '>=' : $required['PHP']['operator']; if (!\version_compare(PHP_VERSION, $required['PHP']['version'], $operator)) { $missing[] = \sprintf('PHP %s %s is required.', $operator, $required['PHP']['version']); } } elseif (!empty($required['PHP_constraint'])) { $version = new \PharIo\Version\Version(self::sanitizeVersionNumber(PHP_VERSION)); if (!$required['PHP_constraint']['constraint']->complies($version)) { $missing[] = \sprintf( 'PHP version does not match the required constraint %s.', $required['PHP_constraint']['constraint']->asString() ); } } if (!empty($required['PHPUnit'])) { $phpunitVersion = Version::id(); $operator = empty($required['PHPUnit']['operator']) ? '>=' : $required['PHPUnit']['operator']; if (!\version_compare($phpunitVersion, $required['PHPUnit']['version'], $operator)) { $missing[] = \sprintf('PHPUnit %s %s is required.', $operator, $required['PHPUnit']['version']); } } elseif (!empty($required['PHPUnit_constraint'])) { $phpunitVersion = new \PharIo\Version\Version(self::sanitizeVersionNumber(Version::id())); if (!$required['PHPUnit_constraint']['constraint']->complies($phpunitVersion)) { $missing[] = \sprintf( 'PHPUnit version does not match the required constraint %s.', $required['PHPUnit_constraint']['constraint']->asString() ); } } if (!empty($required['OSFAMILY']) && $required['OSFAMILY'] !== (new OperatingSystem())->getFamily()) { $missing[] = \sprintf('Operating system %s is required.', $required['OSFAMILY']); } if (!empty($required['OS'])) { $requiredOsPattern = \sprintf('/%s/i', \addcslashes($required['OS'], '/')); if (!\preg_match($requiredOsPattern, PHP_OS)) { $missing[] = \sprintf('Operating system matching %s is required.', $requiredOsPattern); } } if (!empty($required['functions'])) { foreach ($required['functions'] as $function) { $pieces = \explode('::', $function); if (2 === \count($pieces) && \method_exists($pieces[0], $pieces[1])) { continue; } if (\function_exists($function)) { continue; } $missing[] = \sprintf('Function %s is required.', $function); } } if (!empty($required['extensions'])) { foreach ($required['extensions'] as $extension) { if (isset($required['extension_versions'][$extension])) { continue; } if (!\extension_loaded($extension)) { $missing[] = \sprintf('Extension %s is required.', $extension); } } } if (!empty($required['extension_versions'])) { foreach ($required['extension_versions'] as $extension => $required) { $actualVersion = \phpversion($extension); $operator = empty($required['operator']) ? '>=' : $required['operator']; if (false === $actualVersion || !\version_compare($actualVersion, $required['version'], $operator)) { $missing[] = \sprintf('Extension %s %s %s is required.', $extension, $operator, $required['version']); } } } return $missing; } /** * Returns the expected exception for a test. * * @param string $className * @param string $methodName * * @return array|false */ public static function getExpectedException($className, $methodName) { $reflector = new ReflectionMethod($className, $methodName); $docComment = $reflector->getDocComment(); $docComment = \substr($docComment, 3, -2); if (\preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); $class = $matches[1]; $code = null; $message = ''; $messageRegExp = ''; if (isset($matches[2])) { $message = \trim($matches[2]); } elseif (isset($annotations['method']['expectedExceptionMessage'])) { $message = self::parseAnnotationContent( $annotations['method']['expectedExceptionMessage'][0] ); } if (isset($annotations['method']['expectedExceptionMessageRegExp'])) { $messageRegExp = self::parseAnnotationContent( $annotations['method']['expectedExceptionMessageRegExp'][0] ); } if (isset($matches[3])) { $code = $matches[3]; } elseif (isset($annotations['method']['expectedExceptionCode'])) { $code = self::parseAnnotationContent( $annotations['method']['expectedExceptionCode'][0] ); } if (\is_numeric($code)) { $code = (int) $code; } elseif (\is_string($code) && \defined($code)) { $code = (int) \constant($code); } return [ 'class' => $class, 'code' => $code, 'message' => $message, 'message_regex' => $messageRegExp ]; } return false; } /** * Parse annotation content to use constant/class constant values * * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME * * If the constant is not found the string is used as is to ensure maximum BC. * * @param string $message * * @return string */ private static function parseAnnotationContent($message) { if ((\strpos($message, '::') !== false && \count(\explode('::', $message)) == 2) && \defined($message)) { $message = \constant($message); } return $message; } /** * Returns the provided data for a method. * * @param string $className * @param string $methodName * * @return array When a data provider is specified and exists * null When no data provider is specified * * @throws Exception */ public static function getProvidedData($className, $methodName) { $reflector = new ReflectionMethod($className, $methodName); $docComment = $reflector->getDocComment(); $data = self::getDataFromDataProviderAnnotation($docComment, $className, $methodName); if ($data === null) { $data = self::getDataFromTestWithAnnotation($docComment); } if (\is_array($data) && empty($data)) { throw new SkippedTestError; } if ($data !== null) { foreach ($data as $key => $value) { if (!\is_array($value)) { throw new Exception( \sprintf( 'Data set %s is invalid.', \is_int($key) ? '#' . $key : '"' . $key . '"' ) ); } } } return $data; } /** * Returns the provided data for a method. * * @param string $docComment * @param string $className * @param string $methodName * * @return array|Iterator when a data provider is specified and exists * null when no data provider is specified * * @throws Exception */ private static function getDataFromDataProviderAnnotation($docComment, $className, $methodName) { if (\preg_match_all(self::REGEX_DATA_PROVIDER, $docComment, $matches)) { $result = []; foreach ($matches[1] as $match) { $dataProviderMethodNameNamespace = \explode('\\', $match); $leaf = \explode('::', \array_pop($dataProviderMethodNameNamespace)); $dataProviderMethodName = \array_pop($leaf); if (!empty($dataProviderMethodNameNamespace)) { $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\'; } else { $dataProviderMethodNameNamespace = ''; } if (!empty($leaf)) { $dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf); } else { $dataProviderClassName = $className; } $dataProviderClass = new ReflectionClass($dataProviderClassName); $dataProviderMethod = $dataProviderClass->getMethod( $dataProviderMethodName ); if ($dataProviderMethod->isStatic()) { $object = null; } else { $object = $dataProviderClass->newInstance(); } if ($dataProviderMethod->getNumberOfParameters() == 0) { $data = $dataProviderMethod->invoke($object); } else { $data = $dataProviderMethod->invoke($object, $methodName); } if ($data instanceof Traversable) { $origData = $data; $data = []; foreach ($origData as $key => $value) { if (\is_int($key)) { $data[] = $value; } else { $data[$key] = $value; } } } if (\is_array($data)) { $result = \array_merge($result, $data); } } return $result; } } /** * @param string $docComment full docComment string * * @return array|null array when @testWith annotation is defined, * null when @testWith annotation is omitted * * @throws Exception when @testWith annotation is defined but cannot be parsed */ public static function getDataFromTestWithAnnotation($docComment) { $docComment = self::cleanUpMultiLineAnnotation($docComment); if (\preg_match(self::REGEX_TEST_WITH, $docComment, $matches, PREG_OFFSET_CAPTURE)) { $offset = \strlen($matches[0][0]) + $matches[0][1]; $annotationContent = \substr($docComment, $offset); $data = []; foreach (\explode("\n", $annotationContent) as $candidateRow) { $candidateRow = \trim($candidateRow); if ($candidateRow[0] !== '[') { break; } $dataSet = \json_decode($candidateRow, true); if (\json_last_error() != JSON_ERROR_NONE) { throw new Exception( 'The dataset for the @testWith annotation cannot be parsed: ' . \json_last_error_msg() ); } $data[] = $dataSet; } if (!$data) { throw new Exception('The dataset for the @testWith annotation cannot be parsed.'); } return $data; } } private static function cleanUpMultiLineAnnotation($docComment) { //removing initial ' * ' for docComment $docComment = \str_replace("\r\n", "\n", $docComment); $docComment = \preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment); $docComment = \substr($docComment, 0, -1); $docComment = \rtrim($docComment, "\n"); return $docComment; } /** * @param string $className * @param string $methodName * * @return array * * @throws ReflectionException */ public static function parseTestMethodAnnotations($className, $methodName = '') { if (!isset(self::$annotationCache[$className])) { $class = new ReflectionClass($className); $traits = $class->getTraits(); $annotations = []; foreach ($traits as $trait) { $annotations = \array_merge( $annotations, self::parseAnnotations($trait->getDocComment()) ); } self::$annotationCache[$className] = \array_merge( $annotations, self::parseAnnotations($class->getDocComment()) ); } if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) { try { $method = new ReflectionMethod($className, $methodName); $annotations = self::parseAnnotations($method->getDocComment()); } catch (ReflectionException $e) { $annotations = []; } self::$annotationCache[$className . '::' . $methodName] = $annotations; } return [ 'class' => self::$annotationCache[$className], 'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : [] ]; } /** * @param string $className * @param string $methodName * * @return array */ public static function getInlineAnnotations($className, $methodName) { $method = new ReflectionMethod($className, $methodName); $code = \file($method->getFileName()); $lineNumber = $method->getStartLine(); $startLine = $method->getStartLine() - 1; $endLine = $method->getEndLine() - 1; $methodLines = \array_slice($code, $startLine, $endLine - $startLine + 1); $annotations = []; foreach ($methodLines as $line) { if (\preg_match('#/\*\*?\s*@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?\*/$#m', $line, $matches)) { $annotations[\strtolower($matches['name'])] = [ 'line' => $lineNumber, 'value' => $matches['value'] ]; } $lineNumber++; } return $annotations; } /** * @param string $docblock * * @return array */ private static function parseAnnotations($docblock) { $annotations = []; // Strip away the docblock header and footer to ease parsing of one line annotations $docblock = \substr($docblock, 3, -2); if (\preg_match_all('/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m', $docblock, $matches)) { $numMatches = \count($matches[0]); for ($i = 0; $i < $numMatches; ++$i) { $annotations[$matches['name'][$i]][] = (string) $matches['value'][$i]; } } return $annotations; } /** * Returns the backup settings for a test. * * @param string $className * @param string $methodName * * @return array */ public static function getBackupSettings($className, $methodName) { return [ 'backupGlobals' => self::getBooleanAnnotationSetting( $className, $methodName, 'backupGlobals' ), 'backupStaticAttributes' => self::getBooleanAnnotationSetting( $className, $methodName, 'backupStaticAttributes' ) ]; } /** * Returns the dependencies for a test class or method. * * @param string $className * @param string $methodName * * @return array */ public static function getDependencies($className, $methodName) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); $dependencies = []; if (isset($annotations['class']['depends'])) { $dependencies = $annotations['class']['depends']; } if (isset($annotations['method']['depends'])) { $dependencies = \array_merge( $dependencies, $annotations['method']['depends'] ); } return \array_unique($dependencies); } /** * Returns the error handler settings for a test. * * @param string $className * @param string $methodName * * @return ?bool */ public static function getErrorHandlerSettings($className, $methodName) { return self::getBooleanAnnotationSetting( $className, $methodName, 'errorHandler' ); } /** * Returns the groups for a test class or method. * * @param string $className * @param string $methodName * * @return array */ public static function getGroups($className, $methodName = '') { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); $groups = []; if (isset($annotations['method']['author'])) { $groups = $annotations['method']['author']; } elseif (isset($annotations['class']['author'])) { $groups = $annotations['class']['author']; } if (isset($annotations['class']['group'])) { $groups = \array_merge($groups, $annotations['class']['group']); } if (isset($annotations['method']['group'])) { $groups = \array_merge($groups, $annotations['method']['group']); } if (isset($annotations['class']['ticket'])) { $groups = \array_merge($groups, $annotations['class']['ticket']); } if (isset($annotations['method']['ticket'])) { $groups = \array_merge($groups, $annotations['method']['ticket']); } foreach (['method', 'class'] as $element) { foreach (['small', 'medium', 'large'] as $size) { if (isset($annotations[$element][$size])) { $groups[] = $size; break 2; } } } return \array_unique($groups); } /** * Returns the size of the test. * * @param string $className * @param string $methodName * * @return int */ public static function getSize($className, $methodName) { $groups = \array_flip(self::getGroups($className, $methodName)); $class = new ReflectionClass($className); if (isset($groups['large']) || (\class_exists('PHPUnit\DbUnit\TestCase', false) && $class->isSubclassOf('PHPUnit\DbUnit\TestCase'))) { return self::LARGE; } if (isset($groups['medium'])) { return self::MEDIUM; } if (isset($groups['small'])) { return self::SMALL; } return self::UNKNOWN; } /** * Returns the process isolation settings for a test. * * @param string $className * @param string $methodName * * @return bool */ public static function getProcessIsolationSettings($className, $methodName) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']); } public static function getClassProcessIsolationSettings($className, $methodName) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); return isset($annotations['class']['runClassInSeparateProcess']); } /** * Returns the preserve global state settings for a test. * * @param string $className * @param string $methodName * * @return ?bool */ public static function getPreserveGlobalStateSettings($className, $methodName) { return self::getBooleanAnnotationSetting( $className, $methodName, 'preserveGlobalState' ); } /** * @param string $className * * @return array */ public static function getHookMethods($className) { if (!\class_exists($className, false)) { return self::emptyHookMethodsArray(); } if (!isset(self::$hookMethods[$className])) { self::$hookMethods[$className] = self::emptyHookMethodsArray(); try { $class = new ReflectionClass($className); foreach ($class->getMethods() as $method) { if (self::isBeforeClassMethod($method)) { \array_unshift( self::$hookMethods[$className]['beforeClass'], $method->getName() ); } if (self::isBeforeMethod($method)) { \array_unshift( self::$hookMethods[$className]['before'], $method->getName() ); } if (self::isAfterMethod($method)) { self::$hookMethods[$className]['after'][] = $method->getName(); } if (self::isAfterClassMethod($method)) { self::$hookMethods[$className]['afterClass'][] = $method->getName(); } } } catch (ReflectionException $e) { } } return self::$hookMethods[$className]; } /** * @return array */ private static function emptyHookMethodsArray() { return [ 'beforeClass' => ['setUpBeforeClass'], 'before' => ['setUp'], 'after' => ['tearDown'], 'afterClass' => ['tearDownAfterClass'] ]; } /** * @param string $className * @param string $methodName * @param string $settingName * * @return ?bool */ private static function getBooleanAnnotationSetting($className, $methodName, $settingName) { $annotations = self::parseTestMethodAnnotations( $className, $methodName ); if (isset($annotations['class'][$settingName])) { if ($annotations['class'][$settingName][0] == 'enabled') { return true; } if ($annotations['class'][$settingName][0] == 'disabled') { return false; } } if (isset($annotations['method'][$settingName])) { if ($annotations['method'][$settingName][0] == 'enabled') { return true; } if ($annotations['method'][$settingName][0] == 'disabled') { return false; } } } /** * @param string $element * * @return array * * @throws InvalidCoversTargetException */ private static function resolveElementToReflectionObjects($element) { $codeToCoverList = []; if (\strpos($element, '\\') !== false && \function_exists($element)) { $codeToCoverList[] = new ReflectionFunction($element); } elseif (\strpos($element, '::') !== false) { list($className, $methodName) = \explode('::', $element); if (isset($methodName[0]) && $methodName[0] == '<') { $classes = [$className]; foreach ($classes as $className) { if (!\class_exists($className) && !\interface_exists($className) && !\trait_exists($className)) { throw new InvalidCoversTargetException( \sprintf( 'Trying to @cover or @use not existing class or ' . 'interface "%s".', $className ) ); } $class = new ReflectionClass($className); $methods = $class->getMethods(); $inverse = isset($methodName[1]) && $methodName[1] == '!'; if (\strpos($methodName, 'protected')) { $visibility = 'isProtected'; } elseif (\strpos($methodName, 'private')) { $visibility = 'isPrivate'; } elseif (\strpos($methodName, 'public')) { $visibility = 'isPublic'; } foreach ($methods as $method) { if ($inverse && !$method->$visibility()) { $codeToCoverList[] = $method; } elseif (!$inverse && $method->$visibility()) { $codeToCoverList[] = $method; } } } } else { $classes = [$className]; foreach ($classes as $className) { if ($className == '' && \function_exists($methodName)) { $codeToCoverList[] = new ReflectionFunction( $methodName ); } else { if (!((\class_exists($className) || \interface_exists($className) || \trait_exists($className)) && \method_exists($className, $methodName))) { throw new InvalidCoversTargetException( \sprintf( 'Trying to @cover or @use not existing method "%s::%s".', $className, $methodName ) ); } $codeToCoverList[] = new ReflectionMethod( $className, $methodName ); } } } } else { $extended = false; if (\strpos($element, '') !== false) { $element = \str_replace('', '', $element); $extended = true; } $classes = [$element]; if ($extended) { $classes = \array_merge( $classes, \class_implements($element), \class_parents($element) ); } foreach ($classes as $className) { if (!\class_exists($className) && !\interface_exists($className) && !\trait_exists($className)) { throw new InvalidCoversTargetException( \sprintf( 'Trying to @cover or @use not existing class or ' . 'interface "%s".', $className ) ); } $codeToCoverList[] = new ReflectionClass($className); } } return $codeToCoverList; } /** * @param array $reflectors * * @return array */ private static function resolveReflectionObjectsToLines(array $reflectors) { $result = []; foreach ($reflectors as $reflector) { $filename = $reflector->getFileName(); if (!isset($result[$filename])) { $result[$filename] = []; } $result[$filename] = \array_merge( $result[$filename], \range($reflector->getStartLine(), $reflector->getEndLine()) ); } foreach ($result as $filename => $lineNumbers) { $result[$filename] = \array_keys(\array_flip($lineNumbers)); } return $result; } /** * @param ReflectionMethod $method * * @return bool */ private static function isBeforeClassMethod(ReflectionMethod $method) { return $method->isStatic() && \strpos($method->getDocComment(), '@beforeClass') !== false; } /** * @param ReflectionMethod $method * * @return bool */ private static function isBeforeMethod(ReflectionMethod $method) { return \preg_match('/@before\b/', $method->getDocComment()) > 0; } /** * @param ReflectionMethod $method * * @return bool */ private static function isAfterClassMethod(ReflectionMethod $method) { return $method->isStatic() && \strpos($method->getDocComment(), '@afterClass') !== false; } /** * @param ReflectionMethod $method * * @return bool */ private static function isAfterMethod(ReflectionMethod $method) { return \preg_match('/@after\b/', $method->getDocComment()) > 0; } /** * Trims any extensions from version string that follows after * the .[.] format * * @param $version (Optional) * * @return mixed */ private static function sanitizeVersionNumber($version) { return \preg_replace( '/^(\d+\.\d+(?:.\d+)?).*$/', '$1', $version ); } } phpunit-6.5.5/src/Util/TestDox/000077500000000000000000000000001321540746700163255ustar00rootroot00000000000000phpunit-6.5.5/src/Util/TestDox/HtmlResultPrinter.php000066400000000000000000000052571321540746700225160ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace PHPUnit\Util\TestDox; /** * Prints TestDox documentation in HTML format. */ class HtmlResultPrinter extends ResultPrinter { /** * @var string */ private $pageHeader = << Test Documentation EOT; /** * @var string */ private $classHeader = <<%s