Tests: Backport two changes from PHPUnit 9.3:
* Replace the `Match` interface with `ParametersMatch`, to avoid parse errors due to `match` being a reserved keyword in PHP 8. * Replace `ReflectionParameter::getClass()` usage, which is deprecated in PHP 8. This allows tests relying on the `getMockForAbstractClass()` and `getMockBuilder()` methods to run again on PHP 8. When the test suite is updated for compatibility with PHPUnit 9.x, these overrides can be removed. Follow-up to [48972]. See #50913, #50902. git-svn-id: https://develop.svn.wordpress.org/trunk@49037 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
7d15225ad0
commit
c31a551273
@ -16,7 +16,21 @@
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "~0.6.0",
|
||||
"wp-coding-standards/wpcs": "~2.3.0",
|
||||
"phpcompatibility/phpcompatibility-wp": "^2.1.0",
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5"
|
||||
"phpunit/phpunit": "^7.5"
|
||||
},
|
||||
"autoload-dev": {
|
||||
"files": [
|
||||
"tests/phpunit/includes/phpunit7/MockObject/Builder/NamespaceMatch.php",
|
||||
"tests/phpunit/includes/phpunit7/MockObject/Builder/ParametersMatch.php",
|
||||
"tests/phpunit/includes/phpunit7/MockObject/InvocationMocker.php",
|
||||
"tests/phpunit/includes/phpunit7/MockObject/MockMethod.php"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"vendor/phpunit/phpunit/src/Framework/MockObject/Builder/NamespaceMatch.php",
|
||||
"vendor/phpunit/phpunit/src/Framework/MockObject/Builder/ParametersMatch.php",
|
||||
"vendor/phpunit/phpunit/src/Framework/MockObject/InvocationMocker.php",
|
||||
"vendor/phpunit/phpunit/src/Framework/MockObject/MockMethod.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"compat": "@php ./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=phpcompat.xml.dist --report=summary,source",
|
||||
|
@ -134,6 +134,7 @@
|
||||
<exclude-pattern>/src/wp-includes/sodium_compat/*</exclude-pattern>
|
||||
<exclude-pattern>/src/wp-includes/Text/*</exclude-pattern>
|
||||
|
||||
<exclude-pattern>/tests/phpunit/includes/phpunit7/MockObject/*</exclude-pattern>
|
||||
<exclude-pattern>/tests/phpunit/includes/speed-trap-listener\.php</exclude-pattern>
|
||||
|
||||
<!-- Test data and fixtures. -->
|
||||
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of PHPUnit.
|
||||
*
|
||||
* This file is modified to replace the Match interface with ParametersMatch,
|
||||
* to avoid parse errors due to `match` being a reserved keyword in PHP 8.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace PHPUnit\Framework\MockObject\Builder;
|
||||
|
||||
/**
|
||||
* 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, ParametersMatch $builder);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of PHPUnit.
|
||||
*
|
||||
* This file is modified to replace the Match interface with ParametersMatch,
|
||||
* to avoid parse errors due to `match` being a reserved keyword in PHP 8.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace PHPUnit\Framework\MockObject\Builder;
|
||||
|
||||
use PHPUnit\Framework\MockObject\Matcher\AnyParameters;
|
||||
|
||||
/**
|
||||
* Builder interface for parameter matchers.
|
||||
*/
|
||||
interface ParametersMatch 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);
|
||||
|
||||
/**
|
||||
* Sets the parameters to match for, each parameter to this function will
|
||||
* be part of match. To perform specific matches or constraints create a
|
||||
* new PHPUnit\Framework\Constraint\Constraint and use it for the parameter.
|
||||
* If the parameter value is not a constraint it will use the
|
||||
* PHPUnit\Framework\Constraint\IsEqual for the value.
|
||||
*
|
||||
* Some examples:
|
||||
* <code>
|
||||
* // match first parameter with value 2
|
||||
* $b->with(2);
|
||||
* // match first parameter with value 'smock' and second identical to 42
|
||||
* $b->with('smock', new PHPUnit\Framework\Constraint\IsEqual(42));
|
||||
* </code>
|
||||
*
|
||||
* @return ParametersMatch
|
||||
*/
|
||||
public function with(...$arguments);
|
||||
|
||||
/**
|
||||
* Sets a matcher which allows any kind of parameters.
|
||||
*
|
||||
* Some examples:
|
||||
* <code>
|
||||
* // match any number of parameters
|
||||
* $b->withAnyParameters();
|
||||
* </code>
|
||||
*
|
||||
* @return AnyParameters
|
||||
*/
|
||||
public function withAnyParameters();
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
|
||||
@trigger_error({deprecation}, E_USER_DEPRECATED);
|
@ -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}
|
@ -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());
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
public function __clone()
|
||||
{
|
||||
$this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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}
|
||||
)
|
||||
);
|
||||
}
|
@ -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');
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
|
||||
{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];
|
||||
}
|
||||
}
|
||||
|
||||
$__phpunit_invocation = new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation(
|
||||
'{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
|
||||
);
|
||||
|
||||
$__phpunit_invocation->setProxiedCall();
|
||||
|
||||
$this->__phpunit_getInvocationMocker()->invoke($__phpunit_invocation);
|
||||
|
||||
unset($__phpunit_invocation);
|
||||
|
||||
return call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
|
||||
{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];
|
||||
}
|
||||
}
|
||||
|
||||
$__phpunit_invocation = new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation(
|
||||
'{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
|
||||
);
|
||||
|
||||
$__phpunit_invocation->setProxiedCall();
|
||||
|
||||
$this->__phpunit_getInvocationMocker()->invoke($__phpunit_invocation);
|
||||
|
||||
unset($__phpunit_invocation);
|
||||
|
||||
call_user_func_array(array($this->__phpunit_originalObject, "{method_name}"), $__phpunit_arguments);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{prologue}class {class_name}
|
||||
{
|
||||
use {trait_name};
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
public function __clone()
|
||||
{
|
||||
$this->__phpunit_invocationMocker = clone $this->__phpunit_getInvocationMocker();
|
||||
parent::__clone();
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
{namespace}class {class_name} extends \SoapClient
|
||||
{
|
||||
public function __construct($wsdl, array $options)
|
||||
{
|
||||
parent::__construct('{wsdl}', $options);
|
||||
}
|
||||
{methods}}
|
@ -0,0 +1,4 @@
|
||||
|
||||
public function {method_name}({arguments})
|
||||
{
|
||||
}
|
192
tests/phpunit/includes/phpunit7/MockObject/InvocationMocker.php
Normal file
192
tests/phpunit/includes/phpunit7/MockObject/InvocationMocker.php
Normal file
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of PHPUnit.
|
||||
*
|
||||
* This file is modified to replace the Match interface with ParametersMatch,
|
||||
* to avoid parse errors due to `match` being a reserved keyword in PHP 8.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace PHPUnit\Framework\MockObject;
|
||||
|
||||
use Exception;
|
||||
use PHPUnit\Framework\ExpectationFailedException;
|
||||
use PHPUnit\Framework\MockObject\Builder\InvocationMocker as BuilderInvocationMocker;
|
||||
use PHPUnit\Framework\MockObject\Builder\ParametersMatch;
|
||||
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 Invokable, MatcherCollection, 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, ParametersMatch $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();
|
||||
}
|
||||
}
|
||||
}
|
33
tests/phpunit/includes/phpunit7/MockObject/LICENSE
Normal file
33
tests/phpunit/includes/phpunit7/MockObject/LICENSE
Normal file
@ -0,0 +1,33 @@
|
||||
PHPUnit
|
||||
|
||||
Copyright (c) 2001-2019, Sebastian Bergmann <sebastian@phpunit.de>.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Sebastian Bergmann nor the names of his
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
363
tests/phpunit/includes/phpunit7/MockObject/MockMethod.php
Normal file
363
tests/phpunit/includes/phpunit7/MockObject/MockMethod.php
Normal file
@ -0,0 +1,363 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of PHPUnit.
|
||||
*
|
||||
* This file is modified to replace ReflectionParameter::getClass() usage,
|
||||
* which is deprecated in PHP 8.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* (c) Sebastian Bergmann <sebastian@phpunit.de>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace PHPUnit\Framework\MockObject;
|
||||
|
||||
use 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 = $method->getReturnType()->getName();
|
||||
} 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() && $parameter->getType()->getName() !== 'self') {
|
||||
$typeDeclaration = $parameter->getType()->getName() . ' ';
|
||||
} else {
|
||||
try {
|
||||
$class = $parameter->getType() && !$parameter->getType()->isBuiltin()
|
||||
? new ReflectionClass($parameter->getType()->getName())
|
||||
: null;
|
||||
} 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()) {
|
||||
try {
|
||||
$value = \var_export($parameter->getDefaultValue(), true);
|
||||
} catch (\ReflectionException $e) {
|
||||
throw new RuntimeException(
|
||||
$e->getMessage(),
|
||||
(int) $e->getCode(),
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
$default = ' = ' . $value;
|
||||
} elseif ($parameter->isOptional()) {
|
||||
$default = ' = null';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($parameter->isPassedByReference()) {
|
||||
$reference = '&';
|
||||
}
|
||||
|
||||
$parameters[] = $nullable . $typeDeclaration . $reference . $name . $default;
|
||||
}
|
||||
|
||||
return \implode(', ', $parameters);
|
||||
}
|
||||
}
|
@ -37,64 +37,4 @@ class WP_UnitTestCase extends WP_UnitTestCase_Base {
|
||||
|
||||
static::assertThat( $actual, $constraint, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* This method replaces the native PHPUnit method to avoid parse errors
|
||||
* due to `match` being a reserved keyword in PHP 8.
|
||||
*
|
||||
* To run on PHP 8, the tests using this method require PHPUnit 9.3 or later.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* @since 5.6.0
|
||||
*
|
||||
* @param string $original_class_name
|
||||
* @param string $mock_class_name
|
||||
* @param bool $call_original_constructor
|
||||
* @param bool $call_original_clone
|
||||
* @param bool $call_autoload
|
||||
* @param array $mocked_methods
|
||||
* @param bool $clone_arguments
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws RuntimeException
|
||||
* @throws Exception
|
||||
*
|
||||
* @return MockObject
|
||||
*/
|
||||
public function getMockForAbstractClass( $original_class_name, array $arguments = array(), $mock_class_name = '', $call_original_constructor = true, $call_original_clone = true, $call_autoload = true, $mocked_methods = array(), $clone_arguments = false ): PHPUnit\Framework\MockObject\MockObject {
|
||||
if ( PHP_VERSION_ID >= 80000 && version_compare( tests_get_phpunit_version(), '9.3', '<' ) ) {
|
||||
$this->markTestSkipped( 'To run on PHP 8, this test requires PHPUnit 9.3 or later.' );
|
||||
}
|
||||
|
||||
return parent::getMockForAbstractClass( $original_class_name, $arguments, $mock_class_name, $call_original_constructor, $call_original_clone, $call_autoload, $mocked_methods, $clone_arguments );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a builder object to create mock objects using a fluent interface.
|
||||
*
|
||||
* This method replaces the native PHPUnit method to avoid parse errors
|
||||
* due to `match` being a reserved keyword in PHP 8.
|
||||
*
|
||||
* To run on PHP 8, the tests using this method require PHPUnit 9.3 or later.
|
||||
*
|
||||
* When the test suite is updated for compatibility with PHPUnit 9.x,
|
||||
* this override can be removed.
|
||||
*
|
||||
* @since 5.6.0
|
||||
*
|
||||
* @param string|string[] $class_name
|
||||
*/
|
||||
public function getMockBuilder( $class_name ): PHPUnit\Framework\MockObject\MockBuilder {
|
||||
if ( PHP_VERSION_ID >= 80000 && version_compare( tests_get_phpunit_version(), '9.3', '<' ) ) {
|
||||
$this->markTestSkipped( 'To run on PHP 8, this test requires PHPUnit 9.3 or later.' );
|
||||
}
|
||||
|
||||
return parent::getMockBuilder( $class_name );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user