From 040f2141dcc770383351457b415c1c1e0468dd06 Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Tue, 29 Jan 2019 07:00:13 +0100 Subject: [PATCH 1/9] DevKit updates --- README.md | 47 +++++++++++++++++++++----------------- composer.json | 2 +- src/Resources/meta/LICENSE | 2 +- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index f7744b6..75e716d 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,13 @@ [![Monthly Downloads](https://poser.pugx.org/symfony-cmf/resource/d/monthly)](https://packagist.org/packages/symfony-cmf/resource) [![Daily Downloads](https://poser.pugx.org/symfony-cmf/resource/d/daily)](https://packagist.org/packages/symfony-cmf/resource) -Branch | Travis | Coveralls | ------- | ------ | --------- | -master | [![Build Status][travis_unstable_badge]][travis_link] | [![Coverage Status][coveralls_unstable_badge]][coveralls_unstable_link] | +Branch | Travis | Coveralls | Scrutinizer | +------ | ------ | --------- | ----------- | +1.1 | [![Build Status][travis_stable_badge]][travis_stable_link] | [![Coverage Status][coveralls_stable_badge]][coveralls_stable_link] | [![Scrutinizer Status][scrutinizer_stable_badge]][scrutinizer_stable_link] | +3.0-dev | [![Build Status][travis_unstable_badge]][travis_unstable_link] | [![Coverage Status][coveralls_unstable_badge]][coveralls_unstable_link] | [![Scrutinizer Status][scrutinizer_unstable_badge]][scrutinizer_unstable_link] | -This package is part of the [Symfony Content Management Framework (CMF)](http://cmf.symfony.com/) and licensed + +This package is part of the [Symfony Content Management Framework (CMF)](https://cmf.symfony.com/) and licensed under the [MIT License](LICENSE). The Resource component provides PHPCR/ODM integration with Puli. @@ -24,7 +26,7 @@ The Resource component provides PHPCR/ODM integration with Puli. ## Requirements -* PHP 7.1 / 7.2 +* PHP 7.2 / 7.3 * Symfony * See also the `require` section of [composer.json](composer.json) @@ -32,16 +34,16 @@ The Resource component provides PHPCR/ODM integration with Puli. For the install guide and reference, see: -* [symfony-cmf/resource Documentation](http://symfony.com/doc/master/cmf/components/resource/index.html) +* [symfony-cmf/resource Documentation](https://symfony.com/doc/master/cmf/components/resource/index.html) See also: -* [All Symfony CMF documentation](http://symfony.com/doc/master/cmf/index.html) - complete Symfony CMF reference -* [Symfony CMF Website](http://cmf.symfony.com/) - introduction, live demo, support and community links +* [All Symfony CMF documentation](https://symfony.com/doc/master/cmf/index.html) - complete Symfony CMF reference +* [Symfony CMF Website](https://cmf.symfony.com/) - introduction, live demo, support and community links ## Support -For general support and questions, please use [StackOverflow](http://stackoverflow.com/questions/tagged/symfony-cmf). +For general support and questions, please use [StackOverflow](https://stackoverflow.com/questions/tagged/symfony-cmf). ## Contributing @@ -50,7 +52,7 @@ Pull requests are welcome. Please see our guide. Unit and/or functional tests exist for this package. See the -[Testing documentation](http://symfony.com/doc/master/cmf/components/testing.html) +[Testing documentation](https://symfony.com/doc/master/cmf/components/testing.html) for a guide to running the tests. Thanks to @@ -60,14 +62,17 @@ Thanks to This package is available under the [MIT license](src/Resources/meta/LICENSE). -[travis_legacy_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=master -[travis_stable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=master -[travis_unstable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=master -[travis_link]: https://travis-ci.org/symfony-cmf/resource - -[coveralls_legacy_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=master -[coveralls_legacy_link]: https://coveralls.io/github/symfony-cmf/resource?branch=master -[coveralls_stable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=master -[coveralls_stable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=master -[coveralls_unstable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=master -[coveralls_unstable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=master +[travis_stable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=1.1 +[travis_stable_link]: https://travis-ci.org/symfony-cmf/resource +[travis_unstable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=3.0-dev +[travis_unstable_link]: https://travis-ci.org/symfony-cmf/resource + +[coveralls_stable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=1.1 +[coveralls_stable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=1.1 +[coveralls_unstable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=3.0-dev +[coveralls_unstable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=3.0-dev + +[scrutinizer_stable_badge]: https://scrutinizer-ci.com/g/symfony-cmf/resource/badges/quality-score.png?b=1.1 +[scrutinizer_stable_link]: https://scrutinizer-ci.com/g/symfony-cmf/resource/?branch=1.1 +[scrutinizer_unstable_badge]: https://scrutinizer-ci.com/g/symfony-cmf/resource/badges/quality-score.png?b=3.0-dev +[scrutinizer_unstable_link]: https://scrutinizer-ci.com/g/symfony-cmf/resource/?branch=3.0-dev diff --git a/composer.json b/composer.json index fa10c7a..894315e 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "^7.1", + "php": "^7.2", "dantleech/glob-finder": "~1.0", "webmozart/assert": "^1.2", "webmozart/path-util": "^2.3" diff --git a/src/Resources/meta/LICENSE b/src/Resources/meta/LICENSE index d9c2f75..dcd7958 100644 --- a/src/Resources/meta/LICENSE +++ b/src/Resources/meta/LICENSE @@ -1,4 +1,4 @@ -Symfony Cmf Resource +Symfony CMF Resource The MIT License From cbb3f258d5562907774b3517d83a395031928acd Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Wed, 30 Jan 2019 23:43:29 +0100 Subject: [PATCH 2/9] DevKit updates --- Makefile | 6 ++++++ README.md | 14 +++++++------- composer.json | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index de4efc6..af4b83b 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,18 @@ ############################################################################ TESTING_SCRIPTS_DIR=vendor/symfony-cmf/testing/bin + +SYMFONY_PHPUNIT_VERSION=6 +SYMFONY_DEPRECATIONS_HELPER==weak CONSOLE=${TESTING_SCRIPTS_DIR}/console +SYMFONY_PHPUNIT_DIR=.phpunit +SYMFONY_PHPUNIT_REMOVE="symfony/yaml" VERSION=dev-master ifdef BRANCH VERSION=dev-${BRANCH} endif PACKAGE=symfony-cmf/resource + list: @echo 'test: will run all tests' @echo 'unit_tests: will run unit tests only' diff --git a/README.md b/README.md index 75e716d..35f0576 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Branch | Travis | Coveralls | Scrutinizer | ------ | ------ | --------- | ----------- | 1.1 | [![Build Status][travis_stable_badge]][travis_stable_link] | [![Coverage Status][coveralls_stable_badge]][coveralls_stable_link] | [![Scrutinizer Status][scrutinizer_stable_badge]][scrutinizer_stable_link] | -3.0-dev | [![Build Status][travis_unstable_badge]][travis_unstable_link] | [![Coverage Status][coveralls_unstable_badge]][coveralls_unstable_link] | [![Scrutinizer Status][scrutinizer_unstable_badge]][scrutinizer_unstable_link] | +dev-master | [![Build Status][travis_unstable_badge]][travis_unstable_link] | [![Coverage Status][coveralls_unstable_badge]][coveralls_unstable_link] | [![Scrutinizer Status][scrutinizer_unstable_badge]][scrutinizer_unstable_link] | This package is part of the [Symfony Content Management Framework (CMF)](https://cmf.symfony.com/) and licensed @@ -26,7 +26,7 @@ The Resource component provides PHPCR/ODM integration with Puli. ## Requirements -* PHP 7.2 / 7.3 +* PHP 7.1 / 7.2 / 7.3 * Symfony * See also the `require` section of [composer.json](composer.json) @@ -64,15 +64,15 @@ This package is available under the [MIT license](src/Resources/meta/LICENSE). [travis_stable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=1.1 [travis_stable_link]: https://travis-ci.org/symfony-cmf/resource -[travis_unstable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=3.0-dev +[travis_unstable_badge]: https://travis-ci.org/symfony-cmf/resource.svg?branch=dev-master [travis_unstable_link]: https://travis-ci.org/symfony-cmf/resource [coveralls_stable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=1.1 [coveralls_stable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=1.1 -[coveralls_unstable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=3.0-dev -[coveralls_unstable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=3.0-dev +[coveralls_unstable_badge]: https://coveralls.io/repos/github/symfony-cmf/resource/badge.svg?branch=dev-master +[coveralls_unstable_link]: https://coveralls.io/github/symfony-cmf/resource?branch=dev-master [scrutinizer_stable_badge]: https://scrutinizer-ci.com/g/symfony-cmf/resource/badges/quality-score.png?b=1.1 [scrutinizer_stable_link]: https://scrutinizer-ci.com/g/symfony-cmf/resource/?branch=1.1 -[scrutinizer_unstable_badge]: https://scrutinizer-ci.com/g/symfony-cmf/resource/badges/quality-score.png?b=3.0-dev -[scrutinizer_unstable_link]: https://scrutinizer-ci.com/g/symfony-cmf/resource/?branch=3.0-dev +[scrutinizer_unstable_badge]: https://scrutinizer-ci.com/g/symfony-cmf/resource/badges/quality-score.png?b=dev-master +[scrutinizer_unstable_link]: https://scrutinizer-ci.com/g/symfony-cmf/resource/?branch=dev-master diff --git a/composer.json b/composer.json index 894315e..fa10c7a 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": "^7.2", + "php": "^7.1", "dantleech/glob-finder": "~1.0", "webmozart/assert": "^1.2", "webmozart/path-util": "^2.3" From 6e159aa955330c07c91715b853d781cc9f9b6582 Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Fri, 1 Mar 2019 16:54:50 +0100 Subject: [PATCH 3/9] DevKit updates --- .php_cs.dist | 64 +++++++++++++++++++++++++++++++++++ .styleci.yml | 2 +- .travis/after_success_test.sh | 5 +++ .travis/install_lint.sh | 11 ++++++ .travis/install_test.sh | 19 +++++++++++ Makefile | 48 +++++++++++++++++++++----- phpunit.xml.dist | 30 ++++++++++++---- src/Resources/meta/LICENSE | 2 +- 8 files changed, 163 insertions(+), 18 deletions(-) create mode 100644 .php_cs.dist create mode 100755 .travis/after_success_test.sh create mode 100755 .travis/install_lint.sh create mode 100755 .travis/install_test.sh diff --git a/.php_cs.dist b/.php_cs.dist new file mode 100644 index 0000000..5759af5 --- /dev/null +++ b/.php_cs.dist @@ -0,0 +1,64 @@ + true, + '@Symfony:risky' => true, + 'array_syntax' => [ + 'syntax' => 'short', + ], + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'header_comment' => [ + 'header' => $header, + ], + 'no_extra_blank_lines' => true, + 'no_php4_constructor' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'ordered_class_elements' => true, + 'ordered_imports' => true, + 'phpdoc_order' => true, + '@PHP56Migration' => true, + '@PHP56Migration:risky' => true, + '@PHPUnit57Migration:risky' => true, + '@PHP70Migration' => true, + '@PHP70Migration:risky' => true, + '@PHPUnit60Migration:risky' => true, + '@PHP71Migration' => true, + '@PHP71Migration:risky' => true, + 'compact_nullable_typehint' => true, + 'void_return' => null, + 'strict_comparison' => true, + 'strict_param' => true, +]; + + +$finder = PhpCsFixer\Finder::create() + ->in(__DIR__) + ->exclude('Tests/Fixtures') + ->exclude('tests/Fixtures') + ->exclude('Resources/skeleton') + ->exclude('Resources/public/vendor') +; + +return PhpCsFixer\Config::create() + ->setFinder($finder) + ->setRiskyAllowed(true) + ->setRules($rules) + ->setUsingCache(true) +; diff --git a/.styleci.yml b/.styleci.yml index 2bdb04b..c721eb6 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -7,7 +7,7 @@ ############################################################################ # This file is part of the Symfony CMF package. # # # -# (c) 2011-2017 Symfony CMF # +# (c) Symfony CMF # # # # For the full copyright and license information, please view the LICENSE # # file that was distributed with this source code. # diff --git a/.travis/after_success_test.sh b/.travis/after_success_test.sh new file mode 100755 index 0000000..9837420 --- /dev/null +++ b/.travis/after_success_test.sh @@ -0,0 +1,5 @@ + +#!/usr/bin/env sh +set -ev + +coveralls -v diff --git a/.travis/install_lint.sh b/.travis/install_lint.sh new file mode 100755 index 0000000..864c751 --- /dev/null +++ b/.travis/install_lint.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -ev + +mkdir --parents "${HOME}/bin" + +wget "http://cs.sensiolabs.org/download/php-cs-fixer-v2.phar" --output-document="${HOME}/bin/php-cs-fixer" +chmod u+x "${HOME}/bin/php-cs-fixer" + +composer global require sllh/composer-lint:@stable --prefer-dist --no-interaction + +gem install yaml-lint diff --git a/.travis/install_test.sh b/.travis/install_test.sh new file mode 100755 index 0000000..a033500 --- /dev/null +++ b/.travis/install_test.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env sh +set -ev + +mkdir --parents "${HOME}/bin" + +wget "https://phar.phpunit.de/phpunit-${PHPUNIT_VERSION}.phar" --output-document="${HOME}/bin/phpunit" +chmod u+x "${HOME}/bin/phpunit" + +# Coveralls client install +wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar --output-document="${HOME}/bin/coveralls" +chmod u+x "${HOME}/bin/coveralls" + +# To be removed when these issues are resolved: +# https://github.com/composer/composer/issues/5355 +if [ "${COMPOSER_FLAGS}" = '--prefer-lowest' ]; then + composer update --prefer-dist --no-interaction --prefer-stable --quiet +fi + +composer update --prefer-dist --no-interaction --prefer-stable ${COMPOSER_FLAGS} diff --git a/Makefile b/Makefile index af4b83b..887095d 100644 --- a/Makefile +++ b/Makefile @@ -7,32 +7,62 @@ ############################################################################ # This file is part of the Symfony CMF package. # # # -# (c) 2011-2017 Symfony CMF # +# (c) Symfony CMF # # # # For the full copyright and license information, please view the LICENSE # # file that was distributed with this source code. # ############################################################################ TESTING_SCRIPTS_DIR=vendor/symfony-cmf/testing/bin - -SYMFONY_PHPUNIT_VERSION=6 -SYMFONY_DEPRECATIONS_HELPER==weak CONSOLE=${TESTING_SCRIPTS_DIR}/console -SYMFONY_PHPUNIT_DIR=.phpunit -SYMFONY_PHPUNIT_REMOVE="symfony/yaml" VERSION=dev-master ifdef BRANCH VERSION=dev-${BRANCH} endif PACKAGE=symfony-cmf/resource +HAS_XDEBUG=$(shell php --modules|grep --quiet xdebug;echo $$?) list: @echo 'test: will run all tests' @echo 'unit_tests: will run unit tests only' - -include ${TESTING_SCRIPTS_DIR}/make/unit_tests.mk +TEST_DEPENDENCIES := "" +EXTRA_INCLUDES:=$(wildcard ${TESTING_SCRIPTS_DIR}/make/unit_tests.mk) +ifneq ($(strip $(EXTRA_INCLUDES)),) + contents := $(shell echo including extra rules $(EXTRA_INCLUDES)) + include $(EXTRA_INCLUDES) + TEST_DEPENDENCIES := $(TEST_DEPENDENCIES)" unit_tests" + endif .PHONY: test -test: unit_tests +test: build/xdebug-filter.php$ +ifneq ($(strip $(wildcard ${TESTING_SCRIPTS_DIR}/make/unit_tests.mk)),) + @make unit_tests +endif + +lint-php: + php-cs-fixer fix --ansi --verbose --diff --dry-run +.PHONY: lint-php + +lint: lint-composer lint-php +.PHONY: lint + +lint-composer: + composer validate +.PHONY: lint-composer + +cs-fix: cs-fix-php +.PHONY: cs-fix + +cs-fix-php: + php-cs-fixer fix --verbose +.PHONY: cs-fix-php + +build: + mkdir $@ + +build/xdebug-filter.php: phpunit.xml.dist build +ifeq ($(HAS_XDEBUG), 0) + phpunit --dump-xdebug-filter $@ +endif diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 635d7db..015b9f6 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,14 +2,30 @@ + colors="true" + bootstrap="vendor/symfony-cmf/testing/bootstrap/bootstrap.php" +> - - - ./tests + + + + + ./tests/Unit - + + + + + + src/ + + Resources/ + + + + + + + diff --git a/src/Resources/meta/LICENSE b/src/Resources/meta/LICENSE index dcd7958..107cd79 100644 --- a/src/Resources/meta/LICENSE +++ b/src/Resources/meta/LICENSE @@ -2,7 +2,7 @@ Symfony CMF Resource The MIT License - Copyright (c) 2011-2017 Symfony CMF + Copyright (c) Symfony CMF Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From f97338adf5e2f185b38578e31ee2d98eb947a53d Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Sat, 2 Mar 2019 00:38:55 +0100 Subject: [PATCH 4/9] cs fixes for php, version changes in composer.json, adjust to use same travis config --- .gitignore | 2 + .travis.yml | 58 ++++++++++++++----- composer.json | 10 ++-- puli/AbstractRepository.php | 4 +- puli/Api/PuliResource.php | 8 ++- puli/Api/ResourceCollection.php | 8 ++- puli/Api/ResourceMetadata.php | 4 +- puli/Api/ResourceRepository.php | 24 ++++---- puli/ArrayResourceCollection.php | 10 ++-- puli/GenericResource.php | 6 +- puli/ResourceCollectionIterator.php | 14 +++-- src/Description/Description.php | 10 ++-- .../DescriptionEnhancerInterface.php | 4 +- src/Description/DescriptionFactory.php | 4 +- src/Description/Descriptor.php | 40 +++++++------ .../Enhancer/Doctrine/PhpcrOdmEnhancer.php | 4 +- .../Enhancer/Sylius/ResourceEnhancer.php | 4 +- src/Repository/AbstractPhpcrRepository.php | 16 ++--- src/Repository/Api/EditableRepository.php | 12 ++-- src/Repository/PhpcrOdmRepository.php | 22 +++---- src/Repository/PhpcrRepository.php | 50 ++++++++-------- src/Repository/Resource/CmfResource.php | 6 +- .../Resource/Metadata/PhpcrMetadata.php | 4 +- src/Repository/Resource/PhpcrOdmResource.php | 6 +- src/Repository/Resource/PhpcrResource.php | 4 +- src/RepositoryRegistryInterface.php | 14 +++-- .../Description/DescriptionFactoryTest.php | 6 +- tests/Unit/Description/DescriptionTest.php | 18 +++--- .../Doctrine/PhpcrOdmEnhancerTest.php | 12 ++-- .../Enhancer/Sylius/ResourceEnhancerTest.php | 6 +- .../AbstractPhpcrRepositoryTestCase.php | 23 ++++---- .../Repository/PhpcrOdmRepositoryTest.php | 24 ++++---- tests/Unit/Repository/PhpcrRepositoryTest.php | 10 ++-- .../Resource/Metadata/PhpcrMetadataTest.php | 6 +- .../Resource/PhpcrOdmResourceTest.php | 6 +- .../Repository/Resource/PhpcrResourceTest.php | 6 +- 36 files changed, 283 insertions(+), 182 deletions(-) diff --git a/.gitignore b/.gitignore index 3d29dee..e10bd1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ Tests/Resources/data composer.lock vendor +build +.php_cs.cache diff --git a/.travis.yml b/.travis.yml index 6738e1d..19e5aa1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,39 +1,71 @@ +####################################################### +# DO NOT EDIT THIS FILE! # +# # +# It's auto-generated by symfony-cmf/dev-kit package. # +####################################################### + +############################################################################ +# This file is part of the Symfony CMF package. # +# # +# (c) Symfony CMF # +# # +# For the full copyright and license information, please view the LICENSE # +# file that was distributed with this source code. # +############################################################################ + language: php php: - 7.1 - + - 7.2 + - 7.3 sudo: false cache: directories: - - $HOME/.composer/cache/files - .phpunit + - $HOME/.composer/cache/files env: + matrix: SYMFONY_VERSION=4.2.* global: - - SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" - - SYMFONY_PHPUNIT_DIR=.phpunit SYMFONY_PHPUNIT_REMOVE="symfony/yaml" - - SYMFONY_PHPUNIT_VERSION=5.7 + - SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" + - SYMFONY_PHPUNIT_DIR=.phpunit SYMFONY_PHPUNIT_REMOVE="symfony/yaml" + - SYMFONY_PHPUNIT_VERSION=7 + - PHPUNIT_VERSION=7 + - TARGET=test matrix: - matrix: SYMFONY_VERSION=4.0.* include: + - env: TARGET=lint + - php: 7.3 + env: STABILITY="dev" SYMFONY_VERSION=4.3.* + - php: 7.3 + env: SYMFONY_VERSION=4.2.* - php: 7.1 - - php: 7.1 - env: COMPOSER_FLAGS="--prefer-lowest" REQUIREMENTS="phpcr/phpcr:2.1.2" + env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_VERSION=3.4.* SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" + - php: 7.2 + env: SYMFONY_VERSION=4.1.* fast_finish: true + allow_failures: + - php: 7.3 + env: STABILITY="dev" SYMFONY_VERSION=4.3.* before_install: - - if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then echo "memory_limit = -1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi - phpenv config-rm xdebug.ini || true - composer self-update - - if [ "$REQUIREMENTS" != "" ]; then composer require --no-update $REQUIREMENTS; fi - - if [ "$DEPS" = "dev" ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi + - composer validate --no-check-all --ansi + - if ! [ -z "$STABILITY" ]; then composer config minimum-stability ${STABILITY}; composer config prefer-stable true; fi; + - if [ "$SYMFONY_VERSION" != "" ]; then composer require symfony/symfony:${SYMFONY_VERSION} --no-update; fi + - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + +install: + - if [ -x .travis/install_${TARGET}.sh ]; then .travis/install_${TARGET}.sh; fi; -install: travis_wait composer update --prefer-dist $COMPOSER_FLAGS +script: make $TARGET -script: vendor/bin/simple-phpunit +after_success: + - if [ -x .travis/after_success_${TARGET}.sh ]; then .travis/after_success_${TARGET}.sh; fi; notifications: irc: "irc.freenode.org#symfony-cmf" diff --git a/composer.json b/composer.json index fa10c7a..f99632d 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "symfony-cmf/resource", + "type": "library", "description": "Bundle which facilitates document resource location via Puli", "homepage": "http://cmf.symfony.com", "license": "MIT", @@ -11,16 +12,17 @@ ], "require": { "php": "^7.1", - "dantleech/glob-finder": "~1.0", + "dantleech/glob-finder": "^1.0", "webmozart/assert": "^1.2", "webmozart/path-util": "^2.3" }, "require-dev": { - "jackalope/jackalope-doctrine-dbal": "^1.2", + "jackalope/jackalope-doctrine-dbal": "^1.3", "sonata-project/admin-bundle": "^3.1", "sylius/resource-bundle": "^0.18", - "symfony/phpunit-bridge": "^3.3 || ^4.0", - "doctrine/phpcr-odm": "^1.4|^2.0" + "symfony/phpunit-bridge": "4.2.2", + "doctrine/phpcr-odm": "^1.4 || ^2.0", + "symfony-cmf/testing": "^2.1.11" }, "suggest": { "doctrine/phpcr-odm": "To enable support for the PHPCR ODM documents", diff --git a/puli/AbstractRepository.php b/puli/AbstractRepository.php index 0419d79..7bcf1c7 100644 --- a/puli/AbstractRepository.php +++ b/puli/AbstractRepository.php @@ -1,9 +1,11 @@ resources = is_array($resources) ? $resources : iterator_to_array($resources); + $this->resources = \is_array($resources) ? $resources : iterator_to_array($resources); } /** @@ -136,7 +138,7 @@ public function merge($resources) */ public function isEmpty() { - return 0 === count($this->resources); + return 0 === \count($this->resources); } /** @@ -203,7 +205,7 @@ function (PuliResource $resource) { public function count() { - return count($this->resources); + return \count($this->resources); } public function getIterator($mode = ResourceCollectionIterator::KEY_AS_CURSOR) diff --git a/puli/GenericResource.php b/puli/GenericResource.php index fd21f1a..f723bf4 100644 --- a/puli/GenericResource.php +++ b/puli/GenericResource.php @@ -1,9 +1,11 @@ getRepository()) { - throw \RuntimeException(sprintf( + throw RuntimeException(sprintf( 'The resource %s does not exist.', $this->getRepositoryPath().'/'.$relPath )); diff --git a/puli/ResourceCollectionIterator.php b/puli/ResourceCollectionIterator.php index 8ed5c83..6738a18 100644 --- a/puli/ResourceCollectionIterator.php +++ b/puli/ResourceCollectionIterator.php @@ -1,9 +1,11 @@ resource->getPath(), - get_class($this->resource), + \get_class($this->resource), implode('", "', array_keys($this->descriptors)) )); } @@ -97,10 +99,10 @@ public function all() */ public function set($descriptor, $value) { - if (null !== $value && !is_scalar($value) && !is_array($value)) { + if (null !== $value && !is_scalar($value) && !\is_array($value)) { throw new \InvalidArgumentException(sprintf( 'Only scalar and array values are allowed as descriptor values, got "%s" when setting descriptor "%s"', - gettype($value), $descriptor + \gettype($value), $descriptor )); } diff --git a/src/Description/DescriptionEnhancerInterface.php b/src/Description/DescriptionEnhancerInterface.php index 4e281fd..eb8553e 100644 --- a/src/Description/DescriptionEnhancerInterface.php +++ b/src/Description/DescriptionEnhancerInterface.php @@ -1,9 +1,11 @@ listChildren($path); - return (bool) count($children); + return (bool) \count($children); } /** @@ -91,7 +93,7 @@ public function remove($query, $language = 'glob') $this->failUnlessGlob($language); $nodes = $this->finder->find($this->resolvePath($query)); - if (0 === count($nodes)) { + if (0 === \count($nodes)) { return 0; } @@ -105,7 +107,7 @@ public function remove($query, $language = 'glob') ), null, $e); } - return count($nodes); + return \count($nodes); } /** @@ -116,7 +118,7 @@ public function move($query, $targetPath, $language = 'glob') $this->failUnlessGlob($language); $nodes = $this->finder->find($this->resolvePath($query)); - if (0 === count($nodes)) { + if (0 === \count($nodes)) { return 0; } @@ -132,7 +134,7 @@ public function move($query, $targetPath, $language = 'glob') ), null, $e); } - return count($nodes); + return \count($nodes); } /** @@ -190,7 +192,7 @@ public function resolvePath($path) */ protected function unresolvePath($path) { - $path = substr($path, strlen($this->basePath)); + $path = substr($path, \strlen($this->basePath)); return $path; } diff --git a/src/Repository/Api/EditableRepository.php b/src/Repository/Api/EditableRepository.php index 6c4347a..cc5243d 100644 --- a/src/Repository/Api/EditableRepository.php +++ b/src/Repository/Api/EditableRepository.php @@ -1,9 +1,11 @@ managerRegistry = $managerRegistry; } - /** - * @return DocumentManagerInterface - */ - protected function getManager() - { - return $this->managerRegistry->getManager(); - } - /** * {@inheritdoc} */ @@ -71,7 +65,7 @@ public function listChildren($path) */ public function contains($selector, $language = 'glob') { - return count($this->find($selector, $language)) > 0; + return \count($this->find($selector, $language)) > 0; } /** @@ -113,6 +107,14 @@ public function reorderNode($sourcePath, $position) $this->getManager()->flush(); } + /** + * @return DocumentManagerInterface + */ + protected function getManager() + { + return $this->managerRegistry->getManager(); + } + /** * {@inheritdoc} */ diff --git a/src/Repository/PhpcrRepository.php b/src/Repository/PhpcrRepository.php index aa14daf..1a65c18 100644 --- a/src/Repository/PhpcrRepository.php +++ b/src/Repository/PhpcrRepository.php @@ -1,9 +1,11 @@ find($selector, $language)) > 0; + return \count($this->find($selector, $language)) > 0; } /** @@ -90,6 +92,28 @@ public function getTags() return []; } + /** + * {@inheritdoc} + */ + public function reorderNode($sourcePath, $position) + { + $node = $this->getNode($sourcePath); + $parent = $node->getParent(); + $nodeNames = $parent->getNodeNames(); + + if (0 === $position) { + $parent->orderBefore($node->getName(), $nodeNames[$position]); + } elseif (isset($nodeNames[$position + 1])) { + $parent->orderBefore($node->getName(), $nodeNames[$position + 1]); + } else { + $lastName = $nodeNames[\count($nodeNames) - 1]; + $parent->orderBefore($node->getName(), $lastName); + $parent->orderBefore($lastName, $node->getName()); + } + + $this->session->save(); + } + /** * {@inheritdoc} */ @@ -132,28 +156,6 @@ protected function moveNodes(array $nodes, $sourceQuery, $targetPath) $this->session->save(); } - /** - * {@inheritdoc} - */ - public function reorderNode($sourcePath, $position) - { - $node = $this->getNode($sourcePath); - $parent = $node->getParent(); - $nodeNames = $parent->getNodeNames(); - - if (0 === $position) { - $parent->orderBefore($node->getName(), $nodeNames[$position]); - } elseif (isset($nodeNames[$position + 1])) { - $parent->orderBefore($node->getName(), $nodeNames[$position + 1]); - } else { - $lastName = $nodeNames[count($nodeNames) - 1]; - $parent->orderBefore($node->getName(), $lastName); - $parent->orderBefore($lastName, $node->getName()); - } - - $this->session->save(); - } - private function doMoveNodes(array $nodes, $sourceQuery, $targetPath) { if (false === $this->isGlobbed($sourceQuery)) { diff --git a/src/Repository/Resource/CmfResource.php b/src/Repository/Resource/CmfResource.php index 316db01..e71ef1a 100644 --- a/src/Repository/Resource/CmfResource.php +++ b/src/Repository/Resource/CmfResource.php @@ -1,9 +1,11 @@ document)); + return ClassUtils::getRealClass(\get_class($this->document)); } /** diff --git a/src/Repository/Resource/PhpcrResource.php b/src/Repository/Resource/PhpcrResource.php index cd783fd..21d81a7 100644 --- a/src/Repository/Resource/PhpcrResource.php +++ b/src/Repository/Resource/PhpcrResource.php @@ -1,9 +1,11 @@ expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Only scalar and array values are allowed as descriptor values, got "object" when setting descriptor "hello"'); + $this->description->set('hello', new \stdClass()); } /** * It should throw an exception when requesting an unsupported descriptor. - * - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Supported descriptors: "foo", "bar" */ public function testGetUnsupported() { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Supported descriptors: "foo", "bar"'); + $this->description->set('foo', 'bar'); $this->description->set('bar', 'foo'); $this->description->get('not there'); diff --git a/tests/Unit/Description/Enhancer/Doctrine/PhpcrOdmEnhancerTest.php b/tests/Unit/Description/Enhancer/Doctrine/PhpcrOdmEnhancerTest.php index b49843a..521f9f6 100644 --- a/tests/Unit/Description/Enhancer/Doctrine/PhpcrOdmEnhancerTest.php +++ b/tests/Unit/Description/Enhancer/Doctrine/PhpcrOdmEnhancerTest.php @@ -1,9 +1,11 @@ prophesize(); $mappedObject1->willImplement(FooInterface::class); $metadata1 = $this->prophesize(ClassMetadata::class); - $metadata1->name = get_class($mappedObject1->reveal()); + $metadata1->name = \get_class($mappedObject1->reveal()); $metadata1->getReflectionClass()->willReturn(new \ReflectionClass($metadata1->name)); // object the extends an allowed abstract class $mappedObject2 = $this->prophesize(); $mappedObject2->willExtend(AbstractFoo::class); $metadata2 = $this->prophesize(ClassMetadata::class); - $metadata2->name = get_class($mappedObject2->reveal()); + $metadata2->name = \get_class($mappedObject2->reveal()); $metadata2->getReflectionClass()->willReturn(new \ReflectionClass($metadata2->name)); // object of exact type that is allowed $mappedObject3 = $this->prophesize(); $metadata3 = $this->prophesize(ClassMetadata::class); - $metadata3->name = get_class($mappedObject3->reveal()); + $metadata3->name = \get_class($mappedObject3->reveal()); $metadata3->getReflectionClass()->willReturn(new \ReflectionClass($metadata3->reveal())); // object that is not permitted diff --git a/tests/Unit/Description/Enhancer/Sylius/ResourceEnhancerTest.php b/tests/Unit/Description/Enhancer/Sylius/ResourceEnhancerTest.php index db3ffdf..bebcbf7 100644 --- a/tests/Unit/Description/Enhancer/Sylius/ResourceEnhancerTest.php +++ b/tests/Unit/Description/Enhancer/Sylius/ResourceEnhancerTest.php @@ -1,9 +1,11 @@ expectException(\InvalidArgumentException::class); + $this->getRepository($basePath)->get($requestedPath); } @@ -100,11 +98,11 @@ public function provideGetInvalid() /** * Clear is not supported. - * - * @expectedException \Exception */ public function testClearShouldThrow() { + $this->expectException(\Exception::class); + $this->getRepository()->clear(); } @@ -128,6 +126,11 @@ public function testMoveZeroNodes() $this->assertEquals(0, $numberOfNodes); } + /** + * @param string $path + */ + abstract protected function getRepository($path = null); + protected function assertWrappedException($outerClass, $outerMessage, $innerClass, $innerMessage, \Exception $e) { $this->assertInstanceOf($outerClass, $e); diff --git a/tests/Unit/Repository/PhpcrOdmRepositoryTest.php b/tests/Unit/Repository/PhpcrOdmRepositoryTest.php index 8dec10e..e27832f 100644 --- a/tests/Unit/Repository/PhpcrOdmRepositoryTest.php +++ b/tests/Unit/Repository/PhpcrOdmRepositoryTest.php @@ -1,9 +1,11 @@ expectException(\RuntimeException::class); + $this->expectExceptionMessage('No PHPCR-ODM document could be found at "/test"'); + $this->documentManager->find(null, '/test')->willReturn(null); $this->getRepository()->get('/test'); } @@ -274,6 +276,13 @@ public function testReorderToLast() $this->doTestReorder(66, false); } + protected function getRepository($path = null) + { + $repository = new PhpcrOdmRepository($this->managerRegistry->reveal(), $path, $this->finder->reveal()); + + return $repository; + } + private function doTestReorder($position, $before) { $evaluatedPath = '/test/foo'; @@ -292,13 +301,6 @@ private function doTestReorder($position, $before) $this->getRepository('/test')->reorder('/foo', $position); } - - protected function getRepository($path = null) - { - $repository = new PhpcrOdmRepository($this->managerRegistry->reveal(), $path, $this->finder->reveal()); - - return $repository; - } } class stdClass2 extends \stdClass diff --git a/tests/Unit/Repository/PhpcrRepositoryTest.php b/tests/Unit/Repository/PhpcrRepositoryTest.php index e98ab1a..bedc167 100644 --- a/tests/Unit/Repository/PhpcrRepositoryTest.php +++ b/tests/Unit/Repository/PhpcrRepositoryTest.php @@ -1,9 +1,11 @@ expectException(\RuntimeException::class); + $this->expectExceptionMessage('No PHPCR node could be found at "/test"'); + $this->session->getNode('/test')->willThrow(new \PHPCR\PathNotFoundException()); $this->getRepository()->get('/test'); } diff --git a/tests/Unit/Repository/Resource/Metadata/PhpcrMetadataTest.php b/tests/Unit/Repository/Resource/Metadata/PhpcrMetadataTest.php index 21ca7ee..f5e766f 100644 --- a/tests/Unit/Repository/Resource/Metadata/PhpcrMetadataTest.php +++ b/tests/Unit/Repository/Resource/Metadata/PhpcrMetadataTest.php @@ -1,9 +1,11 @@ Date: Sat, 2 Mar 2019 00:45:05 +0100 Subject: [PATCH 5/9] DevKit updates --- travis.php.ini | 1 + 1 file changed, 1 insertion(+) create mode 100644 travis.php.ini diff --git a/travis.php.ini b/travis.php.ini new file mode 100644 index 0000000..7999e96 --- /dev/null +++ b/travis.php.ini @@ -0,0 +1 @@ +memory_limit = -1 From 3dda0bb8799fd43076967c004adc357f61367478 Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Sat, 2 Mar 2019 00:45:38 +0100 Subject: [PATCH 6/9] DevKit updates --- .travis.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 19e5aa1..6e1e86b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,6 @@ cache: - $HOME/.composer/cache/files env: - matrix: SYMFONY_VERSION=4.2.* - global: - SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" - SYMFONY_PHPUNIT_DIR=.phpunit SYMFONY_PHPUNIT_REMOVE="symfony/yaml" - SYMFONY_PHPUNIT_VERSION=7 @@ -39,17 +37,11 @@ matrix: include: - env: TARGET=lint - php: 7.3 - env: STABILITY="dev" SYMFONY_VERSION=4.3.* - - php: 7.3 - env: SYMFONY_VERSION=4.2.* + env: SYMFONY_VERSION= - php: 7.1 - env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_VERSION=3.4.* SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" - - php: 7.2 - env: SYMFONY_VERSION=4.1.* + env: COMPOSER_FLAGS="--prefer-lowest" SYMFONY_VERSION= SYMFONY_DEPRECATIONS_HELPER="/.*each.*/" + fast_finish: true - allow_failures: - - php: 7.3 - env: STABILITY="dev" SYMFONY_VERSION=4.3.* before_install: - phpenv config-rm xdebug.ini || true @@ -60,6 +52,8 @@ before_install: - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) install: + - phpenv config-add travis.php.ini + - php -ini | grep memory_limit - if [ -x .travis/install_${TARGET}.sh ]; then .travis/install_${TARGET}.sh; fi; script: make $TARGET From a4367828da98dc9c4f77c9a87ccd97f9e2241378 Mon Sep 17 00:00:00 2001 From: electricmaxxx Date: Sun, 3 Mar 2019 03:18:44 +0100 Subject: [PATCH 7/9] fix tests --- .phpunit/.7.md5 | 2 + .phpunit/phpunit-7/.editorconfig | 11 + .phpunit/phpunit-7/.gitattributes | 4 + .phpunit/phpunit-7/.github/CODE_OF_CONDUCT.md | 28 + .phpunit/phpunit-7/.github/CONTRIBUTING.md | 68 + .phpunit/phpunit-7/.github/ISSUE_TEMPLATE.md | 15 + .phpunit/phpunit-7/.github/stale.yml | 47 + .phpunit/phpunit-7/.gitignore | 20 + .phpunit/phpunit-7/.phan/config.php | 7 + .phpunit/phpunit-7/.php_cs.dist | 198 + .phpunit/phpunit-7/.travis.yml | 58 + .phpunit/phpunit-7/ChangeLog-7.5.md | 84 + .phpunit/phpunit-7/LICENSE | 33 + .phpunit/phpunit-7/README.md | 40 + .phpunit/phpunit-7/appveyor.yml | 59 + .phpunit/phpunit-7/build.xml | 428 +++ .phpunit/phpunit-7/composer.json | 97 + .phpunit/phpunit-7/phive.xml | 7 + .phpunit/phpunit-7/phpunit | 17 + .phpunit/phpunit-7/phpunit.xml | 32 + .phpunit/phpunit-7/phpunit.xsd | 307 ++ .phpunit/phpunit-7/src/Exception.php | 17 + .phpunit/phpunit-7/src/Framework/Assert.php | 2891 ++++++++++++++ .../src/Framework/Assert/Functions.php | 1668 +++++++++ .../src/Framework/AssertionFailedError.php | 24 + .../src/Framework/CodeCoverageException.php | 14 + .../src/Framework/Constraint/ArrayHasKey.php | 81 + .../src/Framework/Constraint/ArraySubset.php | 133 + .../src/Framework/Constraint/Attribute.php | 79 + .../src/Framework/Constraint/Callback.php | 47 + .../Constraint/ClassHasAttribute.php | 80 + .../Constraint/ClassHasStaticAttribute.php | 51 + .../src/Framework/Constraint/Composite.php | 70 + .../src/Framework/Constraint/Constraint.php | 148 + .../src/Framework/Constraint/Count.php | 119 + .../Framework/Constraint/DirectoryExists.php | 53 + .../src/Framework/Constraint/Exception.php | 82 + .../Framework/Constraint/ExceptionCode.php | 63 + .../Framework/Constraint/ExceptionMessage.php | 73 + .../ExceptionMessageRegularExpression.php | 71 + .../src/Framework/Constraint/FileExists.php | 53 + .../src/Framework/Constraint/GreaterThan.php | 53 + .../src/Framework/Constraint/IsAnything.php | 55 + .../src/Framework/Constraint/IsEmpty.php | 61 + .../src/Framework/Constraint/IsEqual.php | 150 + .../src/Framework/Constraint/IsFalse.php | 35 + .../src/Framework/Constraint/IsFinite.php | 35 + .../src/Framework/Constraint/IsIdentical.php | 144 + .../src/Framework/Constraint/IsInfinite.php | 35 + .../src/Framework/Constraint/IsInstanceOf.php | 91 + .../src/Framework/Constraint/IsJson.php | 73 + .../src/Framework/Constraint/IsNan.php | 35 + .../src/Framework/Constraint/IsNull.php | 35 + .../src/Framework/Constraint/IsReadable.php | 53 + .../src/Framework/Constraint/IsTrue.php | 35 + .../src/Framework/Constraint/IsType.php | 152 + .../src/Framework/Constraint/IsWritable.php | 53 + .../src/Framework/Constraint/JsonMatches.php | 111 + .../JsonMatchesErrorMessageProvider.php | 62 + .../src/Framework/Constraint/LessThan.php | 53 + .../src/Framework/Constraint/LogicalAnd.php | 123 + .../src/Framework/Constraint/LogicalNot.php | 171 + .../src/Framework/Constraint/LogicalOr.php | 120 + .../src/Framework/Constraint/LogicalXor.php | 125 + .../Constraint/ObjectHasAttribute.php | 34 + .../Constraint/RegularExpression.php | 56 + .../src/Framework/Constraint/SameSize.php | 18 + .../Framework/Constraint/StringContains.php | 76 + .../Framework/Constraint/StringEndsWith.php | 48 + .../StringMatchesFormatDescription.php | 103 + .../Framework/Constraint/StringStartsWith.php | 48 + .../Constraint/TraversableContains.php | 116 + .../Constraint/TraversableContainsOnly.php | 93 + .../CoveredCodeNotExecutedException.php | 14 + .../src/Framework/DataProviderTestSuite.php | 40 + .../src/Framework/Error/Deprecated.php | 15 + .../phpunit-7/src/Framework/Error/Error.php | 26 + .../phpunit-7/src/Framework/Error/Notice.php | 15 + .../phpunit-7/src/Framework/Error/Warning.php | 15 + .../phpunit-7/src/Framework/Exception.php | 78 + .../src/Framework/ExceptionWrapper.php | 118 + .../Framework/ExpectationFailedException.php | 39 + .../src/Framework/IncompleteTest.php | 18 + .../src/Framework/IncompleteTestCase.php | 76 + .../src/Framework/IncompleteTestError.php | 14 + .../InvalidCoversTargetException.php | 14 + .../MissingCoversAnnotationException.php | 14 + .../Framework/MockObject/Builder/Identity.php | 30 + .../MockObject/Builder/InvocationMocker.php | 277 ++ .../Framework/MockObject/Builder/Match.php | 26 + .../MockObject/Builder/MethodNameMatch.php | 26 + .../MockObject/Builder/NamespaceMatch.php | 37 + .../MockObject/Builder/ParametersMatch.php | 50 + .../src/Framework/MockObject/Builder/Stub.php | 26 + .../Exception/BadMethodCallException.php | 14 + .../MockObject/Exception/Exception.php | 17 + .../MockObject/Exception/RuntimeException.php | 14 + .../ForwardCompatibility/MockObject.php | 16 + .../src/Framework/MockObject/Generator.php | 971 +++++ .../MockObject/Generator/deprecation.tpl.dist | 2 + .../Generator/mocked_class.tpl.dist | 46 + .../Generator/mocked_class_method.tpl.dist | 8 + .../Generator/mocked_clone.tpl.dist | 4 + .../Generator/mocked_method.tpl.dist | 22 + .../Generator/mocked_method_void.tpl.dist | 20 + .../Generator/mocked_static_method.tpl.dist | 5 + .../Generator/proxied_method.tpl.dist | 22 + .../Generator/proxied_method_void.tpl.dist | 22 + .../MockObject/Generator/trait_class.tpl.dist | 4 + .../Generator/unmocked_clone.tpl.dist | 5 + .../MockObject/Generator/wsdl_class.tpl.dist | 7 + .../MockObject/Generator/wsdl_method.tpl.dist | 4 + .../MockObject/Invocation/Invocation.php | 31 + .../Invocation/ObjectInvocation.php | 40 + .../Invocation/StaticInvocation.php | 258 ++ .../Framework/MockObject/InvocationMocker.php | 186 + .../src/Framework/MockObject/Invokable.php | 38 + .../src/Framework/MockObject/Matcher.php | 309 ++ .../MockObject/Matcher/AnyInvokedCount.php | 26 + .../MockObject/Matcher/AnyParameters.php | 31 + .../Matcher/ConsecutiveParameters.php | 126 + .../MockObject/Matcher/DeferredError.php | 40 + .../MockObject/Matcher/Invocation.php | 47 + .../MockObject/Matcher/InvokedAtIndex.php | 81 + .../Matcher/InvokedAtLeastCount.php | 55 + .../MockObject/Matcher/InvokedAtLeastOnce.php | 43 + .../MockObject/Matcher/InvokedAtMostCount.php | 55 + .../MockObject/Matcher/InvokedCount.php | 106 + .../MockObject/Matcher/InvokedRecorder.php | 63 + .../MockObject/Matcher/MethodName.php | 68 + .../MockObject/Matcher/Parameters.php | 158 + .../Matcher/StatelessInvocation.php | 50 + .../src/Framework/MockObject/MockBuilder.php | 408 ++ .../src/Framework/MockObject/MockMethod.php | 354 ++ .../Framework/MockObject/MockMethodSet.php | 36 + .../src/Framework/MockObject/MockObject.php | 57 + .../src/Framework/MockObject/Stub.php | 29 + .../MockObject/Stub/ConsecutiveCalls.php | 56 + .../Framework/MockObject/Stub/Exception.php | 42 + .../MockObject/Stub/MatcherCollection.php | 26 + .../MockObject/Stub/ReturnArgument.php | 41 + .../MockObject/Stub/ReturnCallback.php | 52 + .../MockObject/Stub/ReturnReference.php | 45 + .../Framework/MockObject/Stub/ReturnSelf.php | 38 + .../Framework/MockObject/Stub/ReturnStub.php | 45 + .../MockObject/Stub/ReturnValueMap.php | 51 + .../src/Framework/MockObject/Verifiable.php | 26 + .../phpunit-7/src/Framework/OutputError.php | 14 + .../phpunit-7/src/Framework/RiskyTest.php | 14 + .../src/Framework/RiskyTestError.php | 14 + .../src/Framework/SelfDescribing.php | 21 + .../phpunit-7/src/Framework/SkippedTest.php | 14 + .../src/Framework/SkippedTestCase.php | 76 + .../src/Framework/SkippedTestError.php | 14 + .../src/Framework/SkippedTestSuiteError.php | 14 + .../src/Framework/SyntheticError.php | 61 + .phpunit/phpunit-7/src/Framework/Test.php | 23 + .phpunit/phpunit-7/src/Framework/TestCase.php | 2143 +++++++++++ .../phpunit-7/src/Framework/TestFailure.php | 154 + .../phpunit-7/src/Framework/TestListener.php | 66 + .../TestListenerDefaultImplementation.php | 53 + .../phpunit-7/src/Framework/TestResult.php | 1135 ++++++ .../phpunit-7/src/Framework/TestSuite.php | 956 +++++ .../src/Framework/TestSuiteIterator.php | 91 + .../UnintentionallyCoveredCodeError.php | 18 + .phpunit/phpunit-7/src/Framework/Warning.php | 24 + .../src/Framework/WarningTestCase.php | 71 + .../phpunit-7/src/Runner/BaseTestRunner.php | 145 + .phpunit/phpunit-7/src/Runner/Exception.php | 14 + .../Filter/ExcludeGroupFilterIterator.php | 18 + .../phpunit-7/src/Runner/Filter/Factory.php | 51 + .../src/Runner/Filter/GroupFilterIterator.php | 51 + .../Filter/IncludeGroupFilterIterator.php | 18 + .../src/Runner/Filter/NameFilterIterator.php | 122 + .../Runner/Hook/AfterIncompleteTestHook.php | 15 + .../src/Runner/Hook/AfterLastTestHook.php | 15 + .../src/Runner/Hook/AfterRiskyTestHook.php | 15 + .../src/Runner/Hook/AfterSkippedTestHook.php | 15 + .../Runner/Hook/AfterSuccessfulTestHook.php | 15 + .../src/Runner/Hook/AfterTestErrorHook.php | 15 + .../src/Runner/Hook/AfterTestFailureHook.php | 15 + .../src/Runner/Hook/AfterTestHook.php | 21 + .../src/Runner/Hook/AfterTestWarningHook.php | 15 + .../src/Runner/Hook/BeforeFirstTestHook.php | 15 + .../src/Runner/Hook/BeforeTestHook.php | 15 + .phpunit/phpunit-7/src/Runner/Hook/Hook.php | 14 + .../phpunit-7/src/Runner/Hook/TestHook.php | 14 + .../src/Runner/Hook/TestListenerAdapter.php | 137 + .../phpunit-7/src/Runner/PhptTestCase.php | 598 +++ .../src/Runner/ResultCacheExtension.php | 104 + .../src/Runner/StandardTestSuiteLoader.php | 112 + .../phpunit-7/src/Runner/TestSuiteLoader.php | 22 + .../phpunit-7/src/Runner/TestSuiteSorter.php | 357 ++ .phpunit/phpunit-7/src/Runner/Version.php | 64 + .phpunit/phpunit-7/src/TextUI/Command.php | 1374 +++++++ .../phpunit-7/src/TextUI/ResultPrinter.php | 596 +++ .phpunit/phpunit-7/src/TextUI/TestRunner.php | 1317 +++++++ .phpunit/phpunit-7/src/Util/Blacklist.php | 196 + .phpunit/phpunit-7/src/Util/Configuration.php | 1331 +++++++ .../src/Util/ConfigurationGenerator.php | 60 + .phpunit/phpunit-7/src/Util/ErrorHandler.php | 106 + .phpunit/phpunit-7/src/Util/FileLoader.php | 68 + .phpunit/phpunit-7/src/Util/Filesystem.php | 35 + .phpunit/phpunit-7/src/Util/Filter.php | 83 + .phpunit/phpunit-7/src/Util/Getopt.php | 183 + .phpunit/phpunit-7/src/Util/GlobalState.php | 172 + .../src/Util/InvalidArgumentHelper.php | 35 + .phpunit/phpunit-7/src/Util/Json.php | 83 + .phpunit/phpunit-7/src/Util/Log/JUnit.php | 432 +++ .phpunit/phpunit-7/src/Util/Log/TeamCity.php | 391 ++ .../src/Util/NullTestResultCache.php | 31 + .../src/Util/PHP/AbstractPhpProcess.php | 368 ++ .../src/Util/PHP/DefaultPhpProcess.php | 218 ++ .../Util/PHP/Template/PhptTestCase.tpl.dist | 40 + .../Util/PHP/Template/TestCaseClass.tpl.dist | 108 + .../Util/PHP/Template/TestCaseMethod.tpl.dist | 110 + .../src/Util/PHP/WindowsPhpProcess.php | 46 + .../phpunit-7/src/Util/PHP/eval-stdin.php | 10 + .phpunit/phpunit-7/src/Util/Printer.php | 135 + .../phpunit-7/src/Util/RegularExpression.php | 27 + .phpunit/phpunit-7/src/Util/Test.php | 1121 ++++++ .../src/Util/TestDox/CliTestDoxPrinter.php | 429 +++ .../src/Util/TestDox/HtmlResultPrinter.php | 131 + .../src/Util/TestDox/NamePrettifier.php | 193 + .../src/Util/TestDox/ResultPrinter.php | 339 ++ .../phpunit-7/src/Util/TestDox/TestResult.php | 155 + .../src/Util/TestDox/TextResultPrinter.php | 47 + .../src/Util/TestDox/XmlResultPrinter.php | 205 + .../phpunit-7/src/Util/TestResultCache.php | 191 + .../src/Util/TestResultCacheInterface.php | 21 + .../src/Util/TextTestListRenderer.php | 43 + .phpunit/phpunit-7/src/Util/Type.php | 36 + .../src/Util/XdebugFilterScriptGenerator.php | 69 + .phpunit/phpunit-7/src/Util/Xml.php | 282 ++ .../src/Util/XmlTestListRenderer.php | 81 + .phpunit/phpunit-7/tests/_files/3194.php | 42 + .phpunit/phpunit-7/tests/_files/3530.wsdl | 33 + .../tests/_files/AbstractMockTestClass.php | 18 + .../phpunit-7/tests/_files/AbstractTest.php | 18 + .../phpunit-7/tests/_files/AbstractTrait.php | 23 + .../phpunit-7/tests/_files/AnInterface.php | 13 + .../_files/AnInterfaceWithReturnType.php | 13 + .../tests/_files/AnotherInterface.php | 13 + .../tests/_files/ArrayAccessible.php | 47 + .../tests/_files/AssertionExample.php | 16 + .../tests/_files/AssertionExampleTest.php | 20 + .phpunit/phpunit-7/tests/_files/Author.php | 25 + .../phpunit-7/tests/_files/BankAccount.php | 80 + .../tests/_files/BankAccountTest.php | 93 + .../tests/_files/BankAccountTest.test.php | 86 + .../tests/_files/BankAccountTest2.php | 56 + .phpunit/phpunit-7/tests/_files/Bar.php | 16 + .../tests/_files/BeforeAndAfterTest.php | 47 + .../_files/BeforeClassAndAfterClassTest.php | 47 + .../BeforeClassWithOnlyDataProviderTest.php | 48 + .phpunit/phpunit-7/tests/_files/Book.php | 18 + .../phpunit-7/tests/_files/Calculator.php | 22 + .../ChangeCurrentWorkingDirectoryTest.php | 19 + .../ClassThatImplementsSerializable.php | 23 + .../ClassWithAllPossibleReturnTypes.php | 64 + .../_files/ClassWithNonPublicAttributes.php | 47 + .../ClassWithScalarTypeDeclarations.php | 15 + .../tests/_files/ClassWithSelfTypeHint.php | 15 + .../tests/_files/ClassWithStaticMethod.php | 15 + .../tests/_files/ClassWithToString.php | 20 + .../ClassWithVariadicArgumentMethod.php | 20 + .../tests/_files/ClonedDependencyTest.php | 67 + .../tests/_files/ConcreteTest.my.php | 16 + .../phpunit-7/tests/_files/ConcreteTest.php | 16 + .../tests/_files/CountConstraint.php | 45 + .../_files/CoverageClassExtendedTest.php | 22 + .../tests/_files/CoverageClassTest.php | 22 + ...verageCoversOverridesCoversNothingTest.php | 25 + .../CoverageFunctionParenthesesTest.php | 21 + ...erageFunctionParenthesesWhitespaceTest.php | 21 + .../tests/_files/CoverageFunctionTest.php | 21 + .../CoverageMethodOneLineAnnotationTest.php | 20 + .../_files/CoverageMethodParenthesesTest.php | 22 + ...overageMethodParenthesesWhitespaceTest.php | 22 + .../tests/_files/CoverageMethodTest.php | 22 + .../_files/CoverageNamespacedFunctionTest.php | 21 + .../tests/_files/CoverageNoneTest.php | 19 + .../tests/_files/CoverageNotPrivateTest.php | 22 + .../tests/_files/CoverageNotProtectedTest.php | 22 + .../tests/_files/CoverageNotPublicTest.php | 22 + .../tests/_files/CoverageNothingTest.php | 23 + .../tests/_files/CoveragePrivateTest.php | 22 + .../tests/_files/CoverageProtectedTest.php | 22 + .../tests/_files/CoveragePublicTest.php | 22 + .../CoverageTwoDefaultClassAnnotations.php | 25 + .../phpunit-7/tests/_files/CoveredClass.php | 44 + .../tests/_files/CoveredFunction.php | 12 + .../phpunit-7/tests/_files/CustomPrinter.php | 14 + .../tests/_files/DataProviderDebugTest.php | 58 + .../_files/DataProviderDependencyTest.php | 33 + .../tests/_files/DataProviderFilterTest.php | 49 + .../_files/DataProviderIncompleteTest.php | 47 + .../DataProviderIssue2833/FirstTest.php | 30 + .../DataProviderIssue2833/SecondTest.php | 22 + .../_files/DataProviderIssue2859/phpunit.xml | 10 + .../another/TestWithDataProviderTest.php | 28 + .../DataProviderIssue2922/FirstTest.php | 31 + .../DataProviderIssue2922/SecondTest.php | 21 + .../tests/_files/DataProviderSkippedTest.php | 47 + .../tests/_files/DataProviderTest.php | 31 + .../tests/_files/DataProviderTestDoxTest.php | 83 + .../_files/DataproviderExecutionOrderTest.php | 48 + ...roviderExecutionOrderTest_result_cache.txt | 1 + .../tests/_files/DependencyFailureTest.php | 55 + .../tests/_files/DependencySuccessTest.php | 34 + .../tests/_files/DependencyTestSuite.php | 23 + .../tests/_files/DoNoAssertionTestCase.php | 17 + ...mAssertionsButPerformingAssertionsTest.php | 22 + .../phpunit-7/tests/_files/DoubleTestCase.php | 39 + .../phpunit-7/tests/_files/DummyBarTest.php | 18 + .../phpunit-7/tests/_files/DummyException.php | 12 + .../phpunit-7/tests/_files/DummyFooTest.php | 18 + .../tests/_files/EmptyTestCaseTest.php | 14 + .../phpunit-7/tests/_files/ExampleTrait.php | 16 + .../ExceptionInAssertPostConditionsTest.php | 50 + .../ExceptionInAssertPreConditionsTest.php | 50 + .../tests/_files/ExceptionInSetUpTest.php | 50 + .../ExceptionInTearDownAfterClassTest.php | 28 + .../tests/_files/ExceptionInTearDownTest.php | 50 + .../tests/_files/ExceptionInTest.php | 50 + .../ExceptionInTestDetectedInTeardown.php | 29 + .../tests/_files/ExceptionNamespaceTest.php | 45 + .../tests/_files/ExceptionStackTest.php | 34 + .../phpunit-7/tests/_files/ExceptionTest.php | 149 + .../tests/_files/ExceptionWithThrowable.php | 12 + .phpunit/phpunit-7/tests/_files/Failure.php | 18 + .../phpunit-7/tests/_files/FailureTest.php | 85 + .../tests/_files/FalsyConstraint.php | 26 + .phpunit/phpunit-7/tests/_files/FatalTest.php | 22 + .phpunit/phpunit-7/tests/_files/Foo.php | 16 + .../tests/_files/FunctionCallback.php | 20 + .../tests/_files/Go ogle-Sea.rch.wsdl | 198 + .../phpunit-7/tests/_files/GoogleSearch.wsdl | 198 + .../tests/_files/IgnoreCodeCoverageClass.php | 25 + .../_files/IgnoreCodeCoverageClassTest.php | 25 + .../phpunit-7/tests/_files/IncompleteTest.php | 18 + .../tests/_files/Inheritance/InheritanceA.php | 14 + .../tests/_files/Inheritance/InheritanceB.php | 17 + .../tests/_files/InheritedTestCase.php | 15 + .phpunit/phpunit-7/tests/_files/IniTest.php | 18 + .../InterfaceWithSemiReservedMethodName.php | 13 + .../_files/InterfaceWithStaticMethod.php | 13 + .../phpunit-7/tests/_files/IsolationTest.php | 23 + .../tests/_files/JsonData/arrayObject.json | 1 + .../tests/_files/JsonData/simpleObject.json | 1 + .../phpunit-7/tests/_files/MethodCallback.php | 29 + .../_files/MethodCallbackByReference.php | 21 + .../phpunit-7/tests/_files/MockRunner.php | 17 + .../tests/_files/MockTestInterface.php | 15 + .phpunit/phpunit-7/tests/_files/Mockable.php | 37 + .../tests/_files/MultiDependencyTest.php | 50 + .../MultiDependencyTest_result_cache.txt | 1 + .../tests/_files/MultipleDataProviderTest.php | 89 + .phpunit/phpunit-7/tests/_files/MyCommand.php | 24 + .../phpunit-7/tests/_files/MyTestListener.php | 121 + .../tests/_files/NamedConstraint.php | 37 + .../NamespaceCoverageClassExtendedTest.php | 22 + .../_files/NamespaceCoverageClassTest.php | 22 + ...NamespaceCoverageCoversClassPublicTest.php | 25 + .../NamespaceCoverageCoversClassTest.php | 30 + .../_files/NamespaceCoverageMethodTest.php | 22 + .../NamespaceCoverageNotPrivateTest.php | 22 + .../NamespaceCoverageNotProtectedTest.php | 22 + .../_files/NamespaceCoverageNotPublicTest.php | 22 + .../_files/NamespaceCoveragePrivateTest.php | 22 + .../_files/NamespaceCoverageProtectedTest.php | 22 + .../_files/NamespaceCoveragePublicTest.php | 22 + .../tests/_files/NamespaceCoveredClass.php | 46 + .../tests/_files/NamespaceCoveredFunction.php | 15 + .../tests/_files/NoArgTestCaseTest.php | 17 + .../tests/_files/NoTestCaseClass.php | 12 + .../phpunit-7/tests/_files/NoTestCases.php | 17 + .phpunit/phpunit-7/tests/_files/NonStatic.php | 15 + .../_files/NotExistingCoveredElementTest.php | 34 + .../tests/_files/NotPublicTestCase.php | 21 + .../tests/_files/NotSelfDescribingTest.php | 29 + .../tests/_files/NotVoidTestCase.php | 14 + .../phpunit-7/tests/_files/NothingTest.php | 17 + .../_files/NumericGroupAnnotationTest.php | 38 + .../phpunit-7/tests/_files/OneTestCase.php | 21 + .../phpunit-7/tests/_files/OutputTestCase.php | 37 + .../tests/_files/OverrideTestCase.php | 15 + .../_files/ParseTestMethodAnnotationsMock.php | 24 + .../tests/_files/PartialMockTestClass.php | 26 + .../RequirementsClassBeforeClassHookTest.php | 21 + .../_files/RequirementsClassDocBlockTest.php | 30 + .../tests/_files/RequirementsTest.php | 466 +++ .../phpunit-7/tests/_files/RouterTest.php | 34 + .../tests/_files/SampleArrayAccess.php | 42 + .../phpunit-7/tests/_files/SampleClass.php | 24 + .phpunit/phpunit-7/tests/_files/Singleton.php | 30 + .../phpunit-7/tests/_files/SingletonClass.php | 35 + .phpunit/phpunit-7/tests/_files/SomeClass.php | 19 + .phpunit/phpunit-7/tests/_files/StackTest.php | 34 + .../tests/_files/StaticMockTestClass.php | 20 + .../phpunit-7/tests/_files/StatusTest.php | 50 + .../tests/_files/StopOnErrorTestSuite.php | 29 + .../tests/_files/StopOnWarningTestSuite.php | 23 + .../tests/_files/StopsOnWarningTest.php | 17 + .../tests/_files/StringableClass.php | 16 + .phpunit/phpunit-7/tests/_files/Struct.php | 18 + .phpunit/phpunit-7/tests/_files/Success.php | 18 + .../tests/_files/TemplateMethodsTest.php | 62 + .../tests/_files/TestAutoreferenced.php | 20 + .../tests/_files/TestDoxGroupTest.php | 29 + .../tests/_files/TestGeneratorMaker.php | 18 + .../phpunit-7/tests/_files/TestIncomplete.php | 18 + .../phpunit-7/tests/_files/TestIterator.php | 45 + .../phpunit-7/tests/_files/TestIterator2.php | 43 + .../tests/_files/TestIteratorAggregate.php | 23 + .../tests/_files/TestIteratorAggregate2.php | 24 + .phpunit/phpunit-7/tests/_files/TestRisky.php | 18 + .../phpunit-7/tests/_files/TestSkipped.php | 18 + .../phpunit-7/tests/_files/TestTestError.php | 18 + .../phpunit-7/tests/_files/TestWarning.php | 19 + .../phpunit-7/tests/_files/TestWithTest.php | 34 + .../_files/TestableCliTestDoxPrinter.php | 25 + .../tests/_files/ThrowExceptionTestCase.php | 18 + .../tests/_files/ThrowNoExceptionTestCase.php | 17 + .../_files/TraversableMockTestInterface.php | 12 + .../tests/_files/TruthyConstraint.php | 26 + .../VariousIterableDataProviderTest.php | 47 + .phpunit/phpunit-7/tests/_files/WasRun.php | 20 + .../tests/_files/WrapperIteratorAggregate.php | 29 + .phpunit/phpunit-7/tests/_files/bar.xml | 1 + .../_files/configuration.colors.empty.xml | 1 + .../_files/configuration.colors.false.xml | 1 + .../_files/configuration.colors.invalid.xml | 1 + .../_files/configuration.colors.true.xml | 1 + .../_files/configuration.columns.default.xml | 1 + .../_files/configuration.custom-printer.xml | 2 + .../_files/configuration.defaulttestsuite.xml | 10 + .../_files/configuration.one-file-suite.xml | 7 + .../tests/_files/configuration.suites.xml | 6 + .../phpunit-7/tests/_files/configuration.xml | 162 + .../tests/_files/configuration_empty.xml | 49 + .../configuration_execution_order_options.xml | 9 + .../_files/configuration_stop_on_defect.xml | 2 + .../_files/configuration_stop_on_error.xml | 2 + .../configuration_stop_on_incomplete.xml | 2 + .../_files/configuration_stop_on_warning.xml | 2 + .../tests/_files/configuration_whitelist.xml | 15 + .../tests/_files/configuration_xinclude.xml | 84 + .../tests/_files/expectedFileFormat.txt | 1 + .phpunit/phpunit-7/tests/_files/foo.xml | 1 + .../tests/_files/phpt-for-coverage.phpt | 8 + .../_files/phpt-unsupported-section.phpt | 10 + .../phpunit-7/tests/_files/phpt-xfail.phpt | 11 + .../phpunit-example-extension/phpunit.xml | 10 + .../tests/OneTest.php | 21 + .../phpunit-example-extension-3.0.3.phar | Bin 0 -> 7698 bytes ...uctureAttributesAreSameButValuesAreNot.xml | 10 + .../tests/_files/structureExpected.xml | 10 + .../tests/_files/structureIgnoreTextNodes.xml | 13 + .../_files/structureIsSameButDataIsNot.xml | 10 + .../structureWrongNumberOfAttributes.xml | 10 + .../_files/structureWrongNumberOfNodes.xml | 9 + .phpunit/phpunit-7/tests/bootstrap.php | 17 + .../tests/end-to-end/_files/Extension.php | 93 + .../tests/end-to-end/_files/HookTest.php | 52 + .../tests/end-to-end/_files/NullPrinter.php | 19 + .../end-to-end/_files/expect_external.txt | 1 + .../tests/end-to-end/_files/hooks.xml | 14 + .../end-to-end/_files/phpt-env.expected.txt | 1 + .../tests/end-to-end/_files/phpt_external.php | 10 + .../tests/end-to-end/abstract-test-class.phpt | 24 + .../phpunit-7/tests/end-to-end/assertion.phpt | 38 + .../tests/end-to-end/cache-result.phpt | 29 + .../end-to-end/code-coverage-ignore.phpt | 36 + .../tests/end-to-end/code-coverage-phpt.phpt | 43 + .../tests/end-to-end/colors-always.phpt | 18 + .../tests/end-to-end/concrete-test-class.phpt | 18 + .../end-to-end/custom-printer-debug.phpt | 26 + .../end-to-end/custom-printer-verbose.phpt | 31 + .../tests/end-to-end/dataprovider-debug.phpt | 33 + .../end-to-end/dataprovider-issue-2833.phpt | 17 + .../end-to-end/dataprovider-issue-2859.phpt | 17 + .../end-to-end/dataprovider-issue-2922.phpt | 18 + .../dataprovider-log-xml-isolation.phpt | 46 + .../end-to-end/dataprovider-log-xml.phpt | 45 + .../end-to-end/dataprovider-testdox.phpt | 34 + .../phpunit-7/tests/end-to-end/debug.phpt | 25 + .../tests/end-to-end/default-isolation.phpt | 19 + .../phpunit-7/tests/end-to-end/default.phpt | 18 + .../defaulttestsuite-using-testsuite.phpt | 21 + .../tests/end-to-end/defaulttestsuite.phpt | 19 + .../defects-first-order-via-cli.phpt | 37 + .../tests/end-to-end/dependencies-clone.phpt | 22 + .../end-to-end/dependencies-isolation.phpt | 49 + .../tests/end-to-end/dependencies.phpt | 48 + .../end-to-end/dependencies2-isolation.phpt | 19 + .../tests/end-to-end/dependencies2.phpt | 18 + .../end-to-end/dependencies3-isolation.phpt | 19 + .../tests/end-to-end/dependencies3.phpt | 19 + .../disable-code-coverage-ignore.phpt | 40 + .../tests/end-to-end/dump-xdebug-filter.phpt | 32 + .../tests/end-to-end/empty-testcase.phpt | 25 + .../tests/end-to-end/exception-stack.phpt | 64 + .../end-to-end/exclude-group-isolation.phpt | 21 + .../tests/end-to-end/exclude-group.phpt | 20 + .../execution-order-options-via-config.phpt | 30 + .../tests/end-to-end/failure-isolation.phpt | 140 + .../end-to-end/failure-reverse-list.phpt | 140 + .../phpunit-7/tests/end-to-end/failure.phpt | 139 + .../tests/end-to-end/fatal-isolation.phpt | 24 + .../end-to-end/filter-class-isolation.phpt | 21 + .../tests/end-to-end/filter-class.phpt | 20 + ...ider-by-classname-and-range-isolation.phpt | 21 + ...r-dataprovider-by-classname-and-range.phpt | 20 + ...lter-dataprovider-by-number-isolation.phpt | 21 + .../filter-dataprovider-by-number.phpt | 20 + ...-dataprovider-by-only-range-isolation.phpt | 21 + .../filter-dataprovider-by-only-range.phpt | 20 + ...dataprovider-by-only-regexp-isolation.phpt | 21 + .../filter-dataprovider-by-only-regexp.phpt | 20 + ...dataprovider-by-only-string-isolation.phpt | 21 + .../filter-dataprovider-by-only-string.phpt | 20 + ...ilter-dataprovider-by-range-isolation.phpt | 21 + .../filter-dataprovider-by-range.phpt | 20 + ...lter-dataprovider-by-regexp-isolation.phpt | 21 + .../filter-dataprovider-by-regexp.phpt | 20 + ...lter-dataprovider-by-string-isolation.phpt | 21 + .../filter-dataprovider-by-string.phpt | 20 + .../filter-method-case-insensitive.phpt | 20 + ...ilter-method-case-sensitive-no-result.phpt | 20 + .../end-to-end/filter-method-isolation.phpt | 21 + .../tests/end-to-end/filter-method.phpt | 20 + .../tests/end-to-end/filter-no-results.phpt | 20 + .../end-to-end/forward-compatibility.phpt | 18 + .../tests/end-to-end/group-isolation.phpt | 21 + .../phpunit-7/tests/end-to-end/group.phpt | 23 + .phpunit/phpunit-7/tests/end-to-end/help.phpt | 113 + .../phpunit-7/tests/end-to-end/help2.phpt | 114 + .../phpunit-7/tests/end-to-end/hooks.phpt | 38 + .../tests/end-to-end/ini-isolation.phpt | 21 + .../tests/end-to-end/list-groups.phpt | 18 + .../tests/end-to-end/list-suites.phpt | 16 + .../end-to-end/list-tests-dataprovider.phpt | 19 + .../list-tests-xml-dataprovider.phpt | 31 + .../tests/end-to-end/log-junit-phpt.phpt | 28 + .../phpunit-7/tests/end-to-end/log-junit.phpt | 91 + .../tests/end-to-end/log-teamcity-phpt.phpt | 25 + .../tests/end-to-end/log-teamcity.phpt | 38 + .../mock-objects/generator/232.phpt | 135 + .../3154_namespaced_constant_resolving.phpt | 119 + .../mock-objects/generator/3530.phpt | 27 + .../mock-objects/generator/397.phpt | 105 + .../generator/abstract_class.phpt | 154 + .../mock-objects/generator/class.phpt | 132 + .../generator/class_call_parent_clone.phpt | 84 + .../class_call_parent_constructor.phpt | 83 + .../class_dont_call_parent_clone.phpt | 83 + .../class_dont_call_parent_constructor.phpt | 83 + ...ing_interface_call_parent_constructor.phpt | 88 + ...nterface_dont_call_parent_constructor.phpt | 88 + .../generator/class_nonexistent_method.phpt | 106 + .../mock-objects/generator/class_partial.phpt | 110 + .../class_with_deprecated_method.phpt | 112 + .../generator/class_with_final_method.phpt | 84 + .../class_with_method_named_method.phpt | 98 + ...ullable_typehinted_variadic_arguments.phpt | 106 + ...od_with_typehinted_variadic_arguments.phpt | 106 + ...s_with_method_with_variadic_arguments.phpt | 106 + .../constant_as_parameter_default_value.phpt | 106 + .../mock-objects/generator/interface.phpt | 104 + .../invocation_object_clone_object.phpt | 133 + .../generator/namespaced_class.phpt | 134 + .../namespaced_class_call_parent_clone.phpt | 86 + ...espaced_class_call_parent_constructor.phpt | 85 + ...mespaced_class_dont_call_parent_clone.phpt | 85 + ...ed_class_dont_call_parent_constructor.phpt | 85 + ...ing_interface_call_parent_constructor.phpt | 90 + ...nterface_dont_call_parent_constructor.phpt | 90 + .../generator/namespaced_class_partial.phpt | 112 + .../generator/namespaced_interface.phpt | 106 + .../generator/nonexistent_class.phpt | 81 + .../nonexistent_class_with_namespace.phpt | 89 + ...ith_namespace_starting_with_separator.phpt | 89 + .../generator/nullable_types.phpt | 106 + .../mock-objects/generator/proxy.phpt | 128 + .../return_type_declarations_closure.phpt | 104 + .../return_type_declarations_final.phpt | 111 + .../return_type_declarations_generator.phpt | 104 + .../return_type_declarations_nullable.phpt | 104 + ...eturn_type_declarations_object_method.phpt | 107 + .../return_type_declarations_parent.phpt | 110 + .../return_type_declarations_self.phpt | 104 + ...eturn_type_declarations_static_method.phpt | 90 + .../return_type_declarations_void.phpt | 102 + .../generator/scalar_type_declarations.phpt | 106 + .../mock-objects/generator/wsdl_class.phpt | 37 + .../generator/wsdl_class_namespace.phpt | 38 + .../generator/wsdl_class_partial.phpt | 30 + .../mock-method/call_original.phpt | 45 + .../call_original_with_argument.phpt | 45 + .../call_original_with_argument_variadic.phpt | 45 + .../call_original_with_return_type_void.phpt | 45 + .../mock-method/clone_method_arguments.phpt | 45 + .../deprecated_with_description.phpt | 50 + .../deprecated_without_description.phpt | 50 + .../mock-method/private_method.phpt | 45 + .../mock-method/protected_method.phpt | 45 + .../mock-method/return_by_reference.phpt | 45 + .../return_by_reference_with_return_type.phpt | 45 + .../mock-objects/mock-method/return_type.phpt | 45 + .../mock-method/return_type_parent.phpt | 49 + .../mock-method/return_type_self.phpt | 45 + .../mock-method/static_method.phpt | 28 + .../static_method_with_return_type.phpt | 28 + .../mock-method/with_argument.phpt | 45 + .../mock-method/with_argument_default.phpt | 45 + .../with_argument_default_constant.phpt | 47 + .../with_argument_default_null.phpt | 45 + .../mock-method/with_argument_nullable.phpt | 45 + .../mock-method/with_argument_reference.phpt | 45 + .../with_argument_typed_array.phpt | 45 + .../with_argument_typed_callable.phpt | 45 + .../with_argument_typed_class.phpt | 45 + .../with_argument_typed_scalar.phpt | 45 + .../mock-method/with_argument_typed_self.phpt | 45 + .../with_argument_typed_unkown_class.phpt | 45 + .../with_argument_typed_variadic.phpt | 45 + .../mock-method/with_argument_variadic.phpt | 45 + .../mock-method/with_arguments.phpt | 45 + .../phpunit-7/tests/end-to-end/mycommand.phpt | 24 + .../end-to-end/options-after-arguments.phpt | 18 + .../order-by-default-invalid-via-cli.phpt | 19 + .../tests/end-to-end/output-isolation.phpt | 20 + .../end-to-end/phar-extension-suppressed.phpt | 12 + .../tests/end-to-end/phar-extension.phpt | 21 + .../phpunit-7/tests/end-to-end/phpt-args.phpt | 12 + .../phpunit-7/tests/end-to-end/phpt-env.phpt | 12 + .../tests/end-to-end/phpt-external.phpt | 6 + .../tests/end-to-end/phpt-parsing.phpt | 26 + .../tests/end-to-end/phpt-stderr.phpt | 8 + .../tests/end-to-end/phpt-stdin.phpt | 11 + .../tests/end-to-end/phpt-xfail.phpt | 18 + .../end-to-end/regression/GitHub/1149.phpt | 20 + .../regression/GitHub/1149/Issue1149Test.php | 28 + .../end-to-end/regression/GitHub/1216.phpt | 25 + .../regression/GitHub/1216/Issue1216Test.php | 18 + .../regression/GitHub/1216/bootstrap1216.php | 10 + .../regression/GitHub/1216/phpunit1216.xml | 8 + .../end-to-end/regression/GitHub/1265.phpt | 21 + .../regression/GitHub/1265/Issue1265Test.php | 18 + .../regression/GitHub/1265/phpunit1265.xml | 2 + .../end-to-end/regression/GitHub/1330.phpt | 24 + .../regression/GitHub/1330/Issue1330Test.php | 18 + .../regression/GitHub/1330/phpunit1330.xml | 5 + .../end-to-end/regression/GitHub/1335.phpt | 19 + .../regression/GitHub/1335/Issue1335Test.php | 77 + .../regression/GitHub/1335/bootstrap1335.php | 21 + .../end-to-end/regression/GitHub/1337.phpt | 19 + .../regression/GitHub/1337/Issue1337Test.php | 29 + .../end-to-end/regression/GitHub/1348.phpt | 33 + .../regression/GitHub/1348/Issue1348Test.php | 24 + .../end-to-end/regression/GitHub/1351.phpt | 46 + .../GitHub/1351/ChildProcessClass1351.php | 12 + .../regression/GitHub/1351/Issue1351Test.php | 59 + .../end-to-end/regression/GitHub/1374.phpt | 19 + .../regression/GitHub/1374/Issue1374Test.php | 31 + .../end-to-end/regression/GitHub/1437.phpt | 26 + .../regression/GitHub/1437/Issue1437Test.php | 19 + .../end-to-end/regression/GitHub/1468.phpt | 20 + .../regression/GitHub/1468/Issue1468Test.php | 21 + .../end-to-end/regression/GitHub/1471.phpt | 26 + .../regression/GitHub/1471/Issue1471Test.php | 22 + .../end-to-end/regression/GitHub/1472.phpt | 18 + .../regression/GitHub/1472/Issue1472Test.php | 31 + .../end-to-end/regression/GitHub/1570.phpt | 27 + .../regression/GitHub/1570/Issue1570Test.php | 18 + ...it-options-via-config-without-invoker.phpt | 33 + .../GitHub/2085-without-invoker.phpt | 34 + .../end-to-end/regression/GitHub/2085.phpt | 38 + .../regression/GitHub/2085/Issue2085Test.php | 20 + ...nfiguration_enforce_time_limit_options.xml | 2 + .../regression/GitHub/2137-filter.phpt | 28 + .../regression/GitHub/2137-no_filter.phpt | 30 + .../regression/GitHub/2137/Issue2137Test.php | 43 + .../end-to-end/regression/GitHub/2145.phpt | 27 + .../regression/GitHub/2145/Issue2145Test.php | 24 + .../end-to-end/regression/GitHub/2158.phpt | 19 + .../regression/GitHub/2158/Issue2158Test.php | 33 + .../regression/GitHub/2158/constant.inc | 5 + .../end-to-end/regression/GitHub/2366.phpt | 19 + .../regression/GitHub/2366/Issue2366Test.php | 41 + .../end-to-end/regression/GitHub/2380.phpt | 19 + .../regression/GitHub/2380/Issue2380Test.php | 29 + .../end-to-end/regression/GitHub/2382.phpt | 19 + .../regression/GitHub/2382/Issue2382Test.php | 30 + .../end-to-end/regression/GitHub/2435.phpt | 20 + .../regression/GitHub/2435/Issue2435Test.php | 16 + .../end-to-end/regression/GitHub/244.phpt | 32 + .../regression/GitHub/244/Issue244Test.php | 65 + .../regression/GitHub/2448-existing-test.phpt | 21 + .../GitHub/2448-not-existing-test.phpt | 13 + .../regression/GitHub/2448/.gitignore | 2 + .../regression/GitHub/2448/Test.php | 16 + ...-separate-class-preserve-no-bootstrap.phpt | 35 + .../GitHub/2591-separate-class-preserve.phpt | 21 + ...nction-no-preserve-no-bootstrap-php73.phpt | 37 + ...ction-no-preserve-no-bootstrap-xdebug.phpt | 39 + ...ate-function-no-preserve-no-bootstrap.phpt | 37 + .../2591-separate-function-no-preserve.phpt | 20 + .../2591-separate-function-preserve.phpt | 20 + .../GitHub/2591/SeparateClassPreserveTest.php | 35 + .../2591/SeparateFunctionNoPreserveTest.php | 28 + .../2591/SeparateFunctionPreserveTest.php | 28 + .../GitHub/2591/bootstrapNoBootstrap.php | 15 + .../GitHub/2591/bootstrapWithBootstrap.php | 12 + .../2591/bootstrapWithBootstrapNoGlobal.php | 11 + .../2724-diff-pid-from-master-process.phpt | 22 + ...SeparateClassRunMethodInNewProcessTest.php | 53 + .../2725-separate-class-before-after-pid.phpt | 18 + .../GitHub/2725/BeforeAfterClassPidTest.php | 50 + .../end-to-end/regression/GitHub/2731.phpt | 26 + .../regression/GitHub/2731/Issue2731Test.php | 19 + .../end-to-end/regression/GitHub/2811.phpt | 20 + .../regression/GitHub/2811/Issue2811Test.php | 18 + .../end-to-end/regression/GitHub/2830.phpt | 20 + .../regression/GitHub/2830/Issue2830Test.php | 27 + .../end-to-end/regression/GitHub/2972.phpt | 18 + .../GitHub/2972/issue-2972-test.phpt | 10 + .../2972/unconventiallyNamedIssue2972Test.php | 20 + .../regression/GitHub/3093/Issue3093Test.php | 30 + .../GitHub/3093/issue-3093-test.phpt | 19 + .../regression/GitHub/3107/Issue3107Test.php | 25 + .../GitHub/3107/issue-3107-test.phpt | 27 + .../regression/GitHub/3156/Issue3156Test.php | 41 + .../end-to-end/regression/GitHub/322.phpt | 27 + .../regression/GitHub/322/Issue322Test.php | 29 + .../regression/GitHub/322/phpunit322.xml | 11 + .../GitHub/3364/issue-3364-test.phpt | 58 + .../tests/Issue3364SetupBeforeClassTest.php | 30 + .../GitHub/3364/tests/Issue3364SetupTest.php | 30 + .../end-to-end/regression/GitHub/3379.phpt | 20 + .../regression/GitHub/3379/Issue3379Test.php | 28 + .../GitHub/3379/Issue3379TestListener.php | 26 + .../regression/GitHub/3379/phpunit.xml | 13 + .../GitHub/3380/issue-3380-test.phpt | 63 + .../GitHub/3396/issue-3396-test.phpt | 55 + .../end-to-end/regression/GitHub/433.phpt | 31 + .../regression/GitHub/433/Issue433Test.php | 31 + .../end-to-end/regression/GitHub/445.phpt | 32 + .../regression/GitHub/445/Issue445Test.php | 31 + .../end-to-end/regression/GitHub/498.phpt | 29 + .../regression/GitHub/498/Issue498Test.php | 53 + .../end-to-end/regression/GitHub/503.phpt | 35 + .../regression/GitHub/503/Issue503Test.php | 21 + .../end-to-end/regression/GitHub/581.phpt | 40 + .../regression/GitHub/581/Issue581Test.php | 21 + .../end-to-end/regression/GitHub/74.phpt | 28 + .../regression/GitHub/74/Issue74Test.php | 20 + .../regression/GitHub/74/NewException.php | 12 + .../end-to-end/regression/GitHub/765.phpt | 26 + .../regression/GitHub/765/Issue765Test.php | 32 + .../end-to-end/regression/GitHub/797.phpt | 22 + .../regression/GitHub/797/Issue797Test.php | 20 + .../regression/GitHub/797/bootstrap797.php | 13 + .../end-to-end/regression/GitHub/863.phpt | 24 + .../end-to-end/regression/GitHub/873.phpt | 21 + .../regression/GitHub/873/Issue873Test.php | 16 + .../end-to-end/regression/Trac/1021.phpt | 19 + .../regression/Trac/1021/Issue1021Test.php | 34 + .../tests/end-to-end/regression/Trac/523.phpt | 19 + .../regression/Trac/523/Issue523Test.php | 23 + .../tests/end-to-end/regression/Trac/578.phpt | 37 + .../regression/Trac/578/Issue578Test.php | 30 + .../tests/end-to-end/regression/Trac/684.phpt | 25 + .../regression/Trac/684/Issue684Test.php | 14 + .../tests/end-to-end/regression/Trac/783.phpt | 21 + .../regression/Trac/783/ChildSuite.php | 26 + .../regression/Trac/783/OneTest.php | 21 + .../regression/Trac/783/ParentSuite.php | 23 + .../regression/Trac/783/TwoTest.php | 21 + .../phpunit-7/tests/end-to-end/repeat.phpt | 20 + ...ated-with-does-not-perform-assertions.phpt | 24 + .../report-useless-tests-incomplete.phpt | 19 + .../report-useless-tests-isolation.phpt | 27 + .../end-to-end/report-useless-tests.phpt | 26 + .../end-to-end/stop-on-defect-via-cli.phpt | 25 + .../end-to-end/stop-on-defect-via-config.phpt | 25 + .../end-to-end/stop-on-error-via-cli.phpt | 27 + .../end-to-end/stop-on-error-via-config.phpt | 27 + .../stop-on-incomplete-via-cli.phpt | 20 + .../stop-on-incomplete-via-config.phpt | 20 + .../end-to-end/stop-on-warning-via-cli.phpt | 25 + .../stop-on-warning-via-config.phpt | 26 + .../end-to-end/teamcity-inner-exceptions.phpt | 39 + .../phpunit-7/tests/end-to-end/teamcity.phpt | 37 + ...mized-seed-with-dependency-resolution.phpt | 35 + ...randomized-with-dependency-resolution.phpt | 25 + ...r-reversed-with-dependency-resolution.phpt | 35 + ...eversed-without-dependency-resolution.phpt | 44 + .../end-to-end/test-suffix-multiple.phpt | 19 + .../tests/end-to-end/test-suffix-single.phpt | 19 + .../testdox-dataprovider-placeholder.phpt | 20 + .../end-to-end/testdox-exclude-group.phpt | 25 + .../tests/end-to-end/testdox-group.phpt | 25 + .../tests/end-to-end/testdox-html.phpt | 57 + .../tests/end-to-end/testdox-text.phpt | 25 + .../tests/end-to-end/testdox-verbose.phpt | 25 + .../tests/end-to-end/testdox-xml.phpt | 64 + .../phpunit-7/tests/end-to-end/testdox.phpt | 22 + .phpunit/phpunit-7/tests/fail/fail.phpt | 5 + .../tests/unit/Framework/AssertTest.php | 3320 +++++++++++++++++ .../Framework/Constraint/ArrayHasKeyTest.php | 64 + .../Framework/Constraint/ArraySubsetTest.php | 86 + .../Framework/Constraint/AttributeTest.php | 80 + .../Framework/Constraint/CallbackTest.php | 65 + .../Constraint/ClassHasAttributeTest.php | 70 + .../ClassHasStaticAttributeTest.php | 66 + .../Constraint/ConstraintTestCase.php | 54 + .../unit/Framework/Constraint/CountTest.php | 145 + .../Constraint/DirectoryExistsTest.php | 66 + .../Constraint/ExceptionMessageRegExpTest.php | 53 + .../Constraint/ExceptionMessageTest.php | 47 + .../Framework/Constraint/FileExistsTest.php | 65 + .../Framework/Constraint/GreaterThanTest.php | 66 + .../unit/Framework/Constraint/IsEmptyTest.php | 67 + .../unit/Framework/Constraint/IsEqualTest.php | 321 ++ .../Framework/Constraint/IsIdenticalTest.php | 197 + .../Framework/Constraint/IsInstanceOfTest.php | 41 + .../unit/Framework/Constraint/IsJsonTest.php | 34 + .../unit/Framework/Constraint/IsNullTest.php | 66 + .../Framework/Constraint/IsReadableTest.php | 42 + .../unit/Framework/Constraint/IsTypeTest.php | 111 + .../Framework/Constraint/IsWritableTest.php | 42 + .../JsonMatchesErrorMessageProviderTest.php | 87 + .../Framework/Constraint/JsonMatchesTest.php | 94 + .../Framework/Constraint/LessThanTest.php | 66 + .../Framework/Constraint/LogicalAndTest.php | 237 ++ .../Framework/Constraint/LogicalOrTest.php | 232 ++ .../Framework/Constraint/LogicalXorTest.php | 44 + .../Constraint/ObjectHasAttributeTest.php | 66 + .../Constraint/RegularExpressionTest.php | 66 + .../Framework/Constraint/SameSizeTest.php | 62 + .../Constraint/StringContainsTest.php | 96 + .../Constraint/StringEndsWithTest.php | 103 + .../StringMatchesFormatDescriptionTest.php | 278 ++ .../Constraint/StringStartsWithTest.php | 103 + .../Constraint/TraversableContainsTest.php | 170 + .../tests/unit/Framework/ConstraintTest.php | 1492 ++++++++ .../unit/Framework/ExceptionWrapperTest.php | 55 + .../Builder/InvocationMockerTest.php | 89 + .../Framework/MockObject/GeneratorTest.php | 245 ++ .../Invocation/ObjectInvocationTest.php | 120 + .../Invocation/StaticInvocationTest.php | 114 + .../Matcher/ConsecutiveParametersTest.php | 68 + .../Framework/MockObject/MockBuilderTest.php | 129 + .../Framework/MockObject/MockMethodTest.php | 55 + .../Framework/MockObject/MockObjectTest.php | 1128 ++++++ .../Framework/MockObject/ProxyObjectTest.php | 41 + .../tests/unit/Framework/TestCaseTest.php | 779 ++++ .../tests/unit/Framework/TestFailureTest.php | 141 + .../unit/Framework/TestImplementorTest.php | 25 + .../tests/unit/Framework/TestListenerTest.php | 60 + .../tests/unit/Framework/TestResultTest.php | 86 + .../tests/unit/Framework/TestSuiteTest.php | 250 ++ .../Runner/Filter/NameFilterIteratorTest.php | 38 + .../tests/unit/Runner/PhptTestCaseTest.php | 349 ++ .../unit/Runner/ResultCacheExtensionTest.php | 139 + .../tests/unit/Runner/TestSuiteSorterTest.php | 608 +++ .../tests/unit/TextUI/TestRunnerTest.php | 49 + .../unit/Util/ConfigurationGeneratorTest.php | 51 + .../tests/unit/Util/ConfigurationTest.php | 614 +++ .../phpunit-7/tests/unit/Util/GetoptTest.php | 214 ++ .../tests/unit/Util/GlobalStateTest.php | 35 + .../phpunit-7/tests/unit/Util/JsonTest.php | 80 + .../unit/Util/NullTestResultCacheTest.php | 28 + .../unit/Util/PHP/AbstractPhpProcessTest.php | 119 + .../tests/unit/Util/RegularExpressionTest.php | 56 + .../Util/TestDox/CliTestDoxPrinterTest.php | 209 ++ .../unit/Util/TestDox/NamePrettifierTest.php | 172 + .../tests/unit/Util/TestResultCacheTest.php | 95 + .../phpunit-7/tests/unit/Util/TestTest.php | 1044 ++++++ .../Util/XDebugFilterScriptGeneratorTest.php | 85 + .../phpunit-7/tests/unit/Util/XmlTest.php | 119 + composer.json | 1 - src/Repository/AbstractPhpcrRepository.php | 46 +- src/Repository/PhpcrRepository.php | 20 +- tests/Unit/Repository/PhpcrRepositoryTest.php | 6 +- 887 files changed, 69397 insertions(+), 28 deletions(-) create mode 100644 .phpunit/.7.md5 create mode 100644 .phpunit/phpunit-7/.editorconfig create mode 100644 .phpunit/phpunit-7/.gitattributes create mode 100644 .phpunit/phpunit-7/.github/CODE_OF_CONDUCT.md create mode 100644 .phpunit/phpunit-7/.github/CONTRIBUTING.md create mode 100644 .phpunit/phpunit-7/.github/ISSUE_TEMPLATE.md create mode 100644 .phpunit/phpunit-7/.github/stale.yml create mode 100644 .phpunit/phpunit-7/.gitignore create mode 100644 .phpunit/phpunit-7/.phan/config.php create mode 100644 .phpunit/phpunit-7/.php_cs.dist create mode 100644 .phpunit/phpunit-7/.travis.yml create mode 100644 .phpunit/phpunit-7/ChangeLog-7.5.md create mode 100644 .phpunit/phpunit-7/LICENSE create mode 100644 .phpunit/phpunit-7/README.md create mode 100644 .phpunit/phpunit-7/appveyor.yml create mode 100644 .phpunit/phpunit-7/build.xml create mode 100644 .phpunit/phpunit-7/composer.json create mode 100644 .phpunit/phpunit-7/phive.xml create mode 100755 .phpunit/phpunit-7/phpunit create mode 100644 .phpunit/phpunit-7/phpunit.xml create mode 100644 .phpunit/phpunit-7/phpunit.xsd create mode 100644 .phpunit/phpunit-7/src/Exception.php create mode 100644 .phpunit/phpunit-7/src/Framework/Assert.php create mode 100644 .phpunit/phpunit-7/src/Framework/Assert/Functions.php create mode 100644 .phpunit/phpunit-7/src/Framework/AssertionFailedError.php create mode 100644 .phpunit/phpunit-7/src/Framework/CodeCoverageException.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ArrayHasKey.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ArraySubset.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Attribute.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Callback.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ClassHasAttribute.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ClassHasStaticAttribute.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Composite.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Constraint.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Count.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/DirectoryExists.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/Exception.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ExceptionCode.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessage.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessageRegularExpression.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/FileExists.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/GreaterThan.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsAnything.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsEmpty.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsEqual.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsFalse.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsFinite.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsIdentical.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsInfinite.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsInstanceOf.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsJson.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsNan.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsNull.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsReadable.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsTrue.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsType.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/IsWritable.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/JsonMatches.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/LessThan.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/LogicalAnd.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/LogicalNot.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/LogicalOr.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/LogicalXor.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/ObjectHasAttribute.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/RegularExpression.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/SameSize.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/StringContains.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/StringEndsWith.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/StringMatchesFormatDescription.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/StringStartsWith.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/TraversableContains.php create mode 100644 .phpunit/phpunit-7/src/Framework/Constraint/TraversableContainsOnly.php create mode 100644 .phpunit/phpunit-7/src/Framework/CoveredCodeNotExecutedException.php create mode 100644 .phpunit/phpunit-7/src/Framework/DataProviderTestSuite.php create mode 100644 .phpunit/phpunit-7/src/Framework/Error/Deprecated.php create mode 100644 .phpunit/phpunit-7/src/Framework/Error/Error.php create mode 100644 .phpunit/phpunit-7/src/Framework/Error/Notice.php create mode 100644 .phpunit/phpunit-7/src/Framework/Error/Warning.php create mode 100644 .phpunit/phpunit-7/src/Framework/Exception.php create mode 100644 .phpunit/phpunit-7/src/Framework/ExceptionWrapper.php create mode 100644 .phpunit/phpunit-7/src/Framework/ExpectationFailedException.php create mode 100644 .phpunit/phpunit-7/src/Framework/IncompleteTest.php create mode 100644 .phpunit/phpunit-7/src/Framework/IncompleteTestCase.php create mode 100644 .phpunit/phpunit-7/src/Framework/IncompleteTestError.php create mode 100644 .phpunit/phpunit-7/src/Framework/InvalidCoversTargetException.php create mode 100644 .phpunit/phpunit-7/src/Framework/MissingCoversAnnotationException.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/Identity.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/InvocationMocker.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/Match.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/MethodNameMatch.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/NamespaceMatch.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/ParametersMatch.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Builder/Stub.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Exception/BadMethodCallException.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Exception/Exception.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Exception/RuntimeException.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/ForwardCompatibility/MockObject.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/deprecation.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class_method.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_clone.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method_void.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_static_method.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method_void.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/trait_class.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/unmocked_clone.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_class.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_method.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Invocation/Invocation.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Invocation/ObjectInvocation.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Invocation/StaticInvocation.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/InvocationMocker.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Invokable.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyInvokedCount.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyParameters.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/ConsecutiveParameters.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/DeferredError.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/Invocation.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtIndex.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtMostCount.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedCount.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedRecorder.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/MethodName.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/Parameters.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Matcher/StatelessInvocation.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/MockBuilder.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/MockMethod.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/MockMethodSet.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/MockObject.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ConsecutiveCalls.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/Exception.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/MatcherCollection.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnArgument.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnCallback.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnReference.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnSelf.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnStub.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnValueMap.php create mode 100644 .phpunit/phpunit-7/src/Framework/MockObject/Verifiable.php create mode 100644 .phpunit/phpunit-7/src/Framework/OutputError.php create mode 100644 .phpunit/phpunit-7/src/Framework/RiskyTest.php create mode 100644 .phpunit/phpunit-7/src/Framework/RiskyTestError.php create mode 100644 .phpunit/phpunit-7/src/Framework/SelfDescribing.php create mode 100644 .phpunit/phpunit-7/src/Framework/SkippedTest.php create mode 100644 .phpunit/phpunit-7/src/Framework/SkippedTestCase.php create mode 100644 .phpunit/phpunit-7/src/Framework/SkippedTestError.php create mode 100644 .phpunit/phpunit-7/src/Framework/SkippedTestSuiteError.php create mode 100644 .phpunit/phpunit-7/src/Framework/SyntheticError.php create mode 100644 .phpunit/phpunit-7/src/Framework/Test.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestCase.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestFailure.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestListener.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestListenerDefaultImplementation.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestResult.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestSuite.php create mode 100644 .phpunit/phpunit-7/src/Framework/TestSuiteIterator.php create mode 100644 .phpunit/phpunit-7/src/Framework/UnintentionallyCoveredCodeError.php create mode 100644 .phpunit/phpunit-7/src/Framework/Warning.php create mode 100644 .phpunit/phpunit-7/src/Framework/WarningTestCase.php create mode 100644 .phpunit/phpunit-7/src/Runner/BaseTestRunner.php create mode 100644 .phpunit/phpunit-7/src/Runner/Exception.php create mode 100644 .phpunit/phpunit-7/src/Runner/Filter/ExcludeGroupFilterIterator.php create mode 100644 .phpunit/phpunit-7/src/Runner/Filter/Factory.php create mode 100644 .phpunit/phpunit-7/src/Runner/Filter/GroupFilterIterator.php create mode 100644 .phpunit/phpunit-7/src/Runner/Filter/IncludeGroupFilterIterator.php create mode 100644 .phpunit/phpunit-7/src/Runner/Filter/NameFilterIterator.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterIncompleteTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterLastTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterRiskyTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterSkippedTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterSuccessfulTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterTestErrorHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterTestFailureHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/AfterTestWarningHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/BeforeFirstTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/BeforeTestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/Hook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/TestHook.php create mode 100644 .phpunit/phpunit-7/src/Runner/Hook/TestListenerAdapter.php create mode 100644 .phpunit/phpunit-7/src/Runner/PhptTestCase.php create mode 100644 .phpunit/phpunit-7/src/Runner/ResultCacheExtension.php create mode 100644 .phpunit/phpunit-7/src/Runner/StandardTestSuiteLoader.php create mode 100644 .phpunit/phpunit-7/src/Runner/TestSuiteLoader.php create mode 100644 .phpunit/phpunit-7/src/Runner/TestSuiteSorter.php create mode 100644 .phpunit/phpunit-7/src/Runner/Version.php create mode 100644 .phpunit/phpunit-7/src/TextUI/Command.php create mode 100644 .phpunit/phpunit-7/src/TextUI/ResultPrinter.php create mode 100644 .phpunit/phpunit-7/src/TextUI/TestRunner.php create mode 100644 .phpunit/phpunit-7/src/Util/Blacklist.php create mode 100644 .phpunit/phpunit-7/src/Util/Configuration.php create mode 100644 .phpunit/phpunit-7/src/Util/ConfigurationGenerator.php create mode 100644 .phpunit/phpunit-7/src/Util/ErrorHandler.php create mode 100644 .phpunit/phpunit-7/src/Util/FileLoader.php create mode 100644 .phpunit/phpunit-7/src/Util/Filesystem.php create mode 100644 .phpunit/phpunit-7/src/Util/Filter.php create mode 100644 .phpunit/phpunit-7/src/Util/Getopt.php create mode 100644 .phpunit/phpunit-7/src/Util/GlobalState.php create mode 100644 .phpunit/phpunit-7/src/Util/InvalidArgumentHelper.php create mode 100644 .phpunit/phpunit-7/src/Util/Json.php create mode 100644 .phpunit/phpunit-7/src/Util/Log/JUnit.php create mode 100644 .phpunit/phpunit-7/src/Util/Log/TeamCity.php create mode 100644 .phpunit/phpunit-7/src/Util/NullTestResultCache.php create mode 100644 .phpunit/phpunit-7/src/Util/PHP/AbstractPhpProcess.php create mode 100644 .phpunit/phpunit-7/src/Util/PHP/DefaultPhpProcess.php create mode 100644 .phpunit/phpunit-7/src/Util/PHP/Template/PhptTestCase.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Util/PHP/Template/TestCaseClass.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Util/PHP/Template/TestCaseMethod.tpl.dist create mode 100644 .phpunit/phpunit-7/src/Util/PHP/WindowsPhpProcess.php create mode 100644 .phpunit/phpunit-7/src/Util/PHP/eval-stdin.php create mode 100644 .phpunit/phpunit-7/src/Util/Printer.php create mode 100644 .phpunit/phpunit-7/src/Util/RegularExpression.php create mode 100644 .phpunit/phpunit-7/src/Util/Test.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/CliTestDoxPrinter.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/HtmlResultPrinter.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/NamePrettifier.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/ResultPrinter.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/TestResult.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/TextResultPrinter.php create mode 100644 .phpunit/phpunit-7/src/Util/TestDox/XmlResultPrinter.php create mode 100644 .phpunit/phpunit-7/src/Util/TestResultCache.php create mode 100644 .phpunit/phpunit-7/src/Util/TestResultCacheInterface.php create mode 100644 .phpunit/phpunit-7/src/Util/TextTestListRenderer.php create mode 100644 .phpunit/phpunit-7/src/Util/Type.php create mode 100644 .phpunit/phpunit-7/src/Util/XdebugFilterScriptGenerator.php create mode 100644 .phpunit/phpunit-7/src/Util/Xml.php create mode 100644 .phpunit/phpunit-7/src/Util/XmlTestListRenderer.php create mode 100644 .phpunit/phpunit-7/tests/_files/3194.php create mode 100644 .phpunit/phpunit-7/tests/_files/3530.wsdl create mode 100644 .phpunit/phpunit-7/tests/_files/AbstractMockTestClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/AbstractTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/AbstractTrait.php create mode 100644 .phpunit/phpunit-7/tests/_files/AnInterface.php create mode 100644 .phpunit/phpunit-7/tests/_files/AnInterfaceWithReturnType.php create mode 100644 .phpunit/phpunit-7/tests/_files/AnotherInterface.php create mode 100644 .phpunit/phpunit-7/tests/_files/ArrayAccessible.php create mode 100644 .phpunit/phpunit-7/tests/_files/AssertionExample.php create mode 100644 .phpunit/phpunit-7/tests/_files/AssertionExampleTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/Author.php create mode 100644 .phpunit/phpunit-7/tests/_files/BankAccount.php create mode 100644 .phpunit/phpunit-7/tests/_files/BankAccountTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/BankAccountTest.test.php create mode 100644 .phpunit/phpunit-7/tests/_files/BankAccountTest2.php create mode 100644 .phpunit/phpunit-7/tests/_files/Bar.php create mode 100644 .phpunit/phpunit-7/tests/_files/BeforeAndAfterTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/BeforeClassAndAfterClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/BeforeClassWithOnlyDataProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/Book.php create mode 100644 .phpunit/phpunit-7/tests/_files/Calculator.php create mode 100644 .phpunit/phpunit-7/tests/_files/ChangeCurrentWorkingDirectoryTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassThatImplementsSerializable.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithAllPossibleReturnTypes.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithNonPublicAttributes.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithScalarTypeDeclarations.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithSelfTypeHint.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithStaticMethod.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithToString.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClassWithVariadicArgumentMethod.php create mode 100644 .phpunit/phpunit-7/tests/_files/ClonedDependencyTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ConcreteTest.my.php create mode 100644 .phpunit/phpunit-7/tests/_files/ConcreteTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CountConstraint.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageClassExtendedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageCoversOverridesCoversNothingTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageFunctionParenthesesTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageFunctionParenthesesWhitespaceTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageFunctionTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageMethodOneLineAnnotationTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageMethodParenthesesTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageMethodParenthesesWhitespaceTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageMethodTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNamespacedFunctionTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNoneTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNotPrivateTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNotProtectedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNotPublicTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageNothingTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoveragePrivateTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageProtectedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoveragePublicTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoverageTwoDefaultClassAnnotations.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoveredClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/CoveredFunction.php create mode 100644 .phpunit/phpunit-7/tests/_files/CustomPrinter.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderDebugTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderDependencyTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderFilterTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIncompleteTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2833/FirstTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2833/SecondTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2859/phpunit.xml create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2859/tests/another/TestWithDataProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2922/FirstTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderIssue2922/SecondTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderSkippedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataProviderTestDoxTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataproviderExecutionOrderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DataproviderExecutionOrderTest_result_cache.txt create mode 100644 .phpunit/phpunit-7/tests/_files/DependencyFailureTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DependencySuccessTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DependencyTestSuite.php create mode 100644 .phpunit/phpunit-7/tests/_files/DoNoAssertionTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/DoesNotPerformAssertionsButPerformingAssertionsTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DoubleTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/DummyBarTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/DummyException.php create mode 100644 .phpunit/phpunit-7/tests/_files/DummyFooTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/EmptyTestCaseTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExampleTrait.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInAssertPostConditionsTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInAssertPreConditionsTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInSetUpTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInTearDownAfterClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInTearDownTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionInTestDetectedInTeardown.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionNamespaceTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionStackTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/ExceptionWithThrowable.php create mode 100644 .phpunit/phpunit-7/tests/_files/Failure.php create mode 100644 .phpunit/phpunit-7/tests/_files/FailureTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/FalsyConstraint.php create mode 100644 .phpunit/phpunit-7/tests/_files/FatalTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/Foo.php create mode 100644 .phpunit/phpunit-7/tests/_files/FunctionCallback.php create mode 100644 .phpunit/phpunit-7/tests/_files/Go ogle-Sea.rch.wsdl create mode 100644 .phpunit/phpunit-7/tests/_files/GoogleSearch.wsdl create mode 100644 .phpunit/phpunit-7/tests/_files/IgnoreCodeCoverageClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/IgnoreCodeCoverageClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/IncompleteTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/Inheritance/InheritanceA.php create mode 100644 .phpunit/phpunit-7/tests/_files/Inheritance/InheritanceB.php create mode 100644 .phpunit/phpunit-7/tests/_files/InheritedTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/IniTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/InterfaceWithSemiReservedMethodName.php create mode 100644 .phpunit/phpunit-7/tests/_files/InterfaceWithStaticMethod.php create mode 100644 .phpunit/phpunit-7/tests/_files/IsolationTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/JsonData/arrayObject.json create mode 100644 .phpunit/phpunit-7/tests/_files/JsonData/simpleObject.json create mode 100644 .phpunit/phpunit-7/tests/_files/MethodCallback.php create mode 100644 .phpunit/phpunit-7/tests/_files/MethodCallbackByReference.php create mode 100644 .phpunit/phpunit-7/tests/_files/MockRunner.php create mode 100644 .phpunit/phpunit-7/tests/_files/MockTestInterface.php create mode 100644 .phpunit/phpunit-7/tests/_files/Mockable.php create mode 100644 .phpunit/phpunit-7/tests/_files/MultiDependencyTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/MultiDependencyTest_result_cache.txt create mode 100644 .phpunit/phpunit-7/tests/_files/MultipleDataProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/MyCommand.php create mode 100644 .phpunit/phpunit-7/tests/_files/MyTestListener.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamedConstraint.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageClassExtendedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageCoversClassPublicTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageCoversClassTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageMethodTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageNotPrivateTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageNotProtectedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageNotPublicTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoveragePrivateTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoverageProtectedTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoveragePublicTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoveredClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/NamespaceCoveredFunction.php create mode 100644 .phpunit/phpunit-7/tests/_files/NoArgTestCaseTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NoTestCaseClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/NoTestCases.php create mode 100644 .phpunit/phpunit-7/tests/_files/NonStatic.php create mode 100644 .phpunit/phpunit-7/tests/_files/NotExistingCoveredElementTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NotPublicTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/NotSelfDescribingTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NotVoidTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/NothingTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/NumericGroupAnnotationTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/OneTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/OutputTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/OverrideTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/ParseTestMethodAnnotationsMock.php create mode 100644 .phpunit/phpunit-7/tests/_files/PartialMockTestClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/RequirementsClassBeforeClassHookTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/RequirementsClassDocBlockTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/RequirementsTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/RouterTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/SampleArrayAccess.php create mode 100644 .phpunit/phpunit-7/tests/_files/SampleClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/Singleton.php create mode 100644 .phpunit/phpunit-7/tests/_files/SingletonClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/SomeClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/StackTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/StaticMockTestClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/StatusTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/StopOnErrorTestSuite.php create mode 100644 .phpunit/phpunit-7/tests/_files/StopOnWarningTestSuite.php create mode 100644 .phpunit/phpunit-7/tests/_files/StopsOnWarningTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/StringableClass.php create mode 100644 .phpunit/phpunit-7/tests/_files/Struct.php create mode 100644 .phpunit/phpunit-7/tests/_files/Success.php create mode 100644 .phpunit/phpunit-7/tests/_files/TemplateMethodsTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestAutoreferenced.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestDoxGroupTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestGeneratorMaker.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestIncomplete.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestIterator.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestIterator2.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestIteratorAggregate.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestIteratorAggregate2.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestRisky.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestSkipped.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestTestError.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestWarning.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestWithTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/TestableCliTestDoxPrinter.php create mode 100644 .phpunit/phpunit-7/tests/_files/ThrowExceptionTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/ThrowNoExceptionTestCase.php create mode 100644 .phpunit/phpunit-7/tests/_files/TraversableMockTestInterface.php create mode 100644 .phpunit/phpunit-7/tests/_files/TruthyConstraint.php create mode 100644 .phpunit/phpunit-7/tests/_files/VariousIterableDataProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/WasRun.php create mode 100644 .phpunit/phpunit-7/tests/_files/WrapperIteratorAggregate.php create mode 100644 .phpunit/phpunit-7/tests/_files/bar.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.colors.empty.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.colors.false.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.colors.invalid.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.colors.true.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.columns.default.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.custom-printer.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.defaulttestsuite.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.one-file-suite.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.suites.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_empty.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_execution_order_options.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_stop_on_defect.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_stop_on_error.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_stop_on_incomplete.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_stop_on_warning.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_whitelist.xml create mode 100644 .phpunit/phpunit-7/tests/_files/configuration_xinclude.xml create mode 100644 .phpunit/phpunit-7/tests/_files/expectedFileFormat.txt create mode 100644 .phpunit/phpunit-7/tests/_files/foo.xml create mode 100644 .phpunit/phpunit-7/tests/_files/phpt-for-coverage.phpt create mode 100644 .phpunit/phpunit-7/tests/_files/phpt-unsupported-section.phpt create mode 100644 .phpunit/phpunit-7/tests/_files/phpt-xfail.phpt create mode 100644 .phpunit/phpunit-7/tests/_files/phpunit-example-extension/phpunit.xml create mode 100644 .phpunit/phpunit-7/tests/_files/phpunit-example-extension/tests/OneTest.php create mode 100644 .phpunit/phpunit-7/tests/_files/phpunit-example-extension/tools/phpunit.d/phpunit-example-extension-3.0.3.phar create mode 100644 .phpunit/phpunit-7/tests/_files/structureAttributesAreSameButValuesAreNot.xml create mode 100644 .phpunit/phpunit-7/tests/_files/structureExpected.xml create mode 100644 .phpunit/phpunit-7/tests/_files/structureIgnoreTextNodes.xml create mode 100644 .phpunit/phpunit-7/tests/_files/structureIsSameButDataIsNot.xml create mode 100644 .phpunit/phpunit-7/tests/_files/structureWrongNumberOfAttributes.xml create mode 100644 .phpunit/phpunit-7/tests/_files/structureWrongNumberOfNodes.xml create mode 100644 .phpunit/phpunit-7/tests/bootstrap.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/Extension.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/HookTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/NullPrinter.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/expect_external.txt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/hooks.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/phpt-env.expected.txt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/_files/phpt_external.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/abstract-test-class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/assertion.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/cache-result.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/code-coverage-ignore.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/code-coverage-phpt.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/colors-always.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/concrete-test-class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/custom-printer-debug.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/custom-printer-verbose.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-debug.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-issue-2833.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-issue-2859.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-issue-2922.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-log-xml-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-log-xml.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dataprovider-testdox.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/debug.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/default-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/default.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/defaulttestsuite-using-testsuite.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/defaulttestsuite.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/defects-first-order-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies-clone.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies2-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies2.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies3-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dependencies3.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/disable-code-coverage-ignore.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/dump-xdebug-filter.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/empty-testcase.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/exception-stack.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/exclude-group-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/exclude-group.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/execution-order-options-via-config.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/failure-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/failure-reverse-list.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/failure.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/fatal-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-class-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-classname-and-range-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-classname-and-range.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-number-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-number.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-range-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-range.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-regexp-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-regexp.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-string-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-only-string.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-range-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-range.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-regexp-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-regexp.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-string-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-dataprovider-by-string.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-method-case-insensitive.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-method-case-sensitive-no-result.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-method-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/filter-no-results.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/forward-compatibility.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/group-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/group.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/help.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/help2.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/hooks.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/ini-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/list-groups.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/list-suites.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/list-tests-dataprovider.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/list-tests-xml-dataprovider.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/log-junit-phpt.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/log-junit.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/log-teamcity-phpt.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/log-teamcity.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/232.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/3154_namespaced_constant_resolving.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/3530.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/397.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/abstract_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_call_parent_clone.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_dont_call_parent_clone.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_dont_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_implementing_interface_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_implementing_interface_dont_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_nonexistent_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_partial.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_deprecated_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_final_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_method_named_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_method_with_nullable_typehinted_variadic_arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_method_with_typehinted_variadic_arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/class_with_method_with_variadic_arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/constant_as_parameter_default_value.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/interface.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/invocation_object_clone_object.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_call_parent_clone.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_dont_call_parent_clone.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_dont_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_implementing_interface_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_implementing_interface_dont_call_parent_constructor.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_class_partial.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/namespaced_interface.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/nonexistent_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/nonexistent_class_with_namespace.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/nonexistent_class_with_namespace_starting_with_separator.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/nullable_types.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/proxy.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_closure.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_final.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_generator.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_nullable.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_object_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_parent.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_self.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_static_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/return_type_declarations_void.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/scalar_type_declarations.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/wsdl_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/wsdl_class_namespace.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/generator/wsdl_class_partial.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/call_original.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/call_original_with_argument.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/call_original_with_argument_variadic.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/call_original_with_return_type_void.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/clone_method_arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/deprecated_with_description.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/deprecated_without_description.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/private_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/protected_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/return_by_reference.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/return_by_reference_with_return_type.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/return_type.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/return_type_parent.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/return_type_self.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/static_method.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/static_method_with_return_type.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_default.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_default_constant.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_default_null.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_nullable.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_reference.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_array.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_callable.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_scalar.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_self.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_unkown_class.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_typed_variadic.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_argument_variadic.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mock-objects/mock-method/with_arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/mycommand.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/options-after-arguments.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/order-by-default-invalid-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/output-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phar-extension-suppressed.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phar-extension.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-args.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-env.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-external.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-parsing.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-stderr.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-stdin.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/phpt-xfail.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1149.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1149/Issue1149Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1216.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1216/Issue1216Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1216/bootstrap1216.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1216/phpunit1216.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1265.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1265/Issue1265Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1265/phpunit1265.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1330.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1330/Issue1330Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1330/phpunit1330.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1335.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1335/Issue1335Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1335/bootstrap1335.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1337.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1337/Issue1337Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1348.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1348/Issue1348Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1351.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1351/ChildProcessClass1351.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1351/Issue1351Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1374.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1374/Issue1374Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1437.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1437/Issue1437Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1468.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1468/Issue1468Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1471.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1471/Issue1471Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1472.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1472/Issue1472Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1570.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/1570/Issue1570Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2085-enforce-time-limit-options-via-config-without-invoker.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2085-without-invoker.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2085.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2085/Issue2085Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2085/configuration_enforce_time_limit_options.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2137-filter.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2137-no_filter.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2137/Issue2137Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2145.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2145/Issue2145Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2158.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2158/Issue2158Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2158/constant.inc create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2366.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2366/Issue2366Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2380.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2380/Issue2380Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2382.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2382/Issue2382Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2435.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2435/Issue2435Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/244.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/244/Issue244Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2448-existing-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2448-not-existing-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2448/.gitignore create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2448/Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-class-preserve-no-bootstrap.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-class-preserve.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-function-no-preserve-no-bootstrap-php73.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-function-no-preserve-no-bootstrap-xdebug.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-function-no-preserve-no-bootstrap.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-function-no-preserve.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591-separate-function-preserve.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/SeparateClassPreserveTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/SeparateFunctionNoPreserveTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/SeparateFunctionPreserveTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/bootstrapNoBootstrap.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/bootstrapWithBootstrap.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2591/bootstrapWithBootstrapNoGlobal.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2724-diff-pid-from-master-process.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2724/SeparateClassRunMethodInNewProcessTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2725-separate-class-before-after-pid.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2725/BeforeAfterClassPidTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2731.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2731/Issue2731Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2811.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2811/Issue2811Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2830.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2830/Issue2830Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2972.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2972/issue-2972-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/2972/unconventiallyNamedIssue2972Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3093/Issue3093Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3093/issue-3093-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3107/Issue3107Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3107/issue-3107-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3156/Issue3156Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/322.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/322/Issue322Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/322/phpunit322.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3364/issue-3364-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3364/tests/Issue3364SetupBeforeClassTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3364/tests/Issue3364SetupTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3379.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3379/Issue3379Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3379/Issue3379TestListener.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3379/phpunit.xml create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3380/issue-3380-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/3396/issue-3396-test.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/433.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/433/Issue433Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/445.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/445/Issue445Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/498.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/498/Issue498Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/503.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/503/Issue503Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/581.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/581/Issue581Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/74.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/74/Issue74Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/74/NewException.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/765.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/765/Issue765Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/797.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/797/Issue797Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/797/bootstrap797.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/863.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/873.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/GitHub/873/Issue873Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/1021.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/1021/Issue1021Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/523.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/523/Issue523Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/578.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/578/Issue578Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/684.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/684/Issue684Test.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/783.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/783/ChildSuite.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/783/OneTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/783/ParentSuite.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/regression/Trac/783/TwoTest.php create mode 100644 .phpunit/phpunit-7/tests/end-to-end/repeat.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/report-tests-performing-assertions-when-annotated-with-does-not-perform-assertions.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/report-useless-tests-incomplete.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/report-useless-tests-isolation.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/report-useless-tests.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-defect-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-defect-via-config.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-error-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-error-via-config.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-incomplete-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-incomplete-via-config.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-warning-via-cli.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/stop-on-warning-via-config.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/teamcity-inner-exceptions.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/teamcity.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-order-randomized-seed-with-dependency-resolution.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-order-randomized-with-dependency-resolution.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-order-reversed-with-dependency-resolution.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-order-reversed-without-dependency-resolution.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-suffix-multiple.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/test-suffix-single.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-dataprovider-placeholder.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-exclude-group.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-group.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-html.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-text.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-verbose.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox-xml.phpt create mode 100644 .phpunit/phpunit-7/tests/end-to-end/testdox.phpt create mode 100644 .phpunit/phpunit-7/tests/fail/fail.phpt create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/AssertTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ArrayHasKeyTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ArraySubsetTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/AttributeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/CallbackTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ClassHasAttributeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ClassHasStaticAttributeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ConstraintTestCase.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/CountTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/DirectoryExistsTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ExceptionMessageRegExpTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ExceptionMessageTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/FileExistsTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/GreaterThanTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsEmptyTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsEqualTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsIdenticalTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsInstanceOfTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsJsonTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsNullTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsReadableTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsTypeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/IsWritableTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/JsonMatchesErrorMessageProviderTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/JsonMatchesTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/LessThanTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/LogicalAndTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/LogicalOrTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/LogicalXorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/ObjectHasAttributeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/RegularExpressionTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/SameSizeTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/StringContainsTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/StringEndsWithTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/StringMatchesFormatDescriptionTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/StringStartsWithTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/Constraint/TraversableContainsTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/ConstraintTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/ExceptionWrapperTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/Builder/InvocationMockerTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/GeneratorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/Invocation/ObjectInvocationTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/Invocation/StaticInvocationTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/Matcher/ConsecutiveParametersTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/MockBuilderTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/MockMethodTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/MockObjectTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/MockObject/ProxyObjectTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestCaseTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestFailureTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestImplementorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestListenerTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestResultTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Framework/TestSuiteTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Runner/Filter/NameFilterIteratorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Runner/PhptTestCaseTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Runner/ResultCacheExtensionTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Runner/TestSuiteSorterTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/TextUI/TestRunnerTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/ConfigurationGeneratorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/ConfigurationTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/GetoptTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/GlobalStateTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/JsonTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/NullTestResultCacheTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/PHP/AbstractPhpProcessTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/RegularExpressionTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/TestDox/CliTestDoxPrinterTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/TestDox/NamePrettifierTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/TestResultCacheTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/TestTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/XDebugFilterScriptGeneratorTest.php create mode 100644 .phpunit/phpunit-7/tests/unit/Util/XmlTest.php diff --git a/.phpunit/.7.md5 b/.phpunit/.7.md5 new file mode 100644 index 0000000..b1baee3 --- /dev/null +++ b/.phpunit/.7.md5 @@ -0,0 +1,2 @@ +1a8bd1a9142145a86293813f60f175bc +symfony/yaml \ No newline at end of file diff --git a/.phpunit/phpunit-7/.editorconfig b/.phpunit/phpunit-7/.editorconfig new file mode 100644 index 0000000..421bd83 --- /dev/null +++ b/.phpunit/phpunit-7/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +charset = utf-8 + +[tests/_files/*_result_cache.txt] +insert_final_newline = false diff --git a/.phpunit/phpunit-7/.gitattributes b/.phpunit/phpunit-7/.gitattributes new file mode 100644 index 0000000..278ace4 --- /dev/null +++ b/.phpunit/phpunit-7/.gitattributes @@ -0,0 +1,4 @@ +/build export-ignore + +*.php diff=php + diff --git a/.phpunit/phpunit-7/.github/CODE_OF_CONDUCT.md b/.phpunit/phpunit-7/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..ee242a8 --- /dev/null +++ b/.phpunit/phpunit-7/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,28 @@ +# 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 [https://contributor-covenant.org/version/1/3/0/][version] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/3/0/ diff --git a/.phpunit/phpunit-7/.github/CONTRIBUTING.md b/.phpunit/phpunit-7/.github/CONTRIBUTING.md new file mode 100644 index 0000000..15ae47b --- /dev/null +++ b/.phpunit/phpunit-7/.github/CONTRIBUTING.md @@ -0,0 +1,68 @@ +# 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](https://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 made for the oldest branch that is [supported](https://phpunit.de/supported-versions.html). 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 and an executable for [php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) (`.php_cs`) that you can use to (re)format your source code for compliance with this project's coding guidelines: + +```bash +$ ./build/tools/php-cs-fixer 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) +* [Documentation](https://github.com/sebastianbergmann/phpunit-documentation-english/issues) +* [Website](https://github.com/sebastianbergmann/phpunit-website/issues) + diff --git a/.phpunit/phpunit-7/.github/ISSUE_TEMPLATE.md b/.phpunit/phpunit-7/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..ad1dc39 --- /dev/null +++ b/.phpunit/phpunit-7/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,15 @@ +| Q | A +| --------------------| --------------- +| PHPUnit version | x.y.z +| PHP version | x.y.z +| Installation Method | Composer / PHAR + + + diff --git a/.phpunit/phpunit-7/.github/stale.yml b/.phpunit/phpunit-7/.github/stale.yml new file mode 100644 index 0000000..ad14f6c --- /dev/null +++ b/.phpunit/phpunit-7/.github/stale.yml @@ -0,0 +1,47 @@ +# Configuration for probot-stale - https://github.com/probot/stale + +# Number of days of inactivity before an Issue or Pull Request becomes stale +daysUntilStale: 60 + +# Number of days of inactivity before a stale Issue or Pull Request is closed. +# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. +daysUntilClose: 7 + +# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable +exemptLabels: + - blocked + - enhancement + - backward-compatibility-break + - feature-removal + - php-support-removal + - process + - rfc + - refactoring + +# Set to true to ignore issues in a project (defaults to false) +exemptProjects: false + +# Set to true to ignore issues in a milestone (defaults to false) +exemptMilestones: false + +# Label to use when marking as stale +staleLabel: stale + +# Comment to post when marking as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had activity within the last 60 days. It will be closed after 7 days if no further activity occurs. Thank you for your contributions. + +# Comment to post when removing the stale label. +# unmarkComment: > +# Your comment here. + +# Comment to post when closing a stale Issue or Pull Request. +closeComment: > + This issue has been automatically closed because it has not had activity since it was marked as stale. Thank you for your contributions. + +# Limit the number of actions per hour, from 1-30. Default is 30 +limitPerRun: 30 + +# Limit to only `issues` or `pulls` +only: issues + diff --git a/.phpunit/phpunit-7/.gitignore b/.phpunit/phpunit-7/.gitignore new file mode 100644 index 0000000..c313090 --- /dev/null +++ b/.phpunit/phpunit-7/.gitignore @@ -0,0 +1,20 @@ +/.ant_targets +/.idea +/.php_cs +/.php_cs.cache +/.phpunit.result.cache +/build/documentation +/build/logfiles +/build/phar +/build/phpdox +/build/*.phar +/build/*.phar.asc +/build/binary-phar-autoload.php +/cache.properties +/composer.lock +/tests/end-to-end/*.diff +/tests/end-to-end/*.exp +/tests/end-to-end/*.log +/tests/end-to-end/*.out +/tests/end-to-end/*.php +/vendor diff --git a/.phpunit/phpunit-7/.phan/config.php b/.phpunit/phpunit-7/.phan/config.php new file mode 100644 index 0000000..5eb2b87 --- /dev/null +++ b/.phpunit/phpunit-7/.phan/config.php @@ -0,0 +1,7 @@ + [ 'src/', 'vendor/' ], + 'exclude_analysis_directory_list' => [ 'vendor/', 'src/Framework/Assert/' ], + + 'target_php_version' => '7.1', +]; diff --git a/.phpunit/phpunit-7/.php_cs.dist b/.phpunit/phpunit-7/.php_cs.dist new file mode 100644 index 0000000..283cbfb --- /dev/null +++ b/.phpunit/phpunit-7/.php_cs.dist @@ -0,0 +1,198 @@ + + +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( + [ + 'align_multiline_comment' => true, + 'array_indentation' => true, + 'array_syntax' => ['syntax' => 'short'], + 'binary_operator_spaces' => [ + 'operators' => [ + '=' => 'align', + '=>' => 'align', + ], + ], + 'blank_line_after_namespace' => true, + 'blank_line_before_statement' => [ + 'statements' => [ + 'break', + 'continue', + 'declare', + 'do', + 'for', + 'foreach', + 'if', + 'include', + 'include_once', + 'require', + 'require_once', + 'return', + 'switch', + 'throw', + 'try', + 'while', + 'yield', + ], + ], + 'braces' => true, + 'cast_spaces' => true, + 'class_attributes_separation' => ['elements' => ['const', 'method', 'property']], + 'combine_consecutive_issets' => true, + 'combine_consecutive_unsets' => true, + 'compact_nullable_typehint' => true, + 'concat_space' => ['spacing' => 'one'], + 'declare_equal_normalize' => ['space' => 'none'], + 'dir_constant' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'function_declaration' => true, + 'header_comment' => ['header' => $header, 'separate' => 'none'], + 'indentation_type' => true, + 'is_null' => true, + 'line_ending' => true, + 'list_syntax' => ['syntax' => 'short'], + 'logical_operators' => true, + 'lowercase_cast' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'lowercase_static_reference' => true, + 'magic_constant_casing' => true, + 'method_argument_space' => ['ensure_fully_multiline' => true], + 'modernize_types_casting' => true, + 'multiline_comment_opening_closing' => true, + 'multiline_whitespace_before_semicolons' => true, + 'native_constant_invocation' => true, + 'native_function_casing' => true, + 'native_function_invocation' => true, + 'new_with_braces' => false, + 'no_alias_functions' => true, + 'no_alternative_syntax' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_blank_lines_before_namespace' => true, + 'no_closing_tag' => true, + 'no_empty_comment' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_homoglyph_names' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => ['use' => 'print'], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_null_property_initialization' => true, + 'no_php4_constructor' => true, + 'no_short_bool_cast' => true, + 'no_short_echo_tag' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_superfluous_elseif' => true, + 'no_superfluous_phpdoc_tags' => true, + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unneeded_curly_braces' => true, + 'no_unneeded_final_method' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unset_on_property' => true, + 'no_unused_imports' => true, + 'no_useless_else' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'non_printable_character' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'ordered_class_elements' => [ + 'order' => [ + 'use_trait', + 'constant_public', + 'constant_protected', + 'constant_private', + 'property_public_static', + 'property_protected_static', + 'property_private_static', + 'property_public', + 'property_protected', + 'property_private', + 'method_public_static', + 'construct', + 'destruct', + 'magic', + 'phpunit', + 'method_public', + 'method_protected', + 'method_private', + 'method_protected_static', + 'method_private_static', + ], + ], + 'ordered_imports' => true, + 'phpdoc_add_missing_param_annotation' => true, + 'phpdoc_align' => true, + 'phpdoc_annotation_without_dot' => true, + 'phpdoc_indent' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_package' => true, + 'phpdoc_order' => true, + 'phpdoc_return_self_reference' => true, + 'phpdoc_scalar' => true, + 'phpdoc_separation' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_trim_consecutive_blank_line_separation' => true, + 'phpdoc_types' => ['groups' => ['simple', 'meta']], + 'phpdoc_types_order' => true, + 'phpdoc_var_without_name' => true, + 'pow_to_exponentiation' => true, + 'protected_to_private' => true, + 'return_assignment' => true, + 'return_type_declaration' => ['space_before' => 'none'], + 'self_accessor' => true, + 'semicolon_after_instruction' => true, + 'set_type_to_cast' => true, + 'short_scalar_cast' => true, + 'simplified_null_return' => true, + 'single_blank_line_at_eof' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_quote' => true, + 'standardize_not_equals' => true, + 'ternary_to_null_coalescing' => true, + 'trailing_comma_in_multiline_array' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => [ + 'elements' => [ + 'const', + 'method', + 'property', + ], + ], + //'void_return' => true, + 'whitespace_after_comma_in_array' => true, + ] + ) + ->setFinder( + PhpCsFixer\Finder::create() + ->files() + ->in(__DIR__ . '/build') + ->in(__DIR__ . '/src') + ->in(__DIR__ . '/tests') + ->notName('*.phpt') + ); diff --git a/.phpunit/phpunit-7/.travis.yml b/.phpunit/phpunit-7/.travis.yml new file mode 100644 index 0000000..416a3f6 --- /dev/null +++ b/.phpunit/phpunit-7/.travis.yml @@ -0,0 +1,58 @@ +language: php + +sudo: false + +addons: + apt: + packages: + - libxml2-utils + +php: + - 7.1 + - 7.2 + - 7.3 + +matrix: + fast_finish: true + +env: + matrix: + - DEPENDENCIES="high" + - DEPENDENCIES="low" + global: + - DEFAULT_COMPOSER_FLAGS="--no-interaction --no-ansi --no-progress --no-suggest" + +before_install: + - ./build/tools/composer clear-cache + +install: + - if [[ "$DEPENDENCIES" = 'high' ]]; then travis_retry ./build/tools/composer update $DEFAULT_COMPOSER_FLAGS; fi + - if [[ "$DEPENDENCIES" = 'low' ]]; then travis_retry ./build/tools/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 + +jobs: + include: + - stage: Static Code Analysis + php: 7.3 + env: php-cs-fixer + install: + - phpenv config-rm xdebug.ini + script: + - ./build/tools/php-cs-fixer fix --dry-run -v --show-progress=dots --diff-format=udiff diff --git a/.phpunit/phpunit-7/ChangeLog-7.5.md b/.phpunit/phpunit-7/ChangeLog-7.5.md new file mode 100644 index 0000000..8855fda --- /dev/null +++ b/.phpunit/phpunit-7/ChangeLog-7.5.md @@ -0,0 +1,84 @@ +# Changes in PHPUnit 7.5 + +All notable changes of the PHPUnit 7.5 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [7.5.6] - 2019-02-18 + +### Fixed + +* Fixed [#3530](https://github.com/sebastianbergmann/phpunit/issues/3530): `generateClassFromWsdl()` does not handle methods with multiple output values +* Fixed [#3531](https://github.com/sebastianbergmann/phpunit/issues/3531): Test suite fails on warning +* Fixed [#3534](https://github.com/sebastianbergmann/phpunit/pull/3534): Wrong message in `ConstraintTestCase` + +## [7.5.5] - 2019-02-15 + +### Fixed + +* Fixed [#3011](https://github.com/sebastianbergmann/phpunit/issues/3011): Unsupported PHPT `--SECTION--` throws unhandled exception +* Fixed [#3461](https://github.com/sebastianbergmann/phpunit/issues/3461): `StringEndsWith` matches too loosely +* Fixed [#3515](https://github.com/sebastianbergmann/phpunit/issues/3515): Random order seed is only printed in verbose mode +* Fixed [#3517](https://github.com/sebastianbergmann/phpunit/issues/3517): Useless error message when depending on test that does not exist + +## [7.5.4] - 2019-02-07 + +### Fixed + +* Fixed [#3352](https://github.com/sebastianbergmann/phpunit/issues/3352): Using `phpunit.phar` with PHPDBG does not work with `auto_globals_jit=On` +* Fixed [#3502](https://github.com/sebastianbergmann/phpunit/issues/3502): Numeric `@ticket` or `@group` annotations no longer work + +## [7.5.3] - 2019-02-01 + +### Fixed + +* Fixed [#3490](https://github.com/sebastianbergmann/phpunit/pull/3490): Exceptions in `tearDownAfterClass()` kill PHPUnit + +### Deprecated + +* The method `assertArraySubset()` is now deprecated. There is no behavioral change in this version of PHPUnit. Using this method will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 this method will be removed. + +## [7.5.2] - 2019-01-15 + +### Fixed + +* Fixed [#3456](https://github.com/sebastianbergmann/phpunit/pull/3456): Generator for Xdebug filter script does not handle directories with leading `.` correctly +* Fixed [#3459](https://github.com/sebastianbergmann/phpunit/issues/3459): `@requires` function swallows digits at the end of function name + +## [7.5.1] - 2018-12-12 + +### Fixed + +* Fixed [#3441](https://github.com/sebastianbergmann/phpunit/issues/3441): Call to undefined method `DataProviderTestSuite::usesDataProvider()` + +## [7.5.0] - 2018-12-07 + +### Added + +* Implemented [#3340](https://github.com/sebastianbergmann/phpunit/issues/3340): Added `assertEqualsCanonicalizing()`, `assertEqualsIgnoringCase()`, `assertEqualsWithDelta()`, `assertNotEqualsCanonicalizing()`, `assertNotEqualsIgnoringCase()`, and `assertNotEqualsWithDelta()` as alternatives to using `assertEquals()` and `assertNotEquals()` with the `$delta`, `$canonicalize`, or `$ignoreCase` parameters +* Implemented [#3368](https://github.com/sebastianbergmann/phpunit/issues/3368): Added `assertIsArray()`, `assertIsBool()`, `assertIsFloat()`, `assertIsInt()`, `assertIsNumeric()`, `assertIsObject()`, `assertIsResource()`, `assertIsString()`, `assertIsScalar()`, `assertIsCallable()`, `assertIsIterable()`, `assertIsNotArray()`, `assertIsNotBool()`, `assertIsNotFloat()`, `assertIsNotInt()`, `assertIsNotNumeric()`, `assertIsNotObject()`, `assertIsNotResource()`, `assertIsNotString()`, `assertIsNotScalar()`, `assertIsNotCallable()`, `assertIsNotIterable()` as alternatives to `assertInternalType()` and `assertNotInternalType()` +* Implemented [#3391](https://github.com/sebastianbergmann/phpunit/issues/3391): Added a `TestHook` that fires after each test, regardless of result +* Implemented [#3417](https://github.com/sebastianbergmann/phpunit/pull/3417): Refinements related to test suite sorting and TestDox result printer +* Implemented [#3422](https://github.com/sebastianbergmann/phpunit/issues/3422): Added `assertStringContainsString()`, `assertStringContainsStringIgnoringCase()`, `assertStringNotContainsString()`, and `assertStringNotContainsStringIgnoringCase()` + +### Deprecated + +* The methods `assertInternalType()` and `assertNotInternalType()` are now deprecated. There is no behavioral change in this version of PHPUnit. Using these methods will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these methods will be removed. +* The methods `assertAttributeContains()`, `assertAttributeNotContains()`, `assertAttributeContainsOnly()`, `assertAttributeNotContainsOnly()`, `assertAttributeCount()`, `assertAttributeNotCount()`, `assertAttributeEquals()`, `assertAttributeNotEquals()`, `assertAttributeEmpty()`, `assertAttributeNotEmpty()`, `assertAttributeGreaterThan()`, `assertAttributeGreaterThanOrEqual()`, `assertAttributeLessThan()`, `assertAttributeLessThanOrEqual()`, `assertAttributeSame()`, `assertAttributeNotSame()`, `assertAttributeInstanceOf()`, `assertAttributeNotInstanceOf()`, `assertAttributeInternalType()`, `assertAttributeNotInternalType()`, `attributeEqualTo()`, `readAttribute()`, `getStaticAttribute()`, and `getObjectAttribute()` are now deprecated. There is no behavioral change in this version of PHPUnit. Using these methods will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these methods will be removed. +* The optional parameters `$delta`, `$maxDepth`, `$canonicalize`, and `$ignoreCase` of `assertEquals()` and `assertNotEquals()` are now deprecated. There is no behavioral change in this version of PHPUnit. Using these parameters will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these parameters will be removed. +* The annotations `@expectedException`, `@expectedExceptionCode`, `@expectedExceptionMessage`, and `@expectedExceptionMessageRegExp` are now deprecated. There is no behavioral change in this version of PHPUnit. Using these annotations will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these annotations will be removed. +* Using the methods `assertContains()` and `assertNotContains()` on `string` haystacks is now deprecated. There is no behavioral change in this version of PHPUnit. Using these methods on `string` haystacks will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these methods cannot be used on on `string` haystacks anymore. +* The optional parameters `$ignoreCase`, `$checkForObjectIdentity`, and `$checkForNonObjectIdentity` of `assertContains()` and `assertNotContains()` are now deprecated. There is no behavioral change in this version of PHPUnit. Using these parameters will trigger a deprecation warning in PHPUnit 8 and in PHPUnit 9 these parameters will be removed. + +### Fixed + +* Fixed [#3428](https://github.com/sebastianbergmann/phpunit/pull/3428): `TestSuite` setup failures are not logged correctly +* Fixed [#3429](https://github.com/sebastianbergmann/phpunit/pull/3429): Inefficient loop in `getHookMethods()` +* Fixed [#3437](https://github.com/sebastianbergmann/phpunit/pull/3437): JUnit logger skips PHPT tests + +[7.5.6]: https://github.com/sebastianbergmann/phpunit/compare/7.5.5...7.5.6 +[7.5.5]: https://github.com/sebastianbergmann/phpunit/compare/7.5.4...7.5.5 +[7.5.4]: https://github.com/sebastianbergmann/phpunit/compare/7.5.3...7.5.4 +[7.5.3]: https://github.com/sebastianbergmann/phpunit/compare/7.5.2...7.5.3 +[7.5.2]: https://github.com/sebastianbergmann/phpunit/compare/7.5.1...7.5.2 +[7.5.1]: https://github.com/sebastianbergmann/phpunit/compare/7.5.0...7.5.1 +[7.5.0]: https://github.com/sebastianbergmann/phpunit/compare/7.4.5...7.5.0 + diff --git a/.phpunit/phpunit-7/LICENSE b/.phpunit/phpunit-7/LICENSE new file mode 100644 index 0000000..46fabcb --- /dev/null +++ b/.phpunit/phpunit-7/LICENSE @@ -0,0 +1,33 @@ +PHPUnit + +Copyright (c) 2001-2019, 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. diff --git a/.phpunit/phpunit-7/README.md b/.phpunit/phpunit-7/README.md new file mode 100644 index 0000000..ac52cee --- /dev/null +++ b/.phpunit/phpunit-7/README.md @@ -0,0 +1,40 @@ +# 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.1-8892BF.svg?style=flat-square)](https://php.net/) +[![Build Status](https://img.shields.io/travis/sebastianbergmann/phpunit/7.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 7.5 bundled in a single file: + +```bash +$ wget https://phar.phpunit.de/phpunit-7.5.phar + +$ php phpunit-7.5.phar --version +``` + +Alternatively, you may use [Composer](https://getcomposer.org/) to download and install PHPUnit as well as its dependencies. Please refer to the "[Getting Started](https://phpunit.de/getting-started-with-phpunit.html)" guide for details on how to install PHPUnit. + +## Contribute + +Please refer to [CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/.github/CONTRIBUTING.md) for information on how to contribute to PHPUnit and its related projects. + +## List of Contributors + +Thanks to everyone who has contributed to PHPUnit! You can find a detailed list of contributors on every PHPUnit related package on GitHub. This list shows only the major components: + +* [PHPUnit](https://github.com/sebastianbergmann/phpunit/graphs/contributors) +* [php-code-coverage](https://github.com/sebastianbergmann/php-code-coverage/graphs/contributors) + +A very special thanks to everyone who has contributed to the documentation and helps maintain the translations: + +* [English](https://github.com/sebastianbergmann/phpunit-documentation-english/graphs/contributors) +* [Spanish](https://github.com/sebastianbergmann/phpunit-documentation-spanish/graphs/contributors) +* [French](https://github.com/sebastianbergmann/phpunit-documentation-french/graphs/contributors) +* [Japanese](https://github.com/sebastianbergmann/phpunit-documentation-japanese/graphs/contributors) +* [Brazilian Portuguese](https://github.com/sebastianbergmann/phpunit-documentation-brazilian-portuguese/graphs/contributors) +* [Simplified Chinese](https://github.com/sebastianbergmann/phpunit-documentation-chinese/graphs/contributors) + diff --git a/.phpunit/phpunit-7/appveyor.yml b/.phpunit/phpunit-7/appveyor.yml new file mode 100644 index 0000000..e1cf0cf --- /dev/null +++ b/.phpunit/phpunit-7/appveyor.yml @@ -0,0 +1,59 @@ +build: 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: '7.0-dev' + + matrix: + - PHP_VERSION: '7.1' + XDEBUG_VERSION: '2.5.5-7.1' + DEPENDENCIES: '--prefer-lowest' + - PHP_VERSION: '7.1' + 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 curl -fsS -o php-%PHP_VERSION%-Win32-VC14-x86.zip https://windows.php.net/downloads/releases/latest/php-%PHP_VERSION%-Win32-VC14-x86-latest.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 curl -fsS -o composer.phar https://getcomposer.org/composer.phar + - IF NOT EXIST php-installed.txt echo @php %%~dp0composer.phar %%* > composer.bat + - IF NOT EXIST php-installed.txt curl -fsS -o c:\php\%PHP_VERSION%\ext\php_xdebug-%XDEBUG_VERSION%-vc14.dll https://xdebug.org/files/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 diff --git a/.phpunit/phpunit-7/build.xml b/.phpunit/phpunit-7/build.xml new file mode 100644 index 0000000..4e9635b --- /dev/null +++ b/.phpunit/phpunit-7/build.xml @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.phpunit/phpunit-7/composer.json b/.phpunit/phpunit-7/composer.json new file mode 100644 index 0000000..1719696 --- /dev/null +++ b/.phpunit/phpunit-7/composer.json @@ -0,0 +1,97 @@ +{ + "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.1", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "doctrine/instantiator": "^1.1", + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.0", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1", + "symfony/phpunit-bridge": "*@dev" + }, + "require-dev": { + "ext-PDO": "*" + }, + "conflict": { + "phpunit/phpunit-mock-objects": "*" + }, + "config": { + "platform": { + "php": "7.1.0" + }, + "optimize-autoloader": true, + "sort-packages": true + }, + "suggest": { + "phpunit/php-invoker": "^2.0", + "ext-soap": "*", + "ext-xdebug": "*" + }, + "bin": [ + "phpunit" + ], + "autoload": { + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "classmap": [ + "tests/" + ], + "files": [ + "src/Framework/Assert/Functions.php", + "tests/_files/CoverageNamespacedFunctionTest.php", + "tests/_files/CoveredFunction.php", + "tests/_files/NamespaceCoveredFunction.php" + ] + }, + "extra": { + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "repositories": { + "phpunit-bridge": { + "type": "path", + "url": "/home/maximilian/OpenSource/Cmf/maintained/resource/vendor/symfony/phpunit-bridge" + } + } +} diff --git a/.phpunit/phpunit-7/phive.xml b/.phpunit/phpunit-7/phive.xml new file mode 100644 index 0000000..7d4641c --- /dev/null +++ b/.phpunit/phpunit-7/phive.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.phpunit/phpunit-7/phpunit b/.phpunit/phpunit-7/phpunit new file mode 100755 index 0000000..34f3773 --- /dev/null +++ b/.phpunit/phpunit-7/phpunit @@ -0,0 +1,17 @@ + + + + + tests/unit + + + + tests/end-to-end + tests/end-to-end/_files + + + + + + src + + src/Framework/Assert/Functions.php + src/Util/PHP/eval-stdin.php + + + + + + + + diff --git a/.phpunit/phpunit-7/phpunit.xsd b/.phpunit/phpunit-7/phpunit.xsd new file mode 100644 index 0000000..07bd13a --- /dev/null +++ b/.phpunit/phpunit-7/phpunit.xsd @@ -0,0 +1,307 @@ + + + + + This Schema file defines the rules by which the XML configuration file of PHPUnit 7.5 may be structured. + + + + + + Root Element + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The main type specifying the document structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.phpunit/phpunit-7/src/Exception.php b/.phpunit/phpunit-7/src/Exception.php new file mode 100644 index 0000000..055c5b5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Exception.php @@ -0,0 +1,17 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/Assert.php b/.phpunit/phpunit-7/src/Framework/Assert.php new file mode 100644 index 0000000..d24c06a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Assert.php @@ -0,0 +1,2891 @@ + + * + * 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 Traversable; + +/** + * A set of assertion methods. + */ +abstract class Assert +{ + /** + * @var int + */ + private static $count = 0; + + /** + * Asserts that an array has a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertArrayHasKey($key, $array, string $message = ''): void + { + 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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3494 + */ + public static function assertArraySubset($subset, $array, bool $checkForObjectIdentity = false, string $message = ''): void + { + 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, $checkForObjectIdentity); + + static::assertThat($array, $constraint, $message); + } + + /** + * Asserts that an array does not have a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertArrayNotHasKey($key, $array, string $message = ''): void + { + 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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertContains($needle, $haystack, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void + { + 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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeContains($needle, string $haystackAttributeName, $haystackClassOrObject, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void + { + static::assertContains( + $needle, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message, + $ignoreCase, + $checkForObjectIdentity, + $checkForNonObjectIdentity + ); + } + + /** + * Asserts that a haystack does not contain a needle. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotContains($needle, $haystack, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void + { + 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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotContains($needle, string $haystackAttributeName, $haystackClassOrObject, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void + { + static::assertNotContains( + $needle, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message, + $ignoreCase, + $checkForObjectIdentity, + $checkForNonObjectIdentity + ); + } + + /** + * Asserts that a haystack contains only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = Type::isType($type); + } + + static::assertThat( + $haystack, + new TraversableContainsOnly( + $type, + $isNativeType + ), + $message + ); + } + + /** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void + { + 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 object|string $haystackClassOrObject + * @param bool $isNativeType + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeContainsOnly(string $type, string $haystackAttributeName, $haystackClassOrObject, ?bool $isNativeType = null, string $message = ''): void + { + static::assertContainsOnly( + $type, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $isNativeType, + $message + ); + } + + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void + { + if ($isNativeType === null) { + $isNativeType = Type::isType($type); + } + + static::assertThat( + $haystack, + new LogicalNot( + new TraversableContainsOnly( + $type, + $isNativeType + ) + ), + $message + ); + } + + /** + * Asserts 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 object|string $haystackClassOrObject + * @param bool $isNativeType + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotContainsOnly(string $type, string $haystackAttributeName, $haystackClassOrObject, ?bool $isNativeType = null, string $message = ''): void + { + static::assertNotContainsOnly( + $type, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $isNativeType, + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertCount(int $expectedCount, $haystack, string $message = ''): void + { + if (!$haystack instanceof Countable && !\is_iterable($haystack)) { + throw InvalidArgumentHelper::factory(2, 'countable or iterable'); + } + + 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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeCount(int $expectedCount, string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void + { + static::assertCount( + $expectedCount, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotCount(int $expectedCount, $haystack, string $message = ''): void + { + if (!$haystack instanceof Countable && !\is_iterable($haystack)) { + throw InvalidArgumentHelper::factory(2, 'countable or iterable'); + } + + $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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotCount(int $expectedCount, string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void + { + static::assertNotCount( + $expectedCount, + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that two variables are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEquals($expected, $actual, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void + { + $constraint = new IsEqual( + $expected, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + $constraint = new IsEqual( + $expected, + 0.0, + 10, + true, + false + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + $constraint = new IsEqual( + $expected, + 0.0, + 10, + false, + true + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are equal (with delta). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + $constraint = new IsEqual( + $expected, + $delta + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that a variable is equal to an attribute of an object. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeEquals($expected, string $actualAttributeName, $actualClassOrObject, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void + { + static::assertEquals( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that two variables are not equal. + * + * @param float $delta + * @param int $maxDepth + * @param bool $canonicalize + * @param bool $ignoreCase + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotEquals($expected, $actual, string $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false): void + { + $constraint = new LogicalNot( + new IsEqual( + $expected, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (canonicalizing). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotEqualsCanonicalizing($expected, $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqual( + $expected, + 0.0, + 10, + true, + false + ) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (ignoring case). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotEqualsIgnoringCase($expected, $actual, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqual( + $expected, + 0.0, + 10, + false, + true + ) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that two variables are not equal (with delta). + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotEqualsWithDelta($expected, $actual, float $delta, string $message = ''): void + { + $constraint = new LogicalNot( + new IsEqual( + $expected, + $delta + ) + ); + + static::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that a variable is not equal to an attribute of an object. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotEquals($expected, string $actualAttributeName, $actualClassOrObject, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void + { + static::assertNotEquals( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that a variable is empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEmpty($actual, string $message = ''): void + { + static::assertThat($actual, static::isEmpty(), $message); + } + + /** + * Asserts that a static attribute of a class or an attribute of an object + * is empty. + * + * @param object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void + { + static::assertEmpty( + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that a variable is not empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotEmpty($actual, string $message = ''): void + { + 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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void + { + static::assertNotEmpty( + static::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that a value is greater than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertGreaterThan($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::greaterThan($expected), $message); + } + + /** + * Asserts that an attribute is greater than another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeGreaterThan($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + static::assertGreaterThan( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is greater than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + static::greaterThanOrEqual($expected), + $message + ); + } + + /** + * Asserts that an attribute is greater than or equal to another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeGreaterThanOrEqual($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + static::assertGreaterThanOrEqual( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is smaller than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertLessThan($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThan($expected), $message); + } + + /** + * Asserts that an attribute is smaller than another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeLessThan($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + static::assertLessThan( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is smaller than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertLessThanOrEqual($expected, $actual, string $message = ''): void + { + static::assertThat($actual, static::lessThanOrEqual($expected), $message); + } + + /** + * Asserts that an attribute is smaller than or equal to another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeLessThanOrEqual($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + static::assertLessThanOrEqual( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileEquals(string $expected, string $actual, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void + { + 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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileNotEquals(string $expected, string $actual, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void + { + 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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void + { + static::assertFileExists($expectedFile, $message); + + /** @noinspection PhpUnitTestsInspection */ + 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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void + { + static::assertFileExists($expectedFile, $message); + + static::assertNotEquals( + \file_get_contents($expectedFile), + $actualString, + $message, + 0, + 10, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that a file/dir is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertIsReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsReadable, $message); + } + + /** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotIsReadable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsReadable), $message); + } + + /** + * Asserts that a file/dir exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertIsWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new IsWritable, $message); + } + + /** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotIsWritable(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new IsWritable), $message); + } + + /** + * Asserts that a directory exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryExists(string $directory, string $message = ''): void + { + static::assertThat($directory, new DirectoryExists, $message); + } + + /** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryNotExists(string $directory, string $message = ''): void + { + static::assertThat($directory, new LogicalNot(new DirectoryExists), $message); + } + + /** + * Asserts that a directory exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryIsReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryNotIsReadable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertNotIsReadable($directory, $message); + } + + /** + * Asserts that a directory exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryIsWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertIsWritable($directory, $message); + } + + /** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertDirectoryNotIsWritable(string $directory, string $message = ''): void + { + self::assertDirectoryExists($directory, $message); + self::assertNotIsWritable($directory, $message); + } + + /** + * Asserts that a file exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileExists(string $filename, string $message = ''): void + { + static::assertThat($filename, new FileExists, $message); + } + + /** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileNotExists(string $filename, string $message = ''): void + { + static::assertThat($filename, new LogicalNot(new FileExists), $message); + } + + /** + * Asserts that a file exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileIsReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsReadable($file, $message); + } + + /** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileNotIsReadable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertNotIsReadable($file, $message); + } + + /** + * Asserts that a file exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileIsWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertIsWritable($file, $message); + } + + /** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFileNotIsWritable(string $file, string $message = ''): void + { + self::assertFileExists($file, $message); + self::assertNotIsWritable($file, $message); + } + + /** + * Asserts that a condition is true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertTrue($condition, string $message = ''): void + { + static::assertThat($condition, static::isTrue(), $message); + } + + /** + * Asserts that a condition is not true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotTrue($condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isTrue()), $message); + } + + /** + * Asserts that a condition is false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFalse($condition, string $message = ''): void + { + static::assertThat($condition, static::isFalse(), $message); + } + + /** + * Asserts that a condition is not false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotFalse($condition, string $message = ''): void + { + static::assertThat($condition, static::logicalNot(static::isFalse()), $message); + } + + /** + * Asserts that a variable is null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNull($actual, string $message = ''): void + { + static::assertThat($actual, static::isNull(), $message); + } + + /** + * Asserts that a variable is not null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotNull($actual, string $message = ''): void + { + static::assertThat($actual, static::logicalNot(static::isNull()), $message); + } + + /** + * Asserts that a variable is finite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertFinite($actual, string $message = ''): void + { + static::assertThat($actual, static::isFinite(), $message); + } + + /** + * Asserts that a variable is infinite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertInfinite($actual, string $message = ''): void + { + static::assertThat($actual, static::isInfinite(), $message); + } + + /** + * Asserts that a variable is nan. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNan($actual, string $message = ''): void + { + static::assertThat($actual, static::isNan(), $message); + } + + /** + * Asserts that a class has a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\class_exists($className)) { + throw InvalidArgumentHelper::factory(2, 'class name', $className); + } + + static::assertThat($className, new ClassHasAttribute($attributeName), $message); + } + + /** + * Asserts that a class does not have a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\class_exists($className)) { + throw InvalidArgumentHelper::factory(2, 'class name', $className); + } + + static::assertThat( + $className, + new LogicalNot( + new ClassHasAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that a class has a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\class_exists($className)) { + throw InvalidArgumentHelper::factory(2, 'class name', $className); + } + + static::assertThat( + $className, + new ClassHasStaticAttribute($attributeName), + $message + ); + } + + /** + * Asserts that a class does not have a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\class_exists($className)) { + throw InvalidArgumentHelper::factory(2, 'class name', $className); + } + + static::assertThat( + $className, + new LogicalNot( + new ClassHasStaticAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that an object has a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\is_object($object)) { + throw InvalidArgumentHelper::factory(2, 'object'); + } + + static::assertThat( + $object, + new ObjectHasAttribute($attributeName), + $message + ); + } + + /** + * Asserts that an object does not have a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void + { + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!\is_object($object)) { + throw InvalidArgumentHelper::factory(2, 'object'); + } + + static::assertThat( + $object, + new LogicalNot( + new ObjectHasAttribute($attributeName) + ), + $message + ); + } + + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertSame($expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsIdentical($expected), + $message + ); + } + + /** + * Asserts that a variable and an attribute of an object have the same type + * and value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeSame($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + 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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotSame($expected, $actual, string $message = ''): void + { + if (\is_bool($expected) && \is_bool($actual)) { + static::assertNotEquals($expected, $actual, $message); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsIdentical($expected) + ), + $message + ); + } + + /** + * Asserts that a variable and an attribute of an object do not have the + * same type and value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotSame($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void + { + static::assertNotSame( + $expected, + static::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertInstanceOf(string $expected, $actual, string $message = ''): void + { + if (!\class_exists($expected) && !\interface_exists($expected)) { + throw InvalidArgumentHelper::factory(1, 'class or interface name'); + } + + static::assertThat( + $actual, + new IsInstanceOf($expected), + $message + ); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeInstanceOf(string $expected, string $attributeName, $classOrObject, string $message = ''): void + { + static::assertInstanceOf( + $expected, + static::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotInstanceOf(string $expected, $actual, string $message = ''): void + { + if (!\class_exists($expected) && !\interface_exists($expected)) { + throw InvalidArgumentHelper::factory(1, 'class or interface name'); + } + + static::assertThat( + $actual, + new LogicalNot( + new IsInstanceOf($expected) + ), + $message + ); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotInstanceOf(string $expected, string $attributeName, $classOrObject, string $message = ''): void + { + static::assertNotInstanceOf( + $expected, + static::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3369 + */ + public static function assertInternalType(string $expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType($expected), + $message + ); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeInternalType(string $expected, string $attributeName, $classOrObject, string $message = ''): void + { + static::assertInternalType( + $expected, + static::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is of type array. + */ + public static function assertIsArray($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ARRAY), + $message + ); + } + + /** + * Asserts that a variable is of type bool. + */ + public static function assertIsBool($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_BOOL), + $message + ); + } + + /** + * Asserts that a variable is of type float. + */ + public static function assertIsFloat($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_FLOAT), + $message + ); + } + + /** + * Asserts that a variable is of type int. + */ + public static function assertIsInt($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_INT), + $message + ); + } + + /** + * Asserts that a variable is of type numeric. + */ + public static function assertIsNumeric($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_NUMERIC), + $message + ); + } + + /** + * Asserts that a variable is of type object. + */ + public static function assertIsObject($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_OBJECT), + $message + ); + } + + /** + * Asserts that a variable is of type resource. + */ + public static function assertIsResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_RESOURCE), + $message + ); + } + + /** + * Asserts that a variable is of type string. + */ + public static function assertIsString($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_STRING), + $message + ); + } + + /** + * Asserts that a variable is of type scalar. + */ + public static function assertIsScalar($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_SCALAR), + $message + ); + } + + /** + * Asserts that a variable is of type callable. + */ + public static function assertIsCallable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_CALLABLE), + $message + ); + } + + /** + * Asserts that a variable is of type iterable. + */ + public static function assertIsIterable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new IsType(IsType::TYPE_ITERABLE), + $message + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3369 + */ + public static function assertNotInternalType(string $expected, $actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot( + new IsType($expected) + ), + $message + ); + } + + /** + * Asserts that a variable is not of type array. + */ + public static function assertIsNotArray($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ARRAY)), + $message + ); + } + + /** + * Asserts that a variable is not of type bool. + */ + public static function assertIsNotBool($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_BOOL)), + $message + ); + } + + /** + * Asserts that a variable is not of type float. + */ + public static function assertIsNotFloat($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_FLOAT)), + $message + ); + } + + /** + * Asserts that a variable is not of type int. + */ + public static function assertIsNotInt($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_INT)), + $message + ); + } + + /** + * Asserts that a variable is not of type numeric. + */ + public static function assertIsNotNumeric($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_NUMERIC)), + $message + ); + } + + /** + * Asserts that a variable is not of type object. + */ + public static function assertIsNotObject($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_OBJECT)), + $message + ); + } + + /** + * Asserts that a variable is not of type resource. + */ + public static function assertIsNotResource($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_RESOURCE)), + $message + ); + } + + /** + * Asserts that a variable is not of type string. + */ + public static function assertIsNotString($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_STRING)), + $message + ); + } + + /** + * Asserts that a variable is not of type scalar. + */ + public static function assertIsNotScalar($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_SCALAR)), + $message + ); + } + + /** + * Asserts that a variable is not of type callable. + */ + public static function assertIsNotCallable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_CALLABLE)), + $message + ); + } + + /** + * Asserts that a variable is not of type iterable. + */ + public static function assertIsNotIterable($actual, string $message = ''): void + { + static::assertThat( + $actual, + new LogicalNot(new IsType(IsType::TYPE_ITERABLE)), + $message + ); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function assertAttributeNotInternalType(string $expected, string $attributeName, $classOrObject, string $message = ''): void + { + static::assertNotInternalType( + $expected, + static::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertRegExp(string $pattern, string $string, string $message = ''): void + { + static::assertThat($string, new RegularExpression($pattern), $message); + } + + /** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotRegExp(string $pattern, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new RegularExpression($pattern) + ), + $message + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertSameSize($expected, $actual, string $message = ''): void + { + if (!$expected instanceof Countable && !\is_iterable($expected)) { + throw InvalidArgumentHelper::factory(1, 'countable or iterable'); + } + + if (!$actual instanceof Countable && !\is_iterable($actual)) { + throw InvalidArgumentHelper::factory(2, 'countable or iterable'); + } + + static::assertThat( + $actual, + new SameSize($expected), + $message + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertNotSameSize($expected, $actual, string $message = ''): void + { + if (!$expected instanceof Countable && !\is_iterable($expected)) { + throw InvalidArgumentHelper::factory(1, 'countable or iterable'); + } + + if (!$actual instanceof Countable && !\is_iterable($actual)) { + throw InvalidArgumentHelper::factory(2, 'countable or iterable'); + } + + static::assertThat( + $actual, + new LogicalNot( + new SameSize($expected) + ), + $message + ); + } + + /** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat($string, new StringMatchesFormatDescription($format), $message); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription($format) + ), + $message + ); + } + + /** + * Asserts that a string matches a given format file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new StringMatchesFormatDescription( + \file_get_contents($formatFile) + ), + $message + ); + } + + /** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void + { + static::assertFileExists($formatFile, $message); + + static::assertThat( + $string, + new LogicalNot( + new StringMatchesFormatDescription( + \file_get_contents($formatFile) + ) + ), + $message + ); + } + + /** + * Asserts that a string starts with a given prefix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringStartsWith(string $prefix, string $string, string $message = ''): void + { + static::assertThat($string, new StringStartsWith($prefix), $message); + } + + /** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringStartsNotWith($prefix, $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringStartsWith($prefix) + ), + $message + ); + } + + public static function assertStringContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle, false); + + static::assertThat($haystack, $constraint, $message); + } + + public static function assertStringContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new StringContains($needle, true); + + static::assertThat($haystack, $constraint, $message); + } + + public static function assertStringNotContainsString(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle)); + + static::assertThat($haystack, $constraint, $message); + } + + public static function assertStringNotContainsStringIgnoringCase(string $needle, string $haystack, string $message = ''): void + { + $constraint = new LogicalNot(new StringContains($needle, true)); + + static::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a string ends with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringEndsWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat($string, new StringEndsWith($suffix), $message); + } + + /** + * Asserts that a string ends not with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void + { + static::assertThat( + $string, + new LogicalNot( + new StringEndsWith($suffix) + ), + $message + ); + } + + /** + * Asserts that two XML files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = Xml::loadFile($expectedFile); + $actual = Xml::loadFile($actualFile); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void + { + $expected = Xml::loadFile($expectedFile); + $actual = Xml::loadFile($actualFile); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + $expected = Xml::loadFile($expectedFile); + $actual = Xml::load($actualXml); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + { + $expected = Xml::loadFile($expectedFile); + $actual = Xml::load($actualXml); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + $expected = Xml::load($expectedXml); + $actual = Xml::load($actualXml); + + static::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + { + $expected = Xml::load($expectedXml); + $actual = Xml::load($actualXml); + + static::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that a hierarchy of DOMElements matches. + * + * @throws AssertionFailedError + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void + { + $expectedElement = Xml::import($expectedElement); + $actualElement = Xml::import($actualElement); + + static::assertSame( + $expectedElement->tagName, + $actualElement->tagName, + $message + ); + + if ($checkAttributes) { + static::assertSame( + $expectedElement->attributes->length, + $actualElement->attributes->length, + \sprintf( + '%s%sNumber of attributes on node "%s" does not match', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0; $i < $expectedElement->attributes->length; $i++) { + /** @var \DOMAttr $expectedAttribute */ + $expectedAttribute = $expectedElement->attributes->item($i); + + /** @var \DOMAttr $actualAttribute */ + $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::assertSame( + $expectedElement->childNodes->length, + $actualElement->childNodes->length, + \sprintf( + '%s%sNumber of child nodes of "%s" differs', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0; $i < $expectedElement->childNodes->length; $i++) { + static::assertEqualXMLStructure( + $expectedElement->childNodes->item($i), + $actualElement->childNodes->item($i), + $checkAttributes, + $message + ); + } + } + + /** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertThat($value, Constraint $constraint, string $message = ''): void + { + self::$count += \count($constraint); + + $constraint->evaluate($value, $message); + } + + /** + * Asserts that a string is a valid JSON string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJson(string $actualJson, string $message = ''): void + { + static::assertThat($actualJson, static::isJson(), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void + { + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson) + ), + $message + ); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = \file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat($actualJson, new JsonMatches($expectedJson), $message); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + $expectedJson = \file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + static::assertThat( + $actualJson, + new LogicalNot( + new JsonMatches($expectedJson) + ), + $message + ); + } + + /** + * Asserts that two JSON files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = \file_get_contents($actualFile); + $expectedJson = \file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, $constraintActual, $message); + static::assertThat($actualJson, $constraintExpected, $message); + } + + /** + * Asserts that two JSON files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public static function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void + { + static::assertFileExists($expectedFile, $message); + static::assertFileExists($actualFile, $message); + + $actualJson = \file_get_contents($actualFile); + $expectedJson = \file_get_contents($expectedFile); + + static::assertJson($expectedJson, $message); + static::assertJson($actualJson, $message); + + $constraintExpected = new JsonMatches( + $expectedJson + ); + + $constraintActual = new JsonMatches($actualJson); + + static::assertThat($expectedJson, new LogicalNot($constraintActual), $message); + static::assertThat($actualJson, new LogicalNot($constraintExpected), $message); + } + + public static function logicalAnd(): LogicalAnd + { + $constraints = \func_get_args(); + + $constraint = new LogicalAnd; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function logicalOr(): LogicalOr + { + $constraints = \func_get_args(); + + $constraint = new LogicalOr; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function logicalNot(Constraint $constraint): LogicalNot + { + return new LogicalNot($constraint); + } + + public static function logicalXor(): LogicalXor + { + $constraints = \func_get_args(); + + $constraint = new LogicalXor; + $constraint->setConstraints($constraints); + + return $constraint; + } + + public static function anything(): IsAnything + { + return new IsAnything; + } + + public static function isTrue(): IsTrue + { + return new IsTrue; + } + + public static function callback(callable $callback): Callback + { + return new Callback($callback); + } + + public static function isFalse(): IsFalse + { + return new IsFalse; + } + + public static function isJson(): IsJson + { + return new IsJson; + } + + public static function isNull(): IsNull + { + return new IsNull; + } + + public static function isFinite(): IsFinite + { + return new IsFinite; + } + + public static function isInfinite(): IsInfinite + { + return new IsInfinite; + } + + public static function isNan(): IsNan + { + return new IsNan; + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function attribute(Constraint $constraint, string $attributeName): Attribute + { + return new Attribute($constraint, $attributeName); + } + + public static function contains($value, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): TraversableContains + { + return new TraversableContains($value, $checkForObjectIdentity, $checkForNonObjectIdentity); + } + + public static function containsOnly(string $type): TraversableContainsOnly + { + return new TraversableContainsOnly($type); + } + + public static function containsOnlyInstancesOf(string $className): TraversableContainsOnly + { + return new TraversableContainsOnly($className, false); + } + + /** + * @param int|string $key + */ + public static function arrayHasKey($key): ArrayHasKey + { + return new ArrayHasKey($key); + } + + public static function equalTo($value, float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): IsEqual + { + return new IsEqual($value, $delta, $maxDepth, $canonicalize, $ignoreCase); + } + + /** + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function attributeEqualTo(string $attributeName, $value, float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): Attribute + { + return static::attribute( + static::equalTo( + $value, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ), + $attributeName + ); + } + + public static function isEmpty(): IsEmpty + { + return new IsEmpty; + } + + public static function isWritable(): IsWritable + { + return new IsWritable; + } + + public static function isReadable(): IsReadable + { + return new IsReadable; + } + + public static function directoryExists(): DirectoryExists + { + return new DirectoryExists; + } + + public static function fileExists(): FileExists + { + return new FileExists; + } + + public static function greaterThan($value): GreaterThan + { + return new GreaterThan($value); + } + + public static function greaterThanOrEqual($value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new GreaterThan($value) + ); + } + + public static function classHasAttribute(string $attributeName): ClassHasAttribute + { + return new ClassHasAttribute($attributeName); + } + + public static function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute + { + return new ClassHasStaticAttribute($attributeName); + } + + public static function objectHasAttribute($attributeName): ObjectHasAttribute + { + return new ObjectHasAttribute($attributeName); + } + + public static function identicalTo($value): IsIdentical + { + return new IsIdentical($value); + } + + public static function isInstanceOf(string $className): IsInstanceOf + { + return new IsInstanceOf($className); + } + + public static function isType(string $type): IsType + { + return new IsType($type); + } + + public static function lessThan($value): LessThan + { + return new LessThan($value); + } + + public static function lessThanOrEqual($value): LogicalOr + { + return static::logicalOr( + new IsEqual($value), + new LessThan($value) + ); + } + + public static function matchesRegularExpression(string $pattern): RegularExpression + { + return new RegularExpression($pattern); + } + + public static function matches(string $string): StringMatchesFormatDescription + { + return new StringMatchesFormatDescription($string); + } + + public static function stringStartsWith($prefix): StringStartsWith + { + return new StringStartsWith($prefix); + } + + public static function stringContains(string $string, bool $case = true): StringContains + { + return new StringContains($string, $case); + } + + public static function stringEndsWith(string $suffix): StringEndsWith + { + return new StringEndsWith($suffix); + } + + public static function countOf(int $count): Count + { + return new Count($count); + } + + /** + * Fails a test with the given message. + * + * @throws AssertionFailedError + */ + public static function fail(string $message = ''): void + { + 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 object|string $classOrObject + * + * @throws Exception + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function readAttribute($classOrObject, string $attributeName) + { + if (!self::isValidAttributeName($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. + * + * @throws Exception + * @throws ReflectionException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function getStaticAttribute(string $className, string $attributeName) + { + if (!\class_exists($className)) { + throw InvalidArgumentHelper::factory(1, 'class name'); + } + + if (!self::isValidAttributeName($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 + * + * @throws Exception + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338 + */ + public static function getObjectAttribute($object, string $attributeName) + { + if (!\is_object($object)) { + throw InvalidArgumentHelper::factory(1, 'object'); + } + + if (!self::isValidAttributeName($attributeName)) { + throw InvalidArgumentHelper::factory(2, 'valid attribute name'); + } + + try { + $reflector = new ReflectionObject($object); + + do { + try { + $attribute = $reflector->getProperty($attributeName); + + if (!$attribute || $attribute->isPublic()) { + return $object->$attributeName; + } + + $attribute->setAccessible(true); + $value = $attribute->getValue($object); + $attribute->setAccessible(false); + + return $value; + } catch (ReflectionException $e) { + } + } while ($reflector = $reflector->getParentClass()); + } catch (ReflectionException $e) { + } + + throw new Exception( + \sprintf( + 'Attribute "%s" not found in object.', + $attributeName + ) + ); + } + + /** + * Mark the test as incomplete. + * + * @throws IncompleteTestError + */ + public static function markTestIncomplete(string $message = ''): void + { + throw new IncompleteTestError($message); + } + + /** + * Mark the test as skipped. + * + * @throws SkippedTestError + */ + public static function markTestSkipped(string $message = ''): void + { + throw new SkippedTestError($message); + } + + /** + * Return the current assertion count. + */ + public static function getCount(): int + { + return self::$count; + } + + /** + * Reset the assertion counter. + */ + public static function resetCount(): void + { + self::$count = 0; + } + + private static function isValidAttributeName(string $attributeName): bool + { + return \preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName); + } + + private static function createWarning(string $warning): void + { + foreach (\debug_backtrace() as $step) { + if (isset($step['object']) && $step['object'] instanceof TestCase) { + $step['object']->addWarning($warning); + + break; + } + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Assert/Functions.php b/.phpunit/phpunit-7/src/Framework/Assert/Functions.php new file mode 100644 index 0000000..ba6f79f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Assert/Functions.php @@ -0,0 +1,1668 @@ + + * + * 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\Constraint\ArrayHasKey; +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\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\ExpectationFailedException; +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\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; + +/** + * Asserts that an array has a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertArrayHasKey($key, $array, string $message = ''): void +{ + Assert::assertArrayHasKey(...\func_get_args()); +} + +/** + * Asserts that an array has a specified subset. + * + * @param array|ArrayAccess $subset + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3494 + */ +function assertArraySubset($subset, $array, bool $checkForObjectIdentity = false, string $message = ''): void +{ + Assert::assertArraySubset(...\func_get_args()); +} + +/** + * Asserts that an array does not have a specified key. + * + * @param int|string $key + * @param array|ArrayAccess $array + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertArrayNotHasKey($key, $array, string $message = ''): void +{ + Assert::assertArrayNotHasKey(...\func_get_args()); +} + +/** + * Asserts that a haystack contains a needle. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertContains($needle, $haystack, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void +{ + Assert::assertContains(...\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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeContains($needle, string $haystackAttributeName, $haystackClassOrObject, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void +{ + Assert::assertAttributeContains(...\func_get_args()); +} + +/** + * Asserts that a haystack does not contain a needle. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotContains($needle, $haystack, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void +{ + Assert::assertNotContains(...\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 object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotContains($needle, string $haystackAttributeName, $haystackClassOrObject, string $message = '', bool $ignoreCase = false, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): void +{ + Assert::assertAttributeNotContains(...\func_get_args()); +} + +/** + * Asserts that a haystack contains only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void +{ + Assert::assertContainsOnly(...\func_get_args()); +} + +/** + * Asserts that a haystack contains only instances of a given class name. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void +{ + Assert::assertContainsOnlyInstancesOf(...\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 object|string $haystackClassOrObject + * @param bool $isNativeType + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeContainsOnly(string $type, string $haystackAttributeName, $haystackClassOrObject, ?bool $isNativeType = null, string $message = ''): void +{ + Assert::assertAttributeContainsOnly(...\func_get_args()); +} + +/** + * Asserts that a haystack does not contain only values of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void +{ + Assert::assertNotContainsOnly(...\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 object|string $haystackClassOrObject + * @param bool $isNativeType + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotContainsOnly(string $type, string $haystackAttributeName, $haystackClassOrObject, ?bool $isNativeType = null, string $message = ''): void +{ + Assert::assertAttributeNotContainsOnly(...\func_get_args()); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertCount(int $expectedCount, $haystack, string $message = ''): void +{ + Assert::assertCount(...\func_get_args()); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeCount(int $expectedCount, string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void +{ + Assert::assertAttributeCount(...\func_get_args()); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param Countable|iterable $haystack + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotCount(int $expectedCount, $haystack, string $message = ''): void +{ + Assert::assertNotCount(...\func_get_args()); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotCount(int $expectedCount, string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void +{ + Assert::assertAttributeNotCount(...\func_get_args()); +} + +/** + * Asserts that two variables are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertEquals($expected, $actual, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertEquals(...\func_get_args()); +} + +/** + * Asserts that a variable is equal to an attribute of an object. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeEquals($expected, string $actualAttributeName, $actualClassOrObject, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertAttributeEquals(...\func_get_args()); +} + +/** + * Asserts that two variables are not equal. + * + * @param float $delta + * @param int $maxDepth + * @param bool $canonicalize + * @param bool $ignoreCase + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotEquals($expected, $actual, string $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false): void +{ + Assert::assertNotEquals(...\func_get_args()); +} + +/** + * Asserts that a variable is not equal to an attribute of an object. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotEquals($expected, string $actualAttributeName, $actualClassOrObject, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertAttributeNotEquals(...\func_get_args()); +} + +/** + * Asserts that a variable is empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertEmpty($actual, string $message = ''): void +{ + Assert::assertEmpty(...\func_get_args()); +} + +/** + * Asserts that a static attribute of a class or an attribute of an object + * is empty. + * + * @param object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void +{ + Assert::assertAttributeEmpty(...\func_get_args()); +} + +/** + * Asserts that a variable is not empty. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotEmpty($actual, string $message = ''): void +{ + Assert::assertNotEmpty(...\func_get_args()); +} + +/** + * Asserts that a static attribute of a class or an attribute of an object + * is not empty. + * + * @param object|string $haystackClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void +{ + Assert::assertAttributeNotEmpty(...\func_get_args()); +} + +/** + * Asserts that a value is greater than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertGreaterThan($expected, $actual, string $message = ''): void +{ + Assert::assertGreaterThan(...\func_get_args()); +} + +/** + * Asserts that an attribute is greater than another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeGreaterThan($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeGreaterThan(...\func_get_args()); +} + +/** + * Asserts that a value is greater than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertGreaterThanOrEqual($expected, $actual, string $message = ''): void +{ + Assert::assertGreaterThanOrEqual(...\func_get_args()); +} + +/** + * Asserts that an attribute is greater than or equal to another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeGreaterThanOrEqual($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeGreaterThanOrEqual(...\func_get_args()); +} + +/** + * Asserts that a value is smaller than another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertLessThan($expected, $actual, string $message = ''): void +{ + Assert::assertLessThan(...\func_get_args()); +} + +/** + * Asserts that an attribute is smaller than another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeLessThan($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeLessThan(...\func_get_args()); +} + +/** + * Asserts that a value is smaller than or equal to another value. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertLessThanOrEqual($expected, $actual, string $message = ''): void +{ + Assert::assertLessThanOrEqual(...\func_get_args()); +} + +/** + * Asserts that an attribute is smaller than or equal to another value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeLessThanOrEqual($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeLessThanOrEqual(...\func_get_args()); +} + +/** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileEquals(string $expected, string $actual, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertFileEquals(...\func_get_args()); +} + +/** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileNotEquals(string $expected, string $actual, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertFileNotEquals(...\func_get_args()); +} + +/** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertStringEqualsFile(...\func_get_args()); +} + +/** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = '', bool $canonicalize = false, bool $ignoreCase = false): void +{ + Assert::assertStringNotEqualsFile(...\func_get_args()); +} + +/** + * Asserts that a file/dir is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertIsReadable(string $filename, string $message = ''): void +{ + Assert::assertIsReadable(...\func_get_args()); +} + +/** + * Asserts that a file/dir exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotIsReadable(string $filename, string $message = ''): void +{ + Assert::assertNotIsReadable(...\func_get_args()); +} + +/** + * Asserts that a file/dir exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertIsWritable(string $filename, string $message = ''): void +{ + Assert::assertIsWritable(...\func_get_args()); +} + +/** + * Asserts that a file/dir exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotIsWritable(string $filename, string $message = ''): void +{ + Assert::assertNotIsWritable(...\func_get_args()); +} + +/** + * Asserts that a directory exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryExists(string $directory, string $message = ''): void +{ + Assert::assertDirectoryExists(...\func_get_args()); +} + +/** + * Asserts that a directory does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryNotExists(string $directory, string $message = ''): void +{ + Assert::assertDirectoryNotExists(...\func_get_args()); +} + +/** + * Asserts that a directory exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryIsReadable(string $directory, string $message = ''): void +{ + Assert::assertDirectoryIsReadable(...\func_get_args()); +} + +/** + * Asserts that a directory exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryNotIsReadable(string $directory, string $message = ''): void +{ + Assert::assertDirectoryNotIsReadable(...\func_get_args()); +} + +/** + * Asserts that a directory exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryIsWritable(string $directory, string $message = ''): void +{ + Assert::assertDirectoryIsWritable(...\func_get_args()); +} + +/** + * Asserts that a directory exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertDirectoryNotIsWritable(string $directory, string $message = ''): void +{ + Assert::assertDirectoryNotIsWritable(...\func_get_args()); +} + +/** + * Asserts that a file exists. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileExists(string $filename, string $message = ''): void +{ + Assert::assertFileExists(...\func_get_args()); +} + +/** + * Asserts that a file does not exist. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileNotExists(string $filename, string $message = ''): void +{ + Assert::assertFileNotExists(...\func_get_args()); +} + +/** + * Asserts that a file exists and is readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileIsReadable(string $file, string $message = ''): void +{ + Assert::assertFileIsReadable(...\func_get_args()); +} + +/** + * Asserts that a file exists and is not readable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileNotIsReadable(string $file, string $message = ''): void +{ + Assert::assertFileNotIsReadable(...\func_get_args()); +} + +/** + * Asserts that a file exists and is writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileIsWritable(string $file, string $message = ''): void +{ + Assert::assertFileIsWritable(...\func_get_args()); +} + +/** + * Asserts that a file exists and is not writable. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFileNotIsWritable(string $file, string $message = ''): void +{ + Assert::assertFileNotIsWritable(...\func_get_args()); +} + +/** + * Asserts that a condition is true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertTrue($condition, string $message = ''): void +{ + Assert::assertTrue(...\func_get_args()); +} + +/** + * Asserts that a condition is not true. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotTrue($condition, string $message = ''): void +{ + Assert::assertNotTrue(...\func_get_args()); +} + +/** + * Asserts that a condition is false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFalse($condition, string $message = ''): void +{ + Assert::assertFalse(...\func_get_args()); +} + +/** + * Asserts that a condition is not false. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotFalse($condition, string $message = ''): void +{ + Assert::assertNotFalse(...\func_get_args()); +} + +/** + * Asserts that a variable is null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNull($actual, string $message = ''): void +{ + Assert::assertNull(...\func_get_args()); +} + +/** + * Asserts that a variable is not null. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotNull($actual, string $message = ''): void +{ + Assert::assertNotNull(...\func_get_args()); +} + +/** + * Asserts that a variable is finite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertFinite($actual, string $message = ''): void +{ + Assert::assertFinite(...\func_get_args()); +} + +/** + * Asserts that a variable is infinite. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertInfinite($actual, string $message = ''): void +{ + Assert::assertInfinite(...\func_get_args()); +} + +/** + * Asserts that a variable is nan. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNan($actual, string $message = ''): void +{ + Assert::assertNan(...\func_get_args()); +} + +/** + * Asserts that a class has a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void +{ + Assert::assertClassHasAttribute(...\func_get_args()); +} + +/** + * Asserts that a class does not have a specified attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void +{ + Assert::assertClassNotHasAttribute(...\func_get_args()); +} + +/** + * Asserts that a class has a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void +{ + Assert::assertClassHasStaticAttribute(...\func_get_args()); +} + +/** + * Asserts that a class does not have a specified static attribute. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void +{ + Assert::assertClassNotHasStaticAttribute(...\func_get_args()); +} + +/** + * Asserts that an object has a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void +{ + Assert::assertObjectHasAttribute(...\func_get_args()); +} + +/** + * Asserts that an object does not have a specified attribute. + * + * @param object $object + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void +{ + Assert::assertObjectNotHasAttribute(...\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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertSame($expected, $actual, string $message = ''): void +{ + Assert::assertSame(...\func_get_args()); +} + +/** + * Asserts that a variable and an attribute of an object have the same type + * and value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeSame($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeSame(...\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. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotSame($expected, $actual, string $message = ''): void +{ + Assert::assertNotSame(...\func_get_args()); +} + +/** + * Asserts that a variable and an attribute of an object do not have the + * same type and value. + * + * @param object|string $actualClassOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotSame($expected, string $actualAttributeName, $actualClassOrObject, string $message = ''): void +{ + Assert::assertAttributeNotSame(...\func_get_args()); +} + +/** + * Asserts that a variable is of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertInstanceOf(string $expected, $actual, string $message = ''): void +{ + Assert::assertInstanceOf(...\func_get_args()); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeInstanceOf(string $expected, string $attributeName, $classOrObject, string $message = ''): void +{ + Assert::assertAttributeInstanceOf(...\func_get_args()); +} + +/** + * Asserts that a variable is not of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotInstanceOf(string $expected, $actual, string $message = ''): void +{ + Assert::assertNotInstanceOf(...\func_get_args()); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotInstanceOf(string $expected, string $attributeName, $classOrObject, string $message = ''): void +{ + Assert::assertAttributeNotInstanceOf(...\func_get_args()); +} + +/** + * Asserts that a variable is of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertInternalType(string $expected, $actual, string $message = ''): void +{ + Assert::assertInternalType(...\func_get_args()); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeInternalType(string $expected, string $attributeName, $classOrObject, string $message = ''): void +{ + Assert::assertAttributeInternalType(...\func_get_args()); +} + +/** + * Asserts that a variable is not of a given type. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotInternalType(string $expected, $actual, string $message = ''): void +{ + Assert::assertNotInternalType(...\func_get_args()); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param object|string $classOrObject + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertAttributeNotInternalType(string $expected, string $attributeName, $classOrObject, string $message = ''): void +{ + Assert::assertAttributeNotInternalType(...\func_get_args()); +} + +/** + * Asserts that a string matches a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertRegExp(string $pattern, string $string, string $message = ''): void +{ + Assert::assertRegExp(...\func_get_args()); +} + +/** + * Asserts that a string does not match a given regular expression. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotRegExp(string $pattern, string $string, string $message = ''): void +{ + Assert::assertNotRegExp(...\func_get_args()); +} + +/** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertSameSize($expected, $actual, string $message = ''): void +{ + Assert::assertSameSize(...\func_get_args()); +} + +/** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param Countable|iterable $expected + * @param Countable|iterable $actual + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertNotSameSize($expected, $actual, string $message = ''): void +{ + Assert::assertNotSameSize(...\func_get_args()); +} + +/** + * Asserts that a string matches a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringMatchesFormat(string $format, string $string, string $message = ''): void +{ + Assert::assertStringMatchesFormat(...\func_get_args()); +} + +/** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringNotMatchesFormat(string $format, string $string, string $message = ''): void +{ + Assert::assertStringNotMatchesFormat(...\func_get_args()); +} + +/** + * Asserts that a string matches a given format file. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringMatchesFormatFile(string $formatFile, string $string, string $message = ''): void +{ + Assert::assertStringMatchesFormatFile(...\func_get_args()); +} + +/** + * Asserts that a string does not match a given format string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringNotMatchesFormatFile(string $formatFile, string $string, string $message = ''): void +{ + Assert::assertStringNotMatchesFormatFile(...\func_get_args()); +} + +/** + * Asserts that a string starts with a given prefix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringStartsWith(string $prefix, string $string, string $message = ''): void +{ + Assert::assertStringStartsWith(...\func_get_args()); +} + +/** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringStartsNotWith($prefix, $string, string $message = ''): void +{ + Assert::assertStringStartsNotWith(...\func_get_args()); +} + +/** + * Asserts that a string ends with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringEndsWith(string $suffix, string $string, string $message = ''): void +{ + Assert::assertStringEndsWith(...\func_get_args()); +} + +/** + * Asserts that a string ends not with a given suffix. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertStringEndsNotWith(string $suffix, string $string, string $message = ''): void +{ + Assert::assertStringEndsNotWith(...\func_get_args()); +} + +/** + * Asserts that two XML files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlFileEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void +{ + Assert::assertXmlFileEqualsXmlFile(...\func_get_args()); +} + +/** + * Asserts that two XML files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, string $message = ''): void +{ + Assert::assertXmlFileNotEqualsXmlFile(...\func_get_args()); +} + +/** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void +{ + Assert::assertXmlStringEqualsXmlFile(...\func_get_args()); +} + +/** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void +{ + Assert::assertXmlStringNotEqualsXmlFile(...\func_get_args()); +} + +/** + * Asserts that two XML documents are equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void +{ + Assert::assertXmlStringEqualsXmlString(...\func_get_args()); +} + +/** + * Asserts that two XML documents are not equal. + * + * @param DOMDocument|string $expectedXml + * @param DOMDocument|string $actualXml + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void +{ + Assert::assertXmlStringNotEqualsXmlString(...\func_get_args()); +} + +/** + * Asserts that a hierarchy of DOMElements matches. + * + * @throws AssertionFailedError + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, bool $checkAttributes = false, string $message = ''): void +{ + Assert::assertEqualXMLStructure(...\func_get_args()); +} + +/** + * Evaluates a PHPUnit\Framework\Constraint matcher object. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertThat($value, Constraint $constraint, string $message = ''): void +{ + Assert::assertThat(...\func_get_args()); +} + +/** + * Asserts that a string is a valid JSON string. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJson(string $actualJson, string $message = ''): void +{ + Assert::assertJson(...\func_get_args()); +} + +/** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonStringEqualsJsonString(string $expectedJson, string $actualJson, string $message = ''): void +{ + Assert::assertJsonStringEqualsJsonString(...\func_get_args()); +} + +/** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, string $message = ''): void +{ + Assert::assertJsonStringNotEqualsJsonString(...\func_get_args()); +} + +/** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonStringEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void +{ + Assert::assertJsonStringEqualsJsonFile(...\func_get_args()); +} + +/** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonStringNotEqualsJsonFile(string $expectedFile, string $actualJson, string $message = ''): void +{ + Assert::assertJsonStringNotEqualsJsonFile(...\func_get_args()); +} + +/** + * Asserts that two JSON files are equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonFileEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void +{ + Assert::assertJsonFileEqualsJsonFile(...\func_get_args()); +} + +/** + * Asserts that two JSON files are not equal. + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ +function assertJsonFileNotEqualsJsonFile(string $expectedFile, string $actualFile, string $message = ''): void +{ + Assert::assertJsonFileNotEqualsJsonFile(...\func_get_args()); +} + +function logicalAnd(): LogicalAnd +{ + return Assert::logicalAnd(...\func_get_args()); +} + +function logicalOr(): LogicalOr +{ + return Assert::logicalOr(...\func_get_args()); +} + +function logicalNot(Constraint $constraint): LogicalNot +{ + return Assert::logicalNot(...\func_get_args()); +} + +function logicalXor(): LogicalXor +{ + return Assert::logicalXor(...\func_get_args()); +} + +function anything(): IsAnything +{ + return Assert::anything(); +} + +function isTrue(): IsTrue +{ + return Assert::isTrue(); +} + +function callback(callable $callback): Callback +{ + return Assert::callback(...\func_get_args()); +} + +function isFalse(): IsFalse +{ + return Assert::isFalse(); +} + +function isJson(): IsJson +{ + return Assert::isJson(); +} + +function isNull(): IsNull +{ + return Assert::isNull(); +} + +function isFinite(): IsFinite +{ + return Assert::isFinite(); +} + +function isInfinite(): IsInfinite +{ + return Assert::isInfinite(); +} + +function isNan(): IsNan +{ + return Assert::isNan(); +} + +function attribute(Constraint $constraint, string $attributeName): Attribute +{ + return Assert::attribute(...\func_get_args()); +} + +function contains($value, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false): TraversableContains +{ + return Assert::contains(...\func_get_args()); +} + +function containsOnly(string $type): TraversableContainsOnly +{ + return Assert::containsOnly(...\func_get_args()); +} + +function containsOnlyInstancesOf(string $className): TraversableContainsOnly +{ + return Assert::containsOnlyInstancesOf(...\func_get_args()); +} + +function arrayHasKey($key): ArrayHasKey +{ + return Assert::arrayHasKey(...\func_get_args()); +} + +function equalTo($value, float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): IsEqual +{ + return Assert::equalTo(...\func_get_args()); +} + +function attributeEqualTo(string $attributeName, $value, float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false): Attribute +{ + return Assert::attributeEqualTo(...\func_get_args()); +} + +function isEmpty(): IsEmpty +{ + return Assert::isEmpty(); +} + +function isWritable(): IsWritable +{ + return Assert::isWritable(); +} + +function isReadable(): IsReadable +{ + return Assert::isReadable(); +} + +function directoryExists(): DirectoryExists +{ + return Assert::directoryExists(); +} + +function fileExists(): FileExists +{ + return Assert::fileExists(); +} + +function greaterThan($value): GreaterThan +{ + return Assert::greaterThan(...\func_get_args()); +} + +function greaterThanOrEqual($value): LogicalOr +{ + return Assert::greaterThanOrEqual(...\func_get_args()); +} + +function classHasAttribute(string $attributeName): ClassHasAttribute +{ + return Assert::classHasAttribute(...\func_get_args()); +} + +function classHasStaticAttribute(string $attributeName): ClassHasStaticAttribute +{ + return Assert::classHasStaticAttribute(...\func_get_args()); +} + +function objectHasAttribute($attributeName): ObjectHasAttribute +{ + return Assert::objectHasAttribute(...\func_get_args()); +} + +function identicalTo($value): IsIdentical +{ + return Assert::identicalTo(...\func_get_args()); +} + +function isInstanceOf(string $className): IsInstanceOf +{ + return Assert::isInstanceOf(...\func_get_args()); +} + +function isType(string $type): IsType +{ + return Assert::isType(...\func_get_args()); +} + +function lessThan($value): LessThan +{ + return Assert::lessThan(...\func_get_args()); +} + +function lessThanOrEqual($value): LogicalOr +{ + return Assert::lessThanOrEqual(...\func_get_args()); +} + +function matchesRegularExpression(string $pattern): RegularExpression +{ + return Assert::matchesRegularExpression(...\func_get_args()); +} + +function matches(string $string): StringMatchesFormatDescription +{ + return Assert::matches(...\func_get_args()); +} + +function stringStartsWith($prefix): StringStartsWith +{ + return Assert::stringStartsWith(...\func_get_args()); +} + +function stringContains(string $string, bool $case = true): StringContains +{ + return Assert::stringContains(...\func_get_args()); +} + +function stringEndsWith(string $suffix): StringEndsWith +{ + return Assert::stringEndsWith(...\func_get_args()); +} + +function countOf(int $count): Count +{ + return Assert::countOf(...\func_get_args()); +} + +/** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ +function any(): AnyInvokedCountMatcher +{ + return new AnyInvokedCountMatcher; +} + +/** + * Returns a matcher that matches when the method is never executed. + */ +function never(): InvokedCountMatcher +{ + return new InvokedCountMatcher(0); +} + +/** + * Returns a matcher that matches when the method is executed + * at least N times. + * + * @param int $requiredInvocations + */ +function atLeast($requiredInvocations): InvokedAtLeastCountMatcher +{ + return new InvokedAtLeastCountMatcher( + $requiredInvocations + ); +} + +/** + * Returns a matcher that matches when the method is executed at least once. + */ +function atLeastOnce(): InvokedAtLeastOnceMatcher +{ + return new InvokedAtLeastOnceMatcher; +} + +/** + * Returns a matcher that matches when the method is executed exactly once. + */ +function once(): InvokedCountMatcher +{ + return new InvokedCountMatcher(1); +} + +/** + * Returns a matcher that matches when the method is executed + * exactly $count times. + * + * @param int $count + */ +function exactly($count): InvokedCountMatcher +{ + return new InvokedCountMatcher($count); +} + +/** + * Returns a matcher that matches when the method is executed + * at most N times. + * + * @param int $allowedInvocations + */ +function atMost($allowedInvocations): InvokedAtMostCountMatcher +{ + return new InvokedAtMostCountMatcher($allowedInvocations); +} + +/** + * Returns a matcher that matches when the method is executed + * at the given index. + * + * @param int $index + */ +function at($index): InvokedAtIndexMatcher +{ + return new InvokedAtIndexMatcher($index); +} + +function returnValue($value): ReturnStub +{ + return new ReturnStub($value); +} + +function returnValueMap(array $valueMap): ReturnValueMapStub +{ + return new ReturnValueMapStub($valueMap); +} + +/** + * @param int $argumentIndex + */ +function returnArgument($argumentIndex): ReturnArgumentStub +{ + return new ReturnArgumentStub($argumentIndex); +} + +function returnCallback($callback): ReturnCallbackStub +{ + return new ReturnCallbackStub($callback); +} + +/** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + */ +function returnSelf(): ReturnSelfStub +{ + return new ReturnSelfStub; +} + +function throwException(Throwable $exception): ExceptionStub +{ + return new ExceptionStub($exception); +} + +function onConsecutiveCalls(): ConsecutiveCallsStub +{ + $args = \func_get_args(); + + return new ConsecutiveCallsStub($args); +} diff --git a/.phpunit/phpunit-7/src/Framework/AssertionFailedError.php b/.phpunit/phpunit-7/src/Framework/AssertionFailedError.php new file mode 100644 index 0000000..a402e57 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/AssertionFailedError.php @@ -0,0 +1,24 @@ + + * + * 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. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/CodeCoverageException.php b/.phpunit/phpunit-7/src/Framework/CodeCoverageException.php new file mode 100644 index 0000000..298f5c4 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/CodeCoverageException.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ArrayHasKey.php b/.phpunit/phpunit-7/src/Framework/Constraint/ArrayHasKey.php new file mode 100644 index 0000000..c60dd18 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ArrayHasKey.php @@ -0,0 +1,81 @@ + + * + * 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 + */ + private $key; + + /** + * @param int|string $key + */ + public function __construct($key) + { + parent::__construct(); + $this->key = $key; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'has the key ' . $this->exporter->export($this->key); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if (\is_array($other)) { + return \array_key_exists($this->key, $other); + } + + if ($other instanceof ArrayAccess) { + return $other->offsetExists($this->key); + } + + return false; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return 'an array ' . $this->toString(); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ArraySubset.php b/.phpunit/phpunit-7/src/Framework/Constraint/ArraySubset.php new file mode 100644 index 0000000..6294372 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ArraySubset.php @@ -0,0 +1,133 @@ + + * + * 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. + * + * @deprecated https://github.com/sebastianbergmann/phpunit/issues/3494 + */ +class ArraySubset extends Constraint +{ + /** + * @var iterable + */ + private $subset; + + /** + * @var bool + */ + private $strict; + + public function __construct(iterable $subset, bool $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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, + \var_export($patched, true), + \var_export($other, true) + ); + + $this->fail($other, $description, $f); + } + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + 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 + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return 'an array ' . $this->toString(); + } + + private function toArray(iterable $other): array + { + 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; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Attribute.php b/.phpunit/phpunit-7/src/Framework/Constraint/Attribute.php new file mode 100644 index 0000000..36321f3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Attribute.php @@ -0,0 +1,79 @@ + + * + * 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 + */ + private $attributeName; + + public function __construct(Constraint $constraint, string $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 + * + * @throws ExpectationFailedException + * @throws \PHPUnit\Framework\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return parent::evaluate( + Assert::readAttribute( + $other, + $this->attributeName + ), + $description, + $returnResult + ); + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + 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 + */ + protected function failureDescription($other): string + { + return $this->toString(); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Callback.php b/.phpunit/phpunit-7/src/Framework/Constraint/Callback.php new file mode 100644 index 0000000..489d804 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Callback.php @@ -0,0 +1,47 @@ + + * + * 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 evaluates against a specified closure. + */ +class Callback extends Constraint +{ + /** + * @var callable + */ + private $callback; + + public function __construct(callable $callback) + { + parent::__construct(); + + $this->callback = $callback; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is accepted by specified callback'; + } + + /** + * Evaluates the constraint for parameter $value. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \call_user_func($this->callback, $other); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasAttribute.php b/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasAttribute.php new file mode 100644 index 0000000..fb70d5b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasAttribute.php @@ -0,0 +1,80 @@ + + * + * 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 + */ + private $attributeName; + + public function __construct(string $attributeName) + { + parent::__construct(); + + $this->attributeName = $attributeName; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'has attribute "%s"', + $this->attributeName + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + $class = new ReflectionClass($other); + + return $class->hasProperty($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 + */ + protected function failureDescription($other): string + { + return \sprintf( + '%sclass "%s" %s', + \is_object($other) ? 'object of ' : '', + \is_object($other) ? \get_class($other) : $other, + $this->toString() + ); + } + + protected function attributeName(): string + { + return $this->attributeName; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasStaticAttribute.php b/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasStaticAttribute.php new file mode 100644 index 0000000..b68d070 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ClassHasStaticAttribute.php @@ -0,0 +1,51 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'has static attribute "%s"', + $this->attributeName() + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + $class = new ReflectionClass($other); + + if ($class->hasProperty($this->attributeName())) { + $attribute = $class->getProperty($this->attributeName()); + + return $attribute->isStatic(); + } + + return false; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Composite.php b/.phpunit/phpunit-7/src/Framework/Constraint/Composite.php new file mode 100644 index 0000000..3b19df3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Composite.php @@ -0,0 +1,70 @@ + + * + * 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 + */ + private $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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. + */ + public function count(): int + { + return \count($this->innerConstraint); + } + + protected function innerConstraint(): Constraint + { + return $this->innerConstraint; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Constraint.php b/.phpunit/phpunit-7/src/Framework/Constraint/Constraint.php new file mode 100644 index 0000000..175557d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Constraint.php @@ -0,0 +1,148 @@ + + * + * 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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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); + } + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 1; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return false; + } + + /** + * Throws an exception for the given compared value and test description + * + * @param mixed $other evaluated value or object + * @param string $description Additional information about the test + * @param ComparisonFailure $comparisonFailure + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void + { + $failureDescription = \sprintf( + 'Failed asserting that %s.', + $this->failureDescription($other) + ); + + $additionalFailureDescription = $this->additionalFailureDescription($other); + + if ($additionalFailureDescription) { + $failureDescription .= "\n" . $additionalFailureDescription; + } + + if (!empty($description)) { + $failureDescription = $description . "\n" . $failureDescription; + } + + throw new ExpectationFailedException( + $failureDescription, + $comparisonFailure + ); + } + + /** + * Return additional failure description where needed + * + * The function can be overridden to provide additional failure + * information like a diff + * + * @param mixed $other evaluated value or object + */ + protected function additionalFailureDescription($other): string + { + return ''; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * To provide additional failure information additionalFailureDescription + * can be used. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return $this->exporter->export($other) . ' ' . $this->toString(); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Count.php b/.phpunit/phpunit-7/src/Framework/Constraint/Count.php new file mode 100644 index 0000000..7aeb2d7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Count.php @@ -0,0 +1,119 @@ + + * + * 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 + */ + private $expectedCount; + + public function __construct(int $expected) + { + parent::__construct(); + + $this->expectedCount = $expected; + } + + public function toString(): string + { + return \sprintf( + 'count matches %d', + $this->expectedCount + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + */ + protected function matches($other): bool + { + return $this->expectedCount === $this->getCountOf($other); + } + + /** + * @param iterable $other + */ + protected function getCountOf($other): ?int + { + 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. + */ + protected function getCountOfGenerator(Generator $generator): int + { + for ($count = 0; $generator->valid(); $generator->next()) { + ++$count; + } + + return $count; + } + + /** + * Returns the description of the failure. + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + 'actual size %d matches expected size %d', + $this->getCountOf($other), + $this->expectedCount + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/DirectoryExists.php b/.phpunit/phpunit-7/src/Framework/Constraint/DirectoryExists.php new file mode 100644 index 0000000..09f1f4a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/DirectoryExists.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'directory exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_dir($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + 'directory "%s" exists', + $other + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/Exception.php b/.phpunit/phpunit-7/src/Framework/Constraint/Exception.php new file mode 100644 index 0000000..7e0c021 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/Exception.php @@ -0,0 +1,82 @@ + + * + * 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 + */ + private $className; + + public function __construct(string $className) + { + parent::__construct(); + + $this->className = $className; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'exception of type "%s"', + $this->className + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + if ($other !== null) { + $message = ''; + + if ($other instanceof Throwable) { + $message = '. Message was: "' . $other->getMessage() . '" at' + . "\n" . Filter::getFilteredStacktrace($other); + } + + return \sprintf( + 'exception of type "%s" matches expected exception "%s"%s', + \get_class($other), + $this->className, + $message + ); + } + + return \sprintf( + 'exception of type "%s" is thrown', + $this->className + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionCode.php b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionCode.php new file mode 100644 index 0000000..6cb2ac0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionCode.php @@ -0,0 +1,63 @@ + + * + * 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|string + */ + private $expectedCode; + + /** + * @param int|string $expected + */ + public function __construct($expected) + { + parent::__construct(); + + $this->expectedCode = $expected; + } + + public function toString(): string + { + return 'exception code is '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param \Throwable $other + */ + protected function matches($other): bool + { + return (string) $other->getCode() === (string) $this->expectedCode; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return \sprintf( + '%s is equal to expected exception code %s', + $this->exporter->export($other->getCode()), + $this->exporter->export($this->expectedCode) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessage.php b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessage.php new file mode 100644 index 0000000..299d512 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessage.php @@ -0,0 +1,73 @@ + + * + * 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 string + */ + private $expectedMessage; + + public function __construct(string $expected) + { + parent::__construct(); + + $this->expectedMessage = $expected; + } + + public function toString(): string + { + if ($this->expectedMessage === '') { + return 'exception message is empty'; + } + + return 'exception message contains '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param \Throwable $other + */ + protected function matches($other): bool + { + if ($this->expectedMessage === '') { + return $other->getMessage() === ''; + } + + return \strpos($other->getMessage(), $this->expectedMessage) !== false; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + if ($this->expectedMessage === '') { + return \sprintf( + "exception message is empty but is '%s'", + $other->getMessage() + ); + } + + return \sprintf( + "exception message '%s' contains '%s'", + $other->getMessage(), + $this->expectedMessage + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessageRegularExpression.php b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessageRegularExpression.php new file mode 100644 index 0000000..63f323a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ExceptionMessageRegularExpression.php @@ -0,0 +1,71 @@ + + * + * 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 + */ + private $expectedMessageRegExp; + + public function __construct(string $expected) + { + parent::__construct(); + + $this->expectedMessageRegExp = $expected; + } + + public function toString(): string + { + return 'exception message matches '; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param \PHPUnit\Framework\Exception $other + * + * @throws \Exception + * @throws \PHPUnit\Framework\Exception + */ + protected function matches($other): bool + { + $match = RegularExpressionUtil::safeMatch($this->expectedMessageRegExp, $other->getMessage()); + + if ($match === false) { + throw new \PHPUnit\Framework\Exception( + "Invalid expected exception message regex given: '{$this->expectedMessageRegExp}'" + ); + } + + return $match === 1; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + "exception message '%s' matches '%s'", + $other->getMessage(), + $this->expectedMessageRegExp + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/FileExists.php b/.phpunit/phpunit-7/src/Framework/Constraint/FileExists.php new file mode 100644 index 0000000..35e2962 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/FileExists.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'file exists'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \file_exists($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + 'file "%s" exists', + $other + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/GreaterThan.php b/.phpunit/phpunit-7/src/Framework/Constraint/GreaterThan.php new file mode 100644 index 0000000..890e13d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/GreaterThan.php @@ -0,0 +1,53 @@ + + * + * 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 float|int + */ + private $value; + + /** + * @param float|int $value + */ + public function __construct($value) + { + parent::__construct(); + + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'is greater than ' . $this->exporter->export($this->value); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $this->value < $other; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsAnything.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsAnything.php new file mode 100644 index 0000000..526cc37 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsAnything.php @@ -0,0 +1,55 @@ + + * + * 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 + * + * @throws ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return $returnResult ? true : null; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is anything'; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + return 0; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsEmpty.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsEmpty.php new file mode 100644 index 0000000..0eb89ce --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsEmpty.php @@ -0,0 +1,61 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is empty'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other instanceof Countable) { + return \count($other) === 0; + } + + return empty($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + $type = \gettype($other); + + return \sprintf( + '%s %s %s', + $type[0] == 'a' || $type[0] == 'o' ? 'an' : 'a', + $type, + $this->toString() + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsEqual.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsEqual.php new file mode 100644 index 0000000..0cc999e --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsEqual.php @@ -0,0 +1,150 @@ + + * + * 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; +use SebastianBergmann\Comparator\Factory as ComparatorFactory; + +/** + * 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 https://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 + */ + private $value; + + /** + * @var float + */ + private $delta; + + /** + * @var int + */ + private $maxDepth; + + /** + * @var bool + */ + private $canonicalize; + + /** + * @var bool + */ + private $ignoreCase; + + public function __construct($value, float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false) + { + parent::__construct(); + + $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 + * + * @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 = ComparatorFactory::getInstance(); + + try { + $comparator = $comparatorFactory->getComparatorFor( + $this->value, + $other + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + $this->canonicalize, + $this->ignoreCase + ); + } catch (ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new ExpectationFailedException( + \trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + $delta = ''; + + if (\is_string($this->value)) { + if (\strpos($this->value, "\n") !== false) { + return 'is equal to '; + } + + 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 + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsFalse.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsFalse.php new file mode 100644 index 0000000..82858a7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsFalse.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is false'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === false; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsFinite.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsFinite.php new file mode 100644 index 0000000..3d36900 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsFinite.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is finite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_finite($other); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsIdentical.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsIdentical.php new file mode 100644 index 0000000..c4362f0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsIdentical.php @@ -0,0 +1,144 @@ + + * + * 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 one value is identical to another. + * + * Identical check is performed with PHP's === operator, the operator is + * explained in detail at + * {@url https://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 + */ + private const EPSILON = 0.0000000001; + + /** + * @var mixed + */ + private $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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 ComparisonFailure( + $this->value, + $other, + \sprintf("'%s'", $this->value), + \sprintf("'%s'", $other) + ); + } + + // if both values are array, make sure a diff is generated + if (\is_array($this->value) && \is_array($other)) { + $f = new ComparisonFailure( + $this->value, + $other, + $this->exporter->export($this->value), + $this->exporter->export($other) + ); + } + + $this->fail($other, $description, $f); + } + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + if (\is_object($this->value)) { + return 'is identical to an object of class "' . + \get_class($this->value) . '"'; + } + + return 'is identical to ' . $this->exporter->export($this->value); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + if (\is_object($this->value) && \is_object($other)) { + return 'two variables reference the same object'; + } + + if (\is_string($this->value) && \is_string($other)) { + return 'two strings are identical'; + } + + if (\is_array($this->value) && \is_array($other)) { + return 'two arrays are identical'; + } + + return parent::failureDescription($other); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsInfinite.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsInfinite.php new file mode 100644 index 0000000..8ac16d2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsInfinite.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is infinite'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_infinite($other); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsInstanceOf.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsInstanceOf.php new file mode 100644 index 0000000..b7c70ff --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsInstanceOf.php @@ -0,0 +1,91 @@ + + * + * 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 + */ + private $className; + + public function __construct(string $className) + { + parent::__construct(); + + $this->className = $className; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'is instance of %s "%s"', + $this->getType(), + $this->className + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return \sprintf( + '%s is an instance of %s "%s"', + $this->exporter->shortenedExport($other), + $this->getType(), + $this->className + ); + } + + private function getType(): string + { + try { + $reflection = new ReflectionClass($this->className); + + if ($reflection->isInterface()) { + return 'interface'; + } + } catch (ReflectionException $e) { + } + + return 'class'; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsJson.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsJson.php new file mode 100644 index 0000000..ad06ec1 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsJson.php @@ -0,0 +1,73 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is valid JSON'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ($other === '') { + return false; + } + + \json_decode($other); + + if (\json_last_error()) { + return false; + } + + return true; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + if ($other === '') { + return 'an empty string is valid JSON'; + } + + \json_decode($other); + $error = JsonMatchesErrorMessageProvider::determineJsonError( + \json_last_error() + ); + + return \sprintf( + '%s is valid JSON (%s)', + $this->exporter->shortenedExport($other), + $error + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsNan.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsNan.php new file mode 100644 index 0000000..2a62b61 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsNan.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is nan'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_nan($other); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsNull.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsNull.php new file mode 100644 index 0000000..620eae2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsNull.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is null'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === null; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsReadable.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsReadable.php new file mode 100644 index 0000000..bdc8ca3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsReadable.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is readable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_readable($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + '"%s" is readable', + $other + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsTrue.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsTrue.php new file mode 100644 index 0000000..c0a4756 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsTrue.php @@ -0,0 +1,35 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is true'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $other === true; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsType.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsType.php new file mode 100644 index 0000000..4f68477 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsType.php @@ -0,0 +1,152 @@ + + * + * 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 +{ + public const TYPE_ARRAY = 'array'; + + public const TYPE_BOOL = 'bool'; + + public const TYPE_FLOAT = 'float'; + + public const TYPE_INT = 'int'; + + public const TYPE_NULL = 'null'; + + public const TYPE_NUMERIC = 'numeric'; + + public const TYPE_OBJECT = 'object'; + + public const TYPE_RESOURCE = 'resource'; + + public const TYPE_STRING = 'string'; + + public const TYPE_SCALAR = 'scalar'; + + public const TYPE_CALLABLE = 'callable'; + + public const TYPE_ITERABLE = 'iterable'; + + /** + * @var array + */ + private const KNOWN_TYPES = [ + 'array' => true, + 'boolean' => true, + 'bool' => true, + 'double' => true, + 'float' => true, + 'integer' => true, + 'int' => true, + 'null' => true, + 'numeric' => true, + 'object' => true, + 'real' => true, + 'resource' => true, + 'string' => true, + 'scalar' => true, + 'callable' => true, + 'iterable' => true, + ]; + + /** + * @var string + */ + private $type; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(string $type) + { + parent::__construct(); + + if (!isset(self::KNOWN_TYPES[$type])) { + throw new \PHPUnit\Framework\Exception( + \sprintf( + 'Type specified for PHPUnit\Framework\Constraint\IsType <%s> ' . + 'is not a valid type.', + $type + ) + ); + } + + $this->type = $type; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'is of type "%s"', + $this->type + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + switch ($this->type) { + case 'numeric': + return \is_numeric($other); + + case 'integer': + case 'int': + return \is_int($other); + + case 'double': + case 'float': + case 'real': + return \is_float($other); + + case 'string': + return \is_string($other); + + case 'boolean': + case 'bool': + return \is_bool($other); + + case 'null': + return null === $other; + + case 'array': + return \is_array($other); + + case 'object': + return \is_object($other); + + case 'resource': + return \is_resource($other) || \is_string(@\get_resource_type($other)); + + case 'scalar': + return \is_scalar($other); + + case 'callable': + return \is_callable($other); + + case 'iterable': + return \is_iterable($other); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/IsWritable.php b/.phpunit/phpunit-7/src/Framework/Constraint/IsWritable.php new file mode 100644 index 0000000..f19cea9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/IsWritable.php @@ -0,0 +1,53 @@ + + * + * 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 +{ + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'is writable'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \is_writable($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + */ + protected function failureDescription($other): string + { + return \sprintf( + '"%s" is writable', + $other + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatches.php b/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatches.php new file mode 100644 index 0000000..2246199 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatches.php @@ -0,0 +1,111 @@ + + * + * 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 + */ + private $value; + + public function __construct(string $value) + { + parent::__construct(); + + $this->value = $value; + } + + /** + * Returns a string representation of the object. + */ + public function toString(): string + { + return \sprintf( + 'matches JSON string "%s"', + $this->value + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + [$error, $recodedOther] = Json::canonicalize($other); + + if ($error) { + return false; + } + + [$error, $recodedValue] = Json::canonicalize($this->value); + + if ($error) { + return false; + } + + return $recodedOther == $recodedValue; + } + + /** + * Throws an exception for the given compared value and test description + * + * @param mixed $other evaluated value or object + * @param string $description Additional information about the test + * @param ComparisonFailure $comparisonFailure + * + * @throws ExpectationFailedException + * @throws \PHPUnit\Framework\Exception + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function fail($other, $description, ComparisonFailure $comparisonFailure = null): void + { + if ($comparisonFailure === null) { + [$error] = Json::canonicalize($other); + + if ($error) { + parent::fail($other, $description); + + return; + } + + [$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); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php b/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php new file mode 100644 index 0000000..9b3659a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/JsonMatchesErrorMessageProvider.php @@ -0,0 +1,62 @@ + + * + * 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. + */ + public static function determineJsonError(string $error, string $prefix = ''): ?string + { + switch ($error) { + case \JSON_ERROR_NONE: + return null; + case \JSON_ERROR_DEPTH: + return $prefix . 'Maximum stack depth exceeded'; + case \JSON_ERROR_STATE_MISMATCH: + return $prefix . 'Underflow or the modes mismatch'; + case \JSON_ERROR_CTRL_CHAR: + return $prefix . 'Unexpected control character found'; + case \JSON_ERROR_SYNTAX: + return $prefix . 'Syntax error, malformed JSON'; + case \JSON_ERROR_UTF8: + return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded'; + default: + return $prefix . 'Unknown error'; + } + } + + /** + * Translates a given type to a human readable message prefix. + */ + public static function translateTypeToPrefix(string $type): string + { + switch (\strtolower($type)) { + case 'expected': + $prefix = 'Expected value JSON decode error - '; + + break; + case 'actual': + $prefix = 'Actual value JSON decode error - '; + + break; + default: + $prefix = ''; + + break; + } + + return $prefix; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/LessThan.php b/.phpunit/phpunit-7/src/Framework/Constraint/LessThan.php new file mode 100644 index 0000000..8e8d9e5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/LessThan.php @@ -0,0 +1,53 @@ + + * + * 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 float|int + */ + private $value; + + /** + * @param float|int $value + */ + public function __construct($value) + { + parent::__construct(); + + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return 'is less than ' . $this->exporter->export($this->value); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return $this->value > $other; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/LogicalAnd.php b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalAnd.php new file mode 100644 index 0000000..fd7fa29 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalAnd.php @@ -0,0 +1,123 @@ + + * + * 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[] + */ + private $constraints = []; + + 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): void + { + $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = true; + + 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. + */ + public function toString(): string + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' and '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += \count($constraint); + } + + return $count; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/LogicalNot.php b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalNot.php new file mode 100644 index 0000000..0d3b001 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalNot.php @@ -0,0 +1,171 @@ + + * + * 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 + */ + private $constraint; + + public static function negate(string $string): string + { + $positives = [ + 'contains ', + 'exists', + 'has ', + 'is ', + 'are ', + 'matches ', + 'starts with ', + 'ends with ', + 'reference ', + 'not not ', + ]; + + $negatives = [ + 'does not contain ', + 'does not exist', + 'does not have ', + 'is not ', + 'are not ', + 'does not match ', + 'starts not with ', + 'ends not with ', + 'don\'t reference ', + 'not ', + ]; + + \preg_match('/(\'[\w\W]*\')([\w\W]*)("[\w\W]*")/i', $string, $matches); + + if (\count($matches) > 0) { + $nonInput = $matches[2]; + + $negatedString = \str_replace( + $nonInput, + \str_replace( + $positives, + $negatives, + $nonInput + ), + $string + ); + } else { + $negatedString = \str_replace( + $positives, + $negatives, + $string + ); + } + + return $negatedString; + } + + /** + * @param Constraint|mixed $constraint + */ + public function __construct($constraint) + { + parent::__construct(); + + if (!($constraint instanceof Constraint)) { + $constraint = new IsEqual($constraint); + } + + $this->constraint = $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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 a string representation of the constraint. + */ + public function toString(): string + { + 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. + */ + public function count(): int + { + return \count($this->constraint); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + 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) + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/LogicalOr.php b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalOr.php new file mode 100644 index 0000000..dd1fda8 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalOr.php @@ -0,0 +1,120 @@ + + * + * 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[] + */ + private $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): void + { + $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = false; + + 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. + */ + public function toString(): string + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' or '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += \count($constraint); + } + + return $count; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/LogicalXor.php b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalXor.php new file mode 100644 index 0000000..b8a2802 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/LogicalXor.php @@ -0,0 +1,125 @@ + + * + * 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[] + */ + private $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): void + { + $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = true; + $lastResult = 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. + */ + public function toString(): string + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' xor '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + */ + public function count(): int + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += \count($constraint); + } + + return $count; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/ObjectHasAttribute.php b/.phpunit/phpunit-7/src/Framework/Constraint/ObjectHasAttribute.php new file mode 100644 index 0000000..15127c0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/ObjectHasAttribute.php @@ -0,0 +1,34 @@ + + * + * 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 + */ + protected function matches($other): bool + { + $object = new ReflectionObject($other); + + return $object->hasProperty($this->attributeName()); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/RegularExpression.php b/.phpunit/phpunit-7/src/Framework/Constraint/RegularExpression.php new file mode 100644 index 0000000..cb1f665 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/RegularExpression.php @@ -0,0 +1,56 @@ + + * + * 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 + */ + private $pattern; + + public function __construct(string $pattern) + { + parent::__construct(); + + $this->pattern = $pattern; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return \sprintf( + 'matches PCRE pattern "%s"', + $this->pattern + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \preg_match($this->pattern, $other) > 0; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/SameSize.php b/.phpunit/phpunit-7/src/Framework/Constraint/SameSize.php new file mode 100644 index 0000000..dc9b003 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/SameSize.php @@ -0,0 +1,18 @@ + + * + * 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 +{ + public function __construct(iterable $expected) + { + parent::__construct($this->getCountOf($expected)); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/StringContains.php b/.phpunit/phpunit-7/src/Framework/Constraint/StringContains.php new file mode 100644 index 0000000..cc72c32 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/StringContains.php @@ -0,0 +1,76 @@ + + * + * 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 + */ + private $string; + + /** + * @var bool + */ + private $ignoreCase; + + public function __construct(string $string, bool $ignoreCase = false) + { + parent::__construct(); + + $this->string = $string; + $this->ignoreCase = $ignoreCase; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + if ($this->ignoreCase) { + $string = \mb_strtolower($this->string); + } else { + $string = $this->string; + } + + return \sprintf( + 'contains "%s"', + $string + ); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + if ('' === $this->string) { + return true; + } + + if ($this->ignoreCase) { + return \mb_stripos($other, $this->string) !== false; + } + + return \mb_strpos($other, $this->string) !== false; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/StringEndsWith.php b/.phpunit/phpunit-7/src/Framework/Constraint/StringEndsWith.php new file mode 100644 index 0000000..3856078 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/StringEndsWith.php @@ -0,0 +1,48 @@ + + * + * 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 + */ + private $suffix; + + public function __construct(string $suffix) + { + parent::__construct(); + + $this->suffix = $suffix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'ends with "' . $this->suffix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \substr($other, 0 - \strlen($this->suffix)) === $this->suffix; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/StringMatchesFormatDescription.php b/.phpunit/phpunit-7/src/Framework/Constraint/StringMatchesFormatDescription.php new file mode 100644 index 0000000..5b27e53 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/StringMatchesFormatDescription.php @@ -0,0 +1,103 @@ + + * + * 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 + */ + private $string; + + public function __construct(string $string) + { + parent::__construct( + $this->createPatternFromFormat( + $this->convertNewlines($string) + ) + ); + + $this->string = $string; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return parent::matches( + $this->convertNewlines($other) + ); + } + + protected function failureDescription($other): string + { + return 'string matches format description'; + } + + protected function additionalFailureDescription($other): string + { + $from = \explode("\n", $this->string); + $to = \explode("\n", $this->convertNewlines($other)); + + foreach ($from as $index => $line) { + if (isset($to[$index]) && $line !== $to[$index]) { + $line = $this->createPatternFromFormat($line); + + if (\preg_match($line, $to[$index]) > 0) { + $from[$index] = $to[$index]; + } + } + } + + $this->string = \implode("\n", $from); + $other = \implode("\n", $to); + + $differ = new Differ("--- Expected\n+++ Actual\n"); + + return $differ->diff($this->string, $other); + } + + private function createPatternFromFormat(string $string): string + { + $string = \strtr( + \preg_quote($string, '/'), + [ + '%%' => '%', + '%e' => '\\' . \DIRECTORY_SEPARATOR, + '%s' => '[^\r\n]+', + '%S' => '[^\r\n]*', + '%a' => '.+', + '%A' => '.*', + '%w' => '\s*', + '%i' => '[+-]?\d+', + '%d' => '\d+', + '%x' => '[0-9a-fA-F]+', + '%f' => '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', + '%c' => '.', + ] + ); + + return '/^' . $string . '$/s'; + } + + private function convertNewlines($text): string + { + return \preg_replace('/\r\n/', "\n", $text); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/StringStartsWith.php b/.phpunit/phpunit-7/src/Framework/Constraint/StringStartsWith.php new file mode 100644 index 0000000..96365ef --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/StringStartsWith.php @@ -0,0 +1,48 @@ + + * + * 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 + */ + private $prefix; + + public function __construct(string $prefix) + { + parent::__construct(); + + $this->prefix = $prefix; + } + + /** + * Returns a string representation of the constraint. + */ + public function toString(): string + { + return 'starts with "' . $this->prefix . '"'; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + return \strpos($other, $this->prefix) === 0; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContains.php b/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContains.php new file mode 100644 index 0000000..ace1c78 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContains.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\Constraint; + +use SplObjectStorage; + +/** + * Constraint that asserts that the Traversable it is applied to contains + * a given value. + */ +class TraversableContains extends Constraint +{ + /** + * @var bool + */ + private $checkForObjectIdentity; + + /** + * @var bool + */ + private $checkForNonObjectIdentity; + + /** + * @var mixed + */ + private $value; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($value, bool $checkForObjectIdentity = true, bool $checkForNonObjectIdentity = false) + { + parent::__construct(); + + $this->checkForObjectIdentity = $checkForObjectIdentity; + $this->checkForNonObjectIdentity = $checkForNonObjectIdentity; + $this->value = $value; + } + + /** + * Returns a string representation of the constraint. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + if (\is_string($this->value) && \strpos($this->value, "\n") !== false) { + return 'contains "' . $this->value . '"'; + } + + return 'contains ' . $this->exporter->export($this->value); + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other value or object to evaluate + */ + protected function matches($other): bool + { + 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 the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other evaluated value or object + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + protected function failureDescription($other): string + { + return \sprintf( + '%s %s', + \is_array($other) ? 'an array' : 'a traversable', + $this->toString() + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContainsOnly.php b/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContainsOnly.php new file mode 100644 index 0000000..20c5134 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Constraint/TraversableContainsOnly.php @@ -0,0 +1,93 @@ + + * + * 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 + */ + private $constraint; + + /** + * @var string + */ + private $type; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(string $type, bool $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 + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + 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. + */ + public function toString(): string + { + return 'contains only values of type "' . $this->type . '"'; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/CoveredCodeNotExecutedException.php b/.phpunit/phpunit-7/src/Framework/CoveredCodeNotExecutedException.php new file mode 100644 index 0000000..45deaaa --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/CoveredCodeNotExecutedException.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/DataProviderTestSuite.php b/.phpunit/phpunit-7/src/Framework/DataProviderTestSuite.php new file mode 100644 index 0000000..af119d2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/DataProviderTestSuite.php @@ -0,0 +1,40 @@ + + * + * 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 +{ + /** + * @var string[] + */ + private $dependencies = []; + + /** + * @param string[] $dependencies + */ + public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + + foreach ($this->tests as $test) { + $test->setDependencies($dependencies); + } + } + + public function getDependencies(): array + { + return $this->dependencies; + } + + public function hasDependencies(): bool + { + return \count($this->dependencies) > 0; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Error/Deprecated.php b/.phpunit/phpunit-7/src/Framework/Error/Deprecated.php new file mode 100644 index 0000000..f43b8f9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Error/Deprecated.php @@ -0,0 +1,15 @@ + + * + * 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; +} diff --git a/.phpunit/phpunit-7/src/Framework/Error/Error.php b/.phpunit/phpunit-7/src/Framework/Error/Error.php new file mode 100644 index 0000000..3478703 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Error/Error.php @@ -0,0 +1,26 @@ + + * + * 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 +{ + public function __construct(string $message, int $code, string $file, int $line, \Exception $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->file = $file; + $this->line = $line; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Error/Notice.php b/.phpunit/phpunit-7/src/Framework/Error/Notice.php new file mode 100644 index 0000000..0275c09 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Error/Notice.php @@ -0,0 +1,15 @@ + + * + * 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; +} diff --git a/.phpunit/phpunit-7/src/Framework/Error/Warning.php b/.phpunit/phpunit-7/src/Framework/Error/Warning.php new file mode 100644 index 0000000..decb33e --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Error/Warning.php @@ -0,0 +1,15 @@ + + * + * 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; +} diff --git a/.phpunit/phpunit-7/src/Framework/Exception.php b/.phpunit/phpunit-7/src/Framework/Exception.php new file mode 100644 index 0000000..2ea2a1b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Exception.php @@ -0,0 +1,78 @@ + + * + * 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']); + } + } + + /** + * @throws \InvalidArgumentException + */ + public function __toString(): string + { + $string = TestFailure::exceptionToString($this); + + if ($trace = Filter::getFilteredStacktrace($this)) { + $string .= "\n" . $trace; + } + + return $string; + } + + public function __sleep(): array + { + return \array_keys(\get_object_vars($this)); + } + + /** + * Returns the serializable trace (without 'args'). + */ + public function getSerializableTrace(): array + { + return $this->serializableTrace; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/ExceptionWrapper.php b/.phpunit/phpunit-7/src/Framework/ExceptionWrapper.php new file mode 100644 index 0000000..702712a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/ExceptionWrapper.php @@ -0,0 +1,118 @@ + + * + * 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 null|ExceptionWrapper + */ + protected $previous; + + public function __construct(Throwable $t) + { + // PDOException::getCode() is a string. + // @see https://php.net/manual/en/class.pdoexception.php#95812 + parent::__construct($t->getMessage(), (int) $t->getCode()); + $this->setOriginalException($t); + } + + /** + * @throws \InvalidArgumentException + */ + public function __toString(): string + { + $string = TestFailure::exceptionToString($this); + + if ($trace = Filter::getFilteredStacktrace($this)) { + $string .= "\n" . $trace; + } + + if ($this->previous) { + $string .= "\nCaused by\n" . $this->previous; + } + + return $string; + } + + public function getClassName(): string + { + return $this->className; + } + + public function getPreviousWrapped(): ?self + { + return $this->previous; + } + + public function setClassName(string $className): void + { + $this->className = $className; + } + + public function setOriginalException(\Throwable $t): void + { + $this->originalException($t); + + $this->className = \get_class($t); + $this->file = $t->getFile(); + $this->line = $t->getLine(); + + $this->serializableTrace = $t->getTrace(); + + foreach ($this->serializableTrace as $i => $call) { + unset($this->serializableTrace[$i]['args']); + } + + if ($t->getPrevious()) { + $this->previous = new self($t->getPrevious()); + } + } + + public function getOriginalException(): ?Throwable + { + return $this->originalException(); + } + + /** + * Method to contain static originalException to exclude it from stacktrace to prevent the stacktrace contents, + * which can be quite big, from being garbage-collected, thus blocking memory until shutdown. + * Approach works both for var_dump() and var_export() and print_r() + */ + private function originalException(Throwable $exceptionToStore = null): ?Throwable + { + static $originalExceptions; + + $instanceId = \spl_object_hash($this); + + if ($exceptionToStore) { + $originalExceptions[$instanceId] = $exceptionToStore; + } + + return $originalExceptions[$instanceId] ?? null; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/ExpectationFailedException.php b/.phpunit/phpunit-7/src/Framework/ExpectationFailedException.php new file mode 100644 index 0000000..2771d9b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/ExpectationFailedException.php @@ -0,0 +1,39 @@ + + * + * 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 +{ + /** + * @var ComparisonFailure + */ + protected $comparisonFailure; + + public function __construct(string $message, ComparisonFailure $comparisonFailure = null, \Exception $previous = null) + { + $this->comparisonFailure = $comparisonFailure; + + parent::__construct($message, 0, $previous); + } + + public function getComparisonFailure(): ?ComparisonFailure + { + return $this->comparisonFailure; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/IncompleteTest.php b/.phpunit/phpunit-7/src/Framework/IncompleteTest.php new file mode 100644 index 0000000..53654f9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/IncompleteTest.php @@ -0,0 +1,18 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/IncompleteTestCase.php b/.phpunit/phpunit-7/src/Framework/IncompleteTestCase.php new file mode 100644 index 0000000..0092532 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/IncompleteTestCase.php @@ -0,0 +1,76 @@ + + * + * 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; + + public function __construct(string $className, string $methodName, string $message = '') + { + parent::__construct($className . '::' . $methodName); + + $this->message = $message; + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * @throws Exception + */ + protected function runTest(): void + { + $this->markTestIncomplete($this->message); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/IncompleteTestError.php b/.phpunit/phpunit-7/src/Framework/IncompleteTestError.php new file mode 100644 index 0000000..0921f07 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/IncompleteTestError.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/InvalidCoversTargetException.php b/.phpunit/phpunit-7/src/Framework/InvalidCoversTargetException.php new file mode 100644 index 0000000..40e9c33 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/InvalidCoversTargetException.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MissingCoversAnnotationException.php b/.phpunit/phpunit-7/src/Framework/MissingCoversAnnotationException.php new file mode 100644 index 0000000..ed3bcb6 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MissingCoversAnnotationException.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Identity.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Identity.php new file mode 100644 index 0000000..9db235f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Identity.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * Builder interface for unique identifiers. + * + * Defines the interface for recording unique identifiers. The identifiers + * can be used to define the invocation order of expectations. The expectation + * is recorded using id() and then defined in order using + * PHPUnit\Framework\MockObject\Builder\Match::after(). + */ +interface Identity +{ + /** + * Sets the identification of the expectation to $id. + * + * @note The identifier is unique per mock object. + * + * @param string $id unique identification of expectation + */ + public function id($id); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/InvocationMocker.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/InvocationMocker.php new file mode 100644 index 0000000..2801319 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/InvocationMocker.php @@ -0,0 +1,277 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\MockObject\Matcher; +use PHPUnit\Framework\MockObject\Matcher\Invocation; +use PHPUnit\Framework\MockObject\RuntimeException; +use PHPUnit\Framework\MockObject\Stub; +use PHPUnit\Framework\MockObject\Stub\MatcherCollection; + +/** + * Builder for mocked or stubbed invocations. + * + * Provides methods for building expectations without having to resort to + * instantiating the various matchers manually. These methods also form a + * more natural way of reading the expectation. This class should be together + * with the test case PHPUnit\Framework\MockObject\TestCase. + */ +class InvocationMocker implements MethodNameMatch +{ + /** + * @var MatcherCollection + */ + private $collection; + + /** + * @var Matcher + */ + private $matcher; + + /** + * @var string[] + */ + private $configurableMethods; + + public function __construct(MatcherCollection $collection, Invocation $invocationMatcher, array $configurableMethods) + { + $this->collection = $collection; + $this->matcher = new Matcher($invocationMatcher); + + $this->collection->addMatcher($this->matcher); + + $this->configurableMethods = $configurableMethods; + } + + /** + * @return Matcher + */ + public function getMatcher() + { + return $this->matcher; + } + + /** + * @return InvocationMocker + */ + public function id($id) + { + $this->collection->registerId($id, $this); + + return $this; + } + + /** + * @return InvocationMocker + */ + public function will(Stub $stub) + { + $this->matcher->setStub($stub); + + return $this; + } + + /** + * @return InvocationMocker + */ + public function willReturn($value, ...$nextValues) + { + if (\count($nextValues) === 0) { + $stub = new Stub\ReturnStub($value); + } else { + $stub = new Stub\ConsecutiveCalls( + \array_merge([$value], $nextValues) + ); + } + + return $this->will($stub); + } + + /** + * @param mixed $reference + * + * @return InvocationMocker + */ + public function willReturnReference(&$reference) + { + $stub = new Stub\ReturnReference($reference); + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function willReturnMap(array $valueMap) + { + $stub = new Stub\ReturnValueMap($valueMap); + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function willReturnArgument($argumentIndex) + { + $stub = new Stub\ReturnArgument($argumentIndex); + + return $this->will($stub); + } + + /** + * @param callable $callback + * + * @return InvocationMocker + */ + public function willReturnCallback($callback) + { + $stub = new Stub\ReturnCallback($callback); + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function willReturnSelf() + { + $stub = new Stub\ReturnSelf; + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function willReturnOnConsecutiveCalls(...$values) + { + $stub = new Stub\ConsecutiveCalls($values); + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function willThrowException(\Exception $exception) + { + $stub = new Stub\Exception($exception); + + return $this->will($stub); + } + + /** + * @return InvocationMocker + */ + public function after($id) + { + $this->matcher->setAfterMatchBuilderId($id); + + return $this; + } + + /** + * @param array ...$arguments + * + * @throws RuntimeException + * + * @return InvocationMocker + */ + public function with(...$arguments) + { + $this->canDefineParameters(); + + $this->matcher->setParametersMatcher(new Matcher\Parameters($arguments)); + + return $this; + } + + /** + * @param array ...$arguments + * + * @throws RuntimeException + * + * @return InvocationMocker + */ + public function withConsecutive(...$arguments) + { + $this->canDefineParameters(); + + $this->matcher->setParametersMatcher(new Matcher\ConsecutiveParameters($arguments)); + + return $this; + } + + /** + * @throws RuntimeException + * + * @return InvocationMocker + */ + public function withAnyParameters() + { + $this->canDefineParameters(); + + $this->matcher->setParametersMatcher(new Matcher\AnyParameters); + + return $this; + } + + /** + * @param Constraint|string $constraint + * + * @throws RuntimeException + * + * @return InvocationMocker + */ + public function method($constraint) + { + if ($this->matcher->hasMethodNameMatcher()) { + throw new RuntimeException( + 'Method name matcher is already defined, cannot redefine' + ); + } + + if (\is_string($constraint) && !\in_array(\strtolower($constraint), $this->configurableMethods, true)) { + throw new RuntimeException( + \sprintf( + 'Trying to configure method "%s" which cannot be configured because it does not exist, has not been specified, is final, or is static', + $constraint + ) + ); + } + + $this->matcher->setMethodNameMatcher(new Matcher\MethodName($constraint)); + + return $this; + } + + /** + * Validate that a parameters matcher can be defined, throw exceptions otherwise. + * + * @throws RuntimeException + */ + private function canDefineParameters(): void + { + if (!$this->matcher->hasMethodNameMatcher()) { + throw new RuntimeException( + 'Method name matcher is not defined, cannot define parameter ' . + 'matcher without one' + ); + } + + if ($this->matcher->hasParametersMatcher()) { + throw new RuntimeException( + 'Parameter matcher is already defined, cannot redefine' + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Match.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Match.php new file mode 100644 index 0000000..eeace16 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Match.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * Builder interface for invocation order matches. + */ +interface Match extends Stub +{ + /** + * Defines the expectation which must occur before the current is valid. + * + * @param string $id the identification of the expectation that should + * occur before this one + * + * @return Stub + */ + public function after($id); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/MethodNameMatch.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/MethodNameMatch.php new file mode 100644 index 0000000..55816a3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/MethodNameMatch.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * Builder interface for matcher of method names. + */ +interface MethodNameMatch extends ParametersMatch +{ + /** + * Adds a new method name match and returns the parameter match object for + * further matching possibilities. + * + * @param \PHPUnit\Framework\Constraint\Constraint $name Constraint for matching method, if a string is passed it will use the PHPUnit_Framework_Constraint_IsEqual + * + * @return ParametersMatch + */ + public function method($name); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/NamespaceMatch.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/NamespaceMatch.php new file mode 100644 index 0000000..9e1b063 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/NamespaceMatch.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +/** + * Interface for builders which can register builders with a given identification. + * + * This interface relates to Identity. + */ +interface NamespaceMatch +{ + /** + * Looks up the match builder with identification $id and returns it. + * + * @param string $id The identification of the match builder + * + * @return Match + */ + public function lookupId($id); + + /** + * Registers the match builder $builder with the identification $id. The + * builder can later be looked up using lookupId() to figure out if it + * has been invoked. + * + * @param string $id The identification of the match builder + * @param Match $builder The builder which is being registered + */ + public function registerId($id, Match $builder); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/ParametersMatch.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/ParametersMatch.php new file mode 100644 index 0000000..957ded1 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/ParametersMatch.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Matcher\AnyParameters; + +/** + * Builder interface for parameter matchers. + */ +interface ParametersMatch extends Match +{ + /** + * Sets the parameters to match for, each parameter to this function will + * be part of match. To perform specific matches or constraints create a + * new PHPUnit\Framework\Constraint\Constraint and use it for the parameter. + * If the parameter value is not a constraint it will use the + * PHPUnit\Framework\Constraint\IsEqual for the value. + * + * Some examples: + * + * // match first parameter with value 2 + * $b->with(2); + * // match first parameter with value 'smock' and second identical to 42 + * $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42)); + * + * + * @return ParametersMatch + */ + public function with(...$arguments); + + /** + * Sets a matcher which allows any kind of parameters. + * + * Some examples: + * + * // match any number of parameters + * $b->withAnyParameters(); + * + * + * @return AnyParameters + */ + public function withAnyParameters(); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Stub.php b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Stub.php new file mode 100644 index 0000000..ad9e6c1 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Builder/Stub.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Builder; + +use PHPUnit\Framework\MockObject\Stub as BaseStub; + +/** + * Builder interface for stubs which are actions replacing an invocation. + */ +interface Stub extends Identity +{ + /** + * Stubs the matching method with the stub object $stub. Any invocations of + * the matched method will now be handled by the stub instead. + * + * @return Identity + */ + public function will(BaseStub $stub); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Exception/BadMethodCallException.php b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/BadMethodCallException.php new file mode 100644 index 0000000..c0a0128 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/BadMethodCallException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +class BadMethodCallException extends \BadMethodCallException implements Exception +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Exception/Exception.php b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/Exception.php new file mode 100644 index 0000000..bc94225 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/Exception.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * Interface for exceptions used by PHPUnit_MockObject. + */ +interface Exception +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Exception/RuntimeException.php b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/RuntimeException.php new file mode 100644 index 0000000..b286736 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Exception/RuntimeException.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/ForwardCompatibility/MockObject.php b/.phpunit/phpunit-7/src/Framework/MockObject/ForwardCompatibility/MockObject.php new file mode 100644 index 0000000..f020e8c --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/ForwardCompatibility/MockObject.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit_Framework_MockObject_MockObject; + +interface MockObject extends PHPUnit_Framework_MockObject_MockObject +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator.php b/.phpunit/phpunit-7/src/Framework/MockObject/Generator.php new file mode 100644 index 0000000..14cf9e7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator.php @@ -0,0 +1,971 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use Doctrine\Instantiator\Exception\ExceptionInterface as InstantiatorException; +use Doctrine\Instantiator\Instantiator; +use Iterator; +use IteratorAggregate; +use PHPUnit\Framework\Exception; +use PHPUnit\Util\InvalidArgumentHelper; +use ReflectionClass; +use ReflectionMethod; +use SoapClient; +use Text_Template; +use Traversable; + +/** + * Mock Object Code Generator + */ +class Generator +{ + /** + * @var array + */ + private const BLACKLISTED_METHOD_NAMES = [ + '__CLASS__' => true, + '__DIR__' => true, + '__FILE__' => true, + '__FUNCTION__' => true, + '__LINE__' => true, + '__METHOD__' => true, + '__NAMESPACE__' => true, + '__TRAIT__' => true, + '__clone' => true, + '__halt_compiler' => true, + ]; + + /** + * @var array + */ + private static $cache = []; + + /** + * @var Text_Template[] + */ + private static $templates = []; + + /** + * Returns a mock object for the specified class. + * + * @param string|string[] $type + * @param array $methods + * @param string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param bool $cloneArguments + * @param bool $callOriginalMethods + * @param object $proxyTarget + * @param bool $allowMockingUnknownTypes + * @param bool $returnValueGeneration + * + * @throws Exception + * @throws RuntimeException + * @throws \PHPUnit\Framework\Exception + * @throws \ReflectionException + * + * @return MockObject + */ + public function getMock($type, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false, $proxyTarget = null, $allowMockingUnknownTypes = true, $returnValueGeneration = true) + { + if (!\is_array($type) && !\is_string($type)) { + throw InvalidArgumentHelper::factory(1, 'array or string'); + } + + if (!\is_string($mockClassName)) { + throw InvalidArgumentHelper::factory(4, 'string'); + } + + if (!\is_array($methods) && null !== $methods) { + throw InvalidArgumentHelper::factory(2, 'array', $methods); + } + + if ($type === 'Traversable' || $type === '\\Traversable') { + $type = 'Iterator'; + } + + if (\is_array($type)) { + $type = \array_unique( + \array_map( + function ($type) { + if ($type === 'Traversable' || + $type === '\\Traversable' || + $type === '\\Iterator') { + return 'Iterator'; + } + + return $type; + }, + $type + ) + ); + } + + if (!$allowMockingUnknownTypes) { + if (\is_array($type)) { + foreach ($type as $_type) { + if (!\class_exists($_type, $callAutoload) && + !\interface_exists($_type, $callAutoload)) { + throw new RuntimeException( + \sprintf( + 'Cannot stub or mock class or interface "%s" which does not exist', + $_type + ) + ); + } + } + } else { + if (!\class_exists($type, $callAutoload) && + !\interface_exists($type, $callAutoload) + ) { + throw new RuntimeException( + \sprintf( + 'Cannot stub or mock class or interface "%s" which does not exist', + $type + ) + ); + } + } + } + + if (null !== $methods) { + foreach ($methods as $method) { + if (!\preg_match('~[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*~', $method)) { + throw new RuntimeException( + \sprintf( + 'Cannot stub or mock method with invalid name "%s"', + $method + ) + ); + } + } + + if ($methods !== \array_unique($methods)) { + throw new RuntimeException( + \sprintf( + 'Cannot stub or mock using a method list that contains duplicates: "%s" (duplicate: "%s")', + \implode(', ', $methods), + \implode(', ', \array_unique(\array_diff_assoc($methods, \array_unique($methods)))) + ) + ); + } + } + + if ($mockClassName !== '' && \class_exists($mockClassName, false)) { + $reflect = new ReflectionClass($mockClassName); + + if (!$reflect->implementsInterface(MockObject::class)) { + throw new RuntimeException( + \sprintf( + 'Class "%s" already exists.', + $mockClassName + ) + ); + } + } + + if ($callOriginalConstructor === false && $callOriginalMethods === true) { + throw new RuntimeException( + 'Proxying to original methods requires invoking the original constructor' + ); + } + + $mock = $this->generate( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + + return $this->getObject( + $mock['code'], + $mock['mockClassName'], + $type, + $callOriginalConstructor, + $callAutoload, + $arguments, + $callOriginalMethods, + $proxyTarget, + $returnValueGeneration + ); + } + + /** + * Returns a mock object for the specified abstract class with all abstract + * methods of the class mocked. Concrete methods to mock can be specified with + * the last parameter + * + * @param string $originalClassName + * @param string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param array $mockedMethods + * @param bool $cloneArguments + * + * @throws \ReflectionException + * @throws RuntimeException + * @throws Exception + * + * @return MockObject + */ + public function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true) + { + if (!\is_string($originalClassName)) { + throw InvalidArgumentHelper::factory(1, 'string'); + } + + if (!\is_string($mockClassName)) { + throw InvalidArgumentHelper::factory(3, 'string'); + } + + if (\class_exists($originalClassName, $callAutoload) || + \interface_exists($originalClassName, $callAutoload)) { + $reflector = new ReflectionClass($originalClassName); + $methods = $mockedMethods; + + foreach ($reflector->getMethods() as $method) { + if ($method->isAbstract() && !\in_array($method->getName(), $methods, true)) { + $methods[] = $method->getName(); + } + } + + if (empty($methods)) { + $methods = null; + } + + return $this->getMock( + $originalClassName, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments + ); + } + + throw new RuntimeException( + \sprintf('Class "%s" does not exist.', $originalClassName) + ); + } + + /** + * Returns a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @param string $traitName + * @param string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param array $mockedMethods + * @param bool $cloneArguments + * + * @throws \ReflectionException + * @throws RuntimeException + * @throws Exception + * + * @return MockObject + */ + public function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true) + { + if (!\is_string($traitName)) { + throw InvalidArgumentHelper::factory(1, 'string'); + } + + if (!\is_string($mockClassName)) { + throw InvalidArgumentHelper::factory(3, 'string'); + } + + if (!\trait_exists($traitName, $callAutoload)) { + throw new RuntimeException( + \sprintf( + 'Trait "%s" does not exist.', + $traitName + ) + ); + } + + $className = $this->generateClassName( + $traitName, + '', + 'Trait_' + ); + + $classTemplate = $this->getTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => 'abstract ', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ] + ); + + $this->evalClass( + $classTemplate->render(), + $className['className'] + ); + + return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments); + } + + /** + * Returns an object for the specified trait. + * + * @param string $traitName + * @param string $traitClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * + * @throws \ReflectionException + * @throws RuntimeException + * @throws Exception + * + * @return object + */ + public function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true) + { + if (!\is_string($traitName)) { + throw InvalidArgumentHelper::factory(1, 'string'); + } + + if (!\is_string($traitClassName)) { + throw InvalidArgumentHelper::factory(3, 'string'); + } + + if (!\trait_exists($traitName, $callAutoload)) { + throw new RuntimeException( + \sprintf( + 'Trait "%s" does not exist.', + $traitName + ) + ); + } + + $className = $this->generateClassName( + $traitName, + $traitClassName, + 'Trait_' + ); + + $classTemplate = $this->getTemplate('trait_class.tpl'); + + $classTemplate->setVar( + [ + 'prologue' => '', + 'class_name' => $className['className'], + 'trait_name' => $traitName, + ] + ); + + return $this->getObject($classTemplate->render(), $className['className']); + } + + /** + * @param array|string $type + * @param array $methods + * @param string $mockClassName + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param bool $cloneArguments + * @param bool $callOriginalMethods + * + * @throws \ReflectionException + * @throws \PHPUnit\Framework\MockObject\RuntimeException + * + * @return array + */ + public function generate($type, array $methods = null, $mockClassName = '', $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false) + { + if (\is_array($type)) { + \sort($type); + } + + if ($mockClassName !== '') { + return $this->generateMock( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + } + $key = \md5( + \is_array($type) ? \implode('_', $type) : $type . + \serialize($methods) . + \serialize($callOriginalClone) . + \serialize($cloneArguments) . + \serialize($callOriginalMethods) + ); + + if (!isset(self::$cache[$key])) { + self::$cache[$key] = $this->generateMock( + $type, + $methods, + $mockClassName, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + } + + return self::$cache[$key]; + } + + /** + * @param string $wsdlFile + * @param string $className + * + * @throws RuntimeException + * + * @return string + */ + public function generateClassFromWsdl($wsdlFile, $className, array $methods = [], array $options = []) + { + if (!\extension_loaded('soap')) { + throw new RuntimeException( + 'The SOAP extension is required to generate a mock object from WSDL.' + ); + } + + $options = \array_merge($options, ['cache_wsdl' => \WSDL_CACHE_NONE]); + $client = new SoapClient($wsdlFile, $options); + $_methods = \array_unique($client->__getFunctions()); + unset($client); + + \sort($_methods); + + $methodTemplate = $this->getTemplate('wsdl_method.tpl'); + $methodsBuffer = ''; + + foreach ($_methods as $method) { + \preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*\(/', $method, $matches, \PREG_OFFSET_CAPTURE); + $lastFunction = \array_pop($matches[0]); + $nameStart = $lastFunction[1]; + $nameEnd = $nameStart + \strlen($lastFunction[0]) - 1; + $name = \str_replace('(', '', $lastFunction[0]); + + if (empty($methods) || \in_array($name, $methods, true)) { + $args = \explode( + ',', + \str_replace(')', '', \substr($method, $nameEnd + 1)) + ); + + foreach (\range(0, \count($args) - 1) as $i) { + $args[$i] = \substr($args[$i], \strpos($args[$i], '$')); + } + + $methodTemplate->setVar( + [ + 'method_name' => $name, + 'arguments' => \implode(', ', $args), + ] + ); + + $methodsBuffer .= $methodTemplate->render(); + } + } + + $optionsBuffer = '['; + + foreach ($options as $key => $value) { + $optionsBuffer .= $key . ' => ' . $value; + } + + $optionsBuffer .= ']'; + + $classTemplate = $this->getTemplate('wsdl_class.tpl'); + $namespace = ''; + + if (\strpos($className, '\\') !== false) { + $parts = \explode('\\', $className); + $className = \array_pop($parts); + $namespace = 'namespace ' . \implode('\\', $parts) . ';' . "\n\n"; + } + + $classTemplate->setVar( + [ + 'namespace' => $namespace, + 'class_name' => $className, + 'wsdl' => $wsdlFile, + 'options' => $optionsBuffer, + 'methods' => $methodsBuffer, + ] + ); + + return $classTemplate->render(); + } + + /** + * @param string $className + * + * @throws \ReflectionException + * + * @return string[] + */ + public function getClassMethods($className): array + { + $class = new ReflectionClass($className); + $methods = []; + + foreach ($class->getMethods() as $method) { + if ($method->isPublic() || $method->isAbstract()) { + $methods[] = $method->getName(); + } + } + + return $methods; + } + + /** + * @throws \ReflectionException + * + * @return MockMethod[] + */ + public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array + { + $class = new ReflectionClass($className); + $methods = []; + + foreach ($class->getMethods() as $method) { + if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) { + $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); + } + } + + return $methods; + } + + /** + * @param string $code + * @param string $className + * @param array|string $type + * @param bool $callOriginalConstructor + * @param bool $callAutoload + * @param bool $callOriginalMethods + * @param object $proxyTarget + * @param bool $returnValueGeneration + * + * @throws \ReflectionException + * @throws RuntimeException + * + * @return MockObject + */ + private function getObject($code, $className, $type = '', $callOriginalConstructor = false, $callAutoload = false, array $arguments = [], $callOriginalMethods = false, $proxyTarget = null, $returnValueGeneration = true) + { + $this->evalClass($code, $className); + + if ($callOriginalConstructor && + \is_string($type) && + !\interface_exists($type, $callAutoload)) { + if (\count($arguments) === 0) { + $object = new $className; + } else { + $class = new ReflectionClass($className); + $object = $class->newInstanceArgs($arguments); + } + } else { + try { + $instantiator = new Instantiator; + $object = $instantiator->instantiate($className); + } catch (InstantiatorException $exception) { + throw new RuntimeException($exception->getMessage()); + } + } + + if ($callOriginalMethods) { + if (!\is_object($proxyTarget)) { + if (\count($arguments) === 0) { + $proxyTarget = new $type; + } else { + $class = new ReflectionClass($type); + $proxyTarget = $class->newInstanceArgs($arguments); + } + } + + $object->__phpunit_setOriginalObject($proxyTarget); + } + + if ($object instanceof MockObject) { + $object->__phpunit_setReturnValueGeneration($returnValueGeneration); + } + + return $object; + } + + /** + * @param string $code + * @param string $className + */ + private function evalClass($code, $className): void + { + if (!\class_exists($className, false)) { + eval($code); + } + } + + /** + * @param array|string $type + * @param null|array $explicitMethods + * @param string $mockClassName + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param bool $cloneArguments + * @param bool $callOriginalMethods + * + * @throws \InvalidArgumentException + * @throws \ReflectionException + * @throws RuntimeException + * + * @return array + */ + private function generateMock($type, $explicitMethods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods) + { + $classTemplate = $this->getTemplate('mocked_class.tpl'); + + $additionalInterfaces = []; + $cloneTemplate = ''; + $isClass = false; + $isInterface = false; + $class = null; + $mockMethods = new MockMethodSet; + + if (\is_array($type)) { + $interfaceMethods = []; + + foreach ($type as $_type) { + if (!\interface_exists($_type, $callAutoload)) { + throw new RuntimeException( + \sprintf( + 'Interface "%s" does not exist.', + $_type + ) + ); + } + + $additionalInterfaces[] = $_type; + $typeClass = new ReflectionClass($_type); + + foreach ($this->getClassMethods($_type) as $method) { + if (\in_array($method, $interfaceMethods, true)) { + throw new RuntimeException( + \sprintf( + 'Duplicate method "%s" not allowed.', + $method + ) + ); + } + + $methodReflection = $typeClass->getMethod($method); + + if ($this->canMockMethod($methodReflection)) { + $mockMethods->addMethods( + MockMethod::fromReflection($methodReflection, $callOriginalMethods, $cloneArguments) + ); + + $interfaceMethods[] = $method; + } + } + } + + unset($interfaceMethods); + } + + $mockClassName = $this->generateClassName( + $type, + $mockClassName, + 'Mock_' + ); + + if (\class_exists($mockClassName['fullClassName'], $callAutoload)) { + $isClass = true; + } elseif (\interface_exists($mockClassName['fullClassName'], $callAutoload)) { + $isInterface = true; + } + + if (!$isClass && !$isInterface) { + $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n"; + + if (!empty($mockClassName['namespaceName'])) { + $prologue = 'namespace ' . $mockClassName['namespaceName'] . + " {\n\n" . $prologue . "}\n\n" . + "namespace {\n\n"; + + $epilogue = "\n\n}"; + } + + $cloneTemplate = $this->getTemplate('mocked_clone.tpl'); + } else { + $class = new ReflectionClass($mockClassName['fullClassName']); + + if ($class->isFinal()) { + throw new RuntimeException( + \sprintf( + 'Class "%s" is declared "final" and cannot be mocked.', + $mockClassName['fullClassName'] + ) + ); + } + + // @see https://github.com/sebastianbergmann/phpunit/issues/2995 + if ($isInterface && $class->implementsInterface(\Throwable::class)) { + $additionalInterfaces[] = $class->getName(); + $isInterface = false; + + $mockClassName = $this->generateClassName( + \Exception::class, + '', + 'Mock_' + ); + + $class = new ReflectionClass($mockClassName['fullClassName']); + } + + // https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103 + if ($isInterface && $class->implementsInterface(Traversable::class) && + !$class->implementsInterface(Iterator::class) && + !$class->implementsInterface(IteratorAggregate::class)) { + $additionalInterfaces[] = Iterator::class; + + $mockMethods->addMethods( + ...$this->mockClassMethods(Iterator::class, $callOriginalMethods, $cloneArguments) + ); + } + + if ($class->hasMethod('__clone')) { + $cloneMethod = $class->getMethod('__clone'); + + if (!$cloneMethod->isFinal()) { + if ($callOriginalClone && !$isInterface) { + $cloneTemplate = $this->getTemplate('unmocked_clone.tpl'); + } else { + $cloneTemplate = $this->getTemplate('mocked_clone.tpl'); + } + } + } else { + $cloneTemplate = $this->getTemplate('mocked_clone.tpl'); + } + } + + if (\is_object($cloneTemplate)) { + $cloneTemplate = $cloneTemplate->render(); + } + + if ($explicitMethods === [] && + ($isClass || $isInterface)) { + $mockMethods->addMethods( + ...$this->mockClassMethods($mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments) + ); + } + + if (\is_array($explicitMethods)) { + foreach ($explicitMethods as $methodName) { + if ($class !== null && $class->hasMethod($methodName)) { + $method = $class->getMethod($methodName); + + if ($this->canMockMethod($method)) { + $mockMethods->addMethods( + MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments) + ); + } + } else { + $mockMethods->addMethods( + MockMethod::fromName( + $mockClassName['fullClassName'], + $methodName, + $cloneArguments + ) + ); + } + } + } + + $mockedMethods = ''; + $configurable = []; + + /** @var MockMethod $mockMethod */ + foreach ($mockMethods->asArray() as $mockMethod) { + $mockedMethods .= $mockMethod->generateCode(); + $configurable[] = \strtolower($mockMethod->getName()); + } + + $method = ''; + + if (!$mockMethods->hasMethod('method') && (!isset($class) || !$class->hasMethod('method'))) { + $methodTemplate = $this->getTemplate('mocked_class_method.tpl'); + + $method = $methodTemplate->render(); + } + + $classTemplate->setVar( + [ + 'prologue' => $prologue ?? '', + 'epilogue' => $epilogue ?? '', + 'class_declaration' => $this->generateMockClassDeclaration( + $mockClassName, + $isInterface, + $additionalInterfaces + ), + 'clone' => $cloneTemplate, + 'mock_class_name' => $mockClassName['className'], + 'mocked_methods' => $mockedMethods, + 'method' => $method, + 'configurable' => '[' . \implode( + ', ', + \array_map( + function ($m) { + return '\'' . $m . '\''; + }, + $configurable + ) + ) . ']', + ] + ); + + return [ + 'code' => $classTemplate->render(), + 'mockClassName' => $mockClassName['className'], + ]; + } + + /** + * @param array|string $type + * @param string $className + * @param string $prefix + * + * @return array + */ + private function generateClassName($type, $className, $prefix) + { + if (\is_array($type)) { + $type = \implode('_', $type); + } + + if ($type[0] === '\\') { + $type = \substr($type, 1); + } + + $classNameParts = \explode('\\', $type); + + if (\count($classNameParts) > 1) { + $type = \array_pop($classNameParts); + $namespaceName = \implode('\\', $classNameParts); + $fullClassName = $namespaceName . '\\' . $type; + } else { + $namespaceName = ''; + $fullClassName = $type; + } + + if ($className === '') { + do { + $className = $prefix . $type . '_' . + \substr(\md5(\mt_rand()), 0, 8); + } while (\class_exists($className, false)); + } + + return [ + 'className' => $className, + 'originalClassName' => $type, + 'fullClassName' => $fullClassName, + 'namespaceName' => $namespaceName, + ]; + } + + /** + * @param bool $isInterface + * + * @return string + */ + private function generateMockClassDeclaration(array $mockClassName, $isInterface, array $additionalInterfaces = []) + { + $buffer = 'class '; + + $additionalInterfaces[] = MockObject::class; + $interfaces = \implode(', ', $additionalInterfaces); + + if ($isInterface) { + $buffer .= \sprintf( + '%s implements %s', + $mockClassName['className'], + $interfaces + ); + + if (!\in_array($mockClassName['originalClassName'], $additionalInterfaces)) { + $buffer .= ', '; + + if (!empty($mockClassName['namespaceName'])) { + $buffer .= $mockClassName['namespaceName'] . '\\'; + } + + $buffer .= $mockClassName['originalClassName']; + } + } else { + $buffer .= \sprintf( + '%s extends %s%s implements %s', + $mockClassName['className'], + !empty($mockClassName['namespaceName']) ? $mockClassName['namespaceName'] . '\\' : '', + $mockClassName['originalClassName'], + $interfaces + ); + } + + return $buffer; + } + + /** + * @return bool + */ + private function canMockMethod(ReflectionMethod $method) + { + return !($method->isConstructor() || $method->isFinal() || $method->isPrivate() || $this->isMethodNameBlacklisted($method->getName())); + } + + /** + * Returns whether a method name is blacklisted + * + * @param string $name + * + * @return bool + */ + private function isMethodNameBlacklisted($name) + { + return isset(self::BLACKLISTED_METHOD_NAMES[$name]); + } + + /** + * @param string $template + * + * @throws \InvalidArgumentException + * + * @return Text_Template + */ + private function getTemplate($template) + { + $filename = __DIR__ . \DIRECTORY_SEPARATOR . 'Generator' . \DIRECTORY_SEPARATOR . $template; + + if (!isset(self::$templates[$filename])) { + self::$templates[$filename] = new Text_Template($filename); + } + + return self::$templates[$filename]; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/deprecation.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/deprecation.tpl.dist new file mode 100644 index 0000000..5bf06f5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/deprecation.tpl.dist @@ -0,0 +1,2 @@ + + @trigger_error({deprecation}, E_USER_DEPRECATED); diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class.tpl.dist new file mode 100644 index 0000000..4b68a2b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class.tpl.dist @@ -0,0 +1,46 @@ +{prologue}{class_declaration} +{ + private $__phpunit_invocationMocker; + private $__phpunit_originalObject; + private $__phpunit_configurable = {configurable}; + private $__phpunit_returnValueGeneration = true; + +{clone}{mocked_methods} + public function expects(\PHPUnit\Framework\MockObject\Matcher\Invocation $matcher) + { + return $this->__phpunit_getInvocationMocker()->expects($matcher); + } +{method} + public function __phpunit_setOriginalObject($originalObject) + { + $this->__phpunit_originalObject = $originalObject; + } + + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration) + { + $this->__phpunit_returnValueGeneration = $returnValueGeneration; + } + + public function __phpunit_getInvocationMocker() + { + if ($this->__phpunit_invocationMocker === null) { + $this->__phpunit_invocationMocker = new \PHPUnit\Framework\MockObject\InvocationMocker($this->__phpunit_configurable, $this->__phpunit_returnValueGeneration); + } + + return $this->__phpunit_invocationMocker; + } + + public function __phpunit_hasMatchers() + { + return $this->__phpunit_getInvocationMocker()->hasMatchers(); + } + + public function __phpunit_verify(bool $unsetInvocationMocker = true) + { + $this->__phpunit_getInvocationMocker()->verify(); + + if ($unsetInvocationMocker) { + $this->__phpunit_invocationMocker = null; + } + } +}{epilogue} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class_method.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class_method.tpl.dist new file mode 100644 index 0000000..d6a036f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_class_method.tpl.dist @@ -0,0 +1,8 @@ + + public function method() + { + $any = new \PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount; + $expects = $this->expects($any); + + return call_user_func_array([$expects, 'method'], func_get_args()); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_clone.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_clone.tpl.dist new file mode 100644 index 0000000..bd846de --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_clone.tpl.dist @@ -0,0 +1,4 @@ + public function __clone() + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker(); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method.tpl.dist new file mode 100644 index 0000000..3adf2f0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method.tpl.dist @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_delim}{return_type} + {{deprecation} + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $__phpunit_result = $this->__phpunit_getInvocationMocker()->invoke( + new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + + return $__phpunit_result; + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method_void.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method_void.tpl.dist new file mode 100644 index 0000000..3813fe4 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_method_void.tpl.dist @@ -0,0 +1,20 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_delim}{return_type} + {{deprecation} + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationMocker()->invoke( + new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_static_method.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_static_method.tpl.dist new file mode 100644 index 0000000..56b561b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/mocked_static_method.tpl.dist @@ -0,0 +1,5 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_delim}{return_type} + { + throw new \PHPUnit\Framework\MockObject\BadMethodCallException('Static method "{method_name}" cannot be invoked on mock object'); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method.tpl.dist new file mode 100644 index 0000000..fd9e71b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method.tpl.dist @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_delim}{return_type} + { + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationMocker()->invoke( + new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + + return call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method_void.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method_void.tpl.dist new file mode 100644 index 0000000..63c337b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/proxied_method_void.tpl.dist @@ -0,0 +1,22 @@ + + {modifier} function {reference}{method_name}({arguments_decl}){return_delim}{return_type} + { + $__phpunit_arguments = [{arguments_call}]; + $__phpunit_count = func_num_args(); + + if ($__phpunit_count > {arguments_count}) { + $__phpunit_arguments_tmp = func_get_args(); + + for ($__phpunit_i = {arguments_count}; $__phpunit_i < $__phpunit_count; $__phpunit_i++) { + $__phpunit_arguments[] = $__phpunit_arguments_tmp[$__phpunit_i]; + } + } + + $this->__phpunit_getInvocationMocker()->invoke( + new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation( + '{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments} + ) + ); + + call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/trait_class.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/trait_class.tpl.dist new file mode 100644 index 0000000..4143b0f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/trait_class.tpl.dist @@ -0,0 +1,4 @@ +{prologue}class {class_name} +{ + use {trait_name}; +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/unmocked_clone.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/unmocked_clone.tpl.dist new file mode 100644 index 0000000..fa0e70a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/unmocked_clone.tpl.dist @@ -0,0 +1,5 @@ + public function __clone() + { + $this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker(); + parent::__clone(); + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_class.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_class.tpl.dist new file mode 100644 index 0000000..cc69fd3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_class.tpl.dist @@ -0,0 +1,7 @@ +{namespace}class {class_name} extends \SoapClient +{ + public function __construct($wsdl, array $options) + { + parent::__construct('{wsdl}', $options); + } +{methods}} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_method.tpl.dist b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_method.tpl.dist new file mode 100644 index 0000000..bb16e76 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Generator/wsdl_method.tpl.dist @@ -0,0 +1,4 @@ + + public function {method_name}({arguments}) + { + } diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/Invocation.php b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/Invocation.php new file mode 100644 index 0000000..7373867 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/Invocation.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * Interface for invocations. + */ +interface Invocation +{ + /** + * @return mixed mocked return value + */ + public function generateReturnValue(); + + public function getClassName(): string; + + public function getMethodName(): string; + + public function getParameters(): array; + + public function getReturnType(): string; + + public function isReturnTypeNullable(): bool; +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/ObjectInvocation.php b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/ObjectInvocation.php new file mode 100644 index 0000000..eb4475f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/ObjectInvocation.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Invocation; + +/** + * Represents a non-static invocation. + */ +class ObjectInvocation extends StaticInvocation +{ + /** + * @var object + */ + private $object; + + /** + * @param string $className + * @param string $methodName + * @param string $returnType + * @param object $object + * @param bool $cloneObjects + */ + public function __construct($className, $methodName, array $parameters, $returnType, $object, $cloneObjects = false) + { + parent::__construct($className, $methodName, $parameters, $returnType, $cloneObjects); + + $this->object = $object; + } + + public function getObject() + { + return $this->object; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/StaticInvocation.php b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/StaticInvocation.php new file mode 100644 index 0000000..61be600 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Invocation/StaticInvocation.php @@ -0,0 +1,258 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Invocation; + +use PHPUnit\Framework\MockObject\Generator; +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\SelfDescribing; +use ReflectionObject; +use SebastianBergmann\Exporter\Exporter; + +/** + * Represents a static invocation. + */ +class StaticInvocation implements Invocation, SelfDescribing +{ + /** + * @var array + */ + private static $uncloneableExtensions = [ + 'mysqli' => true, + 'SQLite' => true, + 'sqlite3' => true, + 'tidy' => true, + 'xmlwriter' => true, + 'xsl' => true, + ]; + + /** + * @var array + */ + private static $uncloneableClasses = [ + 'Closure', + 'COMPersistHelper', + 'IteratorIterator', + 'RecursiveIteratorIterator', + 'SplFileObject', + 'PDORow', + 'ZipArchive', + ]; + + /** + * @var string + */ + private $className; + + /** + * @var string + */ + private $methodName; + + /** + * @var array + */ + private $parameters; + + /** + * @var string + */ + private $returnType; + + /** + * @var bool + */ + private $isReturnTypeNullable = false; + + /** + * @param string $className + * @param string $methodName + * @param string $returnType + * @param bool $cloneObjects + */ + public function __construct($className, $methodName, array $parameters, $returnType, $cloneObjects = false) + { + $this->className = $className; + $this->methodName = $methodName; + $this->parameters = $parameters; + + if (\strtolower($methodName) === '__tostring') { + $returnType = 'string'; + } + + if (\strpos($returnType, '?') === 0) { + $returnType = \substr($returnType, 1); + $this->isReturnTypeNullable = true; + } + + $this->returnType = $returnType; + + if (!$cloneObjects) { + return; + } + + foreach ($this->parameters as $key => $value) { + if (\is_object($value)) { + $this->parameters[$key] = $this->cloneObject($value); + } + } + } + + public function getClassName(): string + { + return $this->className; + } + + public function getMethodName(): string + { + return $this->methodName; + } + + public function getParameters(): array + { + return $this->parameters; + } + + public function getReturnType(): string + { + return $this->returnType; + } + + public function isReturnTypeNullable(): bool + { + return $this->isReturnTypeNullable; + } + + /** + * @throws \ReflectionException + * @throws \PHPUnit\Framework\MockObject\RuntimeException + * @throws \PHPUnit\Framework\Exception + * + * @return mixed Mocked return value + */ + public function generateReturnValue() + { + if ($this->isReturnTypeNullable) { + return; + } + + switch (\strtolower($this->returnType)) { + case '': + case 'void': + return; + + case 'string': + return ''; + + case 'float': + return 0.0; + + case 'int': + return 0; + + case 'bool': + return false; + + case 'array': + return []; + + case 'object': + return new \stdClass; + + case 'callable': + case 'closure': + return function (): void { + }; + + case 'traversable': + case 'generator': + case 'iterable': + $generator = function () { + yield; + }; + + return $generator(); + + default: + $generator = new Generator; + + return $generator->getMock($this->returnType, [], [], '', false); + } + } + + public function toString(): string + { + $exporter = new Exporter; + + return \sprintf( + '%s::%s(%s)%s', + $this->className, + $this->methodName, + \implode( + ', ', + \array_map( + [$exporter, 'shortenedExport'], + $this->parameters + ) + ), + $this->returnType ? \sprintf(': %s', $this->returnType) : '' + ); + } + + /** + * @param object $original + * + * @return object + */ + private function cloneObject($original) + { + $cloneable = null; + $object = new ReflectionObject($original); + + // Check the blacklist before asking PHP reflection to work around + // https://bugs.php.net/bug.php?id=53967 + if ($object->isInternal() && + isset(self::$uncloneableExtensions[$object->getExtensionName()])) { + $cloneable = false; + } + + if ($cloneable === null) { + foreach (self::$uncloneableClasses as $class) { + if ($original instanceof $class) { + $cloneable = false; + + break; + } + } + } + + if ($cloneable === null) { + $cloneable = $object->isCloneable(); + } + + if ($cloneable === null && $object->hasMethod('__clone')) { + $method = $object->getMethod('__clone'); + $cloneable = $method->isPublic(); + } + + if ($cloneable === null) { + $cloneable = true; + } + + if ($cloneable) { + try { + return clone $original; + } catch (\Exception $e) { + return $original; + } + } else { + return $original; + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/InvocationMocker.php b/.phpunit/phpunit-7/src/Framework/MockObject/InvocationMocker.php new file mode 100644 index 0000000..d93faaa --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/InvocationMocker.php @@ -0,0 +1,186 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use Exception; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker; +use PHPUnit\Framework\MockObject\Builder\Match; +use PHPUnit\Framework\MockObject\Builder\NamespaceMatch; +use PHPUnit\Framework\MockObject\Matcher\DeferredError; +use PHPUnit\Framework\MockObject\Matcher\Invocation as MatcherInvocation; +use PHPUnit\Framework\MockObject\Stub\MatcherCollection; + +/** + * Mocker for invocations which are sent from + * MockObject objects. + * + * Keeps track of all expectations and stubs as well as registering + * identifications for builders. + */ +class InvocationMocker implements MatcherCollection, Invokable, NamespaceMatch +{ + /** + * @var MatcherInvocation[] + */ + private $matchers = []; + + /** + * @var Match[] + */ + private $builderMap = []; + + /** + * @var string[] + */ + private $configurableMethods; + + /** + * @var bool + */ + private $returnValueGeneration; + + public function __construct(array $configurableMethods, bool $returnValueGeneration) + { + $this->configurableMethods = $configurableMethods; + $this->returnValueGeneration = $returnValueGeneration; + } + + public function addMatcher(MatcherInvocation $matcher): void + { + $this->matchers[] = $matcher; + } + + public function hasMatchers() + { + foreach ($this->matchers as $matcher) { + if ($matcher->hasMatchers()) { + return true; + } + } + + return false; + } + + /** + * @return null|bool + */ + public function lookupId($id) + { + if (isset($this->builderMap[$id])) { + return $this->builderMap[$id]; + } + } + + /** + * @throws RuntimeException + */ + public function registerId($id, Match $builder): void + { + if (isset($this->builderMap[$id])) { + throw new RuntimeException( + 'Match builder with id <' . $id . '> is already registered.' + ); + } + + $this->builderMap[$id] = $builder; + } + + /** + * @return BuilderInvocationMocker + */ + public function expects(MatcherInvocation $matcher) + { + return new BuilderInvocationMocker( + $this, + $matcher, + $this->configurableMethods + ); + } + + /** + * @throws Exception + */ + public function invoke(Invocation $invocation) + { + $exception = null; + $hasReturnValue = false; + $returnValue = null; + + foreach ($this->matchers as $match) { + try { + if ($match->matches($invocation)) { + $value = $match->invoked($invocation); + + if (!$hasReturnValue) { + $returnValue = $value; + $hasReturnValue = true; + } + } + } catch (Exception $e) { + $exception = $e; + } + } + + if ($exception !== null) { + throw $exception; + } + + if ($hasReturnValue) { + return $returnValue; + } + + if ($this->returnValueGeneration === false) { + $exception = new ExpectationFailedException( + \sprintf( + 'Return value inference disabled and no expectation set up for %s::%s()', + $invocation->getClassName(), + $invocation->getMethodName() + ) + ); + + if (\strtolower($invocation->getMethodName()) === '__tostring') { + $this->addMatcher(new DeferredError($exception)); + + return ''; + } + + throw $exception; + } + + return $invocation->generateReturnValue(); + } + + /** + * @return bool + */ + public function matches(Invocation $invocation) + { + foreach ($this->matchers as $matcher) { + if (!$matcher->matches($invocation)) { + return false; + } + } + + return true; + } + + /** + * @throws \PHPUnit\Framework\ExpectationFailedException + * + * @return bool + */ + public function verify() + { + foreach ($this->matchers as $matcher) { + $matcher->verify(); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Invokable.php b/.phpunit/phpunit-7/src/Framework/MockObject/Invokable.php new file mode 100644 index 0000000..3411895 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Invokable.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +/** + * Interface for classes which can be invoked. + * + * The invocation will be taken from a mock object and passed to an object + * of this class. + */ +interface Invokable extends Verifiable +{ + /** + * Invokes the invocation object $invocation so that it can be checked for + * expectations or matched against stubs. + * + * @param Invocation $invocation The invocation object passed from mock object + * + * @return object + */ + public function invoke(Invocation $invocation); + + /** + * Checks if the invocation matches. + * + * @param Invocation $invocation The invocation object passed from mock object + * + * @return bool + */ + public function matches(Invocation $invocation); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher.php new file mode 100644 index 0000000..e0552a6 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher.php @@ -0,0 +1,309 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Matcher\AnyInvokedCount; +use PHPUnit\Framework\MockObject\Matcher\AnyParameters; +use PHPUnit\Framework\MockObject\Matcher\Invocation as MatcherInvocation; +use PHPUnit\Framework\MockObject\Matcher\InvokedCount; +use PHPUnit\Framework\MockObject\Matcher\MethodName; +use PHPUnit\Framework\MockObject\Matcher\Parameters; +use PHPUnit\Framework\TestFailure; + +/** + * Main matcher which defines a full expectation using method, parameter and + * invocation matchers. + * This matcher encapsulates all the other matchers and allows the builder to + * set the specific matchers when the appropriate methods are called (once(), + * where() etc.). + * + * All properties are public so that they can easily be accessed by the builder. + */ +class Matcher implements MatcherInvocation +{ + /** + * @var MatcherInvocation + */ + private $invocationMatcher; + + /** + * @var mixed + */ + private $afterMatchBuilderId; + + /** + * @var bool + */ + private $afterMatchBuilderIsInvoked = false; + + /** + * @var MethodName + */ + private $methodNameMatcher; + + /** + * @var Parameters + */ + private $parametersMatcher; + + /** + * @var Stub + */ + private $stub; + + public function __construct(MatcherInvocation $invocationMatcher) + { + $this->invocationMatcher = $invocationMatcher; + } + + public function hasMatchers(): bool + { + return $this->invocationMatcher !== null && !$this->invocationMatcher instanceof AnyInvokedCount; + } + + public function hasMethodNameMatcher(): bool + { + return $this->methodNameMatcher !== null; + } + + public function getMethodNameMatcher(): MethodName + { + return $this->methodNameMatcher; + } + + public function setMethodNameMatcher(MethodName $matcher): void + { + $this->methodNameMatcher = $matcher; + } + + public function hasParametersMatcher(): bool + { + return $this->parametersMatcher !== null; + } + + public function getParametersMatcher(): Parameters + { + return $this->parametersMatcher; + } + + public function setParametersMatcher($matcher): void + { + $this->parametersMatcher = $matcher; + } + + public function setStub($stub): void + { + $this->stub = $stub; + } + + public function setAfterMatchBuilderId($id): void + { + $this->afterMatchBuilderId = $id; + } + + /** + * @throws \Exception + * @throws RuntimeException + * @throws ExpectationFailedException + */ + public function invoked(Invocation $invocation) + { + if ($this->invocationMatcher === null) { + throw new RuntimeException( + 'No invocation matcher is set' + ); + } + + if ($this->methodNameMatcher === null) { + throw new RuntimeException('No method matcher is set'); + } + + if ($this->afterMatchBuilderId !== null) { + $builder = $invocation->getObject() + ->__phpunit_getInvocationMocker() + ->lookupId($this->afterMatchBuilderId); + + if (!$builder) { + throw new RuntimeException( + \sprintf( + 'No builder found for match builder identification <%s>', + $this->afterMatchBuilderId + ) + ); + } + + $matcher = $builder->getMatcher(); + + if ($matcher && $matcher->invocationMatcher->hasBeenInvoked()) { + $this->afterMatchBuilderIsInvoked = true; + } + } + + $this->invocationMatcher->invoked($invocation); + + try { + if ($this->parametersMatcher !== null && + !$this->parametersMatcher->matches($invocation)) { + $this->parametersMatcher->verify(); + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + \sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameMatcher->toString(), + $this->invocationMatcher->toString(), + $e->getMessage() + ), + $e->getComparisonFailure() + ); + } + + if ($this->stub) { + return $this->stub->invoke($invocation); + } + + return $invocation->generateReturnValue(); + } + + /** + * @throws RuntimeException + * @throws ExpectationFailedException + * + * @return bool + */ + public function matches(Invocation $invocation) + { + if ($this->afterMatchBuilderId !== null) { + $builder = $invocation->getObject() + ->__phpunit_getInvocationMocker() + ->lookupId($this->afterMatchBuilderId); + + if (!$builder) { + throw new RuntimeException( + \sprintf( + 'No builder found for match builder identification <%s>', + $this->afterMatchBuilderId + ) + ); + } + + $matcher = $builder->getMatcher(); + + if (!$matcher) { + return false; + } + + if (!$matcher->invocationMatcher->hasBeenInvoked()) { + return false; + } + } + + if ($this->invocationMatcher === null) { + throw new RuntimeException( + 'No invocation matcher is set' + ); + } + + if ($this->methodNameMatcher === null) { + throw new RuntimeException('No method matcher is set'); + } + + if (!$this->invocationMatcher->matches($invocation)) { + return false; + } + + try { + if (!$this->methodNameMatcher->matches($invocation)) { + return false; + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + \sprintf( + "Expectation failed for %s when %s\n%s", + $this->methodNameMatcher->toString(), + $this->invocationMatcher->toString(), + $e->getMessage() + ), + $e->getComparisonFailure() + ); + } + + return true; + } + + /** + * @throws RuntimeException + * @throws ExpectationFailedException + */ + public function verify(): void + { + if ($this->invocationMatcher === null) { + throw new RuntimeException( + 'No invocation matcher is set' + ); + } + + if ($this->methodNameMatcher === null) { + throw new RuntimeException('No method matcher is set'); + } + + try { + $this->invocationMatcher->verify(); + + if ($this->parametersMatcher === null) { + $this->parametersMatcher = new AnyParameters; + } + + $invocationIsAny = $this->invocationMatcher instanceof AnyInvokedCount; + $invocationIsNever = $this->invocationMatcher instanceof InvokedCount && $this->invocationMatcher->isNever(); + + if (!$invocationIsAny && !$invocationIsNever) { + $this->parametersMatcher->verify(); + } + } catch (ExpectationFailedException $e) { + throw new ExpectationFailedException( + \sprintf( + "Expectation failed for %s when %s.\n%s", + $this->methodNameMatcher->toString(), + $this->invocationMatcher->toString(), + TestFailure::exceptionToString($e) + ) + ); + } + } + + public function toString(): string + { + $list = []; + + if ($this->invocationMatcher !== null) { + $list[] = $this->invocationMatcher->toString(); + } + + if ($this->methodNameMatcher !== null) { + $list[] = 'where ' . $this->methodNameMatcher->toString(); + } + + if ($this->parametersMatcher !== null) { + $list[] = 'and ' . $this->parametersMatcher->toString(); + } + + if ($this->afterMatchBuilderId !== null) { + $list[] = 'after ' . $this->afterMatchBuilderId; + } + + if ($this->stub !== null) { + $list[] = 'will ' . $this->stub->toString(); + } + + return \implode(' ', $list); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyInvokedCount.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyInvokedCount.php new file mode 100644 index 0000000..ddabf92 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyInvokedCount.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +/** + * Invocation matcher which checks if a method has been invoked zero or more + * times. This matcher will always match. + */ +class AnyInvokedCount extends InvokedRecorder +{ + public function toString(): string + { + return 'invoked zero or more times'; + } + + public function verify(): void + { + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyParameters.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyParameters.php new file mode 100644 index 0000000..48eb561 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/AnyParameters.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which allows any parameters to a method. + */ +class AnyParameters extends StatelessInvocation +{ + public function toString(): string + { + return 'with any parameters'; + } + + /** + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + return true; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/ConsecutiveParameters.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/ConsecutiveParameters.php new file mode 100644 index 0000000..344849d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/ConsecutiveParameters.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which looks for sets of specific parameters in the invocations. + * + * Checks the parameters of the incoming invocations, the parameter list is + * checked against the defined constraints in $parameters. If the constraint + * is met it will return true in matches(). + * + * It takes a list of match groups and and increases a call index after each invocation. + * So the first invocation uses the first group of constraints, the second the next and so on. + */ +class ConsecutiveParameters extends StatelessInvocation +{ + /** + * @var array + */ + private $parameterGroups = []; + + /** + * @var array + */ + private $invocations = []; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(array $parameterGroups) + { + foreach ($parameterGroups as $index => $parameters) { + foreach ($parameters as $parameter) { + if (!$parameter instanceof Constraint) { + $parameter = new IsEqual($parameter); + } + + $this->parameterGroups[$index][] = $parameter; + } + } + } + + public function toString(): string + { + return 'with consecutive parameters'; + } + + /** + * @throws \PHPUnit\Framework\ExpectationFailedException + * + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + $this->invocations[] = $invocation; + $callIndex = \count($this->invocations) - 1; + + $this->verifyInvocation($invocation, $callIndex); + + return false; + } + + public function verify(): void + { + foreach ($this->invocations as $callIndex => $invocation) { + $this->verifyInvocation($invocation, $callIndex); + } + } + + /** + * Verify a single invocation + * + * @param int $callIndex + * + * @throws ExpectationFailedException + */ + private function verifyInvocation(BaseInvocation $invocation, $callIndex): void + { + if (!isset($this->parameterGroups[$callIndex])) { + // no parameter assertion for this call index + return; + } + + if ($invocation === null) { + throw new ExpectationFailedException( + 'Mocked method does not exist.' + ); + } + + $parameters = $this->parameterGroups[$callIndex]; + + if (\count($invocation->getParameters()) < \count($parameters)) { + throw new ExpectationFailedException( + \sprintf( + 'Parameter count for invocation %s is too low.', + $invocation->toString() + ) + ); + } + + foreach ($parameters as $i => $parameter) { + $parameter->evaluate( + $invocation->getParameters()[$i], + \sprintf( + 'Parameter %s for invocation #%d %s does not match expected ' . + 'value.', + $i, + $callIndex, + $invocation->toString() + ) + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/DeferredError.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/DeferredError.php new file mode 100644 index 0000000..fae95e4 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/DeferredError.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +class DeferredError extends StatelessInvocation +{ + /** + * @var \Throwable + */ + private $exception; + + public function __construct(\Throwable $exception) + { + $this->exception = $exception; + } + + public function verify(): void + { + throw $this->exception; + } + + public function toString(): string + { + return ''; + } + + public function matches(BaseInvocation $invocation): bool + { + return true; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Invocation.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Invocation.php new file mode 100644 index 0000000..d3f93b2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Invocation.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Framework\MockObject\Verifiable; +use PHPUnit\Framework\SelfDescribing; + +/** + * Interface for classes which matches an invocation based on its + * method name, argument, order or call count. + */ +interface Invocation extends SelfDescribing, Verifiable +{ + /** + * Registers the invocation $invocation in the object as being invoked. + * This will only occur after matches() returns true which means the + * current invocation is the correct one. + * + * The matcher can store information from the invocation which can later + * be checked in verify(), or it can check the values directly and throw + * and exception if an expectation is not met. + * + * If the matcher is a stub it will also have a return value. + * + * @param BaseInvocation $invocation Object containing information on a mocked or stubbed method which was invoked + */ + public function invoked(BaseInvocation $invocation); + + /** + * Checks if the invocation $invocation matches the current rules. If it does + * the matcher will get the invoked() method called which should check if an + * expectation is met. + * + * @param BaseInvocation $invocation Object containing information on a mocked or stubbed method which was invoked + * + * @return bool + */ + public function matches(BaseInvocation $invocation); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtIndex.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtIndex.php new file mode 100644 index 0000000..2584ef3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtIndex.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which checks if a method was invoked at a certain index. + * + * If the expected index number does not match the current invocation index it + * will not match which means it skips all method and parameter matching. Only + * once the index is reached will the method and parameter start matching and + * verifying. + * + * If the index is never reached it will throw an exception in index. + */ +class InvokedAtIndex implements Invocation +{ + /** + * @var int + */ + private $sequenceIndex; + + /** + * @var int + */ + private $currentIndex = -1; + + /** + * @param int $sequenceIndex + */ + public function __construct($sequenceIndex) + { + $this->sequenceIndex = $sequenceIndex; + } + + public function toString(): string + { + return 'invoked at sequence index ' . $this->sequenceIndex; + } + + /** + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + $this->currentIndex++; + + return $this->currentIndex == $this->sequenceIndex; + } + + public function invoked(BaseInvocation $invocation): void + { + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + if ($this->currentIndex < $this->sequenceIndex) { + throw new ExpectationFailedException( + \sprintf( + 'The expected invocation at index %s was never reached.', + $this->sequenceIndex + ) + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php new file mode 100644 index 0000000..ada506f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastCount.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * Invocation matcher which checks if a method has been invoked at least + * N times. + */ +class InvokedAtLeastCount extends InvokedRecorder +{ + /** + * @var int + */ + private $requiredInvocations; + + /** + * @param int $requiredInvocations + */ + public function __construct($requiredInvocations) + { + $this->requiredInvocations = $requiredInvocations; + } + + public function toString(): string + { + return 'invoked at least ' . $this->requiredInvocations . ' times'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count < $this->requiredInvocations) { + throw new ExpectationFailedException( + 'Expected invocation at least ' . $this->requiredInvocations . + ' times but it occurred ' . $count . ' time(s).' + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php new file mode 100644 index 0000000..33b6b8f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtLeastOnce.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * Invocation matcher which checks if a method has been invoked at least one + * time. + * + * If the number of invocations is 0 it will throw an exception in verify. + */ +class InvokedAtLeastOnce extends InvokedRecorder +{ + public function toString(): string + { + return 'invoked at least once'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count < 1) { + throw new ExpectationFailedException( + 'Expected invocation at least once but it never occurred.' + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtMostCount.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtMostCount.php new file mode 100644 index 0000000..981ef36 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedAtMostCount.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * Invocation matcher which checks if a method has been invoked at least + * N times. + */ +class InvokedAtMostCount extends InvokedRecorder +{ + /** + * @var int + */ + private $allowedInvocations; + + /** + * @param int $allowedInvocations + */ + public function __construct($allowedInvocations) + { + $this->allowedInvocations = $allowedInvocations; + } + + public function toString(): string + { + return 'invoked at most ' . $this->allowedInvocations . ' times'; + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count > $this->allowedInvocations) { + throw new ExpectationFailedException( + 'Expected invocation at most ' . $this->allowedInvocations . + ' times but it occurred ' . $count . ' time(s).' + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedCount.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedCount.php new file mode 100644 index 0000000..f4cb1ab --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedCount.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which checks if a method has been invoked a certain amount + * of times. + * If the number of invocations exceeds the value it will immediately throw an + * exception, + * If the number is less it will later be checked in verify() and also throw an + * exception. + */ +class InvokedCount extends InvokedRecorder +{ + /** + * @var int + */ + private $expectedCount; + + /** + * @param int $expectedCount + */ + public function __construct($expectedCount) + { + $this->expectedCount = $expectedCount; + } + + /** + * @return bool + */ + public function isNever() + { + return $this->expectedCount === 0; + } + + public function toString(): string + { + return 'invoked ' . $this->expectedCount . ' time(s)'; + } + + /** + * @throws ExpectationFailedException + */ + public function invoked(BaseInvocation $invocation): void + { + parent::invoked($invocation); + + $count = $this->getInvocationCount(); + + if ($count > $this->expectedCount) { + $message = $invocation->toString() . ' '; + + switch ($this->expectedCount) { + case 0: + $message .= 'was not expected to be called.'; + + break; + + case 1: + $message .= 'was not expected to be called more than once.'; + + break; + + default: + $message .= \sprintf( + 'was not expected to be called more than %d times.', + $this->expectedCount + ); + } + + throw new ExpectationFailedException($message); + } + } + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(): void + { + $count = $this->getInvocationCount(); + + if ($count !== $this->expectedCount) { + throw new ExpectationFailedException( + \sprintf( + 'Method was expected to be called %d times, ' . + 'actually called %d times.', + $this->expectedCount, + $count + ) + ); + } + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedRecorder.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedRecorder.php new file mode 100644 index 0000000..216aae7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/InvokedRecorder.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Records invocations and provides convenience methods for checking them later + * on. + * This abstract class can be implemented by matchers which needs to check the + * number of times an invocation has occurred. + */ +abstract class InvokedRecorder implements Invocation +{ + /** + * @var BaseInvocation[] + */ + private $invocations = []; + + /** + * @return int + */ + public function getInvocationCount() + { + return \count($this->invocations); + } + + /** + * @return BaseInvocation[] + */ + public function getInvocations() + { + return $this->invocations; + } + + /** + * @return bool + */ + public function hasBeenInvoked() + { + return \count($this->invocations) > 0; + } + + public function invoked(BaseInvocation $invocation): void + { + $this->invocations[] = $invocation; + } + + /** + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + return true; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/MethodName.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/MethodName.php new file mode 100644 index 0000000..7aea38a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/MethodName.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; +use PHPUnit\Util\InvalidArgumentHelper; + +/** + * Invocation matcher which looks for a specific method name in the invocations. + * + * Checks the method name all incoming invocations, the name is checked against + * the defined constraint $constraint. If the constraint is met it will return + * true in matches(). + */ +class MethodName extends StatelessInvocation +{ + /** + * @var Constraint + */ + private $constraint; + + /** + * @param Constraint|string + * + * @throws Constraint + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($constraint) + { + if (!$constraint instanceof Constraint) { + if (!\is_string($constraint)) { + throw InvalidArgumentHelper::factory(1, 'string'); + } + + $constraint = new IsEqual( + $constraint, + 0, + 10, + false, + true + ); + } + + $this->constraint = $constraint; + } + + public function toString(): string + { + return 'method name ' . $this->constraint->toString(); + } + + /** + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + return $this->constraint->evaluate($invocation->getMethodName(), '', true); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Parameters.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Parameters.php new file mode 100644 index 0000000..a74e3a3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/Parameters.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\Constraint\Constraint; +use PHPUnit\Framework\Constraint\IsAnything; +use PHPUnit\Framework\Constraint\IsEqual; +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which looks for specific parameters in the invocations. + * + * Checks the parameters of all incoming invocations, the parameter list is + * checked against the defined constraints in $parameters. If the constraint + * is met it will return true in matches(). + */ +class Parameters extends StatelessInvocation +{ + /** + * @var Constraint[] + */ + private $parameters = []; + + /** + * @var BaseInvocation + */ + private $invocation; + + /** + * @var ExpectationFailedException + */ + private $parameterVerificationResult; + + /** + * @throws \PHPUnit\Framework\Exception + */ + public function __construct(array $parameters) + { + foreach ($parameters as $parameter) { + if (!($parameter instanceof Constraint)) { + $parameter = new IsEqual( + $parameter + ); + } + + $this->parameters[] = $parameter; + } + } + + public function toString(): string + { + $text = 'with parameter'; + + foreach ($this->parameters as $index => $parameter) { + if ($index > 0) { + $text .= ' and'; + } + + $text .= ' ' . $index . ' ' . $parameter->toString(); + } + + return $text; + } + + /** + * @throws \Exception + * + * @return bool + */ + public function matches(BaseInvocation $invocation) + { + $this->invocation = $invocation; + $this->parameterVerificationResult = null; + + try { + $this->parameterVerificationResult = $this->verify(); + + return $this->parameterVerificationResult; + } catch (ExpectationFailedException $e) { + $this->parameterVerificationResult = $e; + + throw $this->parameterVerificationResult; + } + } + + /** + * Checks if the invocation $invocation matches the current rules. If it + * does the matcher will get the invoked() method called which should check + * if an expectation is met. + * + * @throws ExpectationFailedException + * + * @return bool + */ + public function verify() + { + if (isset($this->parameterVerificationResult)) { + return $this->guardAgainstDuplicateEvaluationOfParameterConstraints(); + } + + if ($this->invocation === null) { + throw new ExpectationFailedException('Mocked method does not exist.'); + } + + if (\count($this->invocation->getParameters()) < \count($this->parameters)) { + $message = 'Parameter count for invocation %s is too low.'; + + // The user called `->with($this->anything())`, but may have meant + // `->withAnyParameters()`. + // + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/199 + if (\count($this->parameters) === 1 && + \get_class($this->parameters[0]) === IsAnything::class) { + $message .= "\nTo allow 0 or more parameters with any value, omit ->with() or use ->withAnyParameters() instead."; + } + + throw new ExpectationFailedException( + \sprintf($message, $this->invocation->toString()) + ); + } + + foreach ($this->parameters as $i => $parameter) { + $parameter->evaluate( + $this->invocation->getParameters()[$i], + \sprintf( + 'Parameter %s for invocation %s does not match expected ' . + 'value.', + $i, + $this->invocation->toString() + ) + ); + } + + return true; + } + + /** + * @throws ExpectationFailedException + * + * @return bool + */ + private function guardAgainstDuplicateEvaluationOfParameterConstraints() + { + if ($this->parameterVerificationResult instanceof \Exception) { + throw $this->parameterVerificationResult; + } + + return (bool) $this->parameterVerificationResult; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/StatelessInvocation.php b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/StatelessInvocation.php new file mode 100644 index 0000000..f4e50a6 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Matcher/StatelessInvocation.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Matcher; + +use PHPUnit\Framework\MockObject\Invocation as BaseInvocation; + +/** + * Invocation matcher which does not care about previous state from earlier + * invocations. + * + * This abstract class can be implemented by matchers which does not care about + * state but only the current run-time value of the invocation itself. + */ +abstract class StatelessInvocation implements Invocation +{ + /** + * Registers the invocation $invocation in the object as being invoked. + * This will only occur after matches() returns true which means the + * current invocation is the correct one. + * + * The matcher can store information from the invocation which can later + * be checked in verify(), or it can check the values directly and throw + * and exception if an expectation is not met. + * + * If the matcher is a stub it will also have a return value. + * + * @param BaseInvocation $invocation Object containing information on a mocked or stubbed method which was invoked + */ + public function invoked(BaseInvocation $invocation) + { + } + + /** + * Checks if the invocation $invocation matches the current rules. If it does + * the matcher will get the invoked() method called which should check if an + * expectation is met. + * + * @return bool + */ + public function verify() + { + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/MockBuilder.php b/.phpunit/phpunit-7/src/Framework/MockObject/MockBuilder.php new file mode 100644 index 0000000..3199afd --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/MockBuilder.php @@ -0,0 +1,408 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\TestCase; + +/** + * Implementation of the Builder pattern for Mock objects. + */ +class MockBuilder +{ + /** + * @var TestCase + */ + private $testCase; + + /** + * @var string + */ + private $type; + + /** + * @var array + */ + private $methods = []; + + /** + * @var array + */ + private $methodsExcept = []; + + /** + * @var string + */ + private $mockClassName = ''; + + /** + * @var array + */ + private $constructorArgs = []; + + /** + * @var bool + */ + private $originalConstructor = true; + + /** + * @var bool + */ + private $originalClone = true; + + /** + * @var bool + */ + private $autoload = true; + + /** + * @var bool + */ + private $cloneArguments = false; + + /** + * @var bool + */ + private $callOriginalMethods = false; + + /** + * @var object + */ + private $proxyTarget; + + /** + * @var bool + */ + private $allowMockingUnknownTypes = true; + + /** + * @var bool + */ + private $returnValueGeneration = true; + + /** + * @var Generator + */ + private $generator; + + /** + * @param array|string $type + */ + public function __construct(TestCase $testCase, $type) + { + $this->testCase = $testCase; + $this->type = $type; + $this->generator = new Generator; + } + + /** + * Creates a mock object using a fluent interface. + * + * @return MockObject + */ + public function getMock() + { + $object = $this->generator->getMock( + $this->type, + $this->methods, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->cloneArguments, + $this->callOriginalMethods, + $this->proxyTarget, + $this->allowMockingUnknownTypes, + $this->returnValueGeneration + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for an abstract class using a fluent interface. + * + * @return MockObject + */ + public function getMockForAbstractClass() + { + $object = $this->generator->getMockForAbstractClass( + $this->type, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Creates a mock object for a trait using a fluent interface. + * + * @return MockObject + */ + public function getMockForTrait() + { + $object = $this->generator->getMockForTrait( + $this->type, + $this->constructorArgs, + $this->mockClassName, + $this->originalConstructor, + $this->originalClone, + $this->autoload, + $this->methods, + $this->cloneArguments + ); + + $this->testCase->registerMockObject($object); + + return $object; + } + + /** + * Specifies the subset of methods to mock. Default is to mock none of them. + * + * @return MockBuilder + */ + public function setMethods(array $methods = null) + { + $this->methods = $methods; + + return $this; + } + + /** + * Specifies the subset of methods to not mock. Default is to mock all of them. + * + * @return MockBuilder + */ + public function setMethodsExcept(array $methods = []) + { + $this->methodsExcept = $methods; + + $this->setMethods( + \array_diff( + $this->generator->getClassMethods($this->type), + $this->methodsExcept + ) + ); + + return $this; + } + + /** + * Specifies the arguments for the constructor. + * + * @return MockBuilder + */ + public function setConstructorArgs(array $args) + { + $this->constructorArgs = $args; + + return $this; + } + + /** + * Specifies the name for the mock class. + * + * @param string $name + * + * @return MockBuilder + */ + public function setMockClassName($name) + { + $this->mockClassName = $name; + + return $this; + } + + /** + * Disables the invocation of the original constructor. + * + * @return MockBuilder + */ + public function disableOriginalConstructor() + { + $this->originalConstructor = false; + + return $this; + } + + /** + * Enables the invocation of the original constructor. + * + * @return MockBuilder + */ + public function enableOriginalConstructor() + { + $this->originalConstructor = true; + + return $this; + } + + /** + * Disables the invocation of the original clone constructor. + * + * @return MockBuilder + */ + public function disableOriginalClone() + { + $this->originalClone = false; + + return $this; + } + + /** + * Enables the invocation of the original clone constructor. + * + * @return MockBuilder + */ + public function enableOriginalClone() + { + $this->originalClone = true; + + return $this; + } + + /** + * Disables the use of class autoloading while creating the mock object. + * + * @return MockBuilder + */ + public function disableAutoload() + { + $this->autoload = false; + + return $this; + } + + /** + * Enables the use of class autoloading while creating the mock object. + * + * @return MockBuilder + */ + public function enableAutoload() + { + $this->autoload = true; + + return $this; + } + + /** + * Disables the cloning of arguments passed to mocked methods. + * + * @return MockBuilder + */ + public function disableArgumentCloning() + { + $this->cloneArguments = false; + + return $this; + } + + /** + * Enables the cloning of arguments passed to mocked methods. + * + * @return MockBuilder + */ + public function enableArgumentCloning() + { + $this->cloneArguments = true; + + return $this; + } + + /** + * Enables the invocation of the original methods. + * + * @return MockBuilder + */ + public function enableProxyingToOriginalMethods() + { + $this->callOriginalMethods = true; + + return $this; + } + + /** + * Disables the invocation of the original methods. + * + * @return MockBuilder + */ + public function disableProxyingToOriginalMethods() + { + $this->callOriginalMethods = false; + $this->proxyTarget = null; + + return $this; + } + + /** + * Sets the proxy target. + * + * @param object $object + * + * @return MockBuilder + */ + public function setProxyTarget($object) + { + $this->proxyTarget = $object; + + return $this; + } + + /** + * @return MockBuilder + */ + public function allowMockingUnknownTypes() + { + $this->allowMockingUnknownTypes = true; + + return $this; + } + + /** + * @return MockBuilder + */ + public function disallowMockingUnknownTypes() + { + $this->allowMockingUnknownTypes = false; + + return $this; + } + + /** + * @return MockBuilder + */ + public function enableAutoReturnValueGeneration() + { + $this->returnValueGeneration = true; + + return $this; + } + + /** + * @return MockBuilder + */ + public function disableAutoReturnValueGeneration() + { + $this->returnValueGeneration = false; + + return $this; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/MockMethod.php b/.phpunit/phpunit-7/src/Framework/MockObject/MockMethod.php new file mode 100644 index 0000000..39e7ac2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/MockMethod.php @@ -0,0 +1,354 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; +use Text_Template; + +final class MockMethod +{ + /** + * @var Text_Template[] + */ + private static $templates = []; + + /** + * @var string + */ + private $className; + + /** + * @var string + */ + private $methodName; + + /** + * @var bool + */ + private $cloneArguments; + + /** + * @var string string + */ + private $modifier; + + /** + * @var string + */ + private $argumentsForDeclaration; + + /** + * @var string + */ + private $argumentsForCall; + + /** + * @var string + */ + private $returnType; + + /** + * @var string + */ + private $reference; + + /** + * @var bool + */ + private $callOriginalMethod; + + /** + * @var bool + */ + private $static; + + /** + * @var ?string + */ + private $deprecation; + + /** + * @var bool + */ + private $allowsReturnNull; + + public static function fromReflection(ReflectionMethod $method, bool $callOriginalMethod, bool $cloneArguments): self + { + if ($method->isPrivate()) { + $modifier = 'private'; + } elseif ($method->isProtected()) { + $modifier = 'protected'; + } else { + $modifier = 'public'; + } + + if ($method->isStatic()) { + $modifier .= ' static'; + } + + if ($method->returnsReference()) { + $reference = '&'; + } else { + $reference = ''; + } + + if ($method->hasReturnType()) { + $returnType = (string) $method->getReturnType(); + } else { + $returnType = ''; + } + + $docComment = $method->getDocComment(); + + if (\is_string($docComment) + && \preg_match('#\*[ \t]*+@deprecated[ \t]*+(.*?)\r?+\n[ \t]*+\*(?:[ \t]*+@|/$)#s', $docComment, $deprecation) + ) { + $deprecation = \trim(\preg_replace('#[ \t]*\r?\n[ \t]*+\*[ \t]*+#', ' ', $deprecation[1])); + } else { + $deprecation = null; + } + + return new self( + $method->getDeclaringClass()->getName(), + $method->getName(), + $cloneArguments, + $modifier, + self::getMethodParameters($method), + self::getMethodParameters($method, true), + $returnType, + $reference, + $callOriginalMethod, + $method->isStatic(), + $deprecation, + $method->hasReturnType() && $method->getReturnType()->allowsNull() + ); + } + + public static function fromName(string $fullClassName, string $methodName, bool $cloneArguments): self + { + return new self( + $fullClassName, + $methodName, + $cloneArguments, + 'public', + '', + '', + '', + '', + false, + false, + null, + false + ); + } + + public function __construct(string $className, string $methodName, bool $cloneArguments, string $modifier, string $argumentsForDeclaration, string $argumentsForCall, string $returnType, string $reference, bool $callOriginalMethod, bool $static, ?string $deprecation, bool $allowsReturnNull) + { + $this->className = $className; + $this->methodName = $methodName; + $this->cloneArguments = $cloneArguments; + $this->modifier = $modifier; + $this->argumentsForDeclaration = $argumentsForDeclaration; + $this->argumentsForCall = $argumentsForCall; + $this->returnType = $returnType; + $this->reference = $reference; + $this->callOriginalMethod = $callOriginalMethod; + $this->static = $static; + $this->deprecation = $deprecation; + $this->allowsReturnNull = $allowsReturnNull; + } + + public function getName(): string + { + return $this->methodName; + } + + /** + * @throws \ReflectionException + * @throws \PHPUnit\Framework\MockObject\RuntimeException + * @throws \InvalidArgumentException + */ + public function generateCode(): string + { + if ($this->static) { + $templateFile = 'mocked_static_method.tpl'; + } elseif ($this->returnType === 'void') { + $templateFile = \sprintf( + '%s_method_void.tpl', + $this->callOriginalMethod ? 'proxied' : 'mocked' + ); + } else { + $templateFile = \sprintf( + '%s_method.tpl', + $this->callOriginalMethod ? 'proxied' : 'mocked' + ); + } + + $returnType = $this->returnType; + // @see https://bugs.php.net/bug.php?id=70722 + if ($returnType === 'self') { + $returnType = $this->className; + } + + // @see https://github.com/sebastianbergmann/phpunit-mock-objects/issues/406 + if ($returnType === 'parent') { + $reflector = new ReflectionClass($this->className); + + $parentClass = $reflector->getParentClass(); + + if ($parentClass === false) { + throw new RuntimeException( + \sprintf( + 'Cannot mock %s::%s because "parent" return type declaration is used but %s does not have a parent class', + $this->className, + $this->methodName, + $this->className + ) + ); + } + + $returnType = $parentClass->getName(); + } + + $deprecation = $this->deprecation; + + if (null !== $this->deprecation) { + $deprecation = "The $this->className::$this->methodName method is deprecated ($this->deprecation)."; + $deprecationTemplate = $this->getTemplate('deprecation.tpl'); + + $deprecationTemplate->setVar([ + 'deprecation' => \var_export($deprecation, true), + ]); + + $deprecation = $deprecationTemplate->render(); + } + + $template = $this->getTemplate($templateFile); + + $template->setVar( + [ + 'arguments_decl' => $this->argumentsForDeclaration, + 'arguments_call' => $this->argumentsForCall, + 'return_delim' => $returnType ? ': ' : '', + 'return_type' => $this->allowsReturnNull ? '?' . $returnType : $returnType, + 'arguments_count' => !empty($this->argumentsForCall) ? \substr_count($this->argumentsForCall, ',') + 1 : 0, + 'class_name' => $this->className, + 'method_name' => $this->methodName, + 'modifier' => $this->modifier, + 'reference' => $this->reference, + 'clone_arguments' => $this->cloneArguments ? 'true' : 'false', + 'deprecation' => $deprecation, + ] + ); + + return $template->render(); + } + + private function getTemplate(string $template): Text_Template + { + $filename = __DIR__ . \DIRECTORY_SEPARATOR . 'Generator' . \DIRECTORY_SEPARATOR . $template; + + if (!isset(self::$templates[$filename])) { + self::$templates[$filename] = new Text_Template($filename); + } + + return self::$templates[$filename]; + } + + /** + * Returns the parameters of a function or method. + * + * @throws RuntimeException + */ + private static function getMethodParameters(ReflectionMethod $method, bool $forCall = false): string + { + $parameters = []; + + foreach ($method->getParameters() as $i => $parameter) { + $name = '$' . $parameter->getName(); + + /* Note: PHP extensions may use empty names for reference arguments + * or "..." for methods taking a variable number of arguments. + */ + if ($name === '$' || $name === '$...') { + $name = '$arg' . $i; + } + + if ($parameter->isVariadic()) { + if ($forCall) { + continue; + } + + $name = '...' . $name; + } + + $nullable = ''; + $default = ''; + $reference = ''; + $typeDeclaration = ''; + + if (!$forCall) { + if ($parameter->hasType() && $parameter->allowsNull()) { + $nullable = '?'; + } + + if ($parameter->hasType() && (string) $parameter->getType() !== 'self') { + $typeDeclaration = $parameter->getType() . ' '; + } else { + try { + $class = $parameter->getClass(); + } catch (ReflectionException $e) { + throw new RuntimeException( + \sprintf( + 'Cannot mock %s::%s() because a class or ' . + 'interface used in the signature is not loaded', + $method->getDeclaringClass()->getName(), + $method->getName() + ), + 0, + $e + ); + } + + if ($class !== null) { + $typeDeclaration = $class->getName() . ' '; + } + } + + if (!$parameter->isVariadic()) { + if ($parameter->isDefaultValueAvailable()) { + $value = $parameter->getDefaultValueConstantName(); + + if ($value === null) { + $value = \var_export($parameter->getDefaultValue(), true); + } elseif (!\defined($value)) { + $rootValue = \preg_replace('/^.*\\\\/', '', $value); + $value = \defined($rootValue) ? $rootValue : $value; + } + + $default = ' = ' . $value; + } elseif ($parameter->isOptional()) { + $default = ' = null'; + } + } + } + + if ($parameter->isPassedByReference()) { + $reference = '&'; + } + + $parameters[] = $nullable . $typeDeclaration . $reference . $name . $default; + } + + return \implode(', ', $parameters); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/MockMethodSet.php b/.phpunit/phpunit-7/src/Framework/MockObject/MockMethodSet.php new file mode 100644 index 0000000..b81536a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/MockMethodSet.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +final class MockMethodSet +{ + /** + * @var MockMethod[] + */ + private $methods = []; + + public function addMethods(MockMethod ...$methods): void + { + foreach ($methods as $method) { + $this->methods[\strtolower($method->getName())] = $method; + } + } + + public function asArray(): array + { + return \array_values($this->methods); + } + + public function hasMethod(string $methodName): bool + { + return \array_key_exists(\strtolower($methodName), $this->methods); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/MockObject.php b/.phpunit/phpunit-7/src/Framework/MockObject/MockObject.php new file mode 100644 index 0000000..cb5e51e --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/MockObject.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\MockObject\Builder\InvocationMocker; +use PHPUnit\Framework\MockObject\Matcher\Invocation; + +/** + * Interface for all mock objects which are generated by + * MockBuilder. + * + * @method InvocationMocker method($constraint) + * + * @deprecated Use PHPUnit\Framework\MockObject\MockObject instead + */ +interface PHPUnit_Framework_MockObject_MockObject /*extends Verifiable*/ +{ + /** + * @return InvocationMocker + */ + public function __phpunit_setOriginalObject($originalObject); + + /** + * @return InvocationMocker + */ + public function __phpunit_getInvocationMocker(); + + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function __phpunit_verify(bool $unsetInvocationMocker = true); + + /** + * @return bool + */ + public function __phpunit_hasMatchers(); + + public function __phpunit_setReturnValueGeneration(bool $returnValueGeneration); + + /** + * Registers a new expectation in the mock object and returns the match + * object which can be infused with further details. + * + * @return InvocationMocker + */ + public function expects(Invocation $matcher); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub.php new file mode 100644 index 0000000..b0f04f5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\SelfDescribing; + +/** + * An object that stubs the process of a normal method for a mock object. + * + * The stub object will replace the code for the stubbed method and return a + * specific value instead of the original value. + */ +interface Stub extends SelfDescribing +{ + /** + * Fakes the processing of the invocation $invocation by returning a + * specific value. + * + * @param Invocation $invocation The invocation which was mocked and matched by the current method and argument matchers + */ + public function invoke(Invocation $invocation); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ConsecutiveCalls.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ConsecutiveCalls.php new file mode 100644 index 0000000..ee60927 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ConsecutiveCalls.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; +use SebastianBergmann\Exporter\Exporter; + +/** + * Stubs a method by returning a user-defined stack of values. + */ +class ConsecutiveCalls implements Stub +{ + /** + * @var array + */ + private $stack; + + /** + * @var mixed + */ + private $value; + + public function __construct(array $stack) + { + $this->stack = $stack; + } + + public function invoke(Invocation $invocation) + { + $this->value = \array_shift($this->stack); + + if ($this->value instanceof Stub) { + $this->value = $this->value->invoke($invocation); + } + + return $this->value; + } + + public function toString(): string + { + $exporter = new Exporter; + + return \sprintf( + 'return user-specified value %s', + $exporter->export($this->value) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/Exception.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/Exception.php new file mode 100644 index 0000000..3080a6e --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/Exception.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; +use SebastianBergmann\Exporter\Exporter; + +/** + * Stubs a method by raising a user-defined exception. + */ +class Exception implements Stub +{ + private $exception; + + public function __construct(\Throwable $exception) + { + $this->exception = $exception; + } + + public function invoke(Invocation $invocation): void + { + throw $this->exception; + } + + public function toString(): string + { + $exporter = new Exporter; + + return \sprintf( + 'raise user-specified exception %s', + $exporter->export($this->exception) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/MatcherCollection.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/MatcherCollection.php new file mode 100644 index 0000000..f53834a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/MatcherCollection.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Matcher\Invocation; + +/** + * Stubs a method by returning a user-defined value. + */ +interface MatcherCollection +{ + /** + * Adds a new matcher to the collection which can be used as an expectation + * or a stub. + * + * @param Invocation $matcher Matcher for invocations to mock objects + */ + public function addMatcher(Invocation $matcher); +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnArgument.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnArgument.php new file mode 100644 index 0000000..3e63d78 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnArgument.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; + +/** + * Stubs a method by returning an argument that was passed to the mocked method. + */ +class ReturnArgument implements Stub +{ + /** + * @var int + */ + private $argumentIndex; + + public function __construct($argumentIndex) + { + $this->argumentIndex = $argumentIndex; + } + + public function invoke(Invocation $invocation) + { + if (isset($invocation->getParameters()[$this->argumentIndex])) { + return $invocation->getParameters()[$this->argumentIndex]; + } + } + + public function toString(): string + { + return \sprintf('return argument #%d', $this->argumentIndex); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnCallback.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnCallback.php new file mode 100644 index 0000000..933e9ca --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnCallback.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; + +class ReturnCallback implements Stub +{ + private $callback; + + public function __construct($callback) + { + $this->callback = $callback; + } + + public function invoke(Invocation $invocation) + { + return \call_user_func_array($this->callback, $invocation->getParameters()); + } + + public function toString(): string + { + if (\is_array($this->callback)) { + if (\is_object($this->callback[0])) { + $class = \get_class($this->callback[0]); + $type = '->'; + } else { + $class = $this->callback[0]; + $type = '::'; + } + + return \sprintf( + 'return result of user defined callback %s%s%s() with the ' . + 'passed arguments', + $class, + $type, + $this->callback[1] + ); + } + + return 'return result of user defined callback ' . $this->callback . + ' with the passed arguments'; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnReference.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnReference.php new file mode 100644 index 0000000..2d78442 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnReference.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; +use SebastianBergmann\Exporter\Exporter; + +/** + * Stubs a method by returning a user-defined reference to a value. + */ +class ReturnReference implements Stub +{ + /** + * @var mixed + */ + private $reference; + + public function __construct(&$reference) + { + $this->reference = &$reference; + } + + public function invoke(Invocation $invocation) + { + return $this->reference; + } + + public function toString(): string + { + $exporter = new Exporter; + + return \sprintf( + 'return user-specified reference %s', + $exporter->export($this->reference) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnSelf.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnSelf.php new file mode 100644 index 0000000..4261a6a --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnSelf.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Invocation\ObjectInvocation; +use PHPUnit\Framework\MockObject\RuntimeException; +use PHPUnit\Framework\MockObject\Stub; + +/** + * Stubs a method by returning the current object. + */ +class ReturnSelf implements Stub +{ + public function invoke(Invocation $invocation) + { + if (!$invocation instanceof ObjectInvocation) { + throw new RuntimeException( + 'The current object can only be returned when mocking an ' . + 'object, not a static class.' + ); + } + + return $invocation->getObject(); + } + + public function toString(): string + { + return 'return the current object'; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnStub.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnStub.php new file mode 100644 index 0000000..76dc7b6 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnStub.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; +use SebastianBergmann\Exporter\Exporter; + +/** + * Stubs a method by returning a user-defined value. + */ +class ReturnStub implements Stub +{ + /** + * @var mixed + */ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + public function invoke(Invocation $invocation) + { + return $this->value; + } + + public function toString(): string + { + $exporter = new Exporter; + + return \sprintf( + 'return user-specified value %s', + $exporter->export($this->value) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnValueMap.php b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnValueMap.php new file mode 100644 index 0000000..195cc16 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Stub/ReturnValueMap.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject\Stub; + +use PHPUnit\Framework\MockObject\Invocation; +use PHPUnit\Framework\MockObject\Stub; + +/** + * Stubs a method by returning a value from a map. + */ +class ReturnValueMap implements Stub +{ + /** + * @var array + */ + private $valueMap; + + public function __construct(array $valueMap) + { + $this->valueMap = $valueMap; + } + + public function invoke(Invocation $invocation) + { + $parameterCount = \count($invocation->getParameters()); + + foreach ($this->valueMap as $map) { + if (!\is_array($map) || $parameterCount !== (\count($map) - 1)) { + continue; + } + + $return = \array_pop($map); + + if ($invocation->getParameters() === $map) { + return $return; + } + } + } + + public function toString(): string + { + return 'return value from a map'; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/MockObject/Verifiable.php b/.phpunit/phpunit-7/src/Framework/MockObject/Verifiable.php new file mode 100644 index 0000000..1e18846 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/MockObject/Verifiable.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework\MockObject; + +use PHPUnit\Framework\ExpectationFailedException; + +/** + * Interface for classes which must verify a given expectation. + */ +interface Verifiable +{ + /** + * Verifies that the current expectation is valid. If everything is OK the + * code should just return, if not it must throw an exception. + * + * @throws ExpectationFailedException + */ + public function verify(); +} diff --git a/.phpunit/phpunit-7/src/Framework/OutputError.php b/.phpunit/phpunit-7/src/Framework/OutputError.php new file mode 100644 index 0000000..5b1517b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/OutputError.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/RiskyTest.php b/.phpunit/phpunit-7/src/Framework/RiskyTest.php new file mode 100644 index 0000000..e013217 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/RiskyTest.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +interface RiskyTest +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/RiskyTestError.php b/.phpunit/phpunit-7/src/Framework/RiskyTestError.php new file mode 100644 index 0000000..fe1e3a4 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/RiskyTestError.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/SelfDescribing.php b/.phpunit/phpunit-7/src/Framework/SelfDescribing.php new file mode 100644 index 0000000..faf9290 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SelfDescribing.php @@ -0,0 +1,21 @@ + + * + * 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. + */ + public function toString(): string; +} diff --git a/.phpunit/phpunit-7/src/Framework/SkippedTest.php b/.phpunit/phpunit-7/src/Framework/SkippedTest.php new file mode 100644 index 0000000..8151f2d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SkippedTest.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Framework; + +interface SkippedTest +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/SkippedTestCase.php b/.phpunit/phpunit-7/src/Framework/SkippedTestCase.php new file mode 100644 index 0000000..cf88d7b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SkippedTestCase.php @@ -0,0 +1,76 @@ + + * + * 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; + + public function __construct(string $className, string $methodName, string $message = '') + { + parent::__construct($className . '::' . $methodName); + + $this->message = $message; + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * @throws Exception + */ + protected function runTest(): void + { + $this->markTestSkipped($this->message); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/SkippedTestError.php b/.phpunit/phpunit-7/src/Framework/SkippedTestError.php new file mode 100644 index 0000000..0893a5d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SkippedTestError.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/SkippedTestSuiteError.php b/.phpunit/phpunit-7/src/Framework/SkippedTestSuiteError.php new file mode 100644 index 0000000..c74015b --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SkippedTestSuiteError.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/SyntheticError.php b/.phpunit/phpunit-7/src/Framework/SyntheticError.php new file mode 100644 index 0000000..db2280f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/SyntheticError.php @@ -0,0 +1,61 @@ + + * + * 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 = []; + + public function __construct(string $message, int $code, string $file, int $line, array $trace) + { + parent::__construct($message, $code); + + $this->syntheticFile = $file; + $this->syntheticLine = $line; + $this->syntheticTrace = $trace; + } + + public function getSyntheticFile(): string + { + return $this->syntheticFile; + } + + public function getSyntheticLine(): int + { + return $this->syntheticLine; + } + + public function getSyntheticTrace(): array + { + return $this->syntheticTrace; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/Test.php b/.phpunit/phpunit-7/src/Framework/Test.php new file mode 100644 index 0000000..347a63f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Test.php @@ -0,0 +1,23 @@ + + * + * 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. + */ + public function run(TestResult $result = null): TestResult; +} diff --git a/.phpunit/phpunit-7/src/Framework/TestCase.php b/.phpunit/phpunit-7/src/Framework/TestCase.php new file mode 100644 index 0000000..ce229c0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestCase.php @@ -0,0 +1,2143 @@ + + * + * 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\PHP\AbstractPhpProcess; +use Prophecy; +use Prophecy\Exception\Prediction\PredictionException; +use Prophecy\Prophecy\MethodProphecy; +use Prophecy\Prophecy\ObjectProphecy; +use Prophecy\Prophet; +use ReflectionClass; +use ReflectionException; +use ReflectionObject; +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; + +abstract class TestCase extends Assert implements Test, SelfDescribing +{ + private const LOCALE_CATEGORIES = [\LC_ALL, \LC_COLLATE, \LC_CTYPE, \LC_MONETARY, \LC_NUMERIC, \LC_TIME]; + + /** + * @var bool + */ + protected $backupGlobals; + + /** + * @var array + */ + protected $backupGlobalsBlacklist = []; + + /** + * @var bool + */ + protected $backupStaticAttributes; + + /** + * @var array + */ + protected $backupStaticAttributesBlacklist = []; + + /** + * @var bool + */ + protected $runTestInSeparateProcess; + + /** + * @var bool + */ + protected $preserveGlobalState = true; + + /** + * @var bool + */ + private $runClassInSeparateProcess; + + /** + * @var bool + */ + private $inIsolation = false; + + /** + * @var array + */ + private $data; + + /** + * @var string + */ + private $dataName; + + /** + * @var bool + */ + private $useErrorHandler; + + /** + * @var null|string + */ + private $expectedException; + + /** + * @var string + */ + private $expectedExceptionMessage; + + /** + * @var string + */ + private $expectedExceptionMessageRegExp; + + /** + * @var null|int|string + */ + private $expectedExceptionCode; + + /** + * @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 MockGenerator + */ + private $mockObjectGenerator; + + /** + * @var int + */ + private $status = BaseTestRunner::STATUS_UNKNOWN; + + /** + * @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 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 = []; + + /** + * Returns a matcher that matches when the method is executed + * zero or more times. + */ + public static function any(): AnyInvokedCountMatcher + { + return new AnyInvokedCountMatcher; + } + + /** + * Returns a matcher that matches when the method is never executed. + */ + public static function never(): InvokedCountMatcher + { + return new InvokedCountMatcher(0); + } + + /** + * Returns a matcher that matches when the method is executed + * at least N times. + */ + public static function atLeast(int $requiredInvocations): InvokedAtLeastCountMatcher + { + return new InvokedAtLeastCountMatcher( + $requiredInvocations + ); + } + + /** + * Returns a matcher that matches when the method is executed at least once. + */ + public static function atLeastOnce(): InvokedAtLeastOnceMatcher + { + return new InvokedAtLeastOnceMatcher; + } + + /** + * Returns a matcher that matches when the method is executed exactly once. + */ + public static function once(): InvokedCountMatcher + { + return new InvokedCountMatcher(1); + } + + /** + * Returns a matcher that matches when the method is executed + * exactly $count times. + */ + public static function exactly(int $count): InvokedCountMatcher + { + return new InvokedCountMatcher($count); + } + + /** + * Returns a matcher that matches when the method is executed + * at most N times. + */ + public static function atMost(int $allowedInvocations): InvokedAtMostCountMatcher + { + return new InvokedAtMostCountMatcher($allowedInvocations); + } + + /** + * Returns a matcher that matches when the method is executed + * at the given index. + */ + public static function at(int $index): InvokedAtIndexMatcher + { + return new InvokedAtIndexMatcher($index); + } + + public static function returnValue($value): ReturnStub + { + return new ReturnStub($value); + } + + public static function returnValueMap(array $valueMap): ReturnValueMapStub + { + return new ReturnValueMapStub($valueMap); + } + + public static function returnArgument(int $argumentIndex): ReturnArgumentStub + { + return new ReturnArgumentStub($argumentIndex); + } + + public static function returnCallback($callback): ReturnCallbackStub + { + return new ReturnCallbackStub($callback); + } + + /** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + */ + public static function returnSelf(): ReturnSelfStub + { + return new ReturnSelfStub; + } + + public static function throwException(Throwable $exception): ExceptionStub + { + return new ExceptionStub($exception); + } + + public static function onConsecutiveCalls(...$args): ConsecutiveCallsStub + { + return new ConsecutiveCallsStub($args); + } + + /** + * @param string $name + * @param string $dataName + */ + public function __construct($name = null, array $data = [], $dataName = '') + { + if ($name !== null) { + $this->setName($name); + } + + $this->data = $data; + $this->dataName = $dataName; + } + + /** + * This method is called before the first test of this test class is run. + */ + public static function setUpBeforeClass()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * This method is called after the last test of this test class is run. + */ + public static function tearDownAfterClass()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * This method is called before each test. + */ + protected function setUp()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * This method is called after each test. + */ + protected function tearDown()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * Returns a string representation of the test case. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \ReflectionException + */ + public function toString(): string + { + $class = new ReflectionClass($this); + + $buffer = \sprintf( + '%s::%s', + $class->name, + $this->getName(false) + ); + + return $buffer . $this->getDataSetAsString(); + } + + public function count(): int + { + return 1; + } + + public function getGroups(): array + { + return $this->groups; + } + + public function setGroups(array $groups): void + { + $this->groups = $groups; + } + + public function getAnnotations(): array + { + return \PHPUnit\Util\Test::parseTestMethodAnnotations( + \get_class($this), + $this->name + ); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function getName(bool $withDataSet = true): ?string + { + if ($withDataSet) { + return $this->name . $this->getDataSetAsString(false); + } + + return $this->name; + } + + /** + * Returns the size of the test. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function getSize(): int + { + return \PHPUnit\Util\Test::getSize( + \get_class($this), + $this->getName(false) + ); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function hasSize(): bool + { + return $this->getSize() !== \PHPUnit\Util\Test::UNKNOWN; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function isSmall(): bool + { + return $this->getSize() === \PHPUnit\Util\Test::SMALL; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function isMedium(): bool + { + return $this->getSize() === \PHPUnit\Util\Test::MEDIUM; + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function isLarge(): bool + { + return $this->getSize() === \PHPUnit\Util\Test::LARGE; + } + + public function getActualOutput(): string + { + if (!$this->outputBufferingActive) { + return $this->output; + } + + return \ob_get_contents(); + } + + public function hasOutput(): bool + { + if ($this->output === '') { + return false; + } + + if ($this->hasExpectationOnOutput()) { + return false; + } + + return true; + } + + public function doesNotPerformAssertions(): bool + { + return $this->doesNotPerformAssertions; + } + + public function expectOutputRegex(string $expectedRegex): void + { + $this->outputExpectedRegex = $expectedRegex; + } + + public function expectOutputString(string $expectedString): void + { + $this->outputExpectedString = $expectedString; + } + + public function hasExpectationOnOutput(): bool + { + return \is_string($this->outputExpectedString) || \is_string($this->outputExpectedRegex); + } + + public function getExpectedException(): ?string + { + return $this->expectedException; + } + + /** + * @return null|int|string + */ + public function getExpectedExceptionCode() + { + return $this->expectedExceptionCode; + } + + public function getExpectedExceptionMessage(): string + { + return $this->expectedExceptionMessage; + } + + public function getExpectedExceptionMessageRegExp(): string + { + return $this->expectedExceptionMessageRegExp; + } + + public function expectException(string $exception): void + { + $this->expectedException = $exception; + } + + /** + * @param int|string $code + */ + public function expectExceptionCode($code): void + { + $this->expectedExceptionCode = $code; + } + + public function expectExceptionMessage(string $message): void + { + $this->expectedExceptionMessage = $message; + } + + public function expectExceptionMessageRegExp(string $messageRegExp): void + { + $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): void + { + $this->expectException(\get_class($exception)); + $this->expectExceptionMessage($exception->getMessage()); + $this->expectExceptionCode($exception->getCode()); + } + + public function expectNotToPerformAssertions() + { + $this->doesNotPerformAssertions = true; + } + + public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void + { + $this->registerMockObjectsFromTestArgumentsRecursively = $flag; + } + + public function setUseErrorHandler(bool $useErrorHandler): void + { + $this->useErrorHandler = $useErrorHandler; + } + + public function getStatus(): int + { + return $this->status; + } + + public function markAsRisky(): void + { + $this->status = BaseTestRunner::STATUS_RISKY; + } + + public function getStatusMessage(): string + { + return $this->statusMessage; + } + + public function hasFailed(): bool + { + $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. + * + * @throws CodeCoverageException + * @throws ReflectionException + * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException + * @throws \SebastianBergmann\CodeCoverage\RuntimeException + * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function run(TestResult $result = null): TestResult + { + 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 $result; + } + + if ($this->runInSeparateProcess()) { + $runEntireClass = $this->runClassInSeparateProcess && !$this->runTestInSeparateProcess; + + $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, + 'name' => $this->getName(false), + ]; + + if (!$runEntireClass) { + $var['methodName'] = $this->name; + } + + $template->setVar( + $var + ); + + $php = AbstractPhpProcess::factory(); + $php->runTestJob($template->render(), $this, $result); + } else { + $result->run($this); + } + + if (isset($oldErrorHandlerSetting)) { + $result->convertErrorsToExceptions($oldErrorHandlerSetting); + } + + $this->result = null; + + return $result; + } + + /** + * @throws \Throwable + */ + public function runBare(): void + { + $this->numAssertions = 0; + + $this->snapshotGlobalState(); + $this->startOutputBuffering(); + \clearstatcache(); + $currentWorkingDirectory = \getcwd(); + + $hookMethods = \PHPUnit\Util\Test::getHookMethods(\get_class($this)); + + $hasMetRequirements = false; + + try { + $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; + $this->status = BaseTestRunner::STATUS_ERROR; + $this->statusMessage = $_e->getMessage(); + } + + $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) { + $e = $e ?? $_e; + } + + try { + $this->stopOutputBuffering(); + } catch (RiskyTestError $_e) { + $e = $e ?? $_e; + } + + if (isset($_e)) { + $this->status = BaseTestRunner::STATUS_ERROR; + $this->statusMessage = $_e->getMessage(); + } + + \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); + } + } + + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * @param string[] $dependencies + */ + public function setDependencies(array $dependencies): void + { + $this->dependencies = $dependencies; + } + + public function getDependencies(): array + { + return $this->dependencies; + } + + public function hasDependencies(): bool + { + return \count($this->dependencies) > 0; + } + + public function setDependencyInput(array $dependencyInput): void + { + $this->dependencyInput = $dependencyInput; + } + + public function setBeStrictAboutChangesToGlobalState(?bool $beStrictAboutChangesToGlobalState): void + { + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + } + + public function setBackupGlobals(?bool $backupGlobals): void + { + if ($this->backupGlobals === null && $backupGlobals !== null) { + $this->backupGlobals = $backupGlobals; + } + } + + public function setBackupStaticAttributes(?bool $backupStaticAttributes): void + { + if ($this->backupStaticAttributes === null && $backupStaticAttributes !== null) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void + { + if ($this->runTestInSeparateProcess === null) { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + } + + public function setRunClassInSeparateProcess(bool $runClassInSeparateProcess): void + { + if ($this->runClassInSeparateProcess === null) { + $this->runClassInSeparateProcess = $runClassInSeparateProcess; + } + } + + public function setPreserveGlobalState(bool $preserveGlobalState): void + { + $this->preserveGlobalState = $preserveGlobalState; + } + + public function setInIsolation(bool $inIsolation): void + { + $this->inIsolation = $inIsolation; + } + + public function isInIsolation(): bool + { + return $this->inIsolation; + } + + public function getResult() + { + return $this->testResult; + } + + public function setResult($result): void + { + $this->testResult = $result; + } + + public function setOutputCallback(callable $callback): void + { + $this->outputCallback = $callback; + } + + public function getTestResultObject(): ?TestResult + { + return $this->result; + } + + public function setTestResultObject(TestResult $result): void + { + $this->result = $result; + } + + public function registerMockObject(MockObject $mockObject): void + { + $this->mockObjects[] = $mockObject; + } + + /** + * Returns a builder object to create mock objects using a fluent interface. + * + * @param string|string[] $className + */ + public function getMockBuilder($className): MockBuilder + { + return new MockBuilder($this, $className); + } + + public function addToAssertionCount(int $count): void + { + $this->numAssertions += $count; + } + + /** + * Returns the number of assertions performed by this test. + */ + public function getNumAssertions(): int + { + return $this->numAssertions; + } + + public function usesDataProvider(): bool + { + return !empty($this->data); + } + + public function dataDescription(): string + { + return \is_string($this->dataName) ? $this->dataName : ''; + } + + /** + * @return int|string + */ + public function dataName() + { + return $this->dataName; + } + + public function registerComparator(Comparator $comparator): void + { + ComparatorFactory::getInstance()->register($comparator); + + $this->customComparators[] = $comparator; + } + + public function getDataSetAsString(bool $includeData = true): string + { + $buffer = ''; + + if (!empty($this->data)) { + if (\is_int($this->dataName)) { + $buffer .= \sprintf(' with data set #%d', $this->dataName); + } else { + $buffer .= \sprintf(' with data set "%s"', $this->dataName); + } + + $exporter = new Exporter; + + if ($includeData) { + $buffer .= \sprintf(' (%s)', $exporter->shortenedRecursiveExport($this->data)); + } + } + + return $buffer; + } + + /** + * Gets the data set of a TestCase. + */ + public function getProvidedData(): array + { + return $this->data; + } + + public function addWarning(string $warning): void + { + $this->warnings[] = $warning; + } + + /** + * Override to run the test and assert its state. + * + * @throws AssertionFailedError + * @throws Exception + * @throws ExpectationFailedException + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + * @throws Throwable + */ + protected function runTest() + { + if ($this->name === null) { + throw new Exception( + 'PHPUnit\Framework\TestCase::$name must not be null.' + ); + } + + $testArguments = \array_merge($this->data, $this->dependencyInput); + + $this->registerMockObjectsFromTestArguments($testArguments); + + try { + $testResult = $this->{$this->name}(...\array_values($testArguments)); + } catch (Throwable $exception) { + if (!$this->checkExceptionExpectations($exception)) { + throw $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; + } + + 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; + } + + /** + * This method is a wrapper for the ini_set() function that automatically + * resets the modified php.ini setting to its original value after the + * test is run. + * + * @throws Exception + */ + protected function iniSet(string $varName, $newValue): void + { + $currentValue = \ini_set($varName, $newValue); + + if ($currentValue !== false) { + $this->iniSettings[$varName] = $currentValue; + } else { + throw new Exception( + \sprintf( + 'INI setting "%s" could not be set to "%s".', + $varName, + $newValue + ) + ); + } + } + + /** + * This method is a wrapper for the setlocale() function that automatically + * resets the locale to its original value after the test is run. + * + * @throws Exception + */ + protected function setLocale(...$args): void + { + if (\count($args) < 2) { + throw new Exception; + } + + [$category, $locale] = $args; + + if (\defined('LC_MESSAGES')) { + $categories[] = \LC_MESSAGES; + } + + if (!\in_array($category, self::LOCALE_CATEGORIES, true)) { + throw new Exception; + } + + if (!\is_array($locale) && !\is_string($locale)) { + throw new Exception; + } + + $this->locale[$category] = \setlocale($category, 0); + + $result = \setlocale(...$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 test double for the specified class. + * + * @param string|string[] $originalClassName + * + * @throws Exception + * @throws \InvalidArgumentException + */ + protected function createMock($originalClassName): MockObject + { + return $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->getMock(); + } + + /** + * Returns a configured test double for the specified class. + * + * @param string|string[] $originalClassName + * + * @throws Exception + * @throws \InvalidArgumentException + */ + protected function createConfiguredMock($originalClassName, array $configuration): MockObject + { + $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|string[] $originalClassName + * @param string[] $methods + * + * @throws Exception + * @throws \InvalidArgumentException + */ + protected function createPartialMock($originalClassName, array $methods): MockObject + { + return $this->getMockBuilder($originalClassName) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->setMethods(empty($methods) ? null : $methods) + ->getMock(); + } + + /** + * Returns a test proxy for the specified class. + * + * @throws Exception + * @throws \InvalidArgumentException + */ + protected function createTestProxy(string $originalClassName, array $constructorArguments = []): MockObject + { + 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 string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param bool $cloneArguments + * + * @throws Exception + * @throws ReflectionException + * @throws \InvalidArgumentException + */ + protected function getMockClass($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false): string + { + $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 string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param array $mockedMethods + * @param bool $cloneArguments + * + * @throws Exception + * @throws ReflectionException + * @throws \InvalidArgumentException + */ + protected function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false): MockObject + { + $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 bool $callOriginalConstructor + * @param array $options An array of options passed to SOAPClient::_construct + * + * @throws Exception + * @throws ReflectionException + * @throws \InvalidArgumentException + */ + protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = [], $callOriginalConstructor = true, array $options = []): MockObject + { + if ($originalClassName === '') { + $fileName = \pathinfo(\basename(\parse_url($wsdlFile)['path']), \PATHINFO_FILENAME); + $originalClassName = \preg_replace('/[^a-zA-Z0-9_]/', '', $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 string $mockClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * @param array $mockedMethods + * @param bool $cloneArguments + * + * @throws Exception + * @throws ReflectionException + * @throws \InvalidArgumentException + */ + protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false): MockObject + { + $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 string $traitClassName + * @param bool $callOriginalConstructor + * @param bool $callOriginalClone + * @param bool $callAutoload + * + * @throws Exception + * @throws ReflectionException + * @throws \InvalidArgumentException + * + * @return object + */ + protected function getObjectForTrait($traitName, array $arguments = [], $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true)/*: object*/ + { + return $this->getMockObjectGenerator()->getObjectForTrait( + $traitName, + $arguments, + $traitClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload + ); + } + + /** + * @param null|string $classOrInterface + * + * @throws Prophecy\Exception\Doubler\ClassNotFoundException + * @throws Prophecy\Exception\Doubler\DoubleException + * @throws Prophecy\Exception\Doubler\InterfaceNotFoundException + */ + protected function prophesize($classOrInterface = null): ObjectProphecy + { + return $this->getProphet()->prophesize($classOrInterface); + } + + /** + * Creates a default TestResult object. + */ + protected function createResult(): TestResult + { + return new TestResult; + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between setUp() and test. + */ + protected function assertPreConditions()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called between test and tearDown(). + */ + protected function assertPostConditions()/* The :void return type declaration that should be here would cause a BC issue */ + { + } + + /** + * This method is called when a test method did not execute successfully. + * + * @throws Throwable + */ + protected function onNotSuccessfulTest(Throwable $t)/* The :void return type declaration that should be here would cause a BC issue */ + { + throw $t; + } + + private function setExpectedExceptionFromAnnotation(): void + { + 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) { + } + } + + private function setUseErrorHandlerFromAnnotation(): void + { + try { + $useErrorHandler = \PHPUnit\Util\Test::getErrorHandlerSettings( + \get_class($this), + $this->name + ); + + if ($useErrorHandler !== null) { + $this->setUseErrorHandler($useErrorHandler); + } + } catch (ReflectionException $e) { + } + } + + private function checkRequirements(): void + { + 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)); + } + } + + private function verifyMockObjects(): void + { + 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) { + /** @var MethodProphecy[] $methodProphecies */ + foreach ($methodProphecies as $methodProphecy) { + $this->numAssertions += \count($methodProphecy->getCheckedPredictions()); + } + } + } + + if (isset($t)) { + throw $t; + } + } + } + + private function handleDependencies(): bool + { + 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])) { + if (!\is_callable($dependency, false, $callableName) || $dependency !== $callableName) { + $this->markWarningForUncallableDependency($dependency); + } else { + $this->markSkippedForMissingDependecy($dependency); + } + + 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; + } + + private function markSkippedForMissingDependecy(string $dependency): void + { + $this->status = BaseTestRunner::STATUS_SKIPPED; + $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); + } + + private function markWarningForUncallableDependency(string $dependency): void + { + $this->status = BaseTestRunner::STATUS_WARNING; + $this->result->startTest($this); + $this->result->addWarning( + $this, + new Warning( + \sprintf( + 'This test depends on "%s" which does not exist.', + $dependency + ) + ), + 0 + ); + $this->result->endTest($this, 0); + } + + /** + * Get the mock object generator, creating it if it doesn't exist. + */ + private function getMockObjectGenerator(): MockGenerator + { + if ($this->mockObjectGenerator === null) { + $this->mockObjectGenerator = new MockGenerator; + } + + return $this->mockObjectGenerator; + } + + private function startOutputBuffering(): void + { + \ob_start(); + + $this->outputBufferingActive = true; + $this->outputBufferingLevel = \ob_get_level(); + } + + /** + * @throws RiskyTestError + */ + private function stopOutputBuffering(): void + { + 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' + ); + } + + $this->output = \ob_get_contents(); + + if ($this->outputCallback !== false) { + $this->output = (string) \call_user_func($this->outputCallback, $this->output); + } + + \ob_end_clean(); + + $this->outputBufferingActive = false; + $this->outputBufferingLevel = \ob_get_level(); + } + + private function snapshotGlobalState(): void + { + if ($this->runTestInSeparateProcess || $this->inIsolation || + (!$this->backupGlobals === true && !$this->backupStaticAttributes)) { + return; + } + + $this->snapshot = $this->createGlobalStateSnapshot($this->backupGlobals === true); + } + + /** + * @throws RiskyTestError + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \InvalidArgumentException + */ + private function restoreGlobalState(): void + { + 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; + } + } + + private function createGlobalStateSnapshot(bool $backupGlobals): Snapshot + { + $blacklist = new Blacklist; + + foreach ($this->backupGlobalsBlacklist as $globalVariable) { + $blacklist->addGlobalVariable($globalVariable); + } + + if (!\defined('PHPUNIT_TESTSUITE')) { + $blacklist->addClassNamePrefix('PHPUnit'); + $blacklist->addClassNamePrefix('SebastianBergmann\CodeCoverage'); + $blacklist->addClassNamePrefix('SebastianBergmann\FileIterator'); + $blacklist->addClassNamePrefix('SebastianBergmann\Invoker'); + $blacklist->addClassNamePrefix('SebastianBergmann\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 + ); + } + + /** + * @throws RiskyTestError + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws \InvalidArgumentException + */ + private function compareGlobalStateSnapshots(Snapshot $before, Snapshot $after): void + { + $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" + ); + } + } + + /** + * @throws RiskyTestError + */ + private function compareGlobalStateSnapshotPart(array $before, array $after, string $header): void + { + if ($before != $after) { + $differ = new Differ($header); + $exporter = new Exporter; + + $diff = $differ->diff( + $exporter->export($before), + $exporter->export($after) + ); + + throw new RiskyTestError( + $diff + ); + } + } + + private function getProphet(): Prophet + { + if ($this->prophet === null) { + $this->prophet = new Prophet; + } + + return $this->prophet; + } + + /** + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + */ + private function shouldInvocationMockerBeReset(MockObject $mock): bool + { + $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; + } + + return !\in_array($mock, $enumerator->enumerate($this->testResult), true); + } + + /** + * @throws \SebastianBergmann\ObjectEnumerator\InvalidArgumentException + * @throws \SebastianBergmann\ObjectReflector\InvalidArgumentException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function registerMockObjectsFromTestArguments(array $testArguments, array &$visited = []): void + { + 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(): void + { + $annotations = $this->getAnnotations(); + + if (isset($annotations['method']['doesNotPerformAssertions'])) { + $this->doesNotPerformAssertions = true; + } + } + + private function isCloneable(MockObject $testArgument): bool + { + $reflector = new ReflectionObject($testArgument); + + if (!$reflector->isCloneable()) { + return false; + } + + if ($reflector->hasMethod('__clone') && + $reflector->getMethod('__clone')->isPublic()) { + return true; + } + + return false; + } + + private function unregisterCustomComparators(): void + { + $factory = ComparatorFactory::getInstance(); + + foreach ($this->customComparators as $comparator) { + $factory->unregister($comparator); + } + + $this->customComparators = []; + } + + private function cleanupIniSettings(): void + { + foreach ($this->iniSettings as $varName => $oldValue) { + \ini_set($varName, $oldValue); + } + + $this->iniSettings = []; + } + + private function cleanupLocaleSettings(): void + { + foreach ($this->locale as $category => $locale) { + \setlocale($category, $locale); + } + + $this->locale = []; + } + + /** + * @throws ReflectionException + */ + 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(Exception::class)) { + $result = true; + } + } + + return $result; + } + + private function runInSeparateProcess(): bool + { + return ($this->runTestInSeparateProcess === true || $this->runClassInSeparateProcess === true) && + $this->inIsolation !== true && !$this instanceof PhptTestCase; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/TestFailure.php b/.phpunit/phpunit-7/src/Framework/TestFailure.php new file mode 100644 index 0000000..fce6af7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestFailure.php @@ -0,0 +1,154 @@ + + * + * 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 null|Test + */ + protected $failedTest; + + /** + * @var Throwable + */ + protected $thrownException; + + /** + * @var string + */ + private $testName; + + /** + * Returns a description for an exception. + * + * @throws \InvalidArgumentException + */ + public static function exceptionToString(Throwable $e): string + { + 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"; + } + + /** + * Constructs a TestFailure with the given test and exception. + * + * @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. + */ + public function toString(): string + { + return \sprintf( + '%s: %s', + $this->testName, + $this->thrownException->getMessage() + ); + } + + /** + * Returns a description for the thrown exception. + * + * @throws \InvalidArgumentException + */ + public function getExceptionAsString(): string + { + return self::exceptionToString($this->thrownException); + } + + /** + * Returns the name of the failing test (including data set, if any). + */ + public function getTestName(): string + { + return $this->testName; + } + + /** + * Returns the failing test. + * + * Note: The test object is not set when the test is executed in process + * isolation. + * + * @see Exception + */ + public function failedTest(): ?Test + { + return $this->failedTest; + } + + /** + * Gets the thrown exception. + */ + public function thrownException(): Throwable + { + return $this->thrownException; + } + + /** + * Returns the exception's message. + */ + public function exceptionMessage(): string + { + return $this->thrownException()->getMessage(); + } + + /** + * Returns true if the thrown exception + * is of type AssertionFailedError. + */ + public function isFailure(): bool + { + return $this->thrownException() instanceof AssertionFailedError; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/TestListener.php b/.phpunit/phpunit-7/src/Framework/TestListener.php new file mode 100644 index 0000000..e1c670c --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestListener.php @@ -0,0 +1,66 @@ + + * + * 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. + */ + public function addError(Test $test, \Throwable $t, float $time): void; + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void; + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void; + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void; + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, \Throwable $t, float $time): void; + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, \Throwable $t, float $time): void; + + /** + * A test suite started. + */ + public function startTestSuite(TestSuite $suite): void; + + /** + * A test suite ended. + */ + public function endTestSuite(TestSuite $suite): void; + + /** + * A test started. + */ + public function startTest(Test $test): void; + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Framework/TestListenerDefaultImplementation.php b/.phpunit/phpunit-7/src/Framework/TestListenerDefaultImplementation.php new file mode 100644 index 0000000..df6416f --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestListenerDefaultImplementation.php @@ -0,0 +1,53 @@ + + * + * 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, \Throwable $t, float $time): void + { + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + } + + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + } + + public function startTestSuite(TestSuite $suite): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } + + public function startTest(Test $test): void + { + } + + public function endTest(Test $test, float $time): void + { + } +} diff --git a/.phpunit/phpunit-7/src/Framework/TestResult.php b/.phpunit/phpunit-7/src/Framework/TestResult.php new file mode 100644 index 0000000..fd81c86 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestResult.php @@ -0,0 +1,1135 @@ + + * + * 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 PHPUnit\Framework\MockObject\Exception as MockObjectException; +use PHPUnit\Util\Blacklist; +use PHPUnit\Util\ErrorHandler; +use PHPUnit\Util\Printer; +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\Invoker\Invoker; +use SebastianBergmann\Invoker\TimeoutException; +use SebastianBergmann\ResourceOperations\ResourceOperations; +use SebastianBergmann\Timer\Timer; +use Throwable; + +/** + * A TestResult collects the results of executing a test case. + */ +class TestResult implements Countable +{ + /** + * @var array + */ + protected $passed = []; + + /** + * @var TestFailure[] + */ + protected $errors = []; + + /** + * @var TestFailure[] + */ + protected $failures = []; + + /** + * @var TestFailure[] + */ + protected $warnings = []; + + /** + * @var TestFailure[] + */ + protected $notImplemented = []; + + /** + * @var TestFailure[] + */ + protected $risky = []; + + /** + * @var TestFailure[] + */ + protected $skipped = []; + + /** + * @var TestListener[] + */ + 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 int + */ + private $defaultTimeLimit = 0; + + /** + * @var bool + */ + private $stopOnDefect = false; + + /** + * @var bool + */ + private $registerMockObjectsFromTestArgumentsRecursively = false; + + public static function isAnyCoverageRequired(TestCase $test) + { + $annotations = $test->getAnnotations(); + + // If any methods have covers, coverage must me generated + if (isset($annotations['method']['covers'])) { + return true; + } + + // If there are no explicit covers, and the test class is + // marked as covers nothing, all coverage can be skipped + if (isset($annotations['class']['coversNothing'])) { + return false; + } + + // Otherwise each test method can generate coverage + return true; + } + + /** + * Registers a TestListener. + */ + public function addListener(TestListener $listener): void + { + $this->listeners[] = $listener; + } + + /** + * Unregisters a TestListener. + */ + public function removeListener(TestListener $listener): void + { + foreach ($this->listeners as $key => $_listener) { + if ($listener === $_listener) { + unset($this->listeners[$key]); + } + } + } + + /** + * Flushes all flushable TestListeners. + */ + public function flushListeners(): void + { + foreach ($this->listeners as $listener) { + if ($listener instanceof Printer) { + $listener->flush(); + } + } + } + + /** + * Adds an error to the list of errors. + */ + public function addError(Test $test, Throwable $t, float $time): void + { + if ($t instanceof RiskyTest) { + $this->risky[] = new TestFailure($test, $t); + $notifyMethod = 'addRiskyTest'; + + if ($test instanceof TestCase) { + $test->markAsRisky(); + } + + if ($this->stopOnRisky || $this->stopOnDefect) { + $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. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + if ($this->stopOnWarning || $this->stopOnDefect) { + $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. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + 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->stopOnDefect) { + $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->stopOnDefect) { + $this->stop(); + } + } + + foreach ($this->listeners as $listener) { + $listener->$notifyMethod($test, $e, $time); + } + + $this->lastTestFailed = true; + $this->time += $time; + } + + /** + * Informs the result that a test suite will be started. + */ + public function startTestSuite(TestSuite $suite): void + { + if ($this->topTestSuite === null) { + $this->topTestSuite = $suite; + } + + foreach ($this->listeners as $listener) { + $listener->startTestSuite($suite); + } + } + + /** + * Informs the result that a test suite was completed. + */ + public function endTestSuite(TestSuite $suite): void + { + foreach ($this->listeners as $listener) { + $listener->endTestSuite($suite); + } + } + + /** + * Informs the result that a test will be started. + */ + public function startTest(Test $test): void + { + $this->lastTestFailed = false; + $this->runTests += \count($test); + + foreach ($this->listeners as $listener) { + $listener->startTest($test); + } + } + + /** + * Informs the result that a test was completed. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function endTest(Test $test, float $time): void + { + 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. + */ + public function allHarmless(): bool + { + return $this->riskyCount() == 0; + } + + /** + * Gets the number of risky tests. + */ + public function riskyCount(): int + { + return \count($this->risky); + } + + /** + * Returns true if no incomplete test occurred. + */ + public function allCompletelyImplemented(): bool + { + return $this->notImplementedCount() == 0; + } + + /** + * Gets the number of incomplete tests. + */ + public function notImplementedCount(): int + { + return \count($this->notImplemented); + } + + /** + * Returns an array of TestFailure objects for the risky tests + * + * @return TestFailure[] + */ + public function risky(): array + { + return $this->risky; + } + + /** + * Returns an array of TestFailure objects for the incomplete tests + * + * @return TestFailure[] + */ + public function notImplemented(): array + { + return $this->notImplemented; + } + + /** + * Returns true if no test has been skipped. + */ + public function noneSkipped(): bool + { + return $this->skippedCount() == 0; + } + + /** + * Gets the number of skipped tests. + */ + public function skippedCount(): int + { + return \count($this->skipped); + } + + /** + * Returns an array of TestFailure objects for the skipped tests + * + * @return TestFailure[] + */ + public function skipped(): array + { + return $this->skipped; + } + + /** + * Gets the number of detected errors. + */ + public function errorCount(): int + { + return \count($this->errors); + } + + /** + * Returns an array of TestFailure objects for the errors + * + * @return TestFailure[] + */ + public function errors(): array + { + return $this->errors; + } + + /** + * Gets the number of detected failures. + */ + public function failureCount(): int + { + return \count($this->failures); + } + + /** + * Returns an array of TestFailure objects for the failures + * + * @return TestFailure[] + */ + public function failures(): array + { + return $this->failures; + } + + /** + * Gets the number of detected warnings. + */ + public function warningCount(): int + { + return \count($this->warnings); + } + + /** + * Returns an array of TestFailure objects for the warnings + * + * @return TestFailure[] + */ + public function warnings(): array + { + return $this->warnings; + } + + /** + * Returns the names of the tests that have passed. + */ + public function passed(): array + { + return $this->passed; + } + + /** + * Returns the (top) test suite. + */ + public function topTestSuite(): TestSuite + { + return $this->topTestSuite; + } + + /** + * Returns whether code coverage information should be collected. + */ + public function getCollectCodeCoverageInformation(): bool + { + return $this->codeCoverage !== null; + } + + /** + * Runs a TestCase. + * + * @throws CodeCoverageException + * @throws OriginalCoveredCodeNotExecutedException + * @throws OriginalMissingCoversAnnotationException + * @throws UnintentionallyCoveredCodeException + * @throws \ReflectionException + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\RuntimeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function run(Test $test): void + { + Assert::resetCount(); + + $coversNothing = false; + + if ($test instanceof TestCase) { + $test->setRegisterMockObjectsFromTestArgumentsRecursively( + $this->registerMockObjectsFromTestArgumentsRecursively + ); + + $isAnyCoverageRequired = self::isAnyCoverageRequired($test); + } + + $error = false; + $failure = false; + $warning = false; + $incomplete = false; + $risky = false; + $skipped = false; + + $this->startTest($test); + + $errorHandlerSet = false; + + if ($this->convertErrorsToExceptions) { + $oldErrorHandler = \set_error_handler( + [ErrorHandler::class, 'handleError'], + \E_ALL | \E_STRICT + ); + + if ($oldErrorHandler === null) { + $errorHandlerSet = true; + } else { + \restore_error_handler(); + } + } + + $collectCodeCoverage = $this->codeCoverage !== null && + !$test instanceof WarningTestCase && + $isAnyCoverageRequired; + + 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) { + /* @noinspection ForgottenDebugOutputInspection */ + \xdebug_start_function_monitor(ResourceOperations::getFunctions()); + } + + Timer::start(); + + try { + if (!$test instanceof WarningTestCase && + $this->enforceTimeLimit && + ($this->defaultTimeLimit || $test->getSize() != \PHPUnit\Util\Test::UNKNOWN) && + \extension_loaded('pcntl') && \class_exists(Invoker::class)) { + 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; + + case \PHPUnit\Util\Test::UNKNOWN: + $_timeout = $this->defaultTimeLimit; + + break; + } + + $invoker = new Invoker; + $invoker->invoke([$test, 'runBare'], [], $_timeout); + } else { + $test->runBare(); + } + } catch (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 = Timer::stop(); + $test->addToAssertionCount(Assert::getCount()); + + if ($monitorFunctions) { + $blacklist = new Blacklist; + + /** @noinspection ForgottenDebugOutputInspection */ + $functions = \xdebug_get_monitored_functions(); + + /* @noinspection ForgottenDebugOutputInspection */ + \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; + + $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) { + $reflected = new \ReflectionClass($test); + $name = $test->getName(false); + + if ($name && $reflected->hasMethod($name)) { + $reflected = $reflected->getMethod($name); + } + $this->addFailure( + $test, + new RiskyTestError(\sprintf( + "This test did not perform any assertions\n\n%s:%d", + $reflected->getFileName(), + $reflected->getStartLine() + )), + $time + ); + } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && + $test->doesNotPerformAssertions() && + $test->getNumAssertions() > 0) { + $this->addFailure( + $test, + new RiskyTestError(\sprintf( + 'This test is annotated with "@doesNotPerformAssertions" but performed %d assertions', + $test->getNumAssertions() + )), + $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. + */ + public function count(): int + { + return $this->runTests; + } + + /** + * Checks whether the test run should stop. + */ + public function shouldStop(): bool + { + return $this->stop; + } + + /** + * Marks that the test run should stop. + */ + public function stop(): void + { + $this->stop = true; + } + + /** + * Returns the code coverage object. + */ + public function getCodeCoverage(): ?CodeCoverage + { + return $this->codeCoverage; + } + + /** + * Sets the code coverage object. + */ + public function setCodeCoverage(CodeCoverage $codeCoverage): void + { + $this->codeCoverage = $codeCoverage; + } + + /** + * Enables or disables the error-to-exception conversion. + */ + public function convertErrorsToExceptions(bool $flag): void + { + $this->convertErrorsToExceptions = $flag; + } + + /** + * Returns the error-to-exception conversion setting. + */ + public function getConvertErrorsToExceptions(): bool + { + return $this->convertErrorsToExceptions; + } + + /** + * Enables or disables the stopping when an error occurs. + */ + public function stopOnError(bool $flag): void + { + $this->stopOnError = $flag; + } + + /** + * Enables or disables the stopping when a failure occurs. + */ + public function stopOnFailure(bool $flag): void + { + $this->stopOnFailure = $flag; + } + + /** + * Enables or disables the stopping when a warning occurs. + */ + public function stopOnWarning(bool $flag): void + { + $this->stopOnWarning = $flag; + } + + public function beStrictAboutTestsThatDoNotTestAnything(bool $flag): void + { + $this->beStrictAboutTestsThatDoNotTestAnything = $flag; + } + + public function isStrictAboutTestsThatDoNotTestAnything(): bool + { + return $this->beStrictAboutTestsThatDoNotTestAnything; + } + + public function beStrictAboutOutputDuringTests(bool $flag): void + { + $this->beStrictAboutOutputDuringTests = $flag; + } + + public function isStrictAboutOutputDuringTests(): bool + { + return $this->beStrictAboutOutputDuringTests; + } + + public function beStrictAboutResourceUsageDuringSmallTests(bool $flag): void + { + $this->beStrictAboutResourceUsageDuringSmallTests = $flag; + } + + public function isStrictAboutResourceUsageDuringSmallTests(): bool + { + return $this->beStrictAboutResourceUsageDuringSmallTests; + } + + public function enforceTimeLimit(bool $flag): void + { + $this->enforceTimeLimit = $flag; + } + + public function enforcesTimeLimit(): bool + { + return $this->enforceTimeLimit; + } + + public function beStrictAboutTodoAnnotatedTests(bool $flag): void + { + $this->beStrictAboutTodoAnnotatedTests = $flag; + } + + public function isStrictAboutTodoAnnotatedTests(): bool + { + return $this->beStrictAboutTodoAnnotatedTests; + } + + /** + * Enables or disables the stopping for risky tests. + */ + public function stopOnRisky(bool $flag): void + { + $this->stopOnRisky = $flag; + } + + /** + * Enables or disables the stopping for incomplete tests. + */ + public function stopOnIncomplete(bool $flag): void + { + $this->stopOnIncomplete = $flag; + } + + /** + * Enables or disables the stopping for skipped tests. + */ + public function stopOnSkipped(bool $flag): void + { + $this->stopOnSkipped = $flag; + } + + /** + * Enables or disables the stopping for defects: error, failure, warning + */ + public function stopOnDefect(bool $flag): void + { + $this->stopOnDefect = $flag; + } + + /** + * Returns the time spent running the tests. + */ + public function time(): float + { + return $this->time; + } + + /** + * Returns whether the entire test was successful or not. + */ + public function wasSuccessful(): bool + { + return $this->wasSuccessfulIgnoringWarnings() && empty($this->warnings); + } + + public function wasSuccessfulIgnoringWarnings(): bool + { + return empty($this->errors) && empty($this->failures); + } + + /** + * Sets the default timeout for tests + */ + public function setDefaultTimeLimit(int $timeout): void + { + $this->defaultTimeLimit = $timeout; + } + + /** + * Sets the timeout for small tests. + */ + public function setTimeoutForSmallTests(int $timeout): void + { + $this->timeoutForSmallTests = $timeout; + } + + /** + * Sets the timeout for medium tests. + */ + public function setTimeoutForMediumTests(int $timeout): void + { + $this->timeoutForMediumTests = $timeout; + } + + /** + * Sets the timeout for large tests. + */ + public function setTimeoutForLargeTests(int $timeout): void + { + $this->timeoutForLargeTests = $timeout; + } + + /** + * Returns the set timeout for large tests. + */ + public function getTimeoutForLargeTests(): int + { + return $this->timeoutForLargeTests; + } + + public function setRegisterMockObjectsFromTestArgumentsRecursively(bool $flag): void + { + $this->registerMockObjectsFromTestArgumentsRecursively = $flag; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/TestSuite.php b/.phpunit/phpunit-7/src/Framework/TestSuite.php new file mode 100644 index 0000000..d968be9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestSuite.php @@ -0,0 +1,956 @@ + + * + * 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 +{ + /** + * 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 + */ + 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 = []; + + /** + * Last count of tests in this suite. + * + * @var null|int + */ + private $cachedNumTests; + + /** + * @var bool + */ + private $beStrictAboutChangesToGlobalState; + + /** + * @var Factory + */ + private $iteratorFilter; + + /** + * @var string[] + */ + private $declaredClasses; + + /** + * @param string $name + * + * @throws Exception + */ + public static function createTest(ReflectionClass $theClass, $name): Test + { + $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) { + throw new Exception('No valid test provided.'); + } + $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) { + $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); + + /* @var TestCase $_test */ + + 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 ($test instanceof TestCase) { + $test->setName($name); + + 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'] + ); + } + } + + return $test; + } + + public static function isTestMethod(ReflectionMethod $method): bool + { + if (\strpos($method->name, 'test') === 0) { + return true; + } + + $annotations = \PHPUnit\Util\Test::parseAnnotations($method->getDocComment()); + + return isset($annotations['test']); + } + + /** + * 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 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, true)) { + $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)) { + $this->setName($theClass); + + return; + } + + 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) { + if ($method->getDeclaringClass()->getName() === Assert::class) { + continue; + } + + if ($method->getDeclaringClass()->getName() === TestCase::class) { + continue; + } + + $this->addTestMethod($theClass, $method); + } + + if (empty($this->tests)) { + $this->addTest( + self::warning( + \sprintf( + 'No tests found in class "%s".', + $theClass->getName() + ) + ) + ); + } + + $this->testCase = true; + } + + /** + * Template Method that is called before the tests + * of this test suite are run. + */ + protected function setUp(): void + { + } + + /** + * Template Method that is called after the tests + * of this test suite have finished running. + */ + protected function tearDown(): void + { + } + + /** + * Returns a string representation of the test suite. + */ + public function toString(): string + { + return $this->getName(); + } + + /** + * Adds a test to the suite. + * + * @param array $groups + */ + public function addTest(Test $test, $groups = []): void + { + $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. + * + * @throws Exception + */ + public function addTestSuite($testClass): void + { + 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() && $testClass->isSubclassOf(TestCase::class)) { + $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. + * + * @throws Exception + */ + public function addTestFile(string $filename): void + { + 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 short name ('NameSpace_ShortName'), or as a + // PSR-1 local short name ('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): void + { + 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 + */ + public function count($preferCache = false): int + { + if ($preferCache && $this->cachedNumTests !== null) { + return $this->cachedNumTests; + } + + $numTests = 0; + + foreach ($this as $test) { + $numTests += \count($test); + } + + $this->cachedNumTests = $numTests; + + return $numTests; + } + + /** + * Returns the name of the suite. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Returns the test groups of the suite. + */ + public function getGroups(): array + { + return \array_keys($this->groups); + } + + public function getGroupDetails() + { + return $this->groups; + } + + /** + * Set tests groups of the test case + */ + public function setGroupDetails(array $groups): void + { + $this->groups = $groups; + } + + /** + * Runs the tests and collects their result in a TestResult. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function run(TestResult $result = null): TestResult + { + 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 $error) { + foreach ($this->tests() as $test) { + $result->startTest($test); + $result->addFailure($test, $error, 0); + $result->endTest($test, 0); + } + + $this->tearDown(); + $result->endTestSuite($this); + + return $result; + } catch (Throwable $t) { + foreach ($this->tests() as $test) { + if ($result->shouldStop()) { + break; + } + + $result->startTest($test); + $result->addError($test, $t, 0); + $result->endTest($test, 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); + } + + try { + 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]); + } + } + } catch (Throwable $t) { + $message = "Exception in {$this->name}::$afterClassMethod" . \PHP_EOL . $t->getMessage(); + $error = new SyntheticError($message, 0, $t->getFile(), $t->getLine(), $t->getTrace()); + $test = new \Failure($afterClassMethod); + + $result->startTest($test); + $result->addFailure($test, $error, 0); + $result->endTest($test, 0); + } + + $this->tearDown(); + + $result->endTestSuite($this); + + return $result; + } + + public function setRunTestInSeparateProcess(bool $runTestInSeparateProcess): void + { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * Returns the test at the given index. + * + * @return false|Test + */ + public function testAt(int $index) + { + if (isset($this->tests[$index])) { + return $this->tests[$index]; + } + + return false; + } + + /** + * Returns the tests as an enumeration. + */ + public function tests(): array + { + return $this->tests; + } + + /** + * Set tests of the test suite + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + /** + * Mark the test suite as skipped. + * + * @param string $message + * + * @throws SkippedTestSuiteError + */ + public function markTestSuiteSkipped($message = ''): void + { + throw new SkippedTestSuiteError($message); + } + + /** + * @param bool $beStrictAboutChangesToGlobalState + */ + public function setBeStrictAboutChangesToGlobalState($beStrictAboutChangesToGlobalState): void + { + if (null === $this->beStrictAboutChangesToGlobalState && \is_bool($beStrictAboutChangesToGlobalState)) { + $this->beStrictAboutChangesToGlobalState = $beStrictAboutChangesToGlobalState; + } + } + + /** + * @param bool $backupGlobals + */ + public function setBackupGlobals($backupGlobals): void + { + if (null === $this->backupGlobals && \is_bool($backupGlobals)) { + $this->backupGlobals = $backupGlobals; + } + } + + /** + * @param bool $backupStaticAttributes + */ + public function setBackupStaticAttributes($backupStaticAttributes): void + { + if (null === $this->backupStaticAttributes && \is_bool($backupStaticAttributes)) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + /** + * Returns an iterator for this test suite. + */ + public function getIterator(): Iterator + { + $iterator = new TestSuiteIterator($this); + + if ($this->iteratorFilter !== null) { + $iterator = $this->iteratorFilter->factory($iterator, $this); + } + + return $iterator; + } + + public function injectFilter(Factory $filter): void + { + $this->iteratorFilter = $filter; + + foreach ($this as $test) { + if ($test instanceof self) { + $test->injectFilter($filter); + } + } + } + + /** + * Creates a default TestResult object. + */ + protected function createResult(): TestResult + { + return new TestResult; + } + + /** + * @throws Exception + */ + protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method): void + { + 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 string $message + */ + protected static function warning($message): WarningTestCase + { + return new WarningTestCase($message); + } + + /** + * @param string $class + * @param string $methodName + * @param string $message + */ + protected static function skipTest($class, $methodName, $message): SkippedTestCase + { + return new SkippedTestCase($class, $methodName, $message); + } + + /** + * @param string $class + * @param string $methodName + * @param string $message + */ + protected static function incompleteTest($class, $methodName, $message): IncompleteTestCase + { + return new IncompleteTestCase($class, $methodName, $message); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/TestSuiteIterator.php b/.phpunit/phpunit-7/src/Framework/TestSuiteIterator.php new file mode 100644 index 0000000..e1f34f1 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/TestSuiteIterator.php @@ -0,0 +1,91 @@ + + * + * 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. + */ +final class TestSuiteIterator implements RecursiveIterator +{ + /** + * @var int + */ + private $position; + + /** + * @var Test[] + */ + private $tests; + + public function __construct(TestSuite $testSuite) + { + $this->tests = $testSuite->tests(); + } + + /** + * Rewinds the Iterator to the first element. + */ + public function rewind(): void + { + $this->position = 0; + } + + /** + * Checks if there is a current element after calls to rewind() or next(). + */ + public function valid(): bool + { + return $this->position < \count($this->tests); + } + + /** + * Returns the key of the current element. + */ + public function key(): int + { + return $this->position; + } + + /** + * Returns the current element. + */ + public function current(): Test + { + return $this->valid() ? $this->tests[$this->position] : null; + } + + /** + * Moves forward to next element. + */ + public function next(): void + { + $this->position++; + } + + /** + * Returns the sub iterator for the current element. + */ + public function getChildren(): self + { + return new self( + $this->tests[$this->position] + ); + } + + /** + * Checks whether the current element has children. + */ + public function hasChildren(): bool + { + return $this->tests[$this->position] instanceof TestSuite; + } +} diff --git a/.phpunit/phpunit-7/src/Framework/UnintentionallyCoveredCodeError.php b/.phpunit/phpunit-7/src/Framework/UnintentionallyCoveredCodeError.php new file mode 100644 index 0000000..af2623d --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/UnintentionallyCoveredCodeError.php @@ -0,0 +1,18 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Framework/Warning.php b/.phpunit/phpunit-7/src/Framework/Warning.php new file mode 100644 index 0000000..726eb07 --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/Warning.php @@ -0,0 +1,24 @@ + + * + * 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. + */ + public function toString(): string + { + return $this->getMessage(); + } +} diff --git a/.phpunit/phpunit-7/src/Framework/WarningTestCase.php b/.phpunit/phpunit-7/src/Framework/WarningTestCase.php new file mode 100644 index 0000000..53f6bff --- /dev/null +++ b/.phpunit/phpunit-7/src/Framework/WarningTestCase.php @@ -0,0 +1,71 @@ + + * + * 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'); + } + + public function getMessage(): string + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return 'Warning'; + } + + /** + * @throws Exception + */ + protected function runTest(): void + { + throw new Warning($this->message); + } +} diff --git a/.phpunit/phpunit-7/src/Runner/BaseTestRunner.php b/.phpunit/phpunit-7/src/Runner/BaseTestRunner.php new file mode 100644 index 0000000..899c737 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/BaseTestRunner.php @@ -0,0 +1,145 @@ + + * + * 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\Exception; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestSuite; +use ReflectionClass; +use ReflectionException; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * Base class for all test runners. + */ +abstract class BaseTestRunner +{ + public const STATUS_UNKNOWN = -1; + + public const STATUS_PASSED = 0; + + public const STATUS_SKIPPED = 1; + + public const STATUS_INCOMPLETE = 2; + + public const STATUS_FAILURE = 3; + + public const STATUS_ERROR = 4; + + public const STATUS_RISKY = 5; + + public const STATUS_WARNING = 6; + + public const SUITE_METHODNAME = 'suite'; + + /** + * Returns the loader to be used. + */ + public function getLoader(): TestSuiteLoader + { + return new StandardTestSuiteLoader; + } + + /** + * Returns the Test corresponding to the given suite. + * This is a template method, subclasses override + * the runFailed() and clearStatus() methods. + * + * @param array|string $suffixes + * + * @throws Exception + */ + public function getTest(string $suiteClassName, string $suiteClassFile = '', $suffixes = ''): ?Test + { + if (\is_dir($suiteClassName) && + !\is_file($suiteClassName . '.php') && empty($suiteClassFile)) { + $facade = new FileIteratorFacade; + $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 null; + } + + try { + $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME); + + if (!$suiteMethod->isStatic()) { + $this->runFailed( + 'suite() method must be static.' + ); + + return null; + } + + try { + $test = $suiteMethod->invoke(null, $testClass->getName()); + } catch (ReflectionException $e) { + $this->runFailed( + \sprintf( + "Failed to invoke suite() method.\n%s", + $e->getMessage() + ) + ); + + return null; + } + } 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. + */ + protected function loadSuiteClass(string $suiteClassName, string $suiteClassFile = ''): ReflectionClass + { + $loader = $this->getLoader(); + + return $loader->load($suiteClassName, $suiteClassFile); + } + + /** + * Clears the status message. + */ + protected function clearStatus(): void + { + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + */ + abstract protected function runFailed(string $message); +} diff --git a/.phpunit/phpunit-7/src/Runner/Exception.php b/.phpunit/phpunit-7/src/Runner/Exception.php new file mode 100644 index 0000000..18cdfa7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Exception.php @@ -0,0 +1,14 @@ + + * + * 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 +{ +} diff --git a/.phpunit/phpunit-7/src/Runner/Filter/ExcludeGroupFilterIterator.php b/.phpunit/phpunit-7/src/Runner/Filter/ExcludeGroupFilterIterator.php new file mode 100644 index 0000000..17af7dc --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Filter/ExcludeGroupFilterIterator.php @@ -0,0 +1,18 @@ + + * + * 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 +{ + protected function doAccept(string $hash): bool + { + return !\in_array($hash, $this->groupTests, true); + } +} diff --git a/.phpunit/phpunit-7/src/Runner/Filter/Factory.php b/.phpunit/phpunit-7/src/Runner/Filter/Factory.php new file mode 100644 index 0000000..139e097 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Filter/Factory.php @@ -0,0 +1,51 @@ + + * + * 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 = []; + + /** + * @throws InvalidArgumentException + */ + public function addFilter(ReflectionClass $filter, $args): void + { + if (!$filter->isSubclassOf(\RecursiveFilterIterator::class)) { + throw new InvalidArgumentException( + \sprintf( + 'Class "%s" does not extend RecursiveFilterIterator', + $filter->name + ) + ); + } + + $this->filters[] = [$filter, $args]; + } + + public function factory(Iterator $iterator, TestSuite $suite): FilterIterator + { + foreach ($this->filters as $filter) { + [$class, $args] = $filter; + $iterator = $class->newInstance($iterator, $args, $suite); + } + + return $iterator; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/Filter/GroupFilterIterator.php b/.phpunit/phpunit-7/src/Runner/Filter/GroupFilterIterator.php new file mode 100644 index 0000000..1d204ad --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Filter/GroupFilterIterator.php @@ -0,0 +1,51 @@ + + * + * 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 string[] + */ + protected $groupTests = []; + + public function __construct(RecursiveIterator $iterator, array $groups, TestSuite $suite) + { + parent::__construct($iterator); + + foreach ($suite->getGroupDetails() as $group => $tests) { + if (\in_array((string) $group, $groups, true)) { + $testHashes = \array_map( + 'spl_object_hash', + $tests + ); + + $this->groupTests = \array_merge($this->groupTests, $testHashes); + } + } + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + return $this->doAccept(\spl_object_hash($test)); + } + + abstract protected function doAccept(string $hash); +} diff --git a/.phpunit/phpunit-7/src/Runner/Filter/IncludeGroupFilterIterator.php b/.phpunit/phpunit-7/src/Runner/Filter/IncludeGroupFilterIterator.php new file mode 100644 index 0000000..c9dc1f8 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Filter/IncludeGroupFilterIterator.php @@ -0,0 +1,18 @@ + + * + * 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 +{ + protected function doAccept(string $hash): bool + { + return \in_array($hash, $this->groupTests, true); + } +} diff --git a/.phpunit/phpunit-7/src/Runner/Filter/NameFilterIterator.php b/.phpunit/phpunit-7/src/Runner/Filter/NameFilterIterator.php new file mode 100644 index 0000000..18734a0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Filter/NameFilterIterator.php @@ -0,0 +1,122 @@ + + * + * 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; + + /** + * @throws \Exception + */ + public function __construct(RecursiveIterator $iterator, string $filter) + { + parent::__construct($iterator); + + $this->setFilter($filter); + } + + public function accept(): bool + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof TestSuite) { + return true; + } + + $tmp = \PHPUnit\Util\Test::describe($test); + + 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 (bool) $accepted; + } + + /** + * @throws \Exception + */ + protected function setFilter(string $filter): void + { + 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/i', \str_replace( + '/', + '\\/', + $filter + )); + } + + $this->filter = $filter; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterIncompleteTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterIncompleteTestHook.php new file mode 100644 index 0000000..35ded5d --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterIncompleteTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterIncompleteTestHook extends TestHook +{ + public function executeAfterIncompleteTest(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterLastTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterLastTestHook.php new file mode 100644 index 0000000..7dee9f9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterLastTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterLastTestHook extends Hook +{ + public function executeAfterLastTest(): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterRiskyTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterRiskyTestHook.php new file mode 100644 index 0000000..7fe9ee7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterRiskyTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterRiskyTestHook extends TestHook +{ + public function executeAfterRiskyTest(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterSkippedTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterSkippedTestHook.php new file mode 100644 index 0000000..f9253b5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterSkippedTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterSkippedTestHook extends TestHook +{ + public function executeAfterSkippedTest(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterSuccessfulTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterSuccessfulTestHook.php new file mode 100644 index 0000000..6b55cc8 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterSuccessfulTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterSuccessfulTestHook extends TestHook +{ + public function executeAfterSuccessfulTest(string $test, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterTestErrorHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestErrorHook.php new file mode 100644 index 0000000..f5c23fb --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestErrorHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterTestErrorHook extends TestHook +{ + public function executeAfterTestError(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterTestFailureHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestFailureHook.php new file mode 100644 index 0000000..9ed2939 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestFailureHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterTestFailureHook extends TestHook +{ + public function executeAfterTestFailure(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestHook.php new file mode 100644 index 0000000..f463732 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestHook.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterTestHook extends Hook +{ + /** + * This hook will fire after any test, regardless of the result. + * + * For more fine grained control, have a look at the other hooks + * that extend PHPUnit\Runner\Hook. + */ + public function executeAfterTest(string $test, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/AfterTestWarningHook.php b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestWarningHook.php new file mode 100644 index 0000000..12de80f --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/AfterTestWarningHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface AfterTestWarningHook extends TestHook +{ + public function executeAfterTestWarning(string $test, string $message, float $time): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/BeforeFirstTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/BeforeFirstTestHook.php new file mode 100644 index 0000000..59b6666 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/BeforeFirstTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface BeforeFirstTestHook extends Hook +{ + public function executeBeforeFirstTest(): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/BeforeTestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/BeforeTestHook.php new file mode 100644 index 0000000..8bbf8a9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/BeforeTestHook.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface BeforeTestHook extends TestHook +{ + public function executeBeforeTest(string $test): void; +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/Hook.php b/.phpunit/phpunit-7/src/Runner/Hook/Hook.php new file mode 100644 index 0000000..546f1a3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/Hook.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface Hook +{ +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/TestHook.php b/.phpunit/phpunit-7/src/Runner/Hook/TestHook.php new file mode 100644 index 0000000..47c41f9 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/TestHook.php @@ -0,0 +1,14 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +interface TestHook extends Hook +{ +} diff --git a/.phpunit/phpunit-7/src/Runner/Hook/TestListenerAdapter.php b/.phpunit/phpunit-7/src/Runner/Hook/TestListenerAdapter.php new file mode 100644 index 0000000..02ed700 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Hook/TestListenerAdapter.php @@ -0,0 +1,137 @@ + + * + * 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\AssertionFailedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Util\Test as TestUtil; + +final class TestListenerAdapter implements TestListener +{ + /** + * @var TestHook[] + */ + private $hooks = []; + + /** + * @var bool + */ + private $lastTestWasNotSuccessful; + + public function add(TestHook $hook): void + { + $this->hooks[] = $hook; + } + + public function startTest(Test $test): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof BeforeTestHook) { + $hook->executeBeforeTest(TestUtil::describeAsString($test)); + } + } + + $this->lastTestWasNotSuccessful = false; + } + + public function addError(Test $test, \Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestErrorHook) { + $hook->executeAfterTestError(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestWarningHook) { + $hook->executeAfterTestWarning(TestUtil::describeAsString($test), $e->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestFailureHook) { + $hook->executeAfterTestFailure(TestUtil::describeAsString($test), $e->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterIncompleteTestHook) { + $hook->executeAfterIncompleteTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterRiskyTestHook) { + $hook->executeAfterRiskyTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterSkippedTestHook) { + $hook->executeAfterSkippedTest(TestUtil::describeAsString($test), $t->getMessage(), $time); + } + } + + $this->lastTestWasNotSuccessful = true; + } + + public function endTest(Test $test, float $time): void + { + if ($this->lastTestWasNotSuccessful !== true) { + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterSuccessfulTestHook) { + $hook->executeAfterSuccessfulTest(TestUtil::describeAsString($test), $time); + } + } + } + + foreach ($this->hooks as $hook) { + if ($hook instanceof AfterTestHook) { + $hook->executeAfterTest(TestUtil::describeAsString($test), $time); + } + } + } + + public function startTestSuite(TestSuite $suite): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } +} diff --git a/.phpunit/phpunit-7/src/Runner/PhptTestCase.php b/.phpunit/phpunit-7/src/Runner/PhptTestCase.php new file mode 100644 index 0000000..57a58fb --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/PhptTestCase.php @@ -0,0 +1,598 @@ + + * + * 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\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\PHP\AbstractPhpProcess; +use SebastianBergmann\Timer\Timer; +use Text_Template; +use Throwable; + +/** + * Runner for PHPT test cases. + */ +class PhptTestCase implements Test, SelfDescribing +{ + /** + * @var string[] + */ + private const 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', + ]; + + /** + * @var string + */ + private $filename; + + /** + * @var AbstractPhpProcess + */ + private $phpUtil; + + /** + * @var string + */ + private $output = ''; + + /** + * Constructs a test case with the given filename. + * + * @throws Exception + */ + public function __construct(string $filename, AbstractPhpProcess $phpUtil = null) + { + 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). + */ + public function count(): int + { + return 1; + } + + /** + * Runs a test and collects its result in a TestResult instance. + * + * @throws Exception + * @throws \ReflectionException + * @throws \SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException + * @throws \SebastianBergmann\CodeCoverage\InvalidArgumentException + * @throws \SebastianBergmann\CodeCoverage\MissingCoversAnnotationException + * @throws \SebastianBergmann\CodeCoverage\RuntimeException + * @throws \SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function run(TestResult $result = null): TestResult + { + if ($result === null) { + $result = new TestResult; + } + + try { + $sections = $this->parse(); + } catch (Exception $e) { + $result->startTest($this); + $result->addFailure($this, new SkippedTestError($e->getMessage()), 0); + $result->endTest($this, 0); + + return $result; + } + + $code = $this->render($sections['FILE']); + $xfail = false; + $settings = $this->parseIniSection(self::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($code); + } + + Timer::start(); + + $jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings)); + $time = Timer::stop(); + $this->output = $jobResult['stdout'] ?? ''; + + 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; + } + + /** + * Returns the name of the test case. + */ + public function getName(): string + { + return $this->toString(); + } + + /** + * Returns a string representation of the test case. + */ + public function toString(): string + { + return $this->filename; + } + + public function usesDataProvider(): bool + { + return false; + } + + public function getNumAssertions(): int + { + return 1; + } + + public function getActualOutput(): string + { + return $this->output; + } + + public function hasOutput(): bool + { + return !empty($this->output); + } + + /** + * Parse --INI-- section key value pairs and return as array. + * + * @param array|string + */ + private function parseIniSection($content, $ini = []): array + { + 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; + } + + private function parseEnvSection(string $content): array + { + $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; + } + + /** + * @throws Exception + */ + private function assertPhptExpectation(array $sections, string $output): void + { + $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])); + $expected = $sectionName === 'EXPECTREGEX' ? "/{$sectionContent}/" : $sectionContent; + + if ($expected === null) { + throw new Exception('No PHPT expectation found'); + } + Assert::$sectionAssertion($expected, $actual); + + return; + } + } + + throw new Exception('No PHPT assertion found'); + } + + /** + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function runSkip(array &$sections, TestResult $result, array $settings): bool + { + 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; + } + + private function runClean(array &$sections): void + { + $this->phpUtil->setStdin(''); + $this->phpUtil->setArgs(''); + + if (isset($sections['CLEAN'])) { + $cleanCode = $this->render($sections['CLEAN']); + + $this->phpUtil->runJob($cleanCode, self::SETTINGS); + } + } + + /** + * @throws Exception + */ + private function parse(): array + { + $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; + } + + if (empty($section)) { + throw new Exception('Invalid PHPT file: empty section header'); + } + + $sections[$section] .= $line; + } + + if (isset($sections['FILEEOF'])) { + $sections['FILE'] = \rtrim($sections['FILEEOF'], "\r\n"); + unset($sections['FILEEOF']); + } + + $this->parseExternal($sections); + + if (!$this->validate($sections)) { + throw new Exception('Invalid PHPT file'); + } + + foreach ($unsupportedSections as $section) { + if (isset($sections[$section])) { + throw new Exception( + "PHPUnit does not support PHPT $section sections" + ); + } + } + + return $sections; + } + + /** + * @throws Exception + */ + private function parseExternal(array &$sections): void + { + $allowSections = [ + 'FILE', + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ]; + $testDirectory = \dirname($this->filename) . \DIRECTORY_SEPARATOR; + + foreach ($allowSections as $section) { + if (isset($sections[$section . '_EXTERNAL'])) { + $externalFilename = \trim($sections[$section . '_EXTERNAL']); + + if (!\is_file($testDirectory . $externalFilename) || + !\is_readable($testDirectory . $externalFilename)) { + throw new 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']); + } + } + } + + private function validate(array &$sections): bool + { + $requiredSections = [ + 'FILE', + [ + 'EXPECT', + 'EXPECTF', + 'EXPECTREGEX', + ], + ]; + + foreach ($requiredSections as $section) { + if (\is_array($section)) { + $foundSection = false; + + foreach ($section as $anySection) { + if (isset($sections[$anySection])) { + $foundSection = true; + + break; + } + } + + if (!$foundSection) { + return false; + } + + continue; + } + + if (!isset($sections[$section])) { + return false; + } + } + + return true; + } + + private function render(string $code): string + { + return \str_replace( + [ + '__DIR__', + '__FILE__', + ], + [ + "'" . \dirname($this->filename) . "'", + "'" . $this->filename . "'", + ], + $code + ); + } + + private function getCoverageFiles(): array + { + $baseDir = \dirname(\realpath($this->filename)) . \DIRECTORY_SEPARATOR; + $basename = \basename($this->filename, 'phpt'); + + return [ + 'coverage' => $baseDir . $basename . 'coverage', + 'job' => $baseDir . $basename . 'php', + ]; + } + + private function renderForCoverage(string &$job): void + { + $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'], + ] + ); + + \file_put_contents($files['job'], $job); + $job = $template->render(); + } + + private function cleanupForCoverage(): array + { + $files = $this->getCoverageFiles(); + $coverage = @\unserialize(\file_get_contents($files['coverage'])); + + if ($coverage === false) { + $coverage = []; + } + + foreach ($files as $file) { + @\unlink($file); + } + + return $coverage; + } + + private function stringifyIni(array $ini): array + { + $settings = []; + + foreach ($ini as $key => $value) { + if (\is_array($value)) { + foreach ($value as $val) { + $settings[] = $key . '=' . $val; + } + + continue; + } + + $settings[] = $key . '=' . $value; + } + + return $settings; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/ResultCacheExtension.php b/.phpunit/phpunit-7/src/Runner/ResultCacheExtension.php new file mode 100644 index 0000000..962bbc0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/ResultCacheExtension.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +final class ResultCacheExtension implements AfterSuccessfulTestHook, AfterSkippedTestHook, AfterRiskyTestHook, AfterIncompleteTestHook, AfterTestErrorHook, AfterTestWarningHook, AfterTestFailureHook, AfterLastTestHook +{ + /** + * @var TestResultCacheInterface + */ + private $cache; + + public function __construct(TestResultCache $cache) + { + $this->cache = $cache; + } + + public function flush(): void + { + $this->cache->persist(); + } + + public function executeAfterSuccessfulTest(string $test, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + } + + public function executeAfterIncompleteTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_INCOMPLETE); + } + + public function executeAfterRiskyTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_RISKY); + } + + public function executeAfterSkippedTest(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_SKIPPED); + } + + public function executeAfterTestError(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_ERROR); + } + + public function executeAfterTestFailure(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_FAILURE); + } + + public function executeAfterTestWarning(string $test, string $message, float $time): void + { + $testName = $this->getTestName($test); + + $this->cache->setTime($testName, \round($time, 3)); + $this->cache->setState($testName, BaseTestRunner::STATUS_WARNING); + } + + public function executeAfterLastTest(): void + { + $this->flush(); + } + + /** + * @param string $test A long description format of the current test + * + * @return string The test name without TestSuiteClassName:: and @dataprovider details + */ + private function getTestName(string $test): string + { + $matches = []; + + if (\preg_match('/^(?\S+::\S+)(?:(? with data set (?:#\d+|"[^"]+"))\s\()?/', $test, $matches)) { + $test = $matches['name'] . ($matches['dataname'] ?? ''); + } + + return $test; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/StandardTestSuiteLoader.php b/.phpunit/phpunit-7/src/Runner/StandardTestSuiteLoader.php new file mode 100644 index 0000000..633a7c2 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/StandardTestSuiteLoader.php @@ -0,0 +1,112 @@ + + * + * 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 +{ + /** + * @throws Exception + * @throws \PHPUnit\Framework\Exception + */ + public function load(string $suiteClassName, string $suiteClassFile = ''): ReflectionClass + { + $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 + ) + ); + } + + public function reload(ReflectionClass $aClass): ReflectionClass + { + return $aClass; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/TestSuiteLoader.php b/.phpunit/phpunit-7/src/Runner/TestSuiteLoader.php new file mode 100644 index 0000000..74cf753 --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/TestSuiteLoader.php @@ -0,0 +1,22 @@ + + * + * 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 +{ + public function load(string $suiteClassName, string $suiteClassFile = ''): ReflectionClass; + + public function reload(ReflectionClass $aClass): ReflectionClass; +} diff --git a/.phpunit/phpunit-7/src/Runner/TestSuiteSorter.php b/.phpunit/phpunit-7/src/Runner/TestSuiteSorter.php new file mode 100644 index 0000000..9607d1d --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/TestSuiteSorter.php @@ -0,0 +1,357 @@ + + * + * 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\DataProviderTestSuite; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestSuite; + +final class TestSuiteSorter +{ + /** + * @var int + */ + public const ORDER_DEFAULT = 0; + + /** + * @var int + */ + public const ORDER_RANDOMIZED = 1; + + /** + * @var int + */ + public const ORDER_REVERSED = 2; + + /** + * @var int + */ + public const ORDER_DEFECTS_FIRST = 3; + + /** + * @var int + */ + public const ORDER_DURATION = 4; + + /** + * List of sorting weights for all test result codes. A higher number gives higher priority. + */ + private const DEFECT_SORT_WEIGHT = [ + BaseTestRunner::STATUS_ERROR => 6, + BaseTestRunner::STATUS_FAILURE => 5, + BaseTestRunner::STATUS_WARNING => 4, + BaseTestRunner::STATUS_INCOMPLETE => 3, + BaseTestRunner::STATUS_RISKY => 2, + BaseTestRunner::STATUS_SKIPPED => 1, + BaseTestRunner::STATUS_UNKNOWN => 0, + ]; + + /** + * @var array Associative array of (string => DEFECT_SORT_WEIGHT) elements + */ + private $defectSortOrder = []; + + /** + * @var TestResultCacheInterface + */ + private $cache; + + /** + * @var array array A list of normalized names of tests before reordering + */ + private $originalExecutionOrder = []; + + /** + * @var array array A list of normalized names of tests affected by reordering + */ + private $executionOrder = []; + + public static function getTestSorterUID(Test $test): string + { + if ($test instanceof PhptTestCase) { + return $test->getName(); + } + + if ($test instanceof TestCase) { + $testName = $test->getName(true); + + if (\strpos($testName, '::') === false) { + $testName = \get_class($test) . '::' . $testName; + } + + return $testName; + } + + return $test->getName(); + } + + public function __construct(?TestResultCacheInterface $cache = null) + { + $this->cache = $cache ?? new NullTestResultCache; + } + + /** + * @throws Exception + */ + public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void + { + $allowedOrders = [ + self::ORDER_DEFAULT, + self::ORDER_REVERSED, + self::ORDER_RANDOMIZED, + self::ORDER_DURATION, + ]; + + if (!\in_array($order, $allowedOrders, true)) { + throw new Exception( + '$order must be one of TestSuiteSorter::ORDER_DEFAULT, TestSuiteSorter::ORDER_REVERSED, or TestSuiteSorter::ORDER_RANDOMIZED, or TestSuiteSorter::ORDER_DURATION' + ); + } + + $allowedOrderDefects = [ + self::ORDER_DEFAULT, + self::ORDER_DEFECTS_FIRST, + ]; + + if (!\in_array($orderDefects, $allowedOrderDefects, true)) { + throw new Exception( + '$orderDefects must be one of TestSuiteSorter::ORDER_DEFAULT, TestSuiteSorter::ORDER_DEFECTS_FIRST' + ); + } + + if ($isRootTestSuite) { + $this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite); + } + + if ($suite instanceof TestSuite) { + foreach ($suite as $_suite) { + $this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST) { + $this->addSuiteToDefectSortOrder($suite); + } + + $this->sort($suite, $order, $resolveDependencies, $orderDefects); + } + + if ($isRootTestSuite) { + $this->executionOrder = $this->calculateTestExecutionOrder($suite); + } + } + + public function getOriginalExecutionOrder(): array + { + return $this->originalExecutionOrder; + } + + public function getExecutionOrder(): array + { + return $this->executionOrder; + } + + private function sort(TestSuite $suite, int $order, bool $resolveDependencies, int $orderDefects): void + { + if (empty($suite->tests())) { + return; + } + + if ($order === self::ORDER_REVERSED) { + $suite->setTests($this->reverse($suite->tests())); + } elseif ($order === self::ORDER_RANDOMIZED) { + $suite->setTests($this->randomize($suite->tests())); + } elseif ($order === self::ORDER_DURATION && $this->cache !== null) { + $suite->setTests($this->sortByDuration($suite->tests())); + } + + if ($orderDefects === self::ORDER_DEFECTS_FIRST && $this->cache !== null) { + $suite->setTests($this->sortDefectsFirst($suite->tests())); + } + + if ($resolveDependencies && !($suite instanceof DataProviderTestSuite) && $this->suiteOnlyContainsTests($suite)) { + $suite->setTests($this->resolveDependencies($suite->tests())); + } + } + + private function addSuiteToDefectSortOrder(TestSuite $suite): void + { + $max = 0; + + foreach ($suite->tests() as $test) { + $testname = self::getTestSorterUID($test); + + if (!isset($this->defectSortOrder[$testname])) { + $this->defectSortOrder[$testname] = self::DEFECT_SORT_WEIGHT[$this->cache->getState($testname)]; + $max = \max($max, $this->defectSortOrder[$testname]); + } + } + + $this->defectSortOrder[$suite->getName()] = $max; + } + + private function suiteOnlyContainsTests(TestSuite $suite): bool + { + return \array_reduce( + $suite->tests(), + function ($carry, $test) { + return $carry && ($test instanceof TestCase || $test instanceof DataProviderTestSuite); + }, + true + ); + } + + private function reverse(array $tests): array + { + return \array_reverse($tests); + } + + private function randomize(array $tests): array + { + \shuffle($tests); + + return $tests; + } + + private function sortDefectsFirst(array $tests): array + { + \usort( + $tests, + function ($left, $right) { + return $this->cmpDefectPriorityAndTime($left, $right); + } + ); + + return $tests; + } + + private function sortByDuration(array $tests): array + { + \usort( + $tests, + function ($left, $right) { + return $this->cmpDuration($left, $right); + } + ); + + return $tests; + } + + /** + * Comparator callback function to sort tests for "reach failure as fast as possible": + * 1. sort tests by defect weight defined in self::DEFECT_SORT_WEIGHT + * 2. when tests are equally defective, sort the fastest to the front + * 3. do not reorder successful tests + */ + private function cmpDefectPriorityAndTime(Test $a, Test $b): int + { + $priorityA = $this->defectSortOrder[self::getTestSorterUID($a)] ?? 0; + $priorityB = $this->defectSortOrder[self::getTestSorterUID($b)] ?? 0; + + if ($priorityB <=> $priorityA) { + // Sort defect weight descending + return $priorityB <=> $priorityA; + } + + if ($priorityA || $priorityB) { + return $this->cmpDuration($a, $b); + } + + // do not change execution order + return 0; + } + + /** + * Compares test duration for sorting tests by duration ascending. + */ + private function cmpDuration(Test $a, Test $b): int + { + return $this->cache->getTime(self::getTestSorterUID($a)) <=> $this->cache->getTime(self::getTestSorterUID($b)); + } + + /** + * Reorder Tests within a TestCase in such a way as to resolve as many dependencies as possible. + * The algorithm will leave the tests in original running order when it can. + * For more details see the documentation for test dependencies. + * + * Short description of algorithm: + * 1. Pick the next Test from remaining tests to be checked for dependencies. + * 2. If the test has no dependencies: mark done, start again from the top + * 3. If the test has dependencies but none left to do: mark done, start again from the top + * 4. When we reach the end add any leftover tests to the end. These will be marked 'skipped' during execution. + * + * @param array $tests + * + * @return array + */ + private function resolveDependencies(array $tests): array + { + $newTestOrder = []; + $i = 0; + + do { + $todoNames = \array_map( + function ($test) { + return self::getTestSorterUID($test); + }, + $tests + ); + + if (!$tests[$i]->hasDependencies() || empty(\array_intersect($this->getNormalizedDependencyNames($tests[$i]), $todoNames))) { + $newTestOrder = \array_merge($newTestOrder, \array_splice($tests, $i, 1)); + $i = 0; + } else { + $i++; + } + } while (!empty($tests) && ($i < \count($tests))); + + return \array_merge($newTestOrder, $tests); + } + + /** + * @param DataProviderTestSuite|TestCase $test + * + * @return array A list of full test names as "TestSuiteClassName::testMethodName" + */ + private function getNormalizedDependencyNames($test): array + { + if ($test instanceof DataProviderTestSuite) { + $testClass = \substr($test->getName(), 0, \strpos($test->getName(), '::')); + } else { + $testClass = \get_class($test); + } + + $names = \array_map( + function ($name) use ($testClass) { + return \strpos($name, '::') === false ? $testClass . '::' . $name : $name; + }, + $test->getDependencies() + ); + + return $names; + } + + private function calculateTestExecutionOrder(Test $suite): array + { + $tests = []; + + if ($suite instanceof TestSuite) { + foreach ($suite->tests() as $test) { + if (!($test instanceof TestSuite)) { + $tests[] = self::getTestSorterUID($test); + } else { + $tests = \array_merge($tests, $this->calculateTestExecutionOrder($test)); + } + } + } + + return $tests; + } +} diff --git a/.phpunit/phpunit-7/src/Runner/Version.php b/.phpunit/phpunit-7/src/Runner/Version.php new file mode 100644 index 0000000..4215c3f --- /dev/null +++ b/.phpunit/phpunit-7/src/Runner/Version.php @@ -0,0 +1,64 @@ + + * + * 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. + */ + public static function id(): string + { + if (self::$pharVersion !== null) { + return self::$pharVersion; + } + + if (self::$version === null) { + $version = new VersionId('7.5.6', \dirname(__DIR__, 2)); + self::$version = $version->getVersion(); + } + + return self::$version; + } + + public static function series(): string + { + if (\strpos(self::id(), '-')) { + $version = \explode('-', self::id())[0]; + } else { + $version = self::id(); + } + + return \implode('.', \array_slice(\explode('.', $version), 0, 2)); + } + + public static function getVersionString(): string + { + return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann and contributors.'; + } + + public static function getReleaseChannel(): string + { + if (\strpos(self::$pharVersion, '-') !== false) { + return '-nightly'; + } + + return ''; + } +} diff --git a/.phpunit/phpunit-7/src/TextUI/Command.php b/.phpunit/phpunit-7/src/TextUI/Command.php new file mode 100644 index 0000000..9b66bc1 --- /dev/null +++ b/.phpunit/phpunit-7/src/TextUI/Command.php @@ -0,0 +1,1374 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\TextUI; + +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\TestSuiteSorter; +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\CliTestDoxPrinter; +use PHPUnit\Util\TextTestListRenderer; +use PHPUnit\Util\XmlTestListRenderer; +use ReflectionClass; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +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, + 'prepend=' => null, + 'bootstrap=' => null, + 'cache-result' => null, + 'cache-result-file=' => 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, + 'default-time-limit=' => null, + 'enforce-time-limit' => null, + 'exclude-group=' => null, + 'filter=' => null, + 'generate-configuration' => null, + 'globals-backup' => null, + 'group=' => null, + 'help' => null, + 'resolve-dependencies' => null, + 'ignore-dependencies' => 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, + 'order-by=' => null, + 'printer=' => null, + 'process-isolation' => null, + 'repeat=' => null, + 'dont-report-useless-tests' => null, + 'random-order' => null, + 'random-order-seed=' => null, + 'reverse-order' => null, + 'reverse-list' => null, + 'static-backup' => null, + 'stderr' => null, + 'stop-on-defect' => 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, + 'dump-xdebug-filter=' => null, + ]; + + /** + * @var bool + */ + private $versionStringPrinted = false; + + /** + * @throws \RuntimeException + * @throws \PHPUnit\Framework\Exception + * @throws \InvalidArgumentException + */ + public static function main(bool $exit = true): int + { + $command = new static; + + return $command->run($_SERVER['argv'], $exit); + } + + /** + * @throws \RuntimeException + * @throws \ReflectionException + * @throws \InvalidArgumentException + * @throws Exception + */ + public function run(array $argv, bool $exit = true): int + { + $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. + */ + protected function createRunner(): TestRunner + { + 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); + * } + * + * } + * + * + * @throws Exception + */ + protected function handleArguments(array $argv): void + { + 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 '--cache-result': + $this->arguments['cacheResult'] = true; + + break; + + case '--cache-result-file': + $this->arguments['cacheResultFile'] = $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 '--order-by': + $this->handleOrderByOption($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-defect': + $this->arguments['stopOnDefect'] = 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'] = CliTestDoxPrinter::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 '--default-time-limit': + $this->arguments['defaultTimeLimit'] = (int) $option[1]; + + 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; + + case '--random-order': + $this->handleOrderByOption('random'); + + break; + + case '--random-order-seed': + $this->arguments['randomOrderSeed'] = (int) $option[1]; + + break; + + case '--resolve-dependencies': + $this->handleOrderByOption('depends'); + + break; + + case '--ignore-dependencies': + $this->arguments['resolveDependencies'] = false; + + break; + + case '--reverse-order': + $this->handleOrderByOption('reverse'); + + break; + + case '--dump-xdebug-filter': + $this->arguments['xdebugFilterFile'] = $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'] ?? ''); + + 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. + */ + protected function handleLoader(string $loaderClass, string $loaderFile = ''): ?TestSuiteLoader + { + 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 null; + } + + $this->exitWithErrorMessage( + \sprintf( + 'Could not use "%s" as loader.', + $loaderClass + ) + ); + + return null; + } + + /** + * Handles the loading of the PHPUnit\Util\Printer implementation. + * + * @return null|Printer|string + */ + protected function handlePrinter(string $printerClass, string $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. + */ + protected function handleBootstrap(string $filename): void + { + try { + FileLoader::checkAndLoad($filename); + } catch (Exception $e) { + $this->exitWithErrorMessage($e->getMessage()); + } + } + + protected function handleVersionCheck(): void + { + $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(): void + { + $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 + --no-coverage Ignore code coverage configuration + --dump-xdebug-filter Generate script to set Xdebug code coverage filter + +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 + --default-time-limit= Timeout in seconds for tests without @small, @medium or @large + --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-defect Stop execution upon first not-passed test + --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 + + --resolve-dependencies Resolve dependencies between tests + --order-by= Run tests in order: default|reverse|random|defects|depends + --random-order-seed= Use a specific random seed for random order + --cache-result Write run result to cache to enable ordering tests defects-first + +Configuration Options: + + --prepend A PHP script that is included as early as possible + --bootstrap A PHP script that is included before the tests run + -c|--configuration Read configuration from XML file + --no-configuration Ignore default configuration file (phpunit.xml) + --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 + --cache-result-file= Specify result cache path and filename + +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(): void + { + } + + private function printVersionString(): void + { + if ($this->versionStringPrinted) { + return; + } + + print Version::getVersionString() . \PHP_EOL . \PHP_EOL; + + $this->versionStringPrinted = true; + } + + private function exitWithErrorMessage(string $message): void + { + $this->printVersionString(); + + print $message . \PHP_EOL; + + exit(TestRunner::FAILURE_EXIT); + } + + private function handleExtensions(string $directory): void + { + $facade = new FileIteratorFacade; + + 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; + } + + private function handleOrderByOption(string $value): void + { + foreach (\explode(',', $value) as $order) { + switch ($order) { + case 'default': + $this->arguments['executionOrder'] = TestSuiteSorter::ORDER_DEFAULT; + $this->arguments['executionOrderDefects'] = TestSuiteSorter::ORDER_DEFAULT; + $this->arguments['resolveDependencies'] = false; + + break; + + case 'reverse': + $this->arguments['executionOrder'] = TestSuiteSorter::ORDER_REVERSED; + + break; + + case 'random': + $this->arguments['executionOrder'] = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + + case 'defects': + $this->arguments['executionOrderDefects'] = TestSuiteSorter::ORDER_DEFECTS_FIRST; + + break; + + case 'depends': + $this->arguments['resolveDependencies'] = true; + + break; + + default: + $this->exitWithErrorMessage("unrecognized --order-by option: $order"); + } + } + } +} diff --git a/.phpunit/phpunit-7/src/TextUI/ResultPrinter.php b/.phpunit/phpunit-7/src/TextUI/ResultPrinter.php new file mode 100644 index 0000000..2782f07 --- /dev/null +++ b/.phpunit/phpunit-7/src/TextUI/ResultPrinter.php @@ -0,0 +1,596 @@ + + * + * 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\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; +use SebastianBergmann\Timer\Timer; + +/** + * Prints the result of a TextUI TestRunner run. + */ +class ResultPrinter extends Printer implements TestListener +{ + public const EVENT_TEST_START = 0; + + public const EVENT_TEST_END = 1; + + public const EVENT_TESTSUITE_START = 2; + + public const EVENT_TESTSUITE_END = 3; + + public const COLOR_NEVER = 'never'; + + public const COLOR_AUTO = 'auto'; + + public const COLOR_ALWAYS = 'always'; + + public const COLOR_DEFAULT = self::COLOR_NEVER; + + private const AVAILABLE_COLORS = [self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS]; + + /** + * @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 string $colors + * @param int|string $numberOfColumns + * @param null|mixed $out + * + * @throws Exception + */ + public function __construct($out = null, bool $verbose = false, $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false) + { + parent::__construct($out); + + if (!\in_array($colors, self::AVAILABLE_COLORS, true)) { + throw InvalidArgumentHelper::factory( + 3, + \vsprintf('value from "%s", "%s" or "%s"', self::AVAILABLE_COLORS) + ); + } + + if (!\is_int($numberOfColumns) && $numberOfColumns !== 'max') { + throw InvalidArgumentHelper::factory(5, 'integer or "max"'); + } + + $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); + } + } + + public function printResult(TestResult $result): void + { + $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); + } + + /** + * An error occurred. + */ + public function addError(Test $test, \Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-red, bold', 'E'); + $this->lastTestFailed = true; + } + + /** + * A failure occurred. + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->writeProgressWithColor('bg-red, fg-white', 'F'); + $this->lastTestFailed = true; + } + + /** + * A warning occurred. + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'W'); + $this->lastTestFailed = true; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'I'); + $this->lastTestFailed = true; + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-yellow, bold', 'R'); + $this->lastTestFailed = true; + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $this->writeProgressWithColor('fg-cyan, bold', 'S'); + $this->lastTestFailed = true; + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + 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. + */ + public function endTestSuite(TestSuite $suite): void + { + } + + /** + * A test started. + */ + public function startTest(Test $test): void + { + if ($this->debug) { + $this->write( + \sprintf( + "Test '%s' started\n", + \PHPUnit\Util\Test::describeAsString($test) + ) + ); + } + } + + /** + * A test ended. + */ + public function endTest(Test $test, float $time): void + { + if ($this->debug) { + $this->write( + \sprintf( + "Test '%s' ended\n", + \PHPUnit\Util\Test::describeAsString($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 && !$test->hasExpectationOnOutput()) { + $this->write($test->getActualOutput()); + } + } + + protected function printDefects(array $defects, string $type): void + { + $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; + } + + protected function printDefect(TestFailure $defect, int $count): void + { + $this->printDefectHeader($defect, $count); + $this->printDefectTrace($defect); + } + + protected function printDefectHeader(TestFailure $defect, int $count): void + { + $this->write( + \sprintf( + "\n%d) %s\n", + $count, + $defect->getTestName() + ) + ); + } + + protected function printDefectTrace(TestFailure $defect): void + { + $e = $defect->thrownException(); + $this->write((string) $e); + + while ($e = $e->getPrevious()) { + $this->write("\nCaused by\n" . $e); + } + } + + protected function printErrors(TestResult $result): void + { + $this->printDefects($result->errors(), 'error'); + } + + protected function printFailures(TestResult $result): void + { + $this->printDefects($result->failures(), 'failure'); + } + + protected function printWarnings(TestResult $result): void + { + $this->printDefects($result->warnings(), 'warning'); + } + + protected function printIncompletes(TestResult $result): void + { + $this->printDefects($result->notImplemented(), 'incomplete test'); + } + + protected function printRisky(TestResult $result): void + { + $this->printDefects($result->risky(), 'risky test'); + } + + protected function printSkipped(TestResult $result): void + { + $this->printDefects($result->skipped(), 'skipped test'); + } + + protected function printHeader(): void + { + $this->write("\n\n" . Timer::resourceUsage() . "\n\n"); + } + + protected function printFooter(TestResult $result): void + { + 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, '.'); + } + } + + protected function writeProgress(string $progress): void + { + 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(): void + { + $this->column = 0; + $this->write("\n"); + } + + /** + * Formats a buffer with a specified ANSI color sequence if colors are + * enabled. + */ + protected function formatWithColor(string $color, string $buffer): string + { + 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. + */ + protected function writeWithColor(string $color, string $buffer, bool $lf = true): void + { + $this->write($this->formatWithColor($color, $buffer)); + + if ($lf) { + $this->write("\n"); + } + } + + /** + * Writes progress with a color sequence if colors are enabled. + */ + protected function writeProgressWithColor(string $color, string $buffer): void + { + $buffer = $this->formatWithColor($color, $buffer); + $this->writeProgress($buffer); + } + + private function writeCountString(int $count, string $name, string $color, bool $always = false): void + { + static $first = true; + + if ($always || $count > 0) { + $this->writeWithColor( + $color, + \sprintf( + '%s%s: %d', + !$first ? ', ' : '', + $name, + $count + ), + false + ); + + $first = false; + } + } +} diff --git a/.phpunit/phpunit-7/src/TextUI/TestRunner.php b/.phpunit/phpunit-7/src/TextUI/TestRunner.php new file mode 100644 index 0000000..35e3a8e --- /dev/null +++ b/.phpunit/phpunit-7/src/TextUI/TestRunner.php @@ -0,0 +1,1317 @@ + + * + * 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\TestCase; +use PHPUnit\Framework\TestListener; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\AfterLastTestHook; +use PHPUnit\Runner\BaseTestRunner; +use PHPUnit\Runner\BeforeFirstTestHook; +use PHPUnit\Runner\Filter\ExcludeGroupFilterIterator; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\Runner\Filter\IncludeGroupFilterIterator; +use PHPUnit\Runner\Filter\NameFilterIterator; +use PHPUnit\Runner\Hook; +use PHPUnit\Runner\NullTestResultCache; +use PHPUnit\Runner\ResultCacheExtension; +use PHPUnit\Runner\StandardTestSuiteLoader; +use PHPUnit\Runner\TestHook; +use PHPUnit\Runner\TestListenerAdapter; +use PHPUnit\Runner\TestResultCache; +use PHPUnit\Runner\TestSuiteLoader; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\Runner\Version; +use PHPUnit\Util\Configuration; +use PHPUnit\Util\Filesystem; +use PHPUnit\Util\Log\JUnit; +use PHPUnit\Util\Log\TeamCity; +use PHPUnit\Util\Printer; +use PHPUnit\Util\TestDox\CliTestDoxPrinter; +use PHPUnit\Util\TestDox\HtmlResultPrinter; +use PHPUnit\Util\TestDox\TextResultPrinter; +use PHPUnit\Util\TestDox\XmlResultPrinter; +use PHPUnit\Util\XdebugFilterScriptGenerator; +use ReflectionClass; +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\Comparator\Comparator; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Invoker\Invoker; + +/** + * A TestRunner for the Command Line Interface (CLI) + * PHP SAPI Module. + */ +class TestRunner extends BaseTestRunner +{ + public const SUCCESS_EXIT = 0; + + public const FAILURE_EXIT = 1; + + public const EXCEPTION_EXIT = 2; + + /** + * @var bool + */ + protected static $versionStringPrinted = false; + + /** + * @var CodeCoverageFilter + */ + protected $codeCoverageFilter; + + /** + * @var TestSuiteLoader + */ + protected $loader; + + /** + * @var ResultPrinter + */ + protected $printer; + + /** + * @var Runtime + */ + private $runtime; + + /** + * @var bool + */ + private $messagePrinted = false; + + /** + * @var Hook[] + */ + private $extensions = []; + + /** + * @param ReflectionClass|Test $test + * @param bool $exit + * + * @throws \RuntimeException + * @throws \InvalidArgumentException + * @throws Exception + * @throws \ReflectionException + */ + public static function run($test, array $arguments = [], $exit = true): TestResult + { + 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.'); + } + + 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; + } + + /** + * @throws \PHPUnit\Runner\Exception + * @throws Exception + * @throws \InvalidArgumentException + * @throws \RuntimeException + * @throws \ReflectionException + */ + public function doRun(Test $suite, array $arguments = [], bool $exit = true): TestResult + { + if (isset($arguments['configuration'])) { + $GLOBALS['__PHPUNIT_CONFIGURATION_FILE'] = $arguments['configuration']; + } + + $this->handleConfiguration($arguments); + + if (\is_int($arguments['columns']) && $arguments['columns'] < 16) { + $arguments['columns'] = 16; + $tooFewColumnsRequested = true; + } + + if (isset($arguments['bootstrap'])) { + $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap']; + } + + if ($suite instanceof TestCase || $suite instanceof TestSuite) { + if ($arguments['backupGlobals'] === true) { + $suite->setBackupGlobals(true); + } + + if ($arguments['backupStaticAttributes'] === true) { + $suite->setBackupStaticAttributes(true); + } + + if ($arguments['beStrictAboutChangesToGlobalState'] === true) { + $suite->setBeStrictAboutChangesToGlobalState(true); + } + } + + if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) { + \mt_srand($arguments['randomOrderSeed']); + } + + if ($arguments['cacheResult']) { + if (isset($arguments['cacheResultFile'])) { + $cache = new TestResultCache($arguments['cacheResultFile']); + } else { + $cache = new TestResultCache; + } + + $this->extensions[] = new ResultCacheExtension($cache); + } + + if ($arguments['executionOrder'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['executionOrderDefects'] !== TestSuiteSorter::ORDER_DEFAULT || $arguments['resolveDependencies']) { + $cache = $cache ?? new NullTestResultCache; + + $cache->load(); + + $sorter = new TestSuiteSorter($cache); + + $sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']); + $originalExecutionOrder = $sorter->getOriginalExecutionOrder(); + + unset($sorter); + } + + 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(); + + $listener = new TestListenerAdapter; + $listenerNeeded = false; + + foreach ($this->extensions as $extension) { + if ($extension instanceof TestHook) { + $listener->add($extension); + + $listenerNeeded = true; + } + } + + if ($listenerNeeded) { + $result->addListener($listener); + } + + unset($listener, $listenerNeeded); + + 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['stopOnDefect']) { + $result->stopOnDefect(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'] + ); + + if (isset($originalExecutionOrder) && ($this->printer instanceof CliTestDoxPrinter)) { + /* @var CliTestDoxPrinter */ + $this->printer->setOriginalExecutionOrder($originalExecutionOrder); + } + } + } + + $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 ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) { + $this->writeMessage( + 'Random seed', + $arguments['randomOrderSeed'] + ); + } + + if (isset($tooFewColumnsRequested)) { + $this->writeMessage('Error', 'Less than 16 columns requested, number of columns set to 16'); + } + + if ($this->runtime->discardsComments()) { + $this->writeMessage('Warning', 'opcache.save_comments=0 set; annotations will not work'); + } + + if (isset($arguments['configuration']) && $arguments['configuration']->hasValidationErrors()) { + $this->write( + "\n Warning - The configuration file did not pass validation!\n The following problems have been detected:\n" + ); + + foreach ($arguments['configuration']->getValidationErrors() as $line => $errors) { + $this->write(\sprintf("\n Line %d:\n", $line)); + + foreach ($errors as $msg) { + $this->write(\sprintf(" - %s\n", $msg)); + } + } + $this->write("\n Test results may not be as expected.\n\n"); + } + + 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 || isset($arguments['xdebugFilterFile'])) { + $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'])) { + 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 ($codeCoverageReports > 0) { + $codeCoverage = new CodeCoverage( + null, + $this->codeCoverageFilter + ); + + $codeCoverage->setUnintentionallyCoveredSubclassesWhitelist( + [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); + } + + if (!empty($filterConfiguration['whitelist'])) { + $codeCoverage->setAddUncoveredFilesFromWhitelist( + $filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist'] + ); + + $codeCoverage->setProcessUncoveredFilesFromWhitelist( + $filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist'] + ); + } + + if (!$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); + } + } + + if (isset($arguments['xdebugFilterFile'], $filterConfiguration)) { + $this->write("\n"); + + $script = (new XdebugFilterScriptGenerator)->generate($filterConfiguration['whitelist']); + + if ($arguments['xdebugFilterFile'] !== 'php://stdout' && $arguments['xdebugFilterFile'] !== 'php://stderr' && !Filesystem::createDirectory(\dirname($arguments['xdebugFilterFile']))) { + $this->write(\sprintf('Cannot write Xdebug filter script to %s ' . \PHP_EOL, $arguments['xdebugFilterFile'])); + + exit(self::EXCEPTION_EXIT); + } + + \file_put_contents($arguments['xdebugFilterFile'], $script); + + $this->write(\sprintf('Wrote Xdebug filter script to %s ' . \PHP_EOL, $arguments['xdebugFilterFile'])); + + exit(self::SUCCESS_EXIT); + } + + $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']); + + if ($arguments['enforceTimeLimit'] === true) { + if (!\class_exists(Invoker::class)) { + $this->writeMessage('Error', 'Package phpunit/php-invoker is required for enforcing time limits'); + } + + if (!\extension_loaded('pcntl') || \strpos(\ini_get('disable_functions'), 'pcntl') !== false) { + $this->writeMessage('Error', 'PHP extension pcntl is required for enforcing time limits'); + } + } + $result->enforceTimeLimit($arguments['enforceTimeLimit']); + $result->setDefaultTimeLimit($arguments['defaultTimeLimit']); + $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']); + $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']); + $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']); + + if ($suite instanceof TestSuite) { + $this->processSuiteFilters($suite, $arguments); + $suite->setRunTestInSeparateProcess($arguments['processIsolation']); + } + + foreach ($this->extensions as $extension) { + if ($extension instanceof BeforeFirstTestHook) { + $extension->executeBeforeFirstTest(); + } + } + + $suite->run($result); + + foreach ($this->extensions as $extension) { + if ($extension instanceof AfterLastTestHook) { + $extension->executeAfterLastTest(); + } + } + + $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->wasSuccessfulIgnoringWarnings()) { + 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; + } + + public function setPrinter(ResultPrinter $resultPrinter): void + { + $this->printer = $resultPrinter; + } + + /** + * Returns the loader to be used. + */ + public function getLoader(): TestSuiteLoader + { + if ($this->loader === null) { + $this->loader = new StandardTestSuiteLoader; + } + + return $this->loader; + } + + protected function createTestResult(): TestResult + { + return new TestResult; + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + */ + protected function runFailed(string $message): void + { + $this->write($message . \PHP_EOL); + + exit(self::FAILURE_EXIT); + } + + protected function write(string $buffer): void + { + if (\PHP_SAPI != 'cli' && \PHP_SAPI != 'phpdbg') { + $buffer = \htmlspecialchars($buffer); + } + + if ($this->printer !== null) { + $this->printer->write($buffer); + } else { + print $buffer; + } + } + + /** + * @throws Exception + */ + protected function handleConfiguration(array &$arguments): void + { + 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['cacheResult']) && !isset($arguments['cacheResult'])) { + $arguments['cacheResult'] = $phpunitConfiguration['cacheResult']; + } + + if (isset($phpunitConfiguration['cacheResultFile']) && !isset($arguments['cacheResultFile'])) { + $arguments['cacheResultFile'] = $phpunitConfiguration['cacheResultFile']; + } + + if (isset($phpunitConfiguration['cacheTokens']) && !isset($arguments['cacheTokens'])) { + $arguments['cacheTokens'] = $phpunitConfiguration['cacheTokens']; + } + + 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['stopOnDefect']) && !isset($arguments['stopOnDefect'])) { + $arguments['stopOnDefect'] = $phpunitConfiguration['stopOnDefect']; + } + + 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['defaultTimeLimit']) && !isset($arguments['defaultTimeLimit'])) { + $arguments['defaultTimeLimit'] = $phpunitConfiguration['defaultTimeLimit']; + } + + 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']; + } + + if (isset($phpunitConfiguration['executionOrder']) && !isset($arguments['executionOrder'])) { + $arguments['executionOrder'] = $phpunitConfiguration['executionOrder']; + } + + if (isset($phpunitConfiguration['executionOrderDefects']) && !isset($arguments['executionOrderDefects'])) { + $arguments['executionOrderDefects'] = $phpunitConfiguration['executionOrderDefects']; + } + + if (isset($phpunitConfiguration['resolveDependencies']) && !isset($arguments['resolveDependencies'])) { + $arguments['resolveDependencies'] = $phpunitConfiguration['resolveDependencies']; + } + + $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']->getExtensionConfiguration() as $extension) { + if (!\class_exists($extension['class'], false) && $extension['file'] !== '') { + require_once $extension['file']; + } + + if (!\class_exists($extension['class'])) { + throw new Exception( + \sprintf( + 'Class "%s" does not exist', + $extension['class'] + ) + ); + } + + $extensionClass = new ReflectionClass($extension['class']); + + if (!$extensionClass->implementsInterface(Hook::class)) { + throw new Exception( + \sprintf( + 'Class "%s" does not implement a PHPUnit\Runner\Hook interface', + $extension['class'] + ) + ); + } + + if (\count($extension['arguments']) == 0) { + $this->extensions[] = $extensionClass->newInstance(); + } else { + $this->extensions[] = $extensionClass->newInstanceArgs( + $extension['arguments'] + ); + } + } + + 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['cacheResult'] = $arguments['cacheResult'] ?? 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['defaultTimeLimit'] = $arguments['defaultTimeLimit'] ?? 0; + $arguments['enforceTimeLimit'] = $arguments['enforceTimeLimit'] ?? false; + $arguments['excludeGroups'] = $arguments['excludeGroups'] ?? []; + $arguments['failOnRisky'] = $arguments['failOnRisky'] ?? false; + $arguments['failOnWarning'] = $arguments['failOnWarning'] ?? false; + $arguments['executionOrderDefects'] = $arguments['executionOrderDefects'] ?? TestSuiteSorter::ORDER_DEFAULT; + $arguments['groups'] = $arguments['groups'] ?? []; + $arguments['processIsolation'] = $arguments['processIsolation'] ?? false; + $arguments['processUncoveredFilesFromWhitelist'] = $arguments['processUncoveredFilesFromWhitelist'] ?? false; + $arguments['randomOrderSeed'] = $arguments['randomOrderSeed'] ?? \time(); + $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['executionOrder'] = $arguments['executionOrder'] ?? TestSuiteSorter::ORDER_DEFAULT; + $arguments['resolveDependencies'] = $arguments['resolveDependencies'] ?? 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['stopOnDefect'] = $arguments['stopOnDefect'] ?? 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; + } + + /** + * @throws \ReflectionException + * @throws \InvalidArgumentException + */ + private function processSuiteFilters(TestSuite $suite, array $arguments): void + { + 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); + } + + private function writeMessage(string $type, string $message): void + { + if (!$this->messagePrinted) { + $this->write("\n"); + } + + $this->write( + \sprintf( + "%-15s%s\n", + $type . ':', + $message + ) + ); + + $this->messagePrinted = true; + } +} diff --git a/.phpunit/phpunit-7/src/Util/Blacklist.php b/.phpunit/phpunit-7/src/Util/Blacklist.php new file mode 100644 index 0000000..0834dea --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Blacklist.php @@ -0,0 +1,196 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use Composer\Autoload\ClassLoader; +use DeepCopy\DeepCopy; +use Doctrine\Instantiator\Instantiator; +use PharIo\Manifest\Manifest; +use PharIo\Version\Version as PharIoVersion; +use PHP_Token; +use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\Project; +use phpDocumentor\Reflection\Type; +use PHPUnit\Framework\TestCase; +use Prophecy\Prophet; +use ReflectionClass; +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; +use SebastianBergmann\Comparator\Comparator; +use SebastianBergmann\Diff\Diff; +use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Exporter\Exporter; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; +use SebastianBergmann\GlobalState\Snapshot; +use SebastianBergmann\Invoker\Invoker; +use SebastianBergmann\ObjectEnumerator\Enumerator; +use SebastianBergmann\RecursionContext\Context; +use SebastianBergmann\ResourceOperations\ResourceOperations; +use SebastianBergmann\Timer\Timer; +use SebastianBergmann\Version; +use Text_Template; +use TheSeer\Tokenizer\Tokenizer; +use Webmozart\Assert\Assert; + +/** + * Utility class for blacklisting PHPUnit's own source code files. + */ +final class Blacklist +{ + /** + * @var array + */ + public static $blacklistedClassNames = [ + // composer + ClassLoader::class => 1, + + // doctrine/instantiator + Instantiator::class => 1, + + // myclabs/deepcopy + DeepCopy::class => 1, + + // phar-io/manifest + Manifest::class => 1, + + // phar-io/version + PharIoVersion::class => 1, + + // phpdocumentor/reflection-common + Project::class => 1, + + // phpdocumentor/reflection-docblock + DocBlock::class => 1, + + // phpdocumentor/type-resolver + Type::class => 1, + + // phpspec/prophecy + Prophet::class => 1, + + // phpunit/phpunit + TestCase::class => 2, + + // phpunit/php-code-coverage + CodeCoverage::class => 1, + + // phpunit/php-file-iterator + FileIteratorFacade::class => 1, + + // phpunit/php-invoker + Invoker::class => 1, + + // phpunit/php-text-template + Text_Template::class => 1, + + // phpunit/php-timer + Timer::class => 1, + + // phpunit/php-token-stream + PHP_Token::class => 1, + + // sebastian/code-unit-reverse-lookup + Wizard::class => 1, + + // sebastian/comparator + Comparator::class => 1, + + // sebastian/diff + Diff::class => 1, + + // sebastian/environment + Runtime::class => 1, + + // sebastian/exporter + Exporter::class => 1, + + // sebastian/global-state + Snapshot::class => 1, + + // sebastian/object-enumerator + Enumerator::class => 1, + + // sebastian/recursion-context + Context::class => 1, + + // sebastian/resource-operations + ResourceOperations::class => 1, + + // sebastian/version + Version::class => 1, + + // theseer/tokenizer + Tokenizer::class => 1, + + // webmozart/assert + Assert::class => 1, + ]; + + /** + * @var string[] + */ + private static $directories; + + /** + * @return string[] + */ + public function getBlacklistedDirectories(): array + { + $this->initialize(); + + return self::$directories; + } + + public function isBlacklisted(string $file): bool + { + 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(): void + { + 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 https://php.net/manual/en/function.tempnam.php + self::$directories[] = \sys_get_temp_dir() . '\\PHP'; + } + } + } +} diff --git a/.phpunit/phpunit-7/src/Util/Configuration.php b/.phpunit/phpunit-7/src/Util/Configuration.php new file mode 100644 index 0000000..0a18430 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Configuration.php @@ -0,0 +1,1331 @@ + + * + * 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 PHPUnit\Framework\Exception; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\ResultPrinter; +use SebastianBergmann\FileIterator\Facade as FileIteratorFacade; + +/** + * 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 + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * . + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +final class Configuration +{ + /** + * @var self[] + */ + private static $instances = []; + + /** + * @var \DOMDocument + */ + private $document; + + /** + * @var DOMXPath + */ + private $xpath; + + /** + * @var string + */ + private $filename; + + /** + * @var \LibXMLError[] + */ + private $errors = []; + + /** + * Returns a PHPUnit configuration object. + * + * @throws Exception + */ + public static function getInstance(string $filename): self + { + $realPath = \realpath($filename); + + if ($realPath === false) { + throw new Exception( + \sprintf( + 'Could not read "%s".', + $filename + ) + ); + } + + /** @var string $realPath */ + if (!isset(self::$instances[$realPath])) { + self::$instances[$realPath] = new self($realPath); + } + + return self::$instances[$realPath]; + } + + /** + * Loads a PHPUnit configuration file. + * + * @throws Exception + */ + private function __construct(string $filename) + { + $this->filename = $filename; + $this->document = Xml::loadFile($filename, false, true, true); + $this->xpath = new DOMXPath($this->document); + + $this->validateConfigurationAgainstSchema(); + } + + /** + * @codeCoverageIgnore + */ + private function __clone() + { + } + + public function hasValidationErrors(): bool + { + return \count($this->errors) > 0; + } + + public function getValidationErrors(): array + { + $result = []; + + foreach ($this->errors as $error) { + if (!isset($result[$error->line])) { + $result[$error->line] = []; + } + $result[$error->line][] = \trim($error->message); + } + + return $result; + } + + /** + * Returns the real path to the configuration file. + */ + public function getFilename(): string + { + return $this->filename; + } + + public function getExtensionConfiguration(): array + { + $result = []; + + foreach ($this->xpath->query('extensions/extension') as $extension) { + /** @var DOMElement $extension */ + $class = (string) $extension->getAttribute('class'); + $file = ''; + $arguments = $this->getConfigurationArguments($extension->childNodes); + + if ($extension->getAttribute('file')) { + $file = $this->toAbsolutePath( + (string) $extension->getAttribute('file'), + true + ); + } + $result[] = [ + 'class' => $class, + 'file' => $file, + 'arguments' => $arguments, + ]; + } + + return $result; + } + + /** + * Returns the configuration for SUT filtering. + */ + public function getFilterConfiguration(): array + { + $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. + */ + public function getGroupConfiguration(): array + { + return $this->parseGroupConfiguration('groups'); + } + + /** + * Returns the configuration for testdox groups. + */ + public function getTestdoxGroupConfiguration(): array + { + return $this->parseGroupConfiguration('testdoxGroups'); + } + + /** + * Returns the configuration for listeners. + */ + public function getListenerConfiguration(): array + { + $result = []; + + foreach ($this->xpath->query('listeners/listener') as $listener) { + /** @var DOMElement $listener */ + $class = (string) $listener->getAttribute('class'); + $file = ''; + $arguments = $this->getConfigurationArguments($listener->childNodes); + + if ($listener->getAttribute('file')) { + $file = $this->toAbsolutePath( + (string) $listener->getAttribute('file'), + true + ); + } + + $result[] = [ + 'class' => $class, + 'file' => $file, + 'arguments' => $arguments, + ]; + } + + return $result; + } + + /** + * Returns the logging configuration. + */ + public function getLoggingConfiguration(): array + { + $result = []; + + foreach ($this->xpath->query('logging/log') as $log) { + /** @var DOMElement $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. + */ + public function getPHPConfiguration(): array + { + $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) { + /** @var DOMElement $ini */ + $name = (string) $ini->getAttribute('name'); + $value = (string) $ini->getAttribute('value'); + + $result['ini'][$name]['value'] = $value; + } + + foreach ($this->xpath->query('php/const') as $const) { + /** @var DOMElement $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) { + /** @var DOMElement $var */ + $name = (string) $var->getAttribute('name'); + $value = (string) $var->getAttribute('value'); + $verbatim = 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(): void + { + $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 = $data['force'] ?? false; + + if ($force || \getenv($name) === false) { + \putenv("{$name}={$value}"); + } + + $value = \getenv($name); + + if (!isset($_ENV[$name])) { + $_ENV[$name] = $value; + } + + if ($force === true) { + $_ENV[$name] = $value; + } + } + } + + /** + * Returns the PHPUnit configuration. + */ + public function getPHPUnitConfiguration(): array + { + $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; + } + } + + /* + * @see https://github.com/sebastianbergmann/phpunit/issues/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('stopOnDefect')) { + $result['stopOnDefect'] = $this->getBoolean( + (string) $root->getAttribute('stopOnDefect'), + 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('defaultTimeLimit')) { + $result['defaultTimeLimit'] = $this->getInteger( + (string) $root->getAttribute('defaultTimeLimit'), + 1 + ); + } + + 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' + ) + ); + } + + if ($root->hasAttribute('cacheResult')) { + $result['cacheResult'] = $this->getBoolean( + (string) $root->getAttribute('cacheResult'), + false + ); + } + + if ($root->hasAttribute('cacheResultFile')) { + $result['cacheResultFile'] = $this->toAbsolutePath( + (string) $root->getAttribute('cacheResultFile') + ); + } + + if ($root->hasAttribute('executionOrder')) { + foreach (\explode(',', $root->getAttribute('executionOrder')) as $order) { + switch ($order) { + case 'default': + $result['executionOrder'] = TestSuiteSorter::ORDER_DEFAULT; + $result['executionOrderDefects'] = TestSuiteSorter::ORDER_DEFAULT; + $result['resolveDependencies'] = false; + + break; + case 'reverse': + $result['executionOrder'] = TestSuiteSorter::ORDER_REVERSED; + + break; + case 'random': + $result['executionOrder'] = TestSuiteSorter::ORDER_RANDOMIZED; + + break; + case 'defects': + $result['executionOrderDefects'] = TestSuiteSorter::ORDER_DEFECTS_FIRST; + + break; + case 'depends': + $result['resolveDependencies'] = true; + + break; + } + } + } + + if ($root->hasAttribute('resolveDependencies')) { + $result['resolveDependencies'] = $this->getBoolean( + (string) $root->getAttribute('resolveDependencies'), + false + ); + } + + return $result; + } + + /** + * Returns the test suite configuration. + * + * @throws Exception + */ + public function getTestSuiteConfiguration(string $testSuiteFilter = ''): TestSuite + { + $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); + } + + $suite = new TestSuite; + + foreach ($testSuiteNodes as $testSuiteNode) { + $suite->addTestSuite( + $this->getTestSuite($testSuiteNode, $testSuiteFilter) + ); + } + + return $suite; + } + + /** + * Returns the test suite names from the configuration. + */ + public function getTestSuiteNames(): array + { + $names = []; + + foreach ($this->xpath->query('*/testsuite') as $node) { + /* @var DOMElement $node */ + $names[] = $node->getAttribute('name'); + } + + return $names; + } + + private function validateConfigurationAgainstSchema(): void + { + $original = \libxml_use_internal_errors(true); + $xsdFilename = __DIR__ . '/../../phpunit.xsd'; + + if (\defined('__PHPUNIT_PHAR_ROOT__')) { + $xsdFilename = __PHPUNIT_PHAR_ROOT__ . '/phpunit.xsd'; + } + + $this->document->schemaValidate($xsdFilename); + $this->errors = \libxml_get_errors(); + \libxml_clear_errors(); + \libxml_use_internal_errors($original); + } + + /** + * Collects and returns the configuration arguments from the PHPUnit + * XML configuration + */ + private function getConfigurationArguments(\DOMNodeList $nodes): array + { + $arguments = []; + + if ($nodes->length === 0) { + return $arguments; + } + + foreach ($nodes as $node) { + if (!$node instanceof DOMElement) { + continue; + } + + if ($node->tagName !== 'arguments') { + continue; + } + + foreach ($node->childNodes as $argument) { + if (!$argument instanceof DOMElement) { + continue; + } + + if ($argument->tagName === 'file' || $argument->tagName === 'directory') { + $arguments[] = $this->toAbsolutePath((string) $argument->textContent); + } else { + $arguments[] = Xml::xmlToVariable($argument); + } + } + } + + return $arguments; + } + + /** + * @throws \PHPUnit\Framework\Exception + */ + private function getTestSuite(DOMElement $testSuiteNode, string $testSuiteFilter = ''): TestSuite + { + 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 FileIteratorFacade; + $testSuiteFilter = $testSuiteFilter ? \explode(',', $testSuiteFilter) : []; + + foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) { + /** @var DOMElement $directoryNode */ + if (!empty($testSuiteFilter) && !\in_array($directoryNode->parentNode->getAttribute('name'), $testSuiteFilter)) { + continue; + } + + $directory = (string) $directoryNode->textContent; + + if (empty($directory)) { + continue; + } + + $prefix = ''; + $suffix = 'Test.php'; + + if (!$this->satisfiesPhpVersion($directoryNode)) { + continue; + } + + if ($directoryNode->hasAttribute('prefix')) { + $prefix = (string) $directoryNode->getAttribute('prefix'); + } + + if ($directoryNode->hasAttribute('suffix')) { + $suffix = (string) $directoryNode->getAttribute('suffix'); + } + + $files = $fileIteratorFacade->getFilesAsArray( + $this->toAbsolutePath($directory), + $suffix, + $prefix, + $exclude + ); + + $suite->addTestFiles($files); + } + + foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) { + /** @var DOMElement $fileNode */ + if (!empty($testSuiteFilter) && !\in_array($fileNode->parentNode->getAttribute('name'), $testSuiteFilter)) { + continue; + } + + $file = (string) $fileNode->textContent; + + if (empty($file)) { + continue; + } + + $file = $fileIteratorFacade->getFilesAsArray( + $this->toAbsolutePath($file) + ); + + if (!isset($file[0])) { + continue; + } + + $file = $file[0]; + + if (!$this->satisfiesPhpVersion($fileNode)) { + continue; + } + + $suite->addTestFile($file); + } + + return $suite; + } + + private function satisfiesPhpVersion(DOMElement $node): bool + { + $phpVersion = \PHP_VERSION; + $phpVersionOperator = '>='; + + if ($node->hasAttribute('phpVersion')) { + $phpVersion = (string) $node->getAttribute('phpVersion'); + } + + if ($node->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = (string) $node->getAttribute('phpVersionOperator'); + } + + return \version_compare(\PHP_VERSION, $phpVersion, $phpVersionOperator); + } + + /** + * 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 bool|string $default + * + * @return bool|string + */ + private function getBoolean(string $value, $default) + { + if (\strtolower($value) === 'false') { + return false; + } + + if (\strtolower($value) === 'true') { + return true; + } + + return $default; + } + + private function getInteger(string $value, int $default): int + { + if (\is_numeric($value)) { + return (int) $value; + } + + return $default; + } + + private function readFilterDirectories(string $query): array + { + $directories = []; + + foreach ($this->xpath->query($query) as $directoryNode) { + /** @var DOMElement $directoryNode */ + $directoryPath = (string) $directoryNode->textContent; + + if (!$directoryPath) { + continue; + } + + $prefix = ''; + $suffix = '.php'; + $group = 'DEFAULT'; + + if ($directoryNode->hasAttribute('prefix')) { + $prefix = (string) $directoryNode->getAttribute('prefix'); + } + + if ($directoryNode->hasAttribute('suffix')) { + $suffix = (string) $directoryNode->getAttribute('suffix'); + } + + if ($directoryNode->hasAttribute('group')) { + $group = (string) $directoryNode->getAttribute('group'); + } + + $directories[] = [ + 'path' => $this->toAbsolutePath($directoryPath), + 'prefix' => $prefix, + 'suffix' => $suffix, + 'group' => $group, + ]; + } + + return $directories; + } + + /** + * @return string[] + */ + private function readFilterFiles(string $query): array + { + $files = []; + + foreach ($this->xpath->query($query) as $file) { + $filePath = (string) $file->textContent; + + if ($filePath) { + $files[] = $this->toAbsolutePath($filePath); + } + } + + return $files; + } + + private function toAbsolutePath(string $path, bool $useIncludePath = false): string + { + $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; + } + + 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; + } + + private function parseGroupConfiguration(string $root): array + { + $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; + } +} diff --git a/.phpunit/phpunit-7/src/Util/ConfigurationGenerator.php b/.phpunit/phpunit-7/src/Util/ConfigurationGenerator.php new file mode 100644 index 0000000..30bb128 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/ConfigurationGenerator.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +final class ConfigurationGenerator +{ + /** + * @var string + */ + private const TEMPLATE = << + + + + {tests_directory} + + + + + + {src_directory} + + + + +EOT; + + public function generateDefaultConfiguration(string $phpunitVersion, string $bootstrapScript, string $testsDirectory, string $srcDirectory): string + { + return \str_replace( + [ + '{phpunit_version}', + '{bootstrap_script}', + '{tests_directory}', + '{src_directory}', + ], + [ + $phpunitVersion, + $bootstrapScript, + $testsDirectory, + $srcDirectory, + ], + self::TEMPLATE + ); + } +} diff --git a/.phpunit/phpunit-7/src/Util/ErrorHandler.php b/.phpunit/phpunit-7/src/Util/ErrorHandler.php new file mode 100644 index 0000000..e71cedb --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/ErrorHandler.php @@ -0,0 +1,106 @@ + + * + * 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. + */ +final class ErrorHandler +{ + private static $errorStack = []; + + /** + * Returns the error stack. + */ + public static function getErrorStack(): array + { + return self::$errorStack; + } + + public static function handleError(int $errorNumber, string $errorString, string $errorFile, int $errorLine): bool + { + if (!($errorNumber & \error_reporting())) { + return false; + } + + self::$errorStack[] = [$errorNumber, $errorString, $errorFile, $errorLine]; + + $trace = \debug_backtrace(); + \array_shift($trace); + + foreach ($trace as $frame) { + if ($frame['function'] === '__toString') { + return false; + } + } + + if ($errorNumber === \E_NOTICE || $errorNumber === \E_USER_NOTICE || $errorNumber === \E_STRICT) { + if (Notice::$enabled !== true) { + return false; + } + + $exception = Notice::class; + } elseif ($errorNumber === \E_WARNING || $errorNumber === \E_USER_WARNING) { + if (Warning::$enabled !== true) { + return false; + } + + $exception = Warning::class; + } elseif ($errorNumber === \E_DEPRECATED || $errorNumber === \E_USER_DEPRECATED) { + if (Deprecated::$enabled !== true) { + return false; + } + + $exception = Deprecated::class; + } else { + $exception = Error::class; + } + + throw new $exception($errorString, $errorNumber, $errorFile, $errorLine); + } + + /** + * Registers an error handler and returns a function that will restore + * the previous handler when invoked + * + * @param int $severity PHP predefined error constant + * + * @throws \Exception if event of specified severity is emitted + */ + public static function handleErrorOnce($severity = \E_WARNING): callable + { + $terminator = function () { + static $expired = false; + + if (!$expired) { + $expired = true; + + return \restore_error_handler(); + } + }; + + \set_error_handler( + function ($errorNumber, $errorString) use ($severity) { + if ($errorNumber === $severity) { + return; + } + + return false; + } + ); + + return $terminator; + } +} diff --git a/.phpunit/phpunit-7/src/Util/FileLoader.php b/.phpunit/phpunit-7/src/Util/FileLoader.php new file mode 100644 index 0000000..cad4bdc --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/FileLoader.php @@ -0,0 +1,68 @@ + + * + * 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. + */ +final class FileLoader +{ + /** + * Checks if a PHP sourcecode file is readable. The sourcecode file is loaded through the load() method. + * + * As a fallback, PHP looks in the directory of the file executing the stream_resolve_include_path function. + * We do not 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. + * + * @throws Exception + */ + public static function checkAndLoad(string $filename): string + { + $includePathFilename = \stream_resolve_include_path($filename); + $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. + */ + public static function load(string $filename): void + { + $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]; + } + } + } +} diff --git a/.phpunit/phpunit-7/src/Util/Filesystem.php b/.phpunit/phpunit-7/src/Util/Filesystem.php new file mode 100644 index 0000000..068a3b0 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Filesystem.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +/** + * Filesystem helpers. + */ +final class Filesystem +{ + /** + * Maps class names to source file names: + * - PEAR CS: Foo_Bar_Baz -> Foo/Bar/Baz.php + * - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php + */ + public static function classNameToFilename(string $className): string + { + return \str_replace( + ['_', '\\'], + \DIRECTORY_SEPARATOR, + $className + ) . '.php'; + } + + public static function createDirectory(string $directory): bool + { + return !(!\is_dir($directory) && !@\mkdir($directory, 0777, true) && !\is_dir($directory)); + } +} diff --git a/.phpunit/phpunit-7/src/Util/Filter.php b/.phpunit/phpunit-7/src/Util/Filter.php new file mode 100644 index 0000000..e57055b --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Filter.php @@ -0,0 +1,83 @@ + + * + * 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; + +final class Filter +{ + public static function getFilteredStacktrace(\Throwable $t): string + { + $prefix = false; + $script = \realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); + + if (\defined('__PHPUNIT_PHAR_ROOT__')) { + $prefix = __PHPUNIT_PHAR_ROOT__; + } + + $filteredStacktrace = ''; + + if ($t instanceof SyntheticError) { + $eTrace = $t->getSyntheticTrace(); + $eFile = $t->getSyntheticFile(); + $eLine = $t->getSyntheticLine(); + } elseif ($t instanceof Exception) { + $eTrace = $t->getSerializableTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } else { + if ($t->getPrevious()) { + $t = $t->getPrevious(); + } + + $eTrace = $t->getTrace(); + $eFile = $t->getFile(); + $eLine = $t->getLine(); + } + + if (!self::frameExists($eTrace, $eFile, $eLine)) { + \array_unshift( + $eTrace, + ['file' => $eFile, 'line' => $eLine] + ); + } + + $blacklist = new Blacklist; + + foreach ($eTrace as $frame) { + if (isset($frame['file']) && \is_file($frame['file']) && + (empty($GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST']) || !\in_array($frame['file'], $GLOBALS['__PHPUNIT_ISOLATION_BLACKLIST'])) && + !$blacklist->isBlacklisted($frame['file']) && + ($prefix === false || \strpos($frame['file'], $prefix) !== 0) && + $frame['file'] !== $script) { + $filteredStacktrace .= \sprintf( + "%s:%s\n", + $frame['file'], + $frame['line'] ?? '?' + ); + } + } + + return $filteredStacktrace; + } + + private static function frameExists(array $trace, string $file, int $line): bool + { + foreach ($trace as $frame) { + if (isset($frame['file']) && $frame['file'] === $file && + isset($frame['line']) && $frame['line'] === $line) { + return true; + } + } + + return false; + } +} diff --git a/.phpunit/phpunit-7/src/Util/Getopt.php b/.phpunit/phpunit-7/src/Util/Getopt.php new file mode 100644 index 0000000..71c9fd5 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Getopt.php @@ -0,0 +1,183 @@ + + * + * 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. + */ +final class Getopt +{ + /** + * @throws Exception + */ + public static function getopt(array $args, string $short_options, array $long_options = null): array + { + 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); + + /* @noinspection ComparisonOperandsOrderInspection */ + 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; + } + + if (\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]; + } + + /** + * @throws Exception + */ + private static function parseShortOption(string $arg, string $short_options, array &$opts, array &$args): void + { + $argLen = \strlen($arg); + + for ($i = 0; $i < $argLen; $i++) { + $opt = $arg[$i]; + $opt_arg = null; + + if ($arg[$i] === ':' || ($spec = \strstr($short_options, $opt)) === false) { + 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] === ':')) { + /* @noinspection ComparisonOperandsOrderInspection */ + if (false === $opt_arg = \current($args)) { + throw new Exception( + "option requires an argument -- $opt" + ); + } + + \next($args); + } + } + + $opts[] = [$opt, $opt_arg]; + } + } + + /** + * @throws Exception + */ + private static function parseLongOption(string $arg, array $long_options, array &$opts, array &$args): void + { + $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 !== '' && $i + 1 < $count && $opt[0] !== '=' && + \strpos($long_options[$i + 1], $opt) === 0) { + throw new Exception( + "option --$opt is ambiguous" + ); + } + + if (\substr($long_opt, -1) === '=') { + /* @noinspection StrlenInEmptyStringCheckContextInspection */ + if (\substr($long_opt, -2) !== '==' && !\strlen($opt_arg)) { + /* @noinspection ComparisonOperandsOrderInspection */ + 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"); + } +} diff --git a/.phpunit/phpunit-7/src/Util/GlobalState.php b/.phpunit/phpunit-7/src/Util/GlobalState.php new file mode 100644 index 0000000..69c151a --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/GlobalState.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use Closure; + +final class GlobalState +{ + /** + * @var string[] + */ + private const SUPER_GLOBAL_ARRAYS = [ + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST', + ]; + + public static function getIncludedFilesAsString(): string + { + return static::processIncludedFilesAsString(\get_included_files()); + } + + /** + * @param string[] $files + */ + public static function processIncludedFilesAsString(array $files): string + { + $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; + } + + public static function getIniSettingsAsString(): string + { + $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; + } + + public static function getConstantsAsString(): string + { + $constants = \get_defined_constants(true); + $result = ''; + + if (isset($constants['user'])) { + foreach ($constants['user'] as $name => $value) { + $result .= \sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + self::exportVariable($value) + ); + } + } + + return $result; + } + + public static function getGlobalsAsString(): string + { + $result = ''; + + foreach (self::SUPER_GLOBAL_ARRAYS as $superGlobalArray) { + if (isset($GLOBALS[$superGlobalArray]) && \is_array($GLOBALS[$superGlobalArray])) { + foreach (\array_keys($GLOBALS[$superGlobalArray]) as $key) { + if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { + continue; + } + + $result .= \sprintf( + '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", + $superGlobalArray, + $key, + self::exportVariable($GLOBALS[$superGlobalArray][$key]) + ); + } + } + } + + $blacklist = self::SUPER_GLOBAL_ARRAYS; + $blacklist[] = 'GLOBALS'; + + foreach (\array_keys($GLOBALS) as $key) { + if (!$GLOBALS[$key] instanceof Closure && !\in_array($key, $blacklist, true)) { + $result .= \sprintf( + '$GLOBALS[\'%s\'] = %s;' . "\n", + $key, + self::exportVariable($GLOBALS[$key]) + ); + } + } + + return $result; + } + + private static function exportVariable($variable): string + { + if (\is_scalar($variable) || $variable === null || + (\is_array($variable) && self::arrayOnlyContainsScalars($variable))) { + return \var_export($variable, true); + } + + return 'unserialize(' . \var_export(\serialize($variable), true) . ')'; + } + + private static function arrayOnlyContainsScalars(array $array): bool + { + $result = true; + + foreach ($array as $element) { + if (\is_array($element)) { + $result = self::arrayOnlyContainsScalars($element); + } elseif (!\is_scalar($element) && $element !== null) { + $result = false; + } + + if ($result === false) { + break; + } + } + + return $result; + } +} diff --git a/.phpunit/phpunit-7/src/Util/InvalidArgumentHelper.php b/.phpunit/phpunit-7/src/Util/InvalidArgumentHelper.php new file mode 100644 index 0000000..1c4ef50 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/InvalidArgumentHelper.php @@ -0,0 +1,35 @@ + + * + * 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. + */ +final class InvalidArgumentHelper +{ + public static function factory(int $argument, string $type, $value = null): Exception + { + $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 + ) + ); + } +} diff --git a/.phpunit/phpunit-7/src/Util/Json.php b/.phpunit/phpunit-7/src/Util/Json.php new file mode 100644 index 0000000..c881191 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Json.php @@ -0,0 +1,83 @@ + + * + * 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; + +final class Json +{ + /** + * Prettify json string + * + * @throws \PHPUnit\Framework\Exception + */ + public static function prettify(string $json): string + { + $decodedJson = \json_decode($json, true); + + if (\json_last_error()) { + throw new Exception( + 'Cannot prettify invalid json' + ); + } + + return \json_encode($decodedJson, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES); + } + + /* + * 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): array + { + $decodedJson = \json_decode($json); + + if (\json_last_error()) { + return [true, null]; + } + + self::recursiveSort($decodedJson); + + $reencodedJson = \json_encode($decodedJson); + + return [false, $reencodedJson]; + } + + /* + * JSON object keys are unordered while PHP array keys are ordered. + * Sort all array keys to ensure both the expected and actual values have + * their keys in the same order. + */ + private static function recursiveSort(&$json): void + { + if (\is_array($json) === false) { + // If the object is not empty, change it to an associative array + // so we can sort the keys (and we will still re-encode it + // correctly, since PHP encodes associative arrays as JSON objects.) + // But EMPTY objects MUST remain empty objects. (Otherwise we will + // re-encode it as a JSON array rather than a JSON object.) + // See #2919. + if (\is_object($json) && \count((array) $json) > 0) { + $json = (array) $json; + } else { + return; + } + } + + \ksort($json); + + foreach ($json as $key => &$value) { + self::recursiveSort($value); + } + } +} diff --git a/.phpunit/phpunit-7/src/Util/Log/JUnit.php b/.phpunit/phpunit-7/src/Util/Log/JUnit.php new file mode 100644 index 0000000..13b9509 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Log/JUnit.php @@ -0,0 +1,432 @@ + + * + * 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\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 null|mixed $out + * + * @throws \PHPUnit\Framework\Exception + */ + public function __construct($out = null, bool $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(): void + { + if ($this->writeDocument === true) { + $this->write($this->getXML()); + } + + parent::flush(); + } + + /** + * An error occurred. + * + * @throws \InvalidArgumentException + */ + public function addError(Test $test, \Throwable $t, float $time): void + { + $this->doAddFault($test, $t, $time, 'error'); + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + + /** + * A warning occurred. + * + * @throws \InvalidArgumentException + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->doAddFault($test, $e, $time, 'warning'); + $this->testSuiteFailures[$this->testSuiteLevel]++; + } + + /** + * A failure occurred. + * + * @throws \InvalidArgumentException + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->doAddFault($test, $e, $time, 'failure'); + $this->testSuiteFailures[$this->testSuiteLevel]++; + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + $this->doAddSkipped($test); + } + + /** + * Risky test. + */ + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + if (!$this->reportUselessTests || $this->currentTestCase === null) { + return; + } + + $error = $this->document->createElement( + 'error', + Xml::prepareString( + "Risky Test\n" . + Filter::getFilteredStacktrace($t) + ) + ); + + $error->setAttribute('type', \get_class($t)); + + $this->currentTestCase->appendChild($error); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + + /** + * Skipped test. + */ + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $this->doAddSkipped($test); + } + + /** + * A testsuite started. + */ + public function startTestSuite(TestSuite $suite): void + { + $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. + */ + public function endTestSuite(TestSuite $suite): void + { + $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. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws ReflectionException + */ + public function startTest(Test $test): void + { + $usesDataprovider = false; + + if (\method_exists($test, 'usesDataProvider')) { + $usesDataprovider = $test->usesDataProvider(); + } + + $testCase = $this->document->createElement('testcase'); + $testCase->setAttribute('name', $test->getName()); + + $class = new ReflectionClass($test); + $methodName = $test->getName(!$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. + */ + public function endTest(Test $test, float $time): void + { + $numAssertions = 0; + + if (\method_exists($test, 'getNumAssertions')) { + $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; + + $testOutput = ''; + + if (\method_exists($test, 'hasOutput') && \method_exists($test, 'getActualOutput')) { + $testOutput = $test->hasOutput() ? $test->getActualOutput() : ''; + } + + if (!empty($testOutput)) { + $systemOut = $this->document->createElement( + 'system-out', + Xml::prepareString($testOutput) + ); + + $this->currentTestCase->appendChild($systemOut); + } + + $this->currentTestCase = null; + } + + /** + * Returns the XML as a string. + */ + public function getXML(): string + { + 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. + */ + public function setWriteDocument(/*bool*/ $flag): void + { + if (\is_bool($flag)) { + $this->writeDocument = $flag; + } + } + + /** + * Method which generalizes addError() and addFailure() + * + * @throws \InvalidArgumentException + */ + private function doAddFault(Test $test, \Throwable $t, float $time, $type): void + { + if ($this->currentTestCase === null) { + return; + } + + if ($test instanceof SelfDescribing) { + $buffer = $test->toString() . "\n"; + } else { + $buffer = ''; + } + + $buffer .= TestFailure::exceptionToString($t) . "\n" . + Filter::getFilteredStacktrace($t); + + $fault = $this->document->createElement( + $type, + Xml::prepareString($buffer) + ); + + if ($t instanceof ExceptionWrapper) { + $fault->setAttribute('type', $t->getClassName()); + } else { + $fault->setAttribute('type', \get_class($t)); + } + + $this->currentTestCase->appendChild($fault); + } + + private function doAddSkipped(Test $test): void + { + if ($this->currentTestCase === null) { + return; + } + + $skipped = $this->document->createElement('skipped'); + $this->currentTestCase->appendChild($skipped); + + $this->testSuiteSkipped[$this->testSuiteLevel]++; + } +} diff --git a/.phpunit/phpunit-7/src/Util/Log/TeamCity.php b/.phpunit/phpunit-7/src/Util/Log/TeamCity.php new file mode 100644 index 0000000..4e8f446 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Log/TeamCity.php @@ -0,0 +1,391 @@ + + * + * 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 false|int + */ + private $flowId; + + public function printResult(TestResult $result): void + { + $this->printHeader(); + $this->printFooter($result); + } + + /** + * An error occurred. + * + * @throws \InvalidArgumentException + */ + public function addError(Test $test, \Throwable $t, float $time): void + { + $this->printEvent( + 'testFailed', + [ + 'name' => $test->getName(), + 'message' => self::getMessage($t), + 'details' => self::getDetails($t), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + /** + * A warning occurred. + * + * @throws \InvalidArgumentException + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->printEvent( + 'testFailed', + [ + 'name' => $test->getName(), + 'message' => self::getMessage($e), + 'details' => self::getDetails($e), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + /** + * A failure occurred. + * + * @throws \InvalidArgumentException + */ + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $parameters = [ + 'name' => $test->getName(), + 'message' => self::getMessage($e), + 'details' => self::getDetails($e), + 'duration' => self::toMilliseconds($time), + ]; + + if ($e instanceof ExpectationFailedException) { + $comparisonFailure = $e->getComparisonFailure(); + + if ($comparisonFailure instanceof ComparisonFailure) { + $expectedString = $comparisonFailure->getExpectedAsString(); + + if ($expectedString === null || empty($expectedString)) { + $expectedString = self::getPrimitiveValueAsString($comparisonFailure->getExpected()); + } + + $actualString = $comparisonFailure->getActualAsString(); + + if ($actualString === null || empty($actualString)) { + $actualString = self::getPrimitiveValueAsString($comparisonFailure->getActual()); + } + + if ($actualString !== null && $expectedString !== null) { + $parameters['type'] = 'comparisonFailure'; + $parameters['actual'] = $actualString; + $parameters['expected'] = $expectedString; + } + } + } + + $this->printEvent('testFailed', $parameters); + } + + /** + * Incomplete test. + */ + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + $this->printIgnoredTest($test->getName(), $t, $time); + } + + /** + * Risky test. + * + * @throws \InvalidArgumentException + */ + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + $this->addError($test, $t, $time); + } + + /** + * Skipped test. + * + * @throws \ReflectionException + */ + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $testName = $test->getName(); + + if ($this->startedTestName !== $testName) { + $this->startTest($test); + $this->printIgnoredTest($testName, $t, $time); + $this->endTest($test, $time); + } else { + $this->printIgnoredTest($testName, $t, $time); + } + } + + public function printIgnoredTest($testName, \Throwable $t, float $time): void + { + $this->printEvent( + 'testIgnored', + [ + 'name' => $testName, + 'message' => self::getMessage($t), + 'details' => self::getDetails($t), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + /** + * A testsuite started. + * + * @throws \ReflectionException + */ + public function startTestSuite(TestSuite $suite): void + { + 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 = \explode('::', $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. + */ + public function endTestSuite(TestSuite $suite): void + { + $suiteName = $suite->getName(); + + if (empty($suiteName)) { + return; + } + + $parameters = ['name' => $suiteName]; + + if (!\class_exists($suiteName, false)) { + $split = \explode('::', $suiteName); + + if (\count($split) === 2 && \method_exists($split[0], $split[1])) { + $parameters['name'] = $split[1]; + } + } + + $this->printEvent('testSuiteFinished', $parameters); + } + + /** + * A test started. + * + * @throws \ReflectionException + */ + public function startTest(Test $test): void + { + $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. + */ + public function endTest(Test $test, float $time): void + { + parent::endTest($test, $time); + + $this->printEvent( + 'testFinished', + [ + 'name' => $test->getName(), + 'duration' => self::toMilliseconds($time), + ] + ); + } + + protected function writeProgress(string $progress): void + { + } + + /** + * @param string $eventName + * @param array $params + */ + private function printEvent($eventName, $params = []): void + { + $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"); + } + + private static function getMessage(\Throwable $t): string + { + $message = ''; + + if ($t instanceof ExceptionWrapper) { + if ($t->getClassName() !== '') { + $message .= $t->getClassName(); + } + + if ($message !== '' && $t->getMessage() !== '') { + $message .= ' : '; + } + } + + return $message . $t->getMessage(); + } + + /** + * @throws \InvalidArgumentException + */ + private static function getDetails(\Throwable $t): string + { + $stackTrace = Filter::getFilteredStacktrace($t); + $previous = $t instanceof ExceptionWrapper ? $t->getPreviousWrapped() : $t->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); + } + + private static function getPrimitiveValueAsString($value): ?string + { + if ($value === null) { + return 'null'; + } + + if (\is_bool($value)) { + return $value === true ? 'true' : 'false'; + } + + if (\is_scalar($value)) { + return \print_r($value, true); + } + + return null; + } + + private static function escapeValue(string $text): string + { + return \str_replace( + ['|', "'", "\n", "\r", ']', '['], + ['||', "|'", '|n', '|r', '|]', '|['], + $text + ); + } + + /** + * @param string $className + * + * @throws \ReflectionException + */ + private static function getFileName($className): string + { + $reflectionClass = new ReflectionClass($className); + + return $reflectionClass->getFileName(); + } + + /** + * @param float $time microseconds + */ + private static function toMilliseconds(float $time): int + { + return \round($time * 1000); + } +} diff --git a/.phpunit/phpunit-7/src/Util/NullTestResultCache.php b/.phpunit/phpunit-7/src/Util/NullTestResultCache.php new file mode 100644 index 0000000..fd63a6d --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/NullTestResultCache.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Runner; + +class NullTestResultCache implements TestResultCacheInterface +{ + public function getState($testName): int + { + return BaseTestRunner::STATUS_UNKNOWN; + } + + public function getTime($testName): float + { + return 0; + } + + public function load(): void + { + } + + public function persist(): void + { + } +} diff --git a/.phpunit/phpunit-7/src/Util/PHP/AbstractPhpProcess.php b/.phpunit/phpunit-7/src/Util/PHP/AbstractPhpProcess.php new file mode 100644 index 0000000..fba0b96 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/AbstractPhpProcess.php @@ -0,0 +1,368 @@ + + * + * 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\TestCase; +use PHPUnit\Framework\TestFailure; +use PHPUnit\Framework\TestResult; +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; + + public static function factory(): self + { + if (\DIRECTORY_SEPARATOR === '\\') { + return new WindowsPhpProcess; + } + + return new DefaultPhpProcess; + } + + public function __construct() + { + $this->runtime = new Runtime; + } + + /** + * Defines if should use STDERR redirection or not. + * + * Then $stderrRedirection is TRUE, STDERR is redirected to STDOUT. + */ + public function setUseStderrRedirection(bool $stderrRedirection): void + { + $this->stderrRedirection = $stderrRedirection; + } + + /** + * Returns TRUE if uses STDERR redirection or FALSE if not. + */ + public function useStderrRedirection(): bool + { + return $this->stderrRedirection; + } + + /** + * Sets the input string to be sent via STDIN + */ + public function setStdin(string $stdin): void + { + $this->stdin = $stdin; + } + + /** + * Returns the input string to be sent via STDIN + */ + public function getStdin(): string + { + return $this->stdin; + } + + /** + * Sets the string of arguments to pass to the php job + */ + public function setArgs(string $args): void + { + $this->args = $args; + } + + /** + * Returns the string of arguments to pass to the php job + */ + public function getArgs(): string + { + return $this->args; + } + + /** + * Sets the array of environment variables to start the child process with + * + * @param array $env + */ + public function setEnv(array $env): void + { + $this->env = $env; + } + + /** + * Returns the array of environment variables to start the child process with + */ + public function getEnv(): array + { + return $this->env; + } + + /** + * Sets the amount of seconds to wait before timing out + */ + public function setTimeout(int $timeout): void + { + $this->timeout = $timeout; + } + + /** + * Returns the amount of seconds to wait before timing out + */ + public function getTimeout(): int + { + return $this->timeout; + } + + /** + * Runs a single test in a separate PHP process. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + public function runTestJob(string $job, Test $test, TestResult $result): void + { + $result->startTest($test); + + $_result = $this->runJob($job); + + $this->processChildResult( + $test, + $result, + $_result['stdout'], + $_result['stderr'] + ); + } + + /** + * Returns the command based into the configurations. + */ + public function getCommand(array $settings, string $file = null): string + { + $command = $this->runtime->getBinary(); + $command .= $this->settingsToParameters($settings); + + if (\PHP_SAPI === 'phpdbg') { + $command .= ' -qrr'; + + if (!$file) { + $command .= 's='; + } + } + + if ($file) { + $command .= ' ' . \escapeshellarg($file); + } + + if ($this->args) { + if (!$file) { + $command .= ' --'; + } + $command .= ' ' . $this->args; + } + + if ($this->stderrRedirection === true) { + $command .= ' 2>&1'; + } + + return $command; + } + + /** + * Runs a single job (PHP code) using a separate PHP process. + */ + abstract public function runJob(string $job, array $settings = []): array; + + protected function settingsToParameters(array $settings): string + { + $buffer = ''; + + foreach ($settings as $setting) { + $buffer .= ' -d ' . \escapeshellarg($setting); + } + + return $buffer; + } + + /** + * Processes the TestResult object from an isolated process. + * + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + */ + private function processChildResult(Test $test, TestResult $result, string $stdout, string $stderr): void + { + $time = 0; + + if (!empty($stderr)) { + $result->addError( + $test, + new Exception(\trim($stderr)), + $time + ); + } else { + \set_error_handler(function ($errno, $errstr, $errfile, $errline): void { + 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']; + } + + /* @var TestCase $test */ + + $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. + * + * @see https://github.com/sebastianbergmann/phpunit/issues/74 + */ + private function getException(TestFailure $error): Exception + { + $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; + } +} diff --git a/.phpunit/phpunit-7/src/Util/PHP/DefaultPhpProcess.php b/.phpunit/phpunit-7/src/Util/PHP/DefaultPhpProcess.php new file mode 100644 index 0000000..396d7d7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/DefaultPhpProcess.php @@ -0,0 +1,218 @@ + + * + * 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; + + /** + * Runs a single job (PHP code) using a separate PHP process. + * + * @throws Exception + */ + public function runJob(string $job, array $settings = []): array + { + if ($this->useTemporaryFile() || $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 + */ + protected function getHandles(): array + { + return []; + } + + /** + * Handles creating the child process and returning the STDOUT and STDERR + * + * @throws Exception + */ + protected function runProcess(string $job, array $settings): array + { + $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]); + + $stderr = $stdout = ''; + + if ($this->timeout) { + unset($pipes[0]); + + while (true) { + $r = $pipes; + $w = null; + $e = null; + + $n = @\stream_select($r, $w, $e, $this->timeout); + + if ($n === false) { + break; + } + + if ($n === 0) { + \proc_terminate($process, 9); + + throw new Exception( + \sprintf( + 'Job execution aborted after %d seconds', + $this->timeout + ) + ); + } + + if ($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 ($line === '') { + \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]; + } + + protected function process($pipe, string $job): void + { + \fwrite($pipe, $job); + } + + protected function cleanup(): void + { + if ($this->tempFile) { + \unlink($this->tempFile); + } + } + + protected function useTemporaryFile(): bool + { + return false; + } +} diff --git a/.phpunit/phpunit-7/src/Util/PHP/Template/PhptTestCase.tpl.dist b/.phpunit/phpunit-7/src/Util/PHP/Template/PhptTestCase.tpl.dist new file mode 100644 index 0000000..14c3e7e --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/Template/PhptTestCase.tpl.dist @@ -0,0 +1,40 @@ +start(__FILE__); +} + +register_shutdown_function(function() use ($coverage) { + $output = null; + if ($coverage) { + $output = $coverage->stop(); + } + file_put_contents('{coverageFile}', serialize($output)); +}); + +ob_end_clean(); + +require '{job}'; diff --git a/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseClass.tpl.dist b/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseClass.tpl.dist new file mode 100644 index 0000000..75ceda3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseClass.tpl.dist @@ -0,0 +1,108 @@ +setCodeCoverage( + new CodeCoverage( + null, + unserialize('{codeCoverageFilter}') + ) + ); + } + + $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); + $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); + $result->enforceTimeLimit({enforcesTimeLimit}); + $result->beStrictAboutTodoAnnotatedTests({isStrictAboutTodoAnnotatedTests}); + $result->beStrictAboutResourceUsageDuringSmallTests({isStrictAboutResourceUsageDuringSmallTests}); + + $test = new {className}('{name}', unserialize('{data}'), '{dataName}'); + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(TRUE); + + ob_end_clean(); + $test->run($result); + $output = ''; + if (!$test->hasExpectationOnOutput()) { + $output = $test->getActualOutput(); + } + + ini_set('xdebug.scream', 0); + @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( + [ + '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(); diff --git a/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseMethod.tpl.dist b/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseMethod.tpl.dist new file mode 100644 index 0000000..b39938d --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/Template/TestCaseMethod.tpl.dist @@ -0,0 +1,110 @@ +setCodeCoverage( + 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(); + } + + ini_set('xdebug.scream', '0'); + @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( + [ + '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(); diff --git a/.phpunit/phpunit-7/src/Util/PHP/WindowsPhpProcess.php b/.phpunit/phpunit-7/src/Util/PHP/WindowsPhpProcess.php new file mode 100644 index 0000000..46fffa3 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/WindowsPhpProcess.php @@ -0,0 +1,46 @@ + + * + * 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 +{ + public function getCommand(array $settings, string $file = null): string + { + return '"' . parent::getCommand($settings, $file) . '"'; + } + + protected function getHandles(): array + { + 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, + ]; + } + + protected function useTemporaryFile(): bool + { + return true; + } +} diff --git a/.phpunit/phpunit-7/src/Util/PHP/eval-stdin.php b/.phpunit/phpunit-7/src/Util/PHP/eval-stdin.php new file mode 100644 index 0000000..37de8ed --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/PHP/eval-stdin.php @@ -0,0 +1,10 @@ + + * + * 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')); diff --git a/.phpunit/phpunit-7/src/Util/Printer.php b/.phpunit/phpunit-7/src/Util/Printer.php new file mode 100644 index 0000000..5e5d675 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Printer.php @@ -0,0 +1,135 @@ + + * + * 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 null|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 && !Filesystem::createDirectory(\dirname($out))) { + throw new Exception(\sprintf('Directory "%s" was not created', \dirname($out))); + } + + $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(): void + { + 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(): void + { + if ($this->out) { + \fflush($this->out); + } else { + \flush(); + } + } + + public function write(string $buffer): void + { + 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. + */ + public function getAutoFlush(): bool + { + 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. + */ + public function setAutoFlush(bool $autoFlush): void + { + $this->autoFlush = $autoFlush; + } +} diff --git a/.phpunit/phpunit-7/src/Util/RegularExpression.php b/.phpunit/phpunit-7/src/Util/RegularExpression.php new file mode 100644 index 0000000..2f7baa7 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/RegularExpression.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +final class RegularExpression +{ + /** + * @throws \Exception + * + * @return false|int + */ + public static function safeMatch(string $pattern, string $subject, ?array $matches = null, int $flags = 0, int $offset = 0) + { + $handler_terminator = ErrorHandler::handleErrorOnce(); + $match = \preg_match($pattern, $subject, $matches, $flags, $offset); + $handler_terminator(); + + return $match; + } +} diff --git a/.phpunit/phpunit-7/src/Util/Test.php b/.phpunit/phpunit-7/src/Util/Test.php new file mode 100644 index 0000000..d3f502d --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/Test.php @@ -0,0 +1,1121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util; + +use PharIo\Version\VersionConstraintParser; +use PHPUnit\Framework\Assert; +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; + +final class Test +{ + /** + * @var int + */ + public const UNKNOWN = -1; + + /** + * @var int + */ + public const SMALL = 0; + + /** + * @var int + */ + public const MEDIUM = 1; + + /** + * @var int + */ + public const LARGE = 2; + + /** + * @var string + * + * @todo This constant should be private (it's public because of TestTest::testGetProvidedDataRegEx) + */ + public const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/'; + + /** + * @var string + */ + private const REGEX_TEST_WITH = '/@testWith\s+/'; + + /** + * @var string + */ + private const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m'; + + /** + * @var string + */ + private const REGEX_REQUIRES_VERSION = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[<>=!]{0,2})\s*(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; + + /** + * @var string + */ + private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[\d\t -.|~^]+)[ \t]*\r?$/m'; + + /** + * @var string + */ + private const REGEX_REQUIRES_OS = '/@requires\s+(?POS(?:FAMILY)?)\s+(?P.+?)[ \t]*\r?$/m'; + + /** + * @var string + */ + private const REGEX_REQUIRES_SETTING = '/@requires\s+(?Psetting)\s+(?P([^ ]+?))\s*(?P[\w\.-]+[\w\.]?)?[ \t]*\r?$/m'; + + /** + * @var string + */ + private const REGEX_REQUIRES = '/@requires\s+(?Pfunction|extension)\s+(?P([^\s<>=!]+))\s*(?P[<>=!]{0,2})\s*(?P[\d\.-]+[\d\.]?)?[ \t]*\r?$/m'; + + /** + * @var array + */ + private static $annotationCache = []; + + /** + * @var array + */ + private static $hookMethods = []; + + public static function describe(\PHPUnit\Framework\Test $test): array + { + if ($test instanceof TestCase) { + return [\get_class($test), $test->getName()]; + } + + if ($test instanceof SelfDescribing) { + return ['', $test->toString()]; + } + + return ['', \get_class($test)]; + } + + public static function describeAsString(\PHPUnit\Framework\Test $test): string + { + if ($test instanceof SelfDescribing) { + return $test->toString(); + } + + return \get_class($test); + } + + /** + * @throws CodeCoverageException + * + * @return array|bool + */ + public static function getLinesToBeCovered(string $className, string $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + if (self::shouldCoversAnnotationBeUsed($annotations) === false) { + return false; + } + + return self::getLinesToBeCoveredOrUsed($className, $methodName, 'covers'); + } + + /** + * Returns lines of code specified with the @uses annotation. + * + * @throws CodeCoverageException + */ + public static function getLinesToBeUsed(string $className, string $methodName): array + { + return self::getLinesToBeCoveredOrUsed($className, $methodName, 'uses'); + } + + /** + * Returns the requirements for a test. + * + * @throws Warning + */ + public static function getRequirements(string $className, string $methodName): array + { + $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_SETTING, $docComment, $matches)) { + $requires['setting'] = []; + + foreach (\range(0, $count - 1) as $i) { + $requires['setting'][$matches['setting'][$i]] = $matches['value'][$i]; + } + } + + 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 ($name !== 'extensions' || empty($matches['version'][$i])) { + continue; + } + + $requires['extension_versions'][$matches['value'][$i]] = [ + 'version' => $matches['version'][$i], + 'operator' => $matches['operator'][$i], + ]; + } + } + + return $requires; + } + + /** + * Returns the missing requirements for a test. + * + * @throws Warning + * + * @return string[] + */ + public static function getMissingRequirements(string $className, string $methodName): array + { + $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 (\count($pieces) === 2 && \method_exists($pieces[0], $pieces[1])) { + continue; + } + + if (\function_exists($function)) { + continue; + } + + $missing[] = \sprintf('Function %s is required.', $function); + } + } + + if (!empty($required['setting'])) { + foreach ($required['setting'] as $setting => $value) { + if (\ini_get($setting) != $value) { + $missing[] = \sprintf('Setting "%s" must be "%s".', $setting, $value); + } + } + } + + 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 ($actualVersion === false || !\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. + * + * @return array|false + */ + public static function getExpectedException(string $className, ?string $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; + } + + /** + * Returns the provided data for a method. + * + * @throws Exception + */ + public static function getProvidedData(string $className, string $methodName): ?array + { + $reflector = new ReflectionMethod($className, $methodName); + $docComment = $reflector->getDocComment(); + + $data = self::getDataFromDataProviderAnnotation($docComment, $className, $methodName); + + if ($data === null) { + $data = self::getDataFromTestWithAnnotation($docComment); + } + + if ($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; + } + + /** + * @throws Exception + */ + public static function getDataFromTestWithAnnotation(string $docComment): ?array + { + $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 data set for the @testWith annotation cannot be parsed: ' . \json_last_error_msg() + ); + } + + $data[] = $dataSet; + } + + if (!$data) { + throw new Exception('The data set for the @testWith annotation cannot be parsed.'); + } + + return $data; + } + + return null; + } + + public static function parseTestMethodAnnotations(string $className, ?string $methodName = ''): array + { + 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()) + ); + } + + $cacheKey = $className . '::' . $methodName; + + if ($methodName !== null && !isset(self::$annotationCache[$cacheKey])) { + try { + $method = new ReflectionMethod($className, $methodName); + $annotations = self::parseAnnotations($method->getDocComment()); + } catch (ReflectionException $e) { + $annotations = []; + } + + self::$annotationCache[$cacheKey] = $annotations; + } + + return [ + 'class' => self::$annotationCache[$className], + 'method' => $methodName !== null ? self::$annotationCache[$cacheKey] : [], + ]; + } + + public static function getInlineAnnotations(string $className, string $methodName): array + { + $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; + } + + public static function parseAnnotations(string $docBlock): array + { + $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; + } + + public static function getBackupSettings(string $className, string $methodName): array + { + return [ + 'backupGlobals' => self::getBooleanAnnotationSetting( + $className, + $methodName, + 'backupGlobals' + ), + 'backupStaticAttributes' => self::getBooleanAnnotationSetting( + $className, + $methodName, + 'backupStaticAttributes' + ), + ]; + } + + public static function getDependencies(string $className, string $methodName): array + { + $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); + } + + public static function getErrorHandlerSettings(string $className, ?string $methodName): ?bool + { + return self::getBooleanAnnotationSetting( + $className, + $methodName, + 'errorHandler' + ); + } + + public static function getGroups(string $className, ?string $methodName = ''): array + { + $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); + } + + public static function getSize(string $className, ?string $methodName): int + { + $groups = \array_flip(self::getGroups($className, $methodName)); + + if (isset($groups['large'])) { + return self::LARGE; + } + + if (isset($groups['medium'])) { + return self::MEDIUM; + } + + if (isset($groups['small'])) { + return self::SMALL; + } + + return self::UNKNOWN; + } + + public static function getProcessIsolationSettings(string $className, string $methodName): bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + return isset($annotations['class']['runTestsInSeparateProcesses']) || isset($annotations['method']['runInSeparateProcess']); + } + + public static function getClassProcessIsolationSettings(string $className, string $methodName): bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + return isset($annotations['class']['runClassInSeparateProcess']); + } + + public static function getPreserveGlobalStateSettings(string $className, string $methodName): ?bool + { + return self::getBooleanAnnotationSetting( + $className, + $methodName, + 'preserveGlobalState' + ); + } + + public static function getHookMethods(string $className): array + { + 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 ($method->getDeclaringClass()->getName() === Assert::class) { + continue; + } + + if ($method->getDeclaringClass()->getName() === TestCase::class) { + continue; + } + + if ($methodComment = $method->getDocComment()) { + if ($method->isStatic()) { + if (\strpos($methodComment, '@beforeClass') !== false) { + \array_unshift( + self::$hookMethods[$className]['beforeClass'], + $method->getName() + ); + } + + if (\strpos($methodComment, '@afterClass') !== false) { + self::$hookMethods[$className]['afterClass'][] = $method->getName(); + } + } + + if (\preg_match('/@before\b/', $methodComment) > 0) { + \array_unshift( + self::$hookMethods[$className]['before'], + $method->getName() + ); + } + + if (\preg_match('/@after\b/', $methodComment) > 0) { + self::$hookMethods[$className]['after'][] = $method->getName(); + } + } + } + } catch (ReflectionException $e) { + } + } + + return self::$hookMethods[$className]; + } + + /** + * @throws CodeCoverageException + */ + private static function getLinesToBeCoveredOrUsed(string $className, string $methodName, string $mode): array + { + $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]; + + if ($mode === 'covers' && \interface_exists($element)) { + throw new InvalidCoversTargetException( + \sprintf( + 'Trying to @cover interface "%s".', + $element + ) + ); + } + + $codeList = \array_merge( + $codeList, + self::resolveElementToReflectionObjects($element) + ); + } + + return self::resolveReflectionObjectsToLines($codeList); + } + + /** + * 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. + */ + private static function parseAnnotationContent(string $message): string + { + if (\defined($message) && (\strpos($message, '::') !== false && \substr_count($message, '::') + 1 === 2)) { + $message = \constant($message); + } + + return $message; + } + + /** + * Returns the provided data for a method. + */ + private static function getDataFromDataProviderAnnotation(string $docComment, string $className, string $methodName): ?iterable + { + 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 = ''; + } else { + $dataProviderMethodNameNamespace = \implode('\\', $dataProviderMethodNameNamespace) . '\\'; + } + + if (empty($leaf)) { + $dataProviderClassName = $className; + } else { + $dataProviderClassName = $dataProviderMethodNameNamespace . \array_pop($leaf); + } + + $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; + } + + return null; + } + + private static function cleanUpMultiLineAnnotation(string $docComment): string + { + //removing initial ' * ' for docComment + $docComment = \str_replace("\r\n", "\n", $docComment); + $docComment = \preg_replace('/' . '\n' . '\s*' . '\*' . '\s?' . '/', "\n", $docComment); + $docComment = \substr($docComment, 0, -1); + + return \rtrim($docComment, "\n"); + } + + private static function emptyHookMethodsArray(): array + { + return [ + 'beforeClass' => ['setUpBeforeClass'], + 'before' => ['setUp'], + 'after' => ['tearDown'], + 'afterClass' => ['tearDownAfterClass'], + ]; + } + + private static function getBooleanAnnotationSetting(string $className, ?string $methodName, string $settingName): ?bool + { + $annotations = self::parseTestMethodAnnotations( + $className, + $methodName + ); + + if (isset($annotations['method'][$settingName])) { + if ($annotations['method'][$settingName][0] === 'enabled') { + return true; + } + + if ($annotations['method'][$settingName][0] === 'disabled') { + return false; + } + } + + if (isset($annotations['class'][$settingName])) { + if ($annotations['class'][$settingName][0] === 'enabled') { + return true; + } + + if ($annotations['class'][$settingName][0] === 'disabled') { + return false; + } + } + + return null; + } + + /** + * @throws InvalidCoversTargetException + */ + private static function resolveElementToReflectionObjects(string $element): array + { + $codeToCoverList = []; + + if (\strpos($element, '\\') !== false && \function_exists($element)) { + $codeToCoverList[] = new ReflectionFunction($element); + } elseif (\strpos($element, '::') !== false) { + [$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] === '!'; + $visibility = 'isPublic'; + + if (\strpos($methodName, 'protected')) { + $visibility = 'isProtected'; + } elseif (\strpos($methodName, 'private')) { + $visibility = 'isPrivate'; + } + + 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; + } + + private static function resolveReflectionObjectsToLines(array $reflectors): array + { + $result = []; + + foreach ($reflectors as $reflector) { + if ($reflector instanceof ReflectionClass) { + foreach ($reflector->getTraits() as $trait) { + $reflectors[] = $trait; + } + } + } + + 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; + } + + /** + * Trims any extensions from version string that follows after + * the .[.] format + */ + private static function sanitizeVersionNumber(string $version) + { + return \preg_replace( + '/^(\d+\.\d+(?:.\d+)?).*$/', + '$1', + $version + ); + } + + private static function shouldCoversAnnotationBeUsed(array $annotations): bool + { + if (isset($annotations['method']['coversNothing'])) { + return false; + } + + if (isset($annotations['method']['covers'])) { + return true; + } + + if (isset($annotations['class']['coversNothing'])) { + return false; + } + + return true; + } +} diff --git a/.phpunit/phpunit-7/src/Util/TestDox/CliTestDoxPrinter.php b/.phpunit/phpunit-7/src/Util/TestDox/CliTestDoxPrinter.php new file mode 100644 index 0000000..217377e --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/TestDox/CliTestDoxPrinter.php @@ -0,0 +1,429 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +namespace PHPUnit\Util\TestDox; + +use PHPUnit\Framework\AssertionFailedError; +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Framework\Warning; +use PHPUnit\Runner\PhptTestCase; +use PHPUnit\Runner\TestSuiteSorter; +use PHPUnit\TextUI\ResultPrinter; +use SebastianBergmann\Timer\Timer; + +/** + * This printer is for CLI output only. For the classes that output to file, html and xml, + * please refer to the PHPUnit\Util\TestDox namespace + */ +class CliTestDoxPrinter extends ResultPrinter +{ + /** + * @var int[] + */ + private $nonSuccessfulTestResults = []; + + /** + * @var NamePrettifier + */ + private $prettifier; + + /** + * @var int The number of test results received from the TestRunner + */ + private $testIndex = 0; + + /** + * @var int The number of test results already sent to the output + */ + private $testFlushIndex = 0; + + /** + * @var array Buffer for write() + */ + private $outputBuffer = []; + + /** + * @var bool + */ + private $bufferExecutionOrder = false; + + /** + * @var array array + */ + private $originalExecutionOrder = []; + + /** + * @var string Classname of the current test + */ + private $className = ''; + + /** + * @var string Classname of the previous test; empty for first test + */ + private $lastClassName = ''; + + /** + * @var string Prettified test name of current test + */ + private $testMethod; + + /** + * @var string Test result message of current test + */ + private $testResultMessage; + + /** + * @var bool Test result message of current test contains a verbose dump + */ + private $lastFlushedTestWasVerbose = false; + + public function __construct( + $out = null, + bool $verbose = false, + $colors = self::COLOR_DEFAULT, + bool $debug = false, + $numberOfColumns = 80, + bool $reverse = false + ) { + parent::__construct($out, $verbose, $colors, $debug, $numberOfColumns, $reverse); + + $this->prettifier = new NamePrettifier; + } + + public function setOriginalExecutionOrder(array $order): void + { + $this->originalExecutionOrder = $order; + $this->bufferExecutionOrder = !empty($order); + } + + public function startTest(Test $test): void + { + if (!$test instanceof TestCase && !$test instanceof PhptTestCase && !$test instanceof TestSuite) { + return; + } + + $this->lastTestFailed = false; + $this->lastClassName = $this->className; + $this->testResultMessage = ''; + + if ($test instanceof TestCase) { + $className = $this->prettifier->prettifyTestClass(\get_class($test)); + $testMethod = $this->prettifier->prettifyTestCase($test); + } elseif ($test instanceof PhptTestCase) { + $className = \get_class($test); + $testMethod = $test->getName(); + } + + $this->className = $className; + $this->testMethod = $testMethod; + + parent::startTest($test); + } + + public function endTest(Test $test, float $time): void + { + if (!$test instanceof TestCase && !$test instanceof PhptTestCase && !$test instanceof TestSuite) { + return; + } + + if ($test instanceof TestCase || $test instanceof PhptTestCase) { + $this->testIndex++; + } + + if ($this->lastTestFailed) { + $resultMessage = $this->testResultMessage; + $this->nonSuccessfulTestResults[] = $this->testIndex; + } else { + $resultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-green', '✔'), + '', + $time, + $this->verbose + ); + } + + if ($this->bufferExecutionOrder) { + $this->bufferTestResult($test, $resultMessage); + $this->flushOutputBuffer(); + } else { + $this->writeTestResult($resultMessage); + + if ($this->lastTestFailed) { + $this->bufferTestResult($test, $resultMessage); + } + } + + parent::endTest($test, $time); + } + + public function addError(Test $test, \Throwable $t, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-yellow', '✘'), + (string) $t, + $time, + true + ); + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-yellow', '✘'), + (string) $e, + $time, + true + ); + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-red', '✘'), + (string) $e, + $time, + true + ); + } + + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-yellow', '∅'), + (string) $t, + $time, + false + ); + } + + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-yellow', '☢'), + (string) $t, + $time, + false + ); + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + $this->lastTestFailed = true; + $this->testResultMessage = $this->formatTestResultMessage( + $this->formatWithColor('fg-yellow', '→'), + (string) $t, + $time, + false + ); + } + + public function bufferTestResult(Test $test, string $msg): void + { + $this->outputBuffer[$this->testIndex] = [ + 'className' => $this->className, + 'testName' => TestSuiteSorter::getTestSorterUID($test), + 'testMethod' => $this->testMethod, + 'message' => $msg, + 'failed' => $this->lastTestFailed, + 'verbose' => $this->lastFlushedTestWasVerbose, + ]; + } + + public function writeTestResult(string $msg): void + { + $msg = $this->formatTestSuiteHeader($this->lastClassName, $this->className, $msg); + $this->write($msg); + } + + public function writeProgress(string $progress): void + { + } + + public function flush(): void + { + } + + public function printResult(TestResult $result): void + { + $this->printHeader(); + + $this->printNonSuccessfulTestsSummary($result->count()); + + $this->printFooter($result); + } + + protected function printHeader(): void + { + $this->write("\n" . Timer::resourceUsage() . "\n\n"); + } + + private function flushOutputBuffer(): void + { + if ($this->testFlushIndex === $this->testIndex) { + return; + } + + if ($this->testFlushIndex > 0) { + $prevResult = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex - 1]); + } else { + $prevResult = $this->getEmptyTestResult(); + } + + do { + $flushed = false; + $result = $this->getTestResultByName($this->originalExecutionOrder[$this->testFlushIndex]); + + if (!empty($result)) { + $this->writeBufferTestResult($prevResult, $result); + $this->testFlushIndex++; + $prevResult = $result; + $flushed = true; + } + } while ($flushed && $this->testFlushIndex < $this->testIndex); + } + + private function writeBufferTestResult(array $prevResult, array $result): void + { + // Write spacer line for new suite headers and after verbose messages + if ($prevResult['testName'] !== '' && + ($prevResult['verbose'] === true || $prevResult['className'] !== $result['className'])) { + $this->write("\n"); + } + + // Write suite header + if ($prevResult['className'] !== $result['className']) { + $this->write($result['className'] . "\n"); + } + + // Write the test result itself + $this->write($result['message']); + } + + private function getTestResultByName(string $testName): array + { + foreach ($this->outputBuffer as $result) { + if ($result['testName'] === $testName) { + return $result; + } + } + + return []; + } + + private function formatTestSuiteHeader(?string $lastClassName, string $className, string $msg): string + { + if ($lastClassName === null || $className !== $lastClassName) { + return \sprintf( + "%s%s\n%s", + ($this->lastClassName !== '') ? "\n" : '', + $className, + $msg + ); + } + + return $msg; + } + + private function formatTestResultMessage( + string $symbol, + string $resultMessage, + float $time, + bool $alwaysVerbose = false + ): string { + $additionalInformation = $this->getFormattedAdditionalInformation($resultMessage, $alwaysVerbose); + $msg = \sprintf( + " %s %s%s\n%s", + $symbol, + $this->testMethod, + $this->verbose ? ' ' . $this->getFormattedRuntime($time) : '', + $additionalInformation + ); + + $this->lastFlushedTestWasVerbose = !empty($additionalInformation); + + return $msg; + } + + private function getFormattedRuntime(float $time): string + { + if ($time > 5) { + return $this->formatWithColor('fg-red', \sprintf('[%.2f ms]', $time * 1000)); + } + + if ($time > 1) { + return $this->formatWithColor('fg-yellow', \sprintf('[%.2f ms]', $time * 1000)); + } + + return \sprintf('[%.2f ms]', $time * 1000); + } + + private function getFormattedAdditionalInformation(string $resultMessage, bool $verbose): string + { + if ($resultMessage === '') { + return ''; + } + + if (!($this->verbose || $verbose)) { + return ''; + } + + return \sprintf( + " │\n%s\n", + \implode( + "\n", + \array_map( + function (string $text) { + return \sprintf(' │ %s', $text); + }, + \explode("\n", $resultMessage) + ) + ) + ); + } + + private function printNonSuccessfulTestsSummary(int $numberOfExecutedTests): void + { + if (empty($this->nonSuccessfulTestResults)) { + return; + } + + if ((\count($this->nonSuccessfulTestResults) / $numberOfExecutedTests) >= 0.7) { + return; + } + + $this->write("Summary of non-successful tests:\n\n"); + + $prevResult = $this->getEmptyTestResult(); + + foreach ($this->nonSuccessfulTestResults as $testIndex) { + $result = $this->outputBuffer[$testIndex]; + $this->writeBufferTestResult($prevResult, $result); + $prevResult = $result; + } + } + + private function getEmptyTestResult(): array + { + return [ + 'className' => '', + 'testName' => '', + 'message' => '', + 'failed' => '', + 'verbose' => '', + ]; + } +} diff --git a/.phpunit/phpunit-7/src/Util/TestDox/HtmlResultPrinter.php b/.phpunit/phpunit-7/src/Util/TestDox/HtmlResultPrinter.php new file mode 100644 index 0000000..7167543 --- /dev/null +++ b/.phpunit/phpunit-7/src/Util/TestDox/HtmlResultPrinter.php @@ -0,0 +1,131 @@ + + * + * 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. + */ +final class HtmlResultPrinter extends ResultPrinter +{ + /** + * @var string + */ + private const PAGE_HEADER = << + + + + Test Documentation + + + +EOT; + + /** + * @var string + */ + private const CLASS_HEADER = <<%s +