updated-packages

This commit is contained in:
RafficMohammed
2023-01-08 00:13:22 +05:30
parent 3ff7df7487
commit da241bacb6
12659 changed files with 563377 additions and 510538 deletions

View File

@@ -2,23 +2,45 @@
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
## [2.0.5] - 2021-12-02
### Changed
* [#73](https://github.com/sebastianbergmann/php-file-iterator/pull/73): Micro performance improvements on parsing paths
### Fixed
* [#74](https://github.com/sebastianbergmann/php-file-iterator/pull/74): Document return type of `SebastianBergmann\FileIterator\Iterator::accept()` so that Symfony's `DebugClassLoader` does not trigger a deprecation warning
## [2.0.4] - 2021-07-19
### Changed
* Added `ReturnTypeWillChange` attribute to `SebastianBergmann\FileIterator\Iterator::accept()` because the return type of `\FilterIterator::accept()` will change in PHP 8.1
## [2.0.3] - 2020-11-30
### Changed
* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1`
## [2.0.2] - 2018-09-13
### Fixed
* Fixed [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory
* [#48](https://github.com/sebastianbergmann/php-file-iterator/issues/48): Excluding an array that contains false ends up excluding the current working directory
## [2.0.1] - 2018-06-11
### Fixed
* Fixed [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory
* [#46](https://github.com/sebastianbergmann/php-file-iterator/issues/46): Regression with hidden parent directory
## [2.0.0] - 2018-05-28
### Fixed
* Fixed [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
### Changed
@@ -32,19 +54,19 @@ All notable changes to this project will be documented in this file. This projec
### Fixed
* Fixed [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30)
* [#37](https://github.com/sebastianbergmann/php-file-iterator/issues/37): Regression caused by fix for [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30)
## [1.4.4] - 2017-11-27
### Fixed
* Fixed [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
* [#30](https://github.com/sebastianbergmann/php-file-iterator/issues/30): Exclude is not considered if it is a parent of the base path
## [1.4.3] - 2017-11-25
### Fixed
* Fixed [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names
* [#34](https://github.com/sebastianbergmann/php-file-iterator/issues/34): Factory should use canonical directory names
## [1.4.2] - 2016-11-26
@@ -60,9 +82,12 @@ No changes
* [Added support for wildcards (glob) in exclude](https://github.com/sebastianbergmann/php-file-iterator/pull/23)
[2.0.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.4...2.0.5
[2.0.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.3...2.0.4
[2.0.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.2...2.0.3
[2.0.2]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/sebastianbergmann/php-file-iterator/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4...master
[2.0.0]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4...2.0.0
[1.4.5]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.4...1.4.5
[1.4.4]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.3...1.4.4
[1.4.3]: https://github.com/sebastianbergmann/php-file-iterator/compare/1.4.2...1.4.3

View File

@@ -19,10 +19,10 @@
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues"
},
"require": {
"php": "^7.1"
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.1"
"phpunit/phpunit": "^8.5"
},
"autoload": {
"classmap": [

View File

@@ -68,16 +68,16 @@ class Factory
protected function getPathsAfterResolvingWildcards(array $paths): array
{
$_paths = [];
$_paths = [[]];
foreach ($paths as $path) {
if ($locals = \glob($path, GLOB_ONLYDIR)) {
$_paths = \array_merge($_paths, \array_map('\realpath', $locals));
$_paths[] = \array_map('\realpath', $locals);
} else {
$_paths[] = \realpath($path);
$_paths[] = [\realpath($path)];
}
}
return \array_filter($_paths);
return \array_filter(\array_merge(...$_paths));
}
}

View File

@@ -52,6 +52,10 @@ class Iterator extends \FilterIterator
parent::__construct($iterator);
}
/**
* @return bool
*/
#[\ReturnTypeWillChange]
public function accept()
{
$current = $this->getInnerIterator()->current();

View File

@@ -0,0 +1 @@
patreon: s_bergmann

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
$header = <<<'EOF'
This file is part of phpunit/php-timer.
@@ -12,27 +12,46 @@ return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules(
[
'align_multiline_comment' => true,
'array_indentation' => true,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => [
'align_double_arrow' => true,
'align_equals' => true
'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' => ['method']],
'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'],
'declare_strict_types' => true,
'dir_constant' => true,
'elseif' => true,
'encoding' => true,
@@ -40,35 +59,47 @@ return PhpCsFixer\Config::create()
'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_consecutive_blank_lines' => 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,
@@ -77,8 +108,10 @@ return PhpCsFixer\Config::create()
'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,
@@ -90,9 +123,13 @@ return PhpCsFixer\Config::create()
'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',
@@ -100,6 +137,8 @@ return PhpCsFixer\Config::create()
'method_public',
'method_protected',
'method_private',
'method_protected_static',
'method_private_static',
],
],
'ordered_imports' => true,
@@ -117,13 +156,17 @@ return PhpCsFixer\Config::create()
'phpdoc_single_line_var_spacing' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => 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,
@@ -132,9 +175,16 @@ return PhpCsFixer\Config::create()
'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' => true,
'visibility_required' => [
'elements' => [
'const',
'method',
'property',
],
],
'void_return' => true,
'whitespace_after_comma_in_array' => true,
]
@@ -144,5 +194,4 @@ return PhpCsFixer\Config::create()
->files()
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
->name('*.php')
);

View File

@@ -3,9 +3,8 @@ language: php
php:
- 7.1
- 7.2
- master
sudo: false
- 7.3
- 7.4snapshot
before_install:
- composer self-update

View File

@@ -2,6 +2,30 @@
All notable changes are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [2.1.3] - 2020-11-30
### Changed
* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1`
## [2.1.2] - 2019-06-07
### Fixed
* Fixed [#21](https://github.com/sebastianbergmann/php-timer/pull/3352): Formatting of memory consumption does not work on 32bit systems
## [2.1.1] - 2019-02-20
### Changed
* Improved formatting of memory consumption for `resourceUsage()`
## [2.1.0] - 2019-02-20
### Changed
* Improved formatting of memory consumption for `resourceUsage()`
## [2.0.0] - 2018-02-01
### Changed
@@ -12,4 +36,8 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
* This component is no longer supported on PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, and PHP 7.0
[2.1.3]: https://github.com/sebastianbergmann/diff/compare/2.1.2...2.1.3
[2.1.2]: https://github.com/sebastianbergmann/diff/compare/2.1.1...2.1.2
[2.1.1]: https://github.com/sebastianbergmann/diff/compare/2.1.0...2.1.1
[2.1.0]: https://github.com/sebastianbergmann/diff/compare/2.0.0...2.1.0
[2.0.0]: https://github.com/sebastianbergmann/diff/compare/1.0.9...2.0.0

View File

@@ -1,6 +1,6 @@
phpunit/php-timer
Copyright (c) 2010-2018, Sebastian Bergmann <sebastian@phpunit.de>.
Copyright (c) 2010-2019, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -19,10 +19,10 @@
},
"prefer-stable": true,
"require": {
"php": "^7.1"
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.0"
"phpunit/phpunit": "^8.5"
},
"config": {
"optimize-autoloader": true,
@@ -35,7 +35,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
"dev-master": "2.1-dev"
}
}
}

View File

@@ -7,7 +7,6 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Timer;
interface Exception

View File

@@ -7,7 +7,6 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Timer;
final class RuntimeException extends \RuntimeException implements Exception

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/*
* This file is part of phpunit/php-timer.
*
@@ -7,22 +7,30 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Timer;
final class Timer
{
/**
* @var array
* @var int[]
*/
private static $sizes = [
'GB' => 1073741824,
'MB' => 1048576,
'KB' => 1024,
];
/**
* @var int[]
*/
private static $times = [
'hour' => 3600000,
'minute' => 60000,
'second' => 1000
'second' => 1000,
];
/**
* @var array
* @var float[]
*/
private static $startTimes = [];
@@ -36,6 +44,17 @@ final class Timer
return \microtime(true) - \array_pop(self::$startTimes);
}
public static function bytesToString(float $bytes): string
{
foreach (self::$sizes as $unit => $value) {
if ($bytes >= $value) {
return \sprintf('%.2f %s', $bytes >= 1024 ? $bytes / $value : $bytes, $unit);
}
}
return $bytes . ' byte' . ((int) $bytes !== 1 ? 's' : '');
}
public static function secondsToTimeString(float $time): string
{
$ms = \round($time * 1000);
@@ -73,9 +92,9 @@ final class Timer
public static function resourceUsage(): string
{
return \sprintf(
'Time: %s, Memory: %4.2fMB',
'Time: %s, Memory: %s',
self::timeSinceStartOfRequest(),
\memory_get_peak_usage(true) / 1048576
self::bytesToString(\memory_get_peak_usage(true))
);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/*
* This file is part of phpunit/php-timer.
*
@@ -7,7 +7,6 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\Timer;
use PHPUnit\Framework\TestCase;
@@ -15,48 +14,34 @@ use PHPUnit\Framework\TestCase;
/**
* @covers \SebastianBergmann\Timer\Timer
*/
class TimerTest extends TestCase
final class TimerTest extends TestCase
{
public function testStartStop(): void
public function testCanBeStartedAndStopped(): void
{
$this->assertInternalType('float', Timer::stop());
$this->assertIsFloat(Timer::stop());
}
public function testCanFormatTimeSinceStartOfRequest(): void
{
$this->assertStringMatchesFormat('%f %s', Timer::timeSinceStartOfRequest());
}
/**
* @dataProvider secondsProvider
* @backupGlobals enabled
*/
public function testSecondsToTimeString(string $string, string $seconds): void
{
$this->assertEquals(
$string,
Timer::secondsToTimeString($seconds)
);
}
public function testTimeSinceStartOfRequest(): void
{
$this->assertStringMatchesFormat(
'%f %s',
Timer::timeSinceStartOfRequest()
);
}
public function testTimeSinceStartOfRequest2(): void
public function testCanFormatSinceStartOfRequestWhenRequestTimeIsNotAvailableAsFloat(): void
{
if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
unset($_SERVER['REQUEST_TIME_FLOAT']);
}
$this->assertStringMatchesFormat(
'%f %s',
Timer::timeSinceStartOfRequest()
);
$this->assertStringMatchesFormat('%f %s', Timer::timeSinceStartOfRequest());
}
/**
* @backupGlobals enabled
* @backupGlobals enabled
*/
public function testTimeSinceStartOfRequest3(): void
public function testCannotFormatTimeSinceStartOfRequestWhenRequestTimeIsNotAvailable(): void
{
if (isset($_SERVER['REQUEST_TIME_FLOAT'])) {
unset($_SERVER['REQUEST_TIME_FLOAT']);
@@ -71,15 +56,20 @@ class TimerTest extends TestCase
Timer::timeSinceStartOfRequest();
}
public function testResourceUsage(): void
public function testCanFormatResourceUsage(): void
{
$this->assertStringMatchesFormat(
'Time: %s, Memory: %fMB',
Timer::resourceUsage()
);
$this->assertStringMatchesFormat('Time: %s, Memory: %f %s', Timer::resourceUsage());
}
public function secondsProvider()
/**
* @dataProvider secondsProvider
*/
public function testCanFormatSecondsAsString(string $string, float $seconds): void
{
$this->assertEquals($string, Timer::secondsToTimeString($seconds));
}
public function secondsProvider(): array
{
return [
['0 ms', 0],
@@ -118,4 +108,27 @@ class TimerTest extends TestCase
['2 hours', 7199.9999],
];
}
/**
* @dataProvider bytesProvider
*/
public function testCanFormatBytesAsString(string $string, float $bytes): void
{
$this->assertEquals($string, Timer::bytesToString($bytes));
}
public function bytesProvider(): array
{
return [
['0 bytes', 0],
['1 byte', 1],
['1023 bytes', 1023],
['1.00 KB', 1024],
['1.50 KB', 1.5 * 1024],
['2.00 MB', 2 * 1048576],
['2.50 MB', 2.5 * 1048576],
['3.00 GB', 3 * 1073741824],
['3.50 GB', 3.5 * 1073741824],
];
}
}

View File

@@ -0,0 +1 @@
patreon: s_bergmann

View File

@@ -4,7 +4,7 @@ php:
- 7.1
- 7.2
- 7.3
- master
- 7.4snapshot
sudo: false

View File

@@ -2,6 +2,36 @@
All notable changes to `sebastianbergmann/php-token-stream` are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [3.1.3] - 2021-07-26
### Changed
* The declarations of methods in `PHP_Token_Stream` that implement the `ArrayAccess`, `Countable`, and `SeekableIterator` interfaces are now compatible with PHP 8.1
## [3.1.2] - 2020-11-30
### Changed
* Changed PHP version constraint in `composer.json` from `^7.1` to `>=7.1` to allow installation of this version of this library on PHP 8. However, this version of this library does not work on PHP 8. PHPUnit 8.5, which uses this version of this library (through phpunit/php-code-coverage), does not call into this library and instead shows a message that code coverage functionality is not available for PHPUnit 8.5 on PHP 8.
## [3.1.1] - 2019-09-17
### Fixed
* Fixed [#84](https://github.com/sebastianbergmann/php-token-stream/issues/84): Methods named `class` are not handled correctly
## [3.1.0] - 2019-07-25
### Added
* Added support for `FN` and `COALESCE_EQUAL` tokens introduced in PHP 7.4
## [3.0.2] - 2019-07-08
### Changed
* Implemented [#82](https://github.com/sebastianbergmann/php-token-stream/issues/82): Make sure this component works when its classes are prefixed using php-scoper
## [3.0.1] - 2018-10-30
### Fixed
@@ -29,6 +59,11 @@ All notable changes to `sebastianbergmann/php-token-stream` are documented in th
## [2.0.0] - 2017-08-03
[3.1.3]: https://github.com/sebastianbergmann/php-token-stream/compare/3.1.2...3.1.3
[3.1.2]: https://github.com/sebastianbergmann/php-token-stream/compare/3.1.1...3.1.2
[3.1.1]: https://github.com/sebastianbergmann/php-token-stream/compare/3.1.0...3.1.1
[3.1.0]: https://github.com/sebastianbergmann/php-token-stream/compare/3.0.2...3.1.0
[3.0.2]: https://github.com/sebastianbergmann/php-token-stream/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/sebastianbergmann/php-token-stream/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/sebastianbergmann/php-token-stream/compare/2.0...3.0.0
[2.0.2]: https://github.com/sebastianbergmann/php-token-stream/compare/2.0.1...2.0.2

View File

@@ -1,6 +1,6 @@
php-token-stream
Copyright (c) 2009-2018, Sebastian Bergmann <sebastian@phpunit.de>.
Copyright (c) 2009-2019, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -16,7 +16,7 @@
},
"prefer-stable": true,
"require": {
"php": "^7.1",
"php": ">=7.1",
"ext-tokenizer": "*"
},
"require-dev": {
@@ -33,7 +33,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
"dev-master": "3.1-dev"
}
}
}

View File

@@ -1,13 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.0/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.4/phpunit.xsd"
bootstrap="tests/bootstrap.php"
forceCoversAnnotation="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuite>
<directory suffix="Test.php">tests</directory>
</testsuite>
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">

View File

@@ -186,7 +186,7 @@ abstract class PHP_TokenWithScopeAndVisibility extends PHP_TokenWithScope
$tokens[$i] instanceof PHP_Token_PROTECTED ||
$tokens[$i] instanceof PHP_Token_PUBLIC)) {
return strtolower(
str_replace('PHP_Token_', '', get_class($tokens[$i]))
str_replace('PHP_Token_', '', PHP_Token_Util::getClass($tokens[$i]))
);
}
if (isset($tokens[$i]) &&
@@ -220,7 +220,7 @@ abstract class PHP_TokenWithScopeAndVisibility extends PHP_TokenWithScope
$tokens[$i] instanceof PHP_Token_FINAL ||
$tokens[$i] instanceof PHP_Token_ABSTRACT)) {
$keywords[] = strtolower(
str_replace('PHP_Token_', '', get_class($tokens[$i]))
str_replace('PHP_Token_', '', PHP_Token_Util::getClass($tokens[$i]))
);
}
}
@@ -272,7 +272,7 @@ abstract class PHP_Token_Includes extends PHP_Token
if ($tokens[$this->id + 2] instanceof PHP_Token_CONSTANT_ENCAPSED_STRING) {
$this->name = trim($tokens[$this->id + 2], "'\"");
$this->type = strtolower(
str_replace('PHP_Token_', '', get_class($tokens[$this->id]))
str_replace('PHP_Token_', '', PHP_Token_Util::getClass($tokens[$this->id]))
);
}
}
@@ -405,7 +405,7 @@ class PHP_Token_FUNCTION extends PHP_TokenWithScopeAndVisibility
$tokens = $this->tokenStream->tokens();
for ($i = $this->id; $i <= $end; $i++) {
switch (get_class($tokens[$i])) {
switch (PHP_Token_Util::getClass($tokens[$i])) {
case 'PHP_Token_IF':
case 'PHP_Token_ELSEIF':
case 'PHP_Token_FOR':
@@ -1350,3 +1350,12 @@ class PHP_Token_SPACESHIP extends PHP_Token
class PHP_Token_YIELD_FROM extends PHP_Token
{
}
// Tokens introduced in PHP 7.4
class PHP_Token_COALESCE_EQUAL extends PHP_Token
{
}
class PHP_Token_FN extends PHP_Token
{
}

View File

@@ -204,10 +204,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
$this->linesOfCode['cloc'];
}
/**
* @return int
*/
public function count()
public function count(): int
{
return count($this->tokens);
}
@@ -303,7 +300,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
];
foreach ($this->tokens as $token) {
switch (get_class($token)) {
switch (PHP_Token_Util::getClass($token)) {
case 'PHP_Token_REQUIRE_ONCE':
case 'PHP_Token_REQUIRE':
case 'PHP_Token_INCLUDE_ONCE':
@@ -358,7 +355,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
$interfaceEndLine = false;
foreach ($this->tokens as $token) {
switch (get_class($token)) {
switch (PHP_Token_Util::getClass($token)) {
case 'PHP_Token_HALT_COMPILER':
return;
@@ -392,15 +389,17 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
'file' => $this->filename
];
if ($token instanceof PHP_Token_CLASS) {
$class[] = $token->getName();
$classEndLine[] = $token->getEndLine();
if ($token->getName() !== null) {
if ($token instanceof PHP_Token_CLASS) {
$class[] = $token->getName();
$classEndLine[] = $token->getEndLine();
$this->classes[$class[count($class) - 1]] = $tmp;
} else {
$trait = $token->getName();
$traitEndLine = $token->getEndLine();
$this->traits[$trait] = $tmp;
$this->classes[$class[count($class) - 1]] = $tmp;
} else {
$trait = $token->getName();
$traitEndLine = $token->getEndLine();
$this->traits[$trait] = $tmp;
}
}
break;
@@ -475,61 +474,42 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
return $this->linesOfCode;
}
/**
*/
public function rewind()
public function rewind(): void
{
$this->position = 0;
}
/**
* @return bool
*/
public function valid()
public function valid(): bool
{
return isset($this->tokens[$this->position]);
}
/**
* @return int
*/
#[\ReturnTypeWillChange]
public function key()
{
return $this->position;
}
/**
* @return PHP_Token
*/
#[\ReturnTypeWillChange]
public function current()
{
return $this->tokens[$this->position];
}
/**
*/
public function next()
public function next(): void
{
$this->position++;
}
/**
* @param int $offset
*
* @return bool
*/
public function offsetExists($offset)
public function offsetExists($offset): bool
{
return isset($this->tokens[$offset]);
}
/**
* @param int $offset
*
* @return mixed
*
* @throws OutOfBoundsException
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
@@ -548,7 +528,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
* @param int $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
public function offsetSet($offset, $value): void
{
$this->tokens[$offset] = $value;
}
@@ -558,7 +538,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
*
* @throws OutOfBoundsException
*/
public function offsetUnset($offset)
public function offsetUnset($offset): void
{
if (!$this->offsetExists($offset)) {
throw new OutOfBoundsException(
@@ -579,7 +559,7 @@ class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
*
* @throws OutOfBoundsException
*/
public function seek($position)
public function seek($position): void
{
$this->position = $position;

View File

@@ -0,0 +1,19 @@
<?php declare(strict_types=1);
/*
* This file is part of php-token-stream.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
final class PHP_Token_Util
{
public static function getClass($object): string
{
$parts = explode('\\', get_class($object));
return array_pop($parts);
}
}

View File

@@ -24,9 +24,7 @@ class PHP_Token_ClassTest extends TestCase
protected function setUp()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source2.php');
foreach ($ts as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'source2.php') as $token) {
if ($token instanceof PHP_Token_CLASS) {
$this->class = $token;
}
@@ -38,25 +36,16 @@ class PHP_Token_ClassTest extends TestCase
}
}
/**
* @covers PHP_Token_CLASS::getKeywords
*/
public function testGetClassKeywords()
{
$this->assertEquals('abstract', $this->class->getKeywords());
}
/**
* @covers PHP_Token_FUNCTION::getKeywords
*/
public function testGetFunctionKeywords()
{
$this->assertEquals('abstract,static', $this->function->getKeywords());
}
/**
* @covers PHP_Token_FUNCTION::getVisibility
*/
public function testGetFunctionVisibility()
{
$this->assertEquals('public', $this->function->getVisibility());
@@ -64,9 +53,7 @@ class PHP_Token_ClassTest extends TestCase
public function testIssue19()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'issue19.php');
foreach ($ts as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'issue19.php') as $token) {
if ($token instanceof PHP_Token_CLASS) {
$this->assertFalse($token->hasInterfaces());
}
@@ -143,9 +130,7 @@ class PHP_Token_ClassTest extends TestCase
*/
public function testClassWithMethodNamedEmptyIsHandledCorrectly()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'class_with_method_named_empty.php');
$classes = $ts->getClasses();
$classes = (new PHP_Token_Stream(TEST_FILES_PATH . 'class_with_method_named_empty.php'))->getClasses();
$this->assertArrayHasKey('class_with_method_named_empty', $classes);
$this->assertArrayHasKey('empty', $classes['class_with_method_named_empty']['methods']);
@@ -156,9 +141,7 @@ class PHP_Token_ClassTest extends TestCase
*/
public function testAnonymousFunctionDoesNotAffectStartAndEndLineOfMethod()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'php-code-coverage-issue-424.php');
$classes = $ts->getClasses();
$classes = (new PHP_Token_Stream(TEST_FILES_PATH . 'php-code-coverage-issue-424.php'))->getClasses();
$this->assertSame(5, $classes['Example']['methods']['even']['startLine']);
$this->assertSame(12, $classes['Example']['methods']['even']['endLine']);

View File

@@ -19,18 +19,13 @@ class PHP_Token_ClosureTest extends TestCase
protected function setUp()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'closure.php');
foreach ($ts as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'closure.php') as $token) {
if ($token instanceof PHP_Token_FUNCTION) {
$this->functions[] = $token;
}
}
}
/**
* @covers PHP_Token_FUNCTION::getArguments
*/
public function testGetArguments()
{
$this->assertEquals(['$foo' => null, '$bar' => null], $this->functions[0]->getArguments());
@@ -41,9 +36,6 @@ class PHP_Token_ClosureTest extends TestCase
$this->assertEquals([], $this->functions[5]->getArguments());
}
/**
* @covers PHP_Token_FUNCTION::getName
*/
public function testGetName()
{
$this->assertEquals('anonymousFunction:2#5', $this->functions[0]->getName());
@@ -54,9 +46,6 @@ class PHP_Token_ClosureTest extends TestCase
$this->assertEquals('anonymousFunction:7#106', $this->functions[5]->getName());
}
/**
* @covers PHP_Token::getLine
*/
public function testGetLine()
{
$this->assertEquals(2, $this->functions[0]->getLine());
@@ -65,9 +54,6 @@ class PHP_Token_ClosureTest extends TestCase
$this->assertEquals(5, $this->functions[3]->getLine());
}
/**
* @covers PHP_TokenWithScope::getEndLine
*/
public function testGetEndLine()
{
$this->assertEquals(2, $this->functions[0]->getLine());

View File

@@ -19,32 +19,27 @@ class PHP_Token_FunctionTest extends TestCase
protected function setUp()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source.php');
foreach ($ts as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'source.php') as $token) {
if ($token instanceof PHP_Token_FUNCTION) {
$this->functions[] = $token;
}
}
}
/**
* @covers PHP_Token_FUNCTION::getArguments
*/
public function testGetArguments()
{
$this->assertEquals([], $this->functions[0]->getArguments());
$this->assertEquals(
['$baz' => 'Baz'], $this->functions[1]->getArguments()
['$baz' => 'Baz'], $this->functions[1]->getArguments()
);
$this->assertEquals(
['$foobar' => 'Foobar'], $this->functions[2]->getArguments()
['$foobar' => 'Foobar'], $this->functions[2]->getArguments()
);
$this->assertEquals(
['$barfoo' => 'Barfoo'], $this->functions[3]->getArguments()
['$barfoo' => 'Barfoo'], $this->functions[3]->getArguments()
);
$this->assertEquals([], $this->functions[4]->getArguments());
@@ -52,9 +47,6 @@ class PHP_Token_FunctionTest extends TestCase
$this->assertEquals(['$x' => null, '$y' => null], $this->functions[5]->getArguments());
}
/**
* @covers PHP_Token_FUNCTION::getName
*/
public function testGetName()
{
$this->assertEquals('foo', $this->functions[0]->getName());
@@ -64,9 +56,6 @@ class PHP_Token_FunctionTest extends TestCase
$this->assertEquals('baz', $this->functions[4]->getName());
}
/**
* @covers PHP_Token::getLine
*/
public function testGetLine()
{
$this->assertEquals(5, $this->functions[0]->getLine());
@@ -77,9 +66,6 @@ class PHP_Token_FunctionTest extends TestCase
$this->assertEquals(37, $this->functions[6]->getLine());
}
/**
* @covers PHP_TokenWithScope::getEndLine
*/
public function testGetEndLine()
{
$this->assertEquals(5, $this->functions[0]->getEndLine());
@@ -90,21 +76,18 @@ class PHP_Token_FunctionTest extends TestCase
$this->assertEquals(41, $this->functions[6]->getEndLine());
}
/**
* @covers PHP_Token_FUNCTION::getDocblock
*/
public function testGetDocblock()
{
$this->assertNull($this->functions[0]->getDocblock());
$this->assertEquals(
"/**\n * @param Baz \$baz\n */",
$this->functions[1]->getDocblock()
"/**\n * @param Baz \$baz\n */",
$this->functions[1]->getDocblock()
);
$this->assertEquals(
"/**\n * @param Foobar \$foobar\n */",
$this->functions[2]->getDocblock()
"/**\n * @param Foobar \$foobar\n */",
$this->functions[2]->getDocblock()
);
$this->assertNull($this->functions[3]->getDocblock());
@@ -113,29 +96,29 @@ class PHP_Token_FunctionTest extends TestCase
public function testSignature()
{
$ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source5.php');
$f = $ts->getFunctions();
$c = $ts->getClasses();
$i = $ts->getInterfaces();
$tokens = new PHP_Token_Stream(TEST_FILES_PATH . 'source5.php');
$functions = $tokens->getFunctions();
$classes = $tokens->getClasses();
$interfaces = $tokens->getInterfaces();
$this->assertEquals(
'foo($a, array $b, array $c = array())',
$f['foo']['signature']
'foo($a, array $b, array $c = array())',
$functions['foo']['signature']
);
$this->assertEquals(
'm($a, array $b, array $c = array())',
$c['c']['methods']['m']['signature']
'm($a, array $b, array $c = array())',
$classes['c']['methods']['m']['signature']
);
$this->assertEquals(
'm($a, array $b, array $c = array())',
$c['a']['methods']['m']['signature']
'm($a, array $b, array $c = array())',
$classes['a']['methods']['m']['signature']
);
$this->assertEquals(
'm($a, array $b, array $c = array())',
$i['i']['methods']['m']['signature']
'm($a, array $b, array $c = array())',
$interfaces['i']['methods']['m']['signature']
);
}
}

View File

@@ -22,44 +22,32 @@ class PHP_Token_IncludeTest extends TestCase
$this->ts = new PHP_Token_Stream(TEST_FILES_PATH . 'source3.php');
}
/**
* @covers PHP_Token_Includes::getName
* @covers PHP_Token_Includes::getType
*/
public function testGetIncludes()
{
$this->assertSame(
['test4.php', 'test3.php', 'test2.php', 'test1.php'],
$this->ts->getIncludes()
['test4.php', 'test3.php', 'test2.php', 'test1.php'],
$this->ts->getIncludes()
);
}
/**
* @covers PHP_Token_Includes::getName
* @covers PHP_Token_Includes::getType
*/
public function testGetIncludesCategorized()
{
$this->assertSame(
[
'require_once' => ['test4.php'],
'require' => ['test3.php'],
'include_once' => ['test2.php'],
'include' => ['test1.php']
],
$this->ts->getIncludes(true)
[
'require_once' => ['test4.php'],
'require' => ['test3.php'],
'include_once' => ['test2.php'],
'include' => ['test1.php']
],
$this->ts->getIncludes(true)
);
}
/**
* @covers PHP_Token_Includes::getName
* @covers PHP_Token_Includes::getType
*/
public function testGetIncludesCategory()
{
$this->assertSame(
['test4.php'],
$this->ts->getIncludes(true, 'require_once')
['test4.php'],
$this->ts->getIncludes(true, 'require_once')
);
}
}

View File

@@ -37,9 +37,6 @@ class PHP_Token_InterfaceTest extends TestCase
}
}
/**
* @covers PHP_Token_INTERFACE::getName
*/
public function testGetName()
{
$this->assertEquals(
@@ -47,9 +44,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::getParent
*/
public function testGetParentNotExists()
{
$this->assertFalse(
@@ -57,9 +51,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::hasParent
*/
public function testHasParentNotExists()
{
$this->assertFalse(
@@ -67,9 +58,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::getParent
*/
public function testGetParentExists()
{
$this->assertEquals(
@@ -77,9 +65,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::hasParent
*/
public function testHasParentExists()
{
$this->assertTrue(
@@ -87,9 +72,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::getInterfaces
*/
public function testGetInterfacesExists()
{
$this->assertEquals(
@@ -98,9 +80,6 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::hasInterfaces
*/
public function testHasInterfacesExists()
{
$this->assertTrue(
@@ -108,13 +87,9 @@ class PHP_Token_InterfaceTest extends TestCase
);
}
/**
* @covers PHP_Token_INTERFACE::getPackage
*/
public function testGetPackageNamespace()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
foreach ($tokenStream as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php') as $token) {
if ($token instanceof PHP_Token_INTERFACE) {
$package = $token->getPackage();
$this->assertSame('Foo\\Bar', $package['namespace']);
@@ -122,7 +97,6 @@ class PHP_Token_InterfaceTest extends TestCase
}
}
public function provideFilesWithClassesWithinMultipleNamespaces()
{
return [
@@ -133,12 +107,12 @@ class PHP_Token_InterfaceTest extends TestCase
/**
* @dataProvider provideFilesWithClassesWithinMultipleNamespaces
* @covers PHP_Token_INTERFACE::getPackage
*/
public function testGetPackageNamespaceForFileWithMultipleNamespaces($filepath)
{
$tokenStream = new PHP_Token_Stream($filepath);
$firstClassFound = false;
foreach ($tokenStream as $token) {
if ($firstClassFound === false && $token instanceof PHP_Token_INTERFACE) {
$package = $token->getPackage();
@@ -167,13 +141,11 @@ class PHP_Token_InterfaceTest extends TestCase
}
}
/**
* @covers PHP_Token_INTERFACE::getPackage
*/
public function testGetPackageNamespaceWhenExtentingFromNamespaceClass()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classExtendsNamespacedClass.php');
$firstClassFound = false;
foreach ($tokenStream as $token) {
if ($firstClassFound === false && $token instanceof PHP_Token_INTERFACE) {
$package = $token->getPackage();
@@ -182,6 +154,7 @@ class PHP_Token_InterfaceTest extends TestCase
$firstClassFound = true;
continue;
}
if ($token instanceof PHP_Token_INTERFACE) {
$package = $token->getPackage();
$this->assertSame('Extender', $token->getName());
@@ -190,6 +163,7 @@ class PHP_Token_InterfaceTest extends TestCase
return;
}
}
$this->fail('Searching for 2 classes failed');
}
}

View File

@@ -12,9 +12,6 @@ use PHPUnit\Framework\TestCase;
class PHP_Token_NamespaceTest extends TestCase
{
/**
* @covers PHP_Token_NAMESPACE::getName
*/
public function testGetName()
{
$tokenStream = new PHP_Token_Stream(
@@ -30,8 +27,7 @@ class PHP_Token_NamespaceTest extends TestCase
public function testGetStartLineWithUnscopedNamespace()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
foreach ($tokenStream as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php') as $token) {
if ($token instanceof PHP_Token_NAMESPACE) {
$this->assertSame(2, $token->getLine());
}
@@ -40,8 +36,7 @@ class PHP_Token_NamespaceTest extends TestCase
public function testGetEndLineWithUnscopedNamespace()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php');
foreach ($tokenStream as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'classInNamespace.php') as $token) {
if ($token instanceof PHP_Token_NAMESPACE) {
$this->assertSame(2, $token->getEndLine());
}
@@ -49,8 +44,7 @@ class PHP_Token_NamespaceTest extends TestCase
}
public function testGetStartLineWithScopedNamespace()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php');
foreach ($tokenStream as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php') as $token) {
if ($token instanceof PHP_Token_NAMESPACE) {
$this->assertSame(2, $token->getLine());
}
@@ -59,8 +53,7 @@ class PHP_Token_NamespaceTest extends TestCase
public function testGetEndLineWithScopedNamespace()
{
$tokenStream = new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php');
foreach ($tokenStream as $token) {
foreach (new PHP_Token_Stream(TEST_FILES_PATH . 'classInScopedNamespace.php') as $token) {
if ($token instanceof PHP_Token_NAMESPACE) {
$this->assertSame(8, $token->getEndLine());
}

View File

@@ -7,5 +7,8 @@ indent_style = space
indent_size = 4
charset = utf-8
[*.yml]
indent_size = 2
[tests/_files/*_result_cache.txt]
insert_final_newline = false

View File

@@ -1,4 +1,7 @@
/.docker export-ignore
/build export-ignore
/tools export-ignore
/tools/* binary
*.php diff=php

View File

@@ -13,7 +13,7 @@ Please note that this project is released with a [Contributor Code of Conduct](C
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 <root@localhost>` look really stupid in the commit history of a project.
Pull requests for bug fixes must be based on the current stable branch whereas pull requests for new features must be based on the `master` branch.
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.
@@ -24,7 +24,7 @@ Due to time constraints, we are not always able to respond as quickly as we woul
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
$ ./tools/php-cs-fixer fix
```
## Using PHPUnit from a Git checkout
@@ -40,7 +40,7 @@ $ cd phpunit
Retrieve PHPUnit's dependencies using [Composer](https://getcomposer.org/):
```bash
$ composer install
$ ./tools/composer install
```
The `phpunit` script can be used to invoke the PHPUnit test runner:

View File

@@ -1,47 +0,0 @@
# 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

View File

@@ -0,0 +1,84 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
on:
- pull_request
- push
name: CI
jobs:
coding-guidelines:
name: Coding Guidelines
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Run friendsofphp/php-cs-fixer
run: php7.3 ./tools/php-cs-fixer fix --diff-format=udiff --dry-run --show-progress=dots --using-cache=no --verbose
lint-xml-configuration:
name: Lint XML Configuration
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build Docker image
uses: ./.docker/lint-xml-configuration
- name: Lint XML configuration files
uses: ./.docker/lint-xml-configuration
with:
args: bash ./build/lint-xml-configuration
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
php-binary:
- php7.1
- php7.2
- php7.3
dependencies:
- lowest
- highest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: "Cache dependencies installed with composer"
uses: actions/cache@v1
with:
path: ~/.composer/cache
key: ${{ matrix.php-binary }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.json') }}
restore-keys: |
${{ matrix.php-binary }}-composer-${{ matrix.dependencies }}-
- name: Install lowest dependencies with composer
if: matrix.dependencies == 'lowest'
run: ${{ matrix.php-binary }} ./tools/composer update --no-ansi --no-interaction --no-progress --no-suggest --prefer-lowest
- name: Install highest dependencies with composer
if: matrix.dependencies == 'highest'
run: ${{ matrix.php-binary }} ./tools/composer update --no-ansi --no-interaction --no-progress --no-suggest
- name: Run sanity check
run: PHP_BINARY=${{ matrix.php-binary }} bash ./build/sanity-check
- name: Run tests with phpunit
run: ${{ matrix.php-binary }} -d assert.exception=1 -d zend.assertions=1 ./phpunit --coverage-clover=coverage.xml
- name: Send code coverage report to Codecov.io
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: bash <(curl -s https://codecov.io/bash) || true

View File

@@ -2,7 +2,6 @@
/.idea
/.php_cs
/.php_cs.cache
/.phpunit.result.cache
/build/documentation
/build/logfiles
/build/phar
@@ -18,3 +17,5 @@
/tests/end-to-end/*.out
/tests/end-to-end/*.php
/vendor
.phpunit.result.cache
.psalm

View File

@@ -1,7 +0,0 @@
<?php declare(strict_types=1);
return [
'directory_list' => [ 'src/', 'vendor/' ],
'exclude_analysis_directory_list' => [ 'vendor/', 'src/Framework/Assert/' ],
'target_php_version' => '7.1',
];

View File

@@ -141,6 +141,10 @@ return PhpCsFixer\Config::create()
],
],
'ordered_imports' => true,
'ordered_interfaces' => [
'direction' => 'ascend',
'order' => 'alpha',
],
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_align' => true,
'phpdoc_annotation_without_dot' => true,
@@ -167,7 +171,7 @@ return PhpCsFixer\Config::create()
'semicolon_after_instruction' => true,
'set_type_to_cast' => true,
'short_scalar_cast' => true,
'simplified_null_return' => true,
'simplified_null_return' => false,
'single_blank_line_at_eof' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
@@ -177,7 +181,13 @@ return PhpCsFixer\Config::create()
'trailing_comma_in_multiline_array' => true,
'trim_array_spaces' => true,
'unary_operator_spaces' => true,
'visibility_required' => true,
'visibility_required' => [
'elements' => [
'const',
'method',
'property',
],
],
//'void_return' => true,
'whitespace_after_comma_in_array' => true,
]
@@ -185,7 +195,6 @@ return PhpCsFixer\Config::create()
->setFinder(
PhpCsFixer\Finder::create()
->files()
->in(__DIR__ . '/build')
->in(__DIR__ . '/src')
->in(__DIR__ . '/tests')
->notName('*.phpt')

View File

@@ -1,61 +1,38 @@
language: php
sudo: false
addons:
apt:
packages:
- libxml2-utils
php:
- 7.1
- 7.2
- 7.3
- master
matrix:
allow_failures:
- php: master
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.2
env: php-cs-fixer
- &COLLECT_CODE_COVERAGE
stage: Collect Code Coverage
php: 7.1
if: type = pull_request
before_install:
- ./tools/composer clear-cache
install:
- phpenv config-rm xdebug.ini
- travis_retry ./tools/composer update --no-ansi --no-interaction --no-progress --no-suggest
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:
- ./build/tools/php-cs-fixer fix --dry-run -v --show-progress=dots --diff-format=udiff
- ./phpunit --coverage-clover=coverage.xml
after_success:
- bash <(curl -s https://codecov.io/bash)
- <<: *COLLECT_CODE_COVERAGE
php: 7.2
- <<: *COLLECT_CODE_COVERAGE
php: 7.3
notifications:
email: false

View File

@@ -1,108 +0,0 @@
# Changes in PHPUnit 6.5
All notable changes of the PHPUnit 6.5 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [6.5.13] - 2018-09-08
* Fixed [#3181](https://github.com/sebastianbergmann/phpunit/issues/3181): `--filter` should be case-insensitive
* Fixed [#3234](https://github.com/sebastianbergmann/phpunit/issues/3234): `assertArraySubset()` with `$strict=true` does not display differences properly
* Fixed [#3254](https://github.com/sebastianbergmann/phpunit/issues/3254): TextUI test runner cannot run a `Test` instance that is not a `TestSuite`
## [6.5.12] - 2018-08-22
* Fixed [#3248](https://github.com/sebastianbergmann/phpunit/issues/3248) and [#3233](https://github.com/sebastianbergmann/phpunit/issues/3233): `phpunit.xsd` dictates element order where it should not
* Fixed [#3251](https://github.com/sebastianbergmann/phpunit/issues/3251): TeamCity result logger is missing test duration information
## [6.5.11] - 2018-08-07
* Fixed [#3219](https://github.com/sebastianbergmann/phpunit/issues/3219): `getMockFromWsdl()` generates invalid PHP code when WSDL filename contains special characters
## [6.5.10] - 2018-08-03
### Fixed
* Fixed [#3209](https://github.com/sebastianbergmann/phpunit/issues/3209): `Test::run()` and `TestCase::run()` interface contradiction
* Fixed [#3218](https://github.com/sebastianbergmann/phpunit/issues/3218): `prefix` attribute for `directory` node missing from `phpunit.xml` XSD
* Fixed [#3225](https://github.com/sebastianbergmann/phpunit/issues/3225): `coverage-php` missing from `phpunit.xsd`
## [6.5.9] - 2018-07-03
### Fixed
* Fixed [#3142](https://github.com/sebastianbergmann/phpunit/issues/3142): Method-level annotations (`@backupGlobals`, `@backupStaticAttributes`, `@errorHandler`, `@preserveGlobalState`) do not override class-level annotations
## [6.5.8] - 2018-04-10
### Fixed
* Fixed [#2830](https://github.com/sebastianbergmann/phpunit/issues/2830): `@runClassInSeparateProcess` does not work for tests that use `@dataProvider`
## [6.5.7] - 2018-02-26
### Fixed
* Fixed [#2974](https://github.com/sebastianbergmann/phpunit/issues/2974): JUnit XML logfile contains invalid characters when test output contains binary data
## [6.5.6] - 2018-02-01
### Fixed
* Fixed [#2236](https://github.com/sebastianbergmann/phpunit/issues/2236): Exceptions in `tearDown()` do not affect `getStatus()`
* Fixed [#2950](https://github.com/sebastianbergmann/phpunit/issues/2950): Class extending `PHPUnit\Framework\TestSuite` does not extend `PHPUnit\FrameworkTestCase`
* Fixed [#2972](https://github.com/sebastianbergmann/phpunit/issues/2972): PHPUnit crashes when test suite contains both `.phpt` files and unconventionally named tests
## [6.5.5] - 2017-12-17
### Fixed
* Fixed [#2922](https://github.com/sebastianbergmann/phpunit/issues/2922): Test class is not discovered when there is a test class with `@group` and provider throwing exception in it, tests are run with `--exclude-group` for that group, there is another class called later (after the class from above), and the name of that another class does not match its filename
## [6.5.4] - 2017-12-10
### Changed
* Require version 5.0.5 of `phpunit/phpunit-mock-objects` for [phpunit-mock-objects#394](https://github.com/sebastianbergmann/phpunit-mock-objects/issues/394)
## [6.5.3] - 2017-12-06
### Fixed
* Fixed an issue with PHPT tests when `forceCoversAnnotation="true"` is configured
## [6.5.2] - 2017-12-02
### Changed
* Require version 5.0.4 of `phpunit/phpunit-mock-objects` for [phpunit-mock-objects#388](https://github.com/sebastianbergmann/phpunit-mock-objects/issues/388)
## [6.5.1] - 2017-12-01
* Fixed [#2886](https://github.com/sebastianbergmann/phpunit/pull/2886): Forced environment variables do not affect `getenv()`
## [6.5.0] - 2017-12-01
### Added
* Implemented [#2286](https://github.com/sebastianbergmann/phpunit/issues/2286): Optional `$exit` parameter for `PHPUnit\TextUI\TestRunner::run()`
* Implemented [#2496](https://github.com/sebastianbergmann/phpunit/issues/2496): Allow shallow copy of dependencies
### Fixed
* Fixed [#2654](https://github.com/sebastianbergmann/phpunit/issues/2654): Problems with `assertJsonStringEqualsJsonString()`
* Fixed [#2810](https://github.com/sebastianbergmann/phpunit/pull/2810): Code Coverage for PHPT tests does not work
[6.5.13]: https://github.com/sebastianbergmann/phpunit/compare/6.5.12...6.5.13
[6.5.12]: https://github.com/sebastianbergmann/phpunit/compare/6.5.11...6.5.12
[6.5.11]: https://github.com/sebastianbergmann/phpunit/compare/6.5.10...6.5.11
[6.5.10]: https://github.com/sebastianbergmann/phpunit/compare/6.5.9...6.5.10
[6.5.9]: https://github.com/sebastianbergmann/phpunit/compare/6.5.8...6.5.9
[6.5.8]: https://github.com/sebastianbergmann/phpunit/compare/6.5.7...6.5.8
[6.5.7]: https://github.com/sebastianbergmann/phpunit/compare/6.5.6...6.5.7
[6.5.6]: https://github.com/sebastianbergmann/phpunit/compare/6.5.5...6.5.6
[6.5.5]: https://github.com/sebastianbergmann/phpunit/compare/6.5.4...6.5.5
[6.5.4]: https://github.com/sebastianbergmann/phpunit/compare/6.5.3...6.5.4
[6.5.3]: https://github.com/sebastianbergmann/phpunit/compare/6.5.2...6.5.3
[6.5.2]: https://github.com/sebastianbergmann/phpunit/compare/6.5.1...6.5.2
[6.5.1]: https://github.com/sebastianbergmann/phpunit/compare/6.5.0...6.5.1
[6.5.0]: https://github.com/sebastianbergmann/phpunit/compare/6.4...6.5.0

View File

@@ -1,56 +0,0 @@
# Changes in PHPUnit 7.0
All notable changes of the PHPUnit 7.0 release series are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
## [7.0.3] - 2018-03-26
* Fixed [#3028](https://github.com/sebastianbergmann/phpunit/pull/3028): TestDox name prettifier does not handle test case classes correctly that are in a `Tests\*` namespace
## [7.0.2] - 2018-02-26
### Fixed
* Fixed [#2974](https://github.com/sebastianbergmann/phpunit/issues/2974): JUnit XML logfile contains invalid characters when test output contains binary data
* Fixed [#3014](https://github.com/sebastianbergmann/phpunit/issues/3014): `TypeError` in `PHPUnit\Framework\TestCase::getActualOutput()` when callback registered using `setOutputCallback()` does not return a string
* Removed more superfluous `@throws \Exception` annotations
## [7.0.1] - 2018-02-13
### Fixed
* Fixed [#3000](https://github.com/sebastianbergmann/phpunit/issues/3000): Directories are not created recursively
* Removed superfluous `@throws \Exception` annotations from assertion methods
## [7.0.0] - 2018-02-02
### Added
* Implemented [#2967](https://github.com/sebastianbergmann/phpunit/pull/2967): Added support for PHP configuration settings to `@requires` annotation
### Changed
* Implemented [#2566](https://github.com/sebastianbergmann/phpunit/issues/2566): Use `Throwable` instead of `Exception` in `PHPUnit\Framework\TestListener` method signatures
* Implemented [#2920](https://github.com/sebastianbergmann/phpunit/pull/2920): Replace CLI TestDox printer with `rpkamp/fancy-testdox-printer`
* Scalar Type Declarations and Return Type Declarations are now used where possible (as a result, the API of `PHPUnit\Framework\TestListener`, for instance, has changed)
* Some classes are now `final`
* The visibility of some methods has been changed from `protected` to `private`
### Removed
* Implemented [#2473](https://github.com/sebastianbergmann/phpunit/issues/2473): Drop support for PHP 7.0
* `@scenario` is no longer an alias for `@test`
* The `PHPUnit\Framework\BaseTestListener` class has been removed (deprecated in PHPUnit 6.4)
* The `PHPUnit\Framework\TestCase::prepareTemplate` template method has been removed
### Fixed
* Fixed [#2169](https://github.com/sebastianbergmann/phpunit/issues/2169): `assertSame()` does not show differences when used on two arrays that are not identical
* Fixed [#2902](https://github.com/sebastianbergmann/phpunit/issues/2902): `@test` annotation gets accepted no matter what
* Fixed [#2907](https://github.com/sebastianbergmann/phpunit/issues/2907): `StringMatchesFormatDescription` constraint does not handle escaped `%` correctly
* Fixed [#2919](https://github.com/sebastianbergmann/phpunit/issues/2919): `assertJsonStringEqualsJsonString()` matches empty object as empty array
[7.0.3]: https://github.com/sebastianbergmann/phpunit/compare/7.0.2...7.0.3
[7.0.2]: https://github.com/sebastianbergmann/phpunit/compare/7.0.1...7.0.2
[7.0.1]: https://github.com/sebastianbergmann/phpunit/compare/7.0.0...7.0.1
[7.0.0]: https://github.com/sebastianbergmann/phpunit/compare/6.5...7.0.0

View File

@@ -1,63 +0,0 @@
# Changes in PHPUnit 7.1
All notable changes of the PHPUnit 7.1 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [7.1.6] - 2018-MM-DD
### Fixed
* Fixed [#3107](https://github.com/sebastianbergmann/phpunit/issues/3107): `CliTestDoxPrinter::addError()` cannot handle errors in `setUpBeforeClass()`
* Fixed [#3142](https://github.com/sebastianbergmann/phpunit/issues/3142): Method-level annotations (`@backupGlobals`, `@backupStaticAttributes`, `@errorHandler`, `@preserveGlobalState`) do not override class-level annotations
## [7.1.5] - 2018-04-29
### Fixed
* Fixed [#3105](https://github.com/sebastianbergmann/phpunit/pull/3105): Name is prettified inconsistently when snake_case notation is used
## [7.1.4] - 2018-04-18
### Fixed
* Fixed [#3034](https://github.com/sebastianbergmann/phpunit/pull/3034): `$this->getStatus()` returns `STATUS_PASSED` in `tearDown()` after unexpected exception
## [7.1.3] - 2018-04-13
### Fixed
* Fixed [#3094](https://github.com/sebastianbergmann/phpunit/issues/3094): Faulty dependency constraint affecting `getObjectForTrait()` (failure using `--prefer-lowest`)
## [7.1.2] - 2018-04-10
### Fixed
* Fixed [#2830](https://github.com/sebastianbergmann/phpunit/issues/2830): `@runClassInSeparateProcess` does not work for tests that use `@dataProvider`
* Fixed [#3059](https://github.com/sebastianbergmann/phpunit/pull/3059): `StringMatchesFormatDescription` constraint fails when matching multiline with `\r\n`
* Fixed [#3087](https://github.com/sebastianbergmann/phpunit/pull/3087): `TestCase::getTestResultObject()` can return `null`
## [7.1.1] - 2018-04-06
### Fixed
* `CliTestDoxPrinter::writeProgress()` and `TeamCity::writeProgress()` are not compatible with `ResultPrinter::writeProgress()` (on PHP 7.1)
## [7.1.0] - 2018-04-06
### Added
* Implemented [#3002](https://github.com/sebastianbergmann/phpunit/issues/3002): Support for test runner extensions
* Implemented [#3035](https://github.com/sebastianbergmann/phpunit/pull/3035): Add support for `iterable` in `assertInternalType()`
### Changed
* `PHPUnit\Framework\Assert` is no longer searched for test methods
* `ReflectionMethod::invokeArgs()` is no longer used to invoke test methods
[7.1.6]: https://github.com/sebastianbergmann/phpunit/compare/7.1.5...7.1.6
[7.1.5]: https://github.com/sebastianbergmann/phpunit/compare/7.1.4...7.1.5
[7.1.4]: https://github.com/sebastianbergmann/phpunit/compare/7.1.3...7.1.4
[7.1.3]: https://github.com/sebastianbergmann/phpunit/compare/7.1.2...7.1.3
[7.1.2]: https://github.com/sebastianbergmann/phpunit/compare/7.1.1...7.1.2
[7.1.1]: https://github.com/sebastianbergmann/phpunit/compare/7.1.0...7.1.1
[7.1.0]: https://github.com/sebastianbergmann/phpunit/compare/7.0...7.1.0

View File

@@ -1,78 +0,0 @@
# Changes in PHPUnit 7.2
All notable changes of the PHPUnit 7.2 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [7.2.7] - 2018-07-15
### Fixed
* Fixed [#3154](https://github.com/sebastianbergmann/phpunit/issues/3154): Global constants as default parameter values are not handled correctly in namespace
* Fixed [#3189](https://github.com/sebastianbergmann/phpunit/issues/3189): PHPUnit 7.2 potentially leaves a messy libxmlerror state
* Fixed [#3199](https://github.com/sebastianbergmann/phpunit/pull/3199): Code Coverage for PHPT tests does not work when PHPDBG is used
## [7.2.6] - 2018-06-21
### Fixed
* Fixed [#3176](https://github.com/sebastianbergmann/phpunit/issues/3176): PHPUnit 7.2.5 breaks backward compatibility
## [7.2.5] - 2018-06-21
### Fixed
* Fixed [#3093](https://github.com/sebastianbergmann/phpunit/issues/3093): Unable to chain a `@dataProvider` in method `a` with a `@depends` in method `b`
* Fixed [#3174](https://github.com/sebastianbergmann/phpunit/issues/3174): Code generator for test doubles does not handle proxied methods with variadic parameters correctly
## [7.2.4] - 2018-06-05
### Fixed
* Fixed [#3160](https://github.com/sebastianbergmann/phpunit/issues/3160): TeamCity logfile writer broken on Windows
## [7.2.3] - 2018-06-03
### Fixed
* Fixed [#3156](https://github.com/sebastianbergmann/phpunit/issues/3156): Combined use of `@depends` and `@dataProvider` is not handled correctly
## [7.2.2] - 2018-06-01
### Changed
* Ensure that `phpunit/php-code-coverage` is used in version `^6.0.7`
## [7.2.1] - 2018-06-01
### Fixed
* Fixed [#3155](https://github.com/sebastianbergmann/phpunit/issues/3155): Calling `getStatus()` on a `TestCase` object before the respective test has been executed results in type error
## [7.2.0] - 2018-06-01
### Added
* Implemented [#3042](https://github.com/sebastianbergmann/phpunit/pull/3042): Add `TestCase::expectNotToPerformAssertions()` method as alternative to `@doesNotPerformAssertions` annotation
* Implemented [#3064](https://github.com/sebastianbergmann/phpunit/issues/3064): Mark tests as risky when they claim not to perform assertions but do
* Implemented [#3066](https://github.com/sebastianbergmann/phpunit/issues/3066): Validate XML configuration against XSD
* Implemented [#3076](https://github.com/sebastianbergmann/phpunit/issues/3076): Extensions can be configured via PHPUnit's XML configuration
* Implemented [#3080](https://github.com/sebastianbergmann/phpunit/issues/3080): The XML configuration arguments can have boolean elements
* Implemented [#3092](https://github.com/sebastianbergmann/phpunit/pull/3092): Ability to run tests in random order, reverse order, ordered using dependency resolution
### Changed
* Implemented [#3103](https://github.com/sebastianbergmann/phpunit/issues/3103): Merge `phpunit-mock-objects` back into PHPUnit's Git repository
* Implemented [#3115](https://github.com/sebastianbergmann/phpunit/pull/3115): Method-level `@covers` annotation overrides class-level `@coversNothing` annotation
### Removed
* Fixed [#3069](https://github.com/sebastianbergmann/phpunit/issues/3069): Method `ResultPrinter::printWaitPrompt()` seems to be unused
[7.2.7]: https://github.com/sebastianbergmann/phpunit/compare/7.2.6...7.2.7
[7.2.6]: https://github.com/sebastianbergmann/phpunit/compare/7.2.5...7.2.6
[7.2.5]: https://github.com/sebastianbergmann/phpunit/compare/7.2.4...7.2.5
[7.2.4]: https://github.com/sebastianbergmann/phpunit/compare/7.2.3...7.2.4
[7.2.3]: https://github.com/sebastianbergmann/phpunit/compare/7.2.2...7.2.3
[7.2.2]: https://github.com/sebastianbergmann/phpunit/compare/7.2.1...7.2.2
[7.2.1]: https://github.com/sebastianbergmann/phpunit/compare/7.2.0...7.2.1
[7.2.0]: https://github.com/sebastianbergmann/phpunit/compare/7.1...7.2.0

View File

@@ -1,82 +0,0 @@
# Changes in PHPUnit 7.3
All notable changes of the PHPUnit 7.3 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [7.3.6] - 2018-MM-DD
### Fixed
* Fixed [#3310](https://github.com/sebastianbergmann/phpunit/issues/3310): Inconsistent `@throws` annotations in `Assert/Functions.php`
## [7.3.5] - 2018-09-08
### Fixed
* Fixed [#3181](https://github.com/sebastianbergmann/phpunit/issues/3181): `--filter` should be case-insensitive
* Fixed [#3234](https://github.com/sebastianbergmann/phpunit/issues/3234): `assertArraySubset()` with `$strict=true` does not display differences properly
* Fixed [#3254](https://github.com/sebastianbergmann/phpunit/issues/3254): TextUI test runner cannot run a `Test` instance that is not a `TestSuite`
## [7.3.4] - 2018-09-05
### Fixed
* Fixed [#3270](https://github.com/sebastianbergmann/phpunit/issues/3270): Array / Object to string conversion in `NamePrettifier`
## [7.3.3] - 2018-09-01
### Fixed
* Fixed [#3265](https://github.com/sebastianbergmann/phpunit/pull/3265): Slashes are unnecessarily escaped in prettified JSON
* Fixed [#3267](https://github.com/sebastianbergmann/phpunit/pull/3267): `%` not escaped correctly for `StringMatchesFormat` constraint
## [7.3.2] - 2018-08-22
### Fixed
* Fixed [#3219](https://github.com/sebastianbergmann/phpunit/issues/3219): `getMockFromWsdl()` generates invalid PHP code when WSDL filename contains special characters
* Fixed [#3248](https://github.com/sebastianbergmann/phpunit/issues/3248) and [#3233](https://github.com/sebastianbergmann/phpunit/issues/3233): `phpunit.xsd` dictates element order where it should not
* Fixed [#3251](https://github.com/sebastianbergmann/phpunit/issues/3251): TeamCity result logger is missing test duration information
## [7.3.1] - 2018-08-07
### Changed
* Reverted [#3161](https://github.com/sebastianbergmann/phpunit/pull/3161) (because of [#3240](https://github.com/sebastianbergmann/phpunit/issues/3240)): Support for indexed arrays in `PHPUnit\Framework\Constraint\ArraySubset`
### Fixed
* Fixed [#3237](https://github.com/sebastianbergmann/phpunit/issues/3237): Result caching enabled by default
* Fixed [#3240](https://github.com/sebastianbergmann/phpunit/issues/3240): `assertArraySubset()` does not work as expected
## [7.3.0] - 2018-08-03
### Added
* Implemented [#3147](https://github.com/sebastianbergmann/phpunit/pull/3147): Support for running tests first that failed in a previous run
* Implemented `cacheResult` configuration directive and `--cache-result` CLI option to control test result cache required for "run defects first" functionality (disabled by default)
* Implemented `cacheResultFile` configuration directive and `--cache-result-file` CLI option to configure test result cache file (default: `.phpunit.result.cache`)
* Implemented `stopOnDefect` configuration directive and `--stop-on-defect` CLI option for aborting test suite execution upon first defective test
* Implemented `executionOrder` configuration directive and `--order-by` CLI option for sorting the test suite before execution
* The `--order-by=random` CLI option should now be used instead of `--random-order`
* The `--order-by=depends` CLI option should now be used instead of `--resolve-dependencies`
* The `--order-by=reverse` CLI option should now be used instead of `--reverse-order`
* Implemented [#3161](https://github.com/sebastianbergmann/phpunit/pull/3161): Support for indexed arrays in `PHPUnit\Framework\Constraint\ArraySubset`
* Implemented [#3194](https://github.com/sebastianbergmann/phpunit/issues/3194): `@covers class` (and `@uses class`) should include traits used by class
* Implemented [#3196](https://github.com/sebastianbergmann/phpunit/issues/3196): Support for replacing placeholders in `@testdox` text with data provider values
* Implemented [#3198](https://github.com/sebastianbergmann/phpunit/pull/3198): Provide source location for useless tests
### Fixed
* Fixed [#3154](https://github.com/sebastianbergmann/phpunit/issues/3154): Global constants as default parameter values are not handled correctly in namespace
* Fixed [#3218](https://github.com/sebastianbergmann/phpunit/issues/3218): `prefix` attribute for `directory` node missing from `phpunit.xml` XSD
* Fixed [#3222](https://github.com/sebastianbergmann/phpunit/pull/3222): Priority of `@covers` and `@coversNothing` is wrong
* Fixed [#3225](https://github.com/sebastianbergmann/phpunit/issues/3225): `coverage-php` missing from `phpunit.xsd`
[7.3.6]: https://github.com/sebastianbergmann/phpunit/compare/7.3.5...7.3.6
[7.3.5]: https://github.com/sebastianbergmann/phpunit/compare/7.3.4...7.3.5
[7.3.4]: https://github.com/sebastianbergmann/phpunit/compare/7.3.3...7.3.4
[7.3.3]: https://github.com/sebastianbergmann/phpunit/compare/7.3.2...7.3.3
[7.3.2]: https://github.com/sebastianbergmann/phpunit/compare/7.3.1...7.3.2
[7.3.1]: https://github.com/sebastianbergmann/phpunit/compare/7.3.0...7.3.1
[7.3.0]: https://github.com/sebastianbergmann/phpunit/compare/7.2...7.3.0

View File

@@ -1,55 +0,0 @@
# Changes in PHPUnit 7.4
All notable changes of the PHPUnit 7.4 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [7.4.5] - 2018-12-03
* Fixed [#3410](https://github.com/sebastianbergmann/phpunit/issues/3410): Parent directory of `cacheResultFile` is not created when it does not exist
* Fixed [#3418](https://github.com/sebastianbergmann/phpunit/pull/3418): Conflicting placeholder replacement and argument exporting inconsistencies in `@testdox`
## [7.4.4] - 2018-11-14
### Fixed
* Fixed [#3379](https://github.com/sebastianbergmann/phpunit/issues/3379): Dependent test of skipped test has status `-1`
* Fixed [#3394](https://github.com/sebastianbergmann/phpunit/issues/3394): Process Isolation does not work when PHPUnit is used as PHAR
* Fixed [#3398](https://github.com/sebastianbergmann/phpunit/pull/3398): Bug when replacing placeholders in `@testdox` annotation using an associative array
* Fixed [#3401](https://github.com/sebastianbergmann/phpunit/pull/3401): Test re-ordering edge cases
* Fixed [#3402](https://github.com/sebastianbergmann/phpunit/pull/3402): Listening to the tests in reverse revealed evil hidden messages
## [7.4.3] - 2018-10-23
### Changed
* Use `^3.1` of `sebastian/environment` again due to [regression](https://github.com/sebastianbergmann/environment/issues/31)
## [7.4.2] - 2018-10-23
### Fixed
* Fixed [#3354](https://github.com/sebastianbergmann/phpunit/pull/3354): Regression when `columns="max"` is used
## [7.4.1] - 2018-10-18
### Fixed
* Fixed [#3321](https://github.com/sebastianbergmann/phpunit/pull/3321): Incorrect TestDox output for data provider with indexed array
* Fixed [#3353](https://github.com/sebastianbergmann/phpunit/issues/3353): Requesting less than 16 columns of output results in an error
## [7.4.0] - 2018-10-05
### Added
* Implemented [#3127](https://github.com/sebastianbergmann/phpunit/issues/3127): Emit error when mocked method is not really mocked
* Implemented [#3224](https://github.com/sebastianbergmann/phpunit/pull/3224): Ability to enforce a time limit for tests not annotated with `@small`, `@medium`, or `@large`
* Implemented [#3272](https://github.com/sebastianbergmann/phpunit/issues/3272): Ability to generate code coverage whitelist filter script for Xdebug
* Implemented [#3284](https://github.com/sebastianbergmann/phpunit/issues/3284): Ability to reorder tests based on execution time
* Implemented [#3290](https://github.com/sebastianbergmann/phpunit/issues/3290): Ability to load a PHP script before any code of PHPUnit itself is loaded
[7.4.5]: https://github.com/sebastianbergmann/phpunit/compare/7.4.4...7.4.5
[7.4.4]: https://github.com/sebastianbergmann/phpunit/compare/7.4.3...7.4.4
[7.4.3]: https://github.com/sebastianbergmann/phpunit/compare/7.4.2...7.4.3
[7.4.2]: https://github.com/sebastianbergmann/phpunit/compare/7.4.1...7.4.2
[7.4.1]: https://github.com/sebastianbergmann/phpunit/compare/7.4.0...7.4.1
[7.4.0]: https://github.com/sebastianbergmann/phpunit/compare/7.3.5...7.4.0

195
vendor/phpunit/phpunit/ChangeLog-7.5.md vendored Normal file
View File

@@ -0,0 +1,195 @@
# 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](https://keepachangelog.com/) principles.
## [7.5.20] - 2020-01-08
### Removed
* `eval-stdin.php` has been removed, it was not used anymore since PHPUnit 7.2.7
## [7.5.19] - 2020-01-06
### Changed
* `eval-stdin.php` can now only be executed with `cli` and `phpdbg`
## [7.5.18] - 2019-12-06
### Fixed
* Fixed [#3967](https://github.com/sebastianbergmann/phpunit/issues/3967): Cannot double interface that extends interface that extends `\Throwable`
* Fixed [#3968](https://github.com/sebastianbergmann/phpunit/pull/3968): Test class run in a separate PHP process are passing when `exit` called inside
## [7.5.17] - 2019-10-28
### Fixed
* Fixed [#3727](https://github.com/sebastianbergmann/phpunit/issues/3727): Problem hidden by PHPUnit's error handler
* Fixed [#3863](https://github.com/sebastianbergmann/phpunit/pull/3863): `\Countable` needs to be checked before `\EmptyIterator`
## [7.5.16] - 2019-09-14
### Fixed
* Fixed [#3801](https://github.com/sebastianbergmann/phpunit/issues/3801): Class constant as default parameter is undefined
* Fixed [#3834](https://github.com/sebastianbergmann/phpunit/issues/3834): Trailing slash breaks code coverage on Windows
## [7.5.15] - 2019-08-21
### Changed
* Implemented [#3765](https://github.com/sebastianbergmann/phpunit/pull/3765): Use `ReflectionType::getName()` instead of `ReflectionType::__toString()` (which is deprecated in PHP 7.4)
## [7.5.14] - 2019-07-15
### Fixed
* Fixed [#3743](https://github.com/sebastianbergmann/phpunit/issues/3743): `EmptyIterator` instances are not handled correctly by `Count` and `IsEmpty` constraints
## [7.5.13] - 2019-06-19
### Fixed
* Fixed [#3722](https://github.com/sebastianbergmann/phpunit/issues/3722): `getObjectForTrait()` does not work for traits that declare a constructor
* Fixed [#3723](https://github.com/sebastianbergmann/phpunit/pull/3723): Unescaped dash in character group in regular expression
## [7.5.12] - 2019-05-28
### Changed
* After each test, `libxml_clear_errors()` is now called to clear the libxml error buffer
### Fixed
* Fixed [#3694](https://github.com/sebastianbergmann/phpunit/pull/3694): Constructor arguments for `Throwable` and `Exception` are ignored
* Fixed [#3709](https://github.com/sebastianbergmann/phpunit/pull/3709): Method-level `@coversNothing` annotation does not prevent code coverage data collection
## [7.5.11] - 2019-05-14
### Fixed
* Fixed [#3683](https://github.com/sebastianbergmann/phpunit/issues/3683): Regression in PHPUnit 7.5.10 with regard to Exception stubbing/mocking
## [7.5.10] - 2019-05-09
### Fixed
* Fixed [#3414](https://github.com/sebastianbergmann/phpunit/pull/3414): `willThrowException()` only accepts `Exception`, not `Throwable`
* Fixed [#3587](https://github.com/sebastianbergmann/phpunit/issues/3587): `.phpunit.result.cache` file is all over the place
* Fixed [#3596](https://github.com/sebastianbergmann/phpunit/issues/3596): Mocking an interface that extends another interface forgets to mock its own methods
* Fixed [#3674](https://github.com/sebastianbergmann/phpunit/issues/3674): `TypeError` when an incorrect file path is given
## [7.5.9] - 2019-04-19
### Fixed
* Fixed [#3607](https://github.com/sebastianbergmann/phpunit/issues/3607): Return value generation interferes with proxying to original method
## [7.5.8] - 2019-03-26
### Fixed
* Fixed [#3564](https://github.com/sebastianbergmann/phpunit/issues/3564): Production code uses class from test suite's fixture
## [7.5.7] - 2019-03-16
### Fixed
* Fixed [#3480](https://github.com/sebastianbergmann/phpunit/issues/3480): Wrong return type declaration for `TestCase::getExpectedExceptionMessage()` and `TestCase::getExpectedExceptionMessageRegExp()`
* Fixed [#3550](https://github.com/sebastianbergmann/phpunit/issues/3550): Check for valid attribute names in `assertObjectHasAttribute()` is too strict
## [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.20]: https://github.com/sebastianbergmann/phpunit/compare/7.5.19...7.5.20
[7.5.19]: https://github.com/sebastianbergmann/phpunit/compare/7.5.18...7.5.19
[7.5.18]: https://github.com/sebastianbergmann/phpunit/compare/7.5.17...7.5.18
[7.5.17]: https://github.com/sebastianbergmann/phpunit/compare/7.5.16...7.5.17
[7.5.16]: https://github.com/sebastianbergmann/phpunit/compare/7.5.15...7.5.16
[7.5.15]: https://github.com/sebastianbergmann/phpunit/compare/7.5.14...7.5.15
[7.5.14]: https://github.com/sebastianbergmann/phpunit/compare/7.5.13...7.5.14
[7.5.13]: https://github.com/sebastianbergmann/phpunit/compare/7.5.12...7.5.13
[7.5.12]: https://github.com/sebastianbergmann/phpunit/compare/7.5.11...7.5.12
[7.5.11]: https://github.com/sebastianbergmann/phpunit/compare/7.5.10...7.5.11
[7.5.10]: https://github.com/sebastianbergmann/phpunit/compare/7.5.9...7.5.10
[7.5.9]: https://github.com/sebastianbergmann/phpunit/compare/7.5.8...7.5.9
[7.5.8]: https://github.com/sebastianbergmann/phpunit/compare/7.5.7...7.5.8
[7.5.7]: https://github.com/sebastianbergmann/phpunit/compare/7.5.6...7.5.7
[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

View File

@@ -1,6 +1,6 @@
PHPUnit
Copyright (c) 2001-2018, Sebastian Bergmann <sebastian@phpunit.de>.
Copyright (c) 2001-2019, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@@ -4,16 +4,16 @@ PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of
[![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.4.svg?style=flat-square)](https://phpunit.de/build-status.html)
[![CI Status](https://github.com/sebastianbergmann/phpunit/workflows/CI/badge.svg)](https://github.com/sebastianbergmann/phpunit/actions)
## Installation
We distribute a [PHP Archive (PHAR)](https://php.net/phar) that has all required (as well as some optional) dependencies of PHPUnit 7.4 bundled in a single file:
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.4.phar
$ wget https://phar.phpunit.de/phpunit-7.5.phar
$ php phpunit-7.4.phar --version
$ 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.

View File

@@ -1,59 +0,0 @@
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.11'
XDEBUG_VERSION: '2.5.5-7.1'
DEPENDENCIES: '--prefer-lowest'
- PHP_VERSION: '7.1.11'
XDEBUG_VERSION: '2.5.5-7.1'
DEPENDENCIES: ''
matrix:
fast_finish: true
cache:
- c:\php -> appveyor.yml
- '%LOCALAPPDATA%\Composer\files'
init:
- SET PATH=c:\php\%PHP_VERSION%;%PATH%
install:
- IF NOT EXIST c:\php mkdir c:\php
- IF NOT EXIST c:\php\%PHP_VERSION% mkdir c:\php\%PHP_VERSION%
- cd c:\php\%PHP_VERSION%
- IF NOT EXIST php-installed.txt curl -fsS -o php-%PHP_VERSION%-Win32-VC14-x86.zip https://windows.php.net/downloads/releases/archives/php-%PHP_VERSION%-Win32-VC14-x86.zip
- IF NOT EXIST php-installed.txt 7z x php-%PHP_VERSION%-Win32-VC14-x86.zip -y >nul
- IF NOT EXIST php-installed.txt del /Q *.zip
- IF NOT EXIST php-installed.txt copy /Y php.ini-development php.ini
- IF NOT EXIST php-installed.txt echo max_execution_time=1200 >> php.ini
- IF NOT EXIST php-installed.txt echo date.timezone="UTC" >> php.ini
- IF NOT EXIST php-installed.txt echo extension_dir=ext >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_curl.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_openssl.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_mbstring.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_fileinfo.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_mysqli.dll >> php.ini
- IF NOT EXIST php-installed.txt echo extension=php_pdo_sqlite.dll >> php.ini
- IF NOT EXIST php-installed.txt echo zend.assertions=1 >> php.ini
- IF NOT EXIST php-installed.txt echo assert.exception=On >> php.ini
- IF NOT EXIST php-installed.txt 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

View File

@@ -27,7 +27,7 @@
</target>
<target name="validate-composer-json" depends="clean" unless="validate-composer-json.done" description="Validate composer.json">
<exec executable="${basedir}/build/tools/composer" failonerror="true" taskname="composer">
<exec executable="${basedir}/tools/composer" failonerror="true" taskname="composer">
<arg value="validate"/>
<arg value="--strict"/>
<arg value="${basedir}/composer.json"/>
@@ -43,13 +43,13 @@
<target name="install-dependencies" unless="dependencies-installed" depends="-dependencies-installed,validate-composer-json" description="Install dependencies with Composer">
<copy file="${basedir}/composer.json" tofile="${basedir}/composer.json.bak"/>
<exec executable="${basedir}/build/tools/composer" taskname="composer">
<exec executable="${basedir}/tools/composer" taskname="composer">
<arg value="require"/>
<arg value="--no-update"/>
<arg value="phpunit/php-invoker:^2.0"/>
</exec>
<exec executable="${basedir}/build/tools/composer" taskname="composer">
<exec executable="${basedir}/tools/composer" taskname="composer">
<arg value="update"/>
<arg value="--no-interaction"/>
<arg value="--no-progress"/>
@@ -61,7 +61,7 @@
</target>
<target name="check-dependencies" description="Performs check for outdated dependencies">
<exec executable="${basedir}/build/tools/composer" taskname="composer">
<exec executable="${basedir}/tools/composer" taskname="composer">
<arg value="show"/>
<arg value="--minor-only"/>
<arg value="--latest"/>
@@ -153,6 +153,12 @@
</fileset>
</copy>
<copy todir="${basedir}/build/phar/php-invoker">
<fileset dir="${basedir}/vendor/phpunit/php-invoker/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/phpunit/php-text-template/LICENSE" tofile="${basedir}/build/phar/php-text-template/LICENSE"/>
<copy todir="${basedir}/build/phar/php-text-template">
<fileset dir="${basedir}/vendor/phpunit/php-text-template/src">
@@ -209,20 +215,6 @@
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/recursion-context/LICENSE" tofile="${basedir}/build/phar/sebastian-recursion-context/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-recursion-context">
<fileset dir="${basedir}/vendor/sebastian/recursion-context/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/resource-operations/LICENSE" tofile="${basedir}/build/phar/sebastian-resource-operations/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-resource-operations">
<fileset dir="${basedir}/vendor/sebastian/resource-operations/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/global-state/LICENSE" tofile="${basedir}/build/phar/sebastian-global-state/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-global-state">
<fileset dir="${basedir}/vendor/sebastian/global-state/src">
@@ -244,6 +236,20 @@
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/recursion-context/LICENSE" tofile="${basedir}/build/phar/sebastian-recursion-context/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-recursion-context">
<fileset dir="${basedir}/vendor/sebastian/recursion-context/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/resource-operations/LICENSE" tofile="${basedir}/build/phar/sebastian-resource-operations/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-resource-operations">
<fileset dir="${basedir}/vendor/sebastian/resource-operations/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/sebastian/version/LICENSE" tofile="${basedir}/build/phar/sebastian-version/LICENSE"/>
<copy todir="${basedir}/build/phar/sebastian-version">
<fileset dir="${basedir}/vendor/sebastian/version/src">
@@ -258,8 +264,23 @@
</fileset>
</copy>
<copy todir="${basedir}/build/phar/php-invoker">
<fileset dir="${basedir}/vendor/phpunit/php-invoker/src">
<copy file="${basedir}/vendor/myclabs/deep-copy/LICENSE" tofile="${basedir}/build/phar/myclabs-deep-copy/LICENSE"/>
<copy todir="${basedir}/build/phar/myclabs-deep-copy">
<fileset dir="${basedir}/vendor/myclabs/deep-copy/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/phar-io/manifest/LICENSE" tofile="${basedir}/build/phar/phar-io-manifest/LICENSE"/>
<copy todir="${basedir}/build/phar/phar-io-manifest">
<fileset dir="${basedir}/vendor/phar-io/manifest/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/phar-io/version/LICENSE" tofile="${basedir}/build/phar/phar-io-version/LICENSE"/>
<copy todir="${basedir}/build/phar/phar-io-version">
<fileset dir="${basedir}/vendor/phar-io/version/src">
<include name="**/*.php" />
</fileset>
</copy>
@@ -292,9 +313,9 @@
</fileset>
</copy>
<copy file="${basedir}/vendor/myclabs/deep-copy/LICENSE" tofile="${basedir}/build/phar/myclabs-deep-copy/LICENSE"/>
<copy todir="${basedir}/build/phar/myclabs-deep-copy">
<fileset dir="${basedir}/vendor/myclabs/deep-copy/src">
<copy file="${basedir}/vendor/theseer/tokenizer/LICENSE" tofile="${basedir}/build/phar/theseer-tokenizer/LICENSE"/>
<copy todir="${basedir}/build/phar/theseer-tokenizer">
<fileset dir="${basedir}/vendor/theseer/tokenizer/src">
<include name="**/*.php" />
</fileset>
</copy>
@@ -305,27 +326,6 @@
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/phar-io/manifest/LICENSE" tofile="${basedir}/build/phar/phar-io-manifest/LICENSE"/>
<copy todir="${basedir}/build/phar/phar-io-manifest">
<fileset dir="${basedir}/vendor/phar-io/manifest/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/phar-io/version/LICENSE" tofile="${basedir}/build/phar/phar-io-version/LICENSE"/>
<copy todir="${basedir}/build/phar/phar-io-version">
<fileset dir="${basedir}/vendor/phar-io/version/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy file="${basedir}/vendor/theseer/tokenizer/LICENSE" tofile="${basedir}/build/phar/theseer-tokenizer/LICENSE"/>
<copy todir="${basedir}/build/phar/theseer-tokenizer">
<fileset dir="${basedir}/vendor/theseer/tokenizer/src">
<include name="**/*.php" />
</fileset>
</copy>
</target>
<target name="-phar-build" depends="-phar-determine-version">
@@ -341,7 +341,7 @@
<arg value="${type}"/>
</exec>
<exec executable="${basedir}/build/tools/phpab" taskname="phpab" failonerror="true">
<exec executable="${basedir}/tools/phpab" taskname="phpab" failonerror="true">
<arg value="--all" />
<arg value="--static" />
<arg value="--once" />
@@ -358,7 +358,7 @@
<copy file="${basedir}/build/binary-phar-autoload.php.in" tofile="${basedir}/build/binary-phar-autoload.php"/>
<replace file="${basedir}/build/binary-phar-autoload.php" token="X.Y.Z" value="${_version}"/>
<exec executable="${basedir}/build/tools/phpab" taskname="phpab" failonerror="true">
<exec executable="${basedir}/tools/phpab" taskname="phpab" failonerror="true">
<arg value="--all" />
<arg value="--nolower" />
<arg value="--static" />
@@ -383,7 +383,7 @@
</target>
<target name="generate-project-documentation" depends="-phploc,-checkstyle,-phpunit">
<exec executable="${basedir}/build/tools/phpdox" dir="${basedir}/build" taskname="phpdox"/>
<exec executable="${basedir}/tools/phpdox" dir="${basedir}/build" taskname="phpdox"/>
</target>
<target name="update-tools">
@@ -392,13 +392,13 @@
<arg value="update"/>
</exec>
<exec executable="${basedir}/build/tools/composer">
<exec executable="${basedir}/tools/composer">
<arg value="self-update"/>
</exec>
</target>
<target name="-phploc" depends="prepare">
<exec executable="${basedir}/build/tools/phploc" output="/dev/null" taskname="phploc">
<exec executable="${basedir}/tools/phploc" output="/dev/null" taskname="phploc">
<arg value="--count-tests"/>
<arg value="--log-xml"/>
<arg path="${basedir}/build/logfiles/phploc.xml"/>
@@ -408,7 +408,7 @@
</target>
<target name="-checkstyle" depends="prepare">
<exec executable="${basedir}/build/tools/php-cs-fixer" output="${basedir}/build/logfiles/checkstyle.xml" error="/dev/null" taskname="php-cs-fixer">
<exec executable="${basedir}/tools/php-cs-fixer" output="${basedir}/build/logfiles/checkstyle.xml" error="/dev/null" taskname="php-cs-fixer">
<arg value="--diff"/>
<arg value="--dry-run"/>
<arg value="fix"/>

View File

@@ -35,7 +35,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",
"phpunit/php-timer": "^2.1",
"sebastian/comparator": "^3.0",
"sebastian/diff": "^3.0",
"sebastian/environment": "^4.0",
@@ -84,7 +84,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "7.4-dev"
"dev-master": "7.5-dev"
}
}
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpab" version="^1.24.1" installed="1.25.1" location="./build/tools/phpab" copy="true"/>
<phar name="php-cs-fixer" version="^2.12.0" installed="2.13.1" location="./build/tools/php-cs-fixer" copy="true"/>
<phar name="phpdox" version="^0.11.2" installed="0.11.2" location="./build/tools/phpdox" copy="true"/>
<phar name="phploc" version="^4.0.1" installed="4.0.1" location="./build/tools/phploc" copy="true"/>
<phar name="phpab" version="^1.25" installed="1.25.8" location="./tools/phpab" copy="true"/>
<phar name="php-cs-fixer" version="^2.16" installed="2.16.1" location="./tools/php-cs-fixer" copy="true"/>
<phar name="phpdox" version="^0.11" installed="0.12.0" location="./tools/phpdox" copy="true"/>
<phar name="phploc" version="^4.0" installed="4.0.1" location="./tools/phploc" copy="true"/>
</phive>

View File

@@ -13,7 +13,7 @@ if (version_compare('7.1.0', PHP_VERSION, '>')) {
fwrite(
STDERR,
sprintf(
'This version of PHPUnit is supported on PHP 7.1 and PHP 7.2.' . PHP_EOL .
'This version of PHPUnit is supported on PHP 7.1, PHP 7.2, and PHP 7.3.' . PHP_EOL .
'You are using PHP %s (%s).' . PHP_EOL,
PHP_VERSION,
PHP_BINARY

View File

@@ -3,6 +3,7 @@
xsi:noNamespaceSchemaLocation="phpunit.xsd"
bootstrap="tests/bootstrap.php"
cacheResult="true"
colors="true"
verbose="true">
<testsuites>
<testsuite name="unit">
@@ -11,6 +12,7 @@
<testsuite name="end-to-end">
<directory suffix=".phpt">tests/end-to-end</directory>
<exclude>tests/end-to-end/_files</exclude>
</testsuite>
</testsuites>

View File

@@ -2,7 +2,7 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:documentation source="https://phpunit.de/documentation.html">
This Schema file defines the rules by which the XML configuration file of PHPUnit 7.4 may be structured.
This Schema file defines the rules by which the XML configuration file of PHPUnit 7.5 may be structured.
</xs:documentation>
<xs:appinfo source="https://phpunit.de/documentation.html"/>
</xs:annotation>
@@ -233,7 +233,7 @@
<xs:attribute name="bootstrap" type="xs:anyURI"/>
<xs:attribute name="cacheResult" type="xs:boolean" default="false"/>
<xs:attribute name="cacheResultFile" type="xs:anyURI"/>
<xs:attribute name="cacheTokens" type="xs:boolean"/>
<xs:attribute name="cacheTokens" type="xs:boolean" default="false"/>
<xs:attribute name="colors" type="xs:boolean" default="false"/>
<xs:attribute name="columns" type="columnsType" default="80"/>
<xs:attribute name="convertDeprecationsToExceptions" type="xs:boolean" default="true"/>

View File

@@ -12,6 +12,6 @@ namespace PHPUnit;
/**
* Marker interface for PHPUnit exceptions.
*/
interface Exception
interface Exception extends \Throwable
{
}

View File

@@ -110,6 +110,8 @@ abstract class Assert
*
* @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
{
@@ -209,6 +211,8 @@ abstract class Assert
*
* @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
{
@@ -271,6 +275,8 @@ abstract class Assert
*
* @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
{
@@ -333,6 +339,8 @@ abstract class Assert
*
* @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
{
@@ -378,6 +386,8 @@ abstract class Assert
*
* @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
{
@@ -418,6 +428,8 @@ abstract class Assert
*
* @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
{
@@ -457,6 +469,8 @@ abstract class Assert
*
* @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
{
@@ -486,6 +500,60 @@ abstract class Assert
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.
*
@@ -493,6 +561,8 @@ abstract class Assert
*
* @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
{
@@ -533,6 +603,66 @@ abstract class Assert
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.
*
@@ -540,6 +670,8 @@ abstract class Assert
*
* @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
{
@@ -573,6 +705,8 @@ abstract class Assert
*
* @throws ExpectationFailedException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338
*/
public static function assertAttributeEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void
{
@@ -601,6 +735,8 @@ abstract class Assert
*
* @throws ExpectationFailedException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338
*/
public static function assertAttributeNotEmpty(string $haystackAttributeName, $haystackClassOrObject, string $message = ''): void
{
@@ -628,6 +764,8 @@ abstract class Assert
*
* @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
{
@@ -660,6 +798,8 @@ abstract class Assert
*
* @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
{
@@ -688,6 +828,8 @@ abstract class Assert
*
* @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
{
@@ -716,6 +858,8 @@ abstract class Assert
*
* @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
{
@@ -1108,7 +1252,7 @@ abstract class Assert
*/
public static function assertClassHasAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1127,7 +1271,7 @@ abstract class Assert
*/
public static function assertClassNotHasAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1152,7 +1296,7 @@ abstract class Assert
*/
public static function assertClassHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1175,7 +1319,7 @@ abstract class Assert
*/
public static function assertClassNotHasStaticAttribute(string $attributeName, string $className, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1202,7 +1346,7 @@ abstract class Assert
*/
public static function assertObjectHasAttribute(string $attributeName, $object, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidObjectAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1227,7 +1371,7 @@ abstract class Assert
*/
public static function assertObjectNotHasAttribute(string $attributeName, $object, string $message = ''): void
{
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidObjectAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(1, 'valid attribute name');
}
@@ -1269,6 +1413,8 @@ abstract class Assert
*
* @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
{
@@ -1310,6 +1456,8 @@ abstract class Assert
*
* @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
{
@@ -1346,6 +1494,8 @@ abstract class Assert
*
* @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
{
@@ -1384,6 +1534,8 @@ abstract class Assert
*
* @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
{
@@ -1399,6 +1551,8 @@ abstract class Assert
*
* @throws ExpectationFailedException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3369
*/
public static function assertInternalType(string $expected, $actual, string $message = ''): void
{
@@ -1416,6 +1570,8 @@ abstract class Assert
*
* @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
{
@@ -1426,11 +1582,145 @@ abstract class Assert
);
}
/**
* 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
{
@@ -1443,6 +1733,138 @@ abstract class Assert
);
}
/**
* 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.
*
@@ -1450,6 +1872,8 @@ abstract class Assert
*
* @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
{
@@ -1643,6 +2067,34 @@ abstract class Assert
);
}
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.
*
@@ -2077,6 +2529,9 @@ abstract class Assert
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);
@@ -2110,6 +2565,9 @@ abstract class Assert
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(
@@ -2254,10 +2712,12 @@ abstract class Assert
* @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)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(2, 'valid attribute name');
}
@@ -2294,6 +2754,8 @@ abstract class Assert
*
* @throws Exception
* @throws ReflectionException
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338
*/
public static function getStaticAttribute(string $className, string $attributeName)
{
@@ -2301,7 +2763,7 @@ abstract class Assert
throw InvalidArgumentHelper::factory(1, 'class name');
}
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(2, 'valid attribute name');
}
@@ -2332,6 +2794,8 @@ abstract class Assert
* @param object $object
*
* @throws Exception
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3338
*/
public static function getObjectAttribute($object, string $attributeName)
{
@@ -2339,7 +2803,7 @@ abstract class Assert
throw InvalidArgumentHelper::factory(1, 'object');
}
if (!self::isValidAttributeName($attributeName)) {
if (!self::isValidClassAttributeName($attributeName)) {
throw InvalidArgumentHelper::factory(2, 'valid attribute name');
}
@@ -2409,8 +2873,24 @@ abstract class Assert
self::$count = 0;
}
private static function isValidAttributeName(string $attributeName): bool
private static function isValidObjectAttributeName(string $attributeName): bool
{
return \preg_match('/[^\x00-\x1f\x7f-\x9f]+/', $attributeName);
}
private static function isValidClassAttributeName(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;
}
}
}
}

View File

@@ -84,6 +84,8 @@ function assertArrayHasKey($key, $array, string $message = ''): void
*
* @throws ExpectationFailedException
* @throws \SebastianBergmann\RecursionContext\InvalidArgumentException
*
* @deprecated https://github.com/sebastianbergmann/phpunit/issues/3494
*/
function assertArraySubset($subset, $array, bool $checkForObjectIdentity = false, string $message = ''): void
{

View File

@@ -17,6 +17,8 @@ use SebastianBergmann\Comparator\ComparisonFailure;
*
* 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
{

View File

@@ -55,6 +55,10 @@ class Count extends Constraint
return \count($other);
}
if ($other instanceof \EmptyIterator) {
return 0;
}
if ($other instanceof Traversable) {
while ($other instanceof IteratorAggregate) {
$other = $other->getIterator();

View File

@@ -32,6 +32,10 @@ class IsEmpty extends Constraint
*/
protected function matches($other): bool
{
if ($other instanceof \EmptyIterator) {
return true;
}
if ($other instanceof Countable) {
return \count($other) === 0;
}

View File

@@ -43,6 +43,6 @@ class StringEndsWith extends Constraint
*/
protected function matches($other): bool
{
return \substr($other, 0 - \strlen($this->suffix)) == $this->suffix;
return \substr($other, 0 - \strlen($this->suffix)) === $this->suffix;
}
}

View File

@@ -9,6 +9,8 @@
*/
namespace PHPUnit\Framework\Constraint;
use PHPUnit\Util\InvalidArgumentHelper;
/**
* Constraint that asserts that the string it is evaluated for begins with a
* given prefix.
@@ -24,6 +26,10 @@ class StringStartsWith extends Constraint
{
parent::__construct();
if (\strlen($prefix) === 0) {
throw InvalidArgumentHelper::factory(1, 'non-empty string');
}
$this->prefix = $prefix;
}

View File

@@ -76,6 +76,7 @@ class TraversableContains extends Constraint
return true;
}
/* @noinspection TypeUnsafeComparisonInspection */
if (!$this->checkForObjectIdentity && $element == $this->value) {
return true;
}
@@ -86,6 +87,7 @@ class TraversableContains extends Constraint
return true;
}
/* @noinspection TypeUnsafeComparisonInspection */
if (!$this->checkForNonObjectIdentity && $element == $this->value) {
return true;
}

View File

@@ -24,6 +24,10 @@ class DataProviderTestSuite extends TestSuite
$this->dependencies = $dependencies;
foreach ($this->tests as $test) {
if (!$test instanceof TestCase) {
continue;
}
$test->setDependencies($dependencies);
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
@@ -7,6 +7,11 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$globalString = 'Hello';
namespace PHPUnit\Framework;
require __DIR__ . '/../../../../bootstrap.php';
/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class InvalidParameterGroupException extends Exception
{
}

View File

@@ -162,7 +162,7 @@ class InvocationMocker implements MethodNameMatch
/**
* @return InvocationMocker
*/
public function willThrowException(\Exception $exception)
public function willThrowException(\Throwable $exception)
{
$stub = new Stub\Exception($exception);

View File

@@ -12,6 +12,6 @@ namespace PHPUnit\Framework\MockObject;
/**
* Interface for exceptions used by PHPUnit_MockObject.
*/
interface Exception
interface Exception extends \Throwable
{
}

View File

@@ -374,7 +374,14 @@ class Generator
]
);
return $this->getObject($classTemplate->render(), $className['className']);
return $this->getObject(
$classTemplate->render(),
$className['className'],
'',
$callOriginalConstructor,
$callAutoload,
$arguments
);
}
/**
@@ -458,18 +465,16 @@ class Generator
$methodsBuffer = '';
foreach ($_methods as $method) {
$nameStart = \strpos($method, ' ') + 1;
$nameEnd = \strpos($method, '(');
$name = \substr($method, $nameStart, $nameEnd - $nameStart);
\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(
$args = \explode(
',',
\substr(
$method,
$nameEnd + 1,
\strpos($method, ')') - $nameEnd - 1
)
\str_replace(')', '', \substr($method, $nameEnd + 1))
);
foreach (\range(0, \count($args) - 1) as $i) {
@@ -557,6 +562,27 @@ class Generator
return $methods;
}
/**
* @throws \ReflectionException
*
* @return \ReflectionMethod[]
*/
private function userDefinedInterfaceMethods(string $interfaceName): array
{
$interface = new ReflectionClass($interfaceName);
$methods = [];
foreach ($interface->getMethods() as $method) {
if (!$method->isUserDefined()) {
continue;
}
$methods[] = $method;
}
return $methods;
}
/**
* @param string $code
* @param string $className
@@ -576,9 +602,7 @@ class Generator
{
$this->evalClass($code, $className);
if ($callOriginalConstructor &&
\is_string($type) &&
!\interface_exists($type, $callAutoload)) {
if ($callOriginalConstructor) {
if (\count($arguments) === 0) {
$object = new $className;
} else {
@@ -730,16 +754,49 @@ class Generator
// @see https://github.com/sebastianbergmann/phpunit/issues/2995
if ($isInterface && $class->implementsInterface(\Throwable::class)) {
$actualClassName = \Exception::class;
$additionalInterfaces[] = $class->getName();
$isInterface = false;
try {
$class = new \ReflectionClass($actualClassName);
} catch (\ReflectionException $e) {
throw new RuntimeException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
foreach ($this->userDefinedInterfaceMethods($mockClassName['fullClassName']) as $method) {
$methodName = $method->getName();
if ($class->hasMethod($methodName)) {
try {
$classMethod = $class->getMethod($methodName);
} catch (\ReflectionException $e) {
throw new RuntimeException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
if (!$this->canMockMethod($classMethod)) {
continue;
}
}
$mockMethods->addMethods(
MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments)
);
}
$mockClassName = $this->generateClassName(
\Exception::class,
'',
$actualClassName,
$mockClassName['className'],
'Mock_'
);
$class = new ReflectionClass($mockClassName['fullClassName']);
}
// https://github.com/sebastianbergmann/phpunit-mock-objects/issues/103
@@ -772,7 +829,7 @@ class Generator
$cloneTemplate = $cloneTemplate->render();
}
if (\is_array($explicitMethods) && empty($explicitMethods) &&
if ($explicitMethods === [] &&
($isClass || $isInterface)) {
$mockMethods->addMethods(
...$this->mockClassMethods($mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments)

View File

@@ -12,11 +12,15 @@
}
}
$this->__phpunit_getInvocationMocker()->invoke(
new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation(
'{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
)
$__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);
}

View File

@@ -12,11 +12,15 @@
}
}
$this->__phpunit_getInvocationMocker()->invoke(
new \PHPUnit\Framework\MockObject\Invocation\ObjectInvocation(
'{class_name}', '{method_name}', $__phpunit_arguments, '{return_type}', $this, {clone_arguments}
)
$__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);
}

View File

@@ -70,6 +70,11 @@ class StaticInvocation implements Invocation, SelfDescribing
*/
private $isReturnTypeNullable = false;
/**
* @var bool
*/
private $proxiedCall = false;
/**
* @param string $className
* @param string $methodName
@@ -138,7 +143,7 @@ class StaticInvocation implements Invocation, SelfDescribing
*/
public function generateReturnValue()
{
if ($this->isReturnTypeNullable) {
if ($this->isReturnTypeNullable || $this->proxiedCall) {
return;
}
@@ -186,6 +191,11 @@ class StaticInvocation implements Invocation, SelfDescribing
}
}
public function setProxiedCall(): void
{
$this->proxiedCall = true;
}
public function toString(): string
{
$exporter = new Exporter;

View File

@@ -25,7 +25,7 @@ use PHPUnit\Framework\MockObject\Stub\MatcherCollection;
* Keeps track of all expectations and stubs as well as registering
* identifications for builders.
*/
class InvocationMocker implements MatcherCollection, Invokable, NamespaceMatch
class InvocationMocker implements Invokable, MatcherCollection, NamespaceMatch
{
/**
* @var MatcherInvocation[]

View File

@@ -12,6 +12,7 @@ namespace PHPUnit\Framework\MockObject\Matcher;
use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\IsEqual;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\InvalidParameterGroupException;
use PHPUnit\Framework\MockObject\Invocation as BaseInvocation;
/**
@@ -42,6 +43,16 @@ class ConsecutiveParameters extends StatelessInvocation
public function __construct(array $parameterGroups)
{
foreach ($parameterGroups as $index => $parameters) {
if (!\is_iterable($parameters)) {
throw new InvalidParameterGroupException(
\sprintf(
'Parameter group #%d must be an array or Traversable, got %s',
$index,
\gettype($parameters)
)
);
}
foreach ($parameters as $parameter) {
if (!$parameter instanceof Constraint) {
$parameter = new IsEqual($parameter);

View File

@@ -102,7 +102,7 @@ final class MockMethod
}
if ($method->hasReturnType()) {
$returnType = (string) $method->getReturnType();
$returnType = $method->getReturnType()->getName();
} else {
$returnType = '';
}
@@ -301,8 +301,8 @@ final class MockMethod
$nullable = '?';
}
if ($parameter->hasType() && (string) $parameter->getType() !== 'self') {
$typeDeclaration = $parameter->getType() . ' ';
if ($parameter->hasType() && $parameter->getType()->getName() !== 'self') {
$typeDeclaration = $parameter->getType()->getName() . ' ';
} else {
try {
$class = $parameter->getClass();
@@ -326,13 +326,14 @@ final class MockMethod
if (!$parameter->isVariadic()) {
if ($parameter->isDefaultValueAvailable()) {
$value = $parameter->getDefaultValueConstantName();
if ($value === null) {
try {
$value = \var_export($parameter->getDefaultValue(), true);
} elseif (!\defined($value)) {
$rootValue = \preg_replace('/^.*\\\\/', '', $value);
$value = \defined($rootValue) ? $rootValue : $value;
} catch (\ReflectionException $e) {
throw new RuntimeException(
$e->getMessage(),
(int) $e->getCode(),
$e
);
}
$default = ' = ' . $value;

View File

@@ -17,6 +17,8 @@ use PHPUnit\Framework\MockObject\Matcher\Invocation;
* MockBuilder.
*
* @method InvocationMocker method($constraint)
*
* @deprecated Use PHPUnit\Framework\MockObject\MockObject instead
*/
interface PHPUnit_Framework_MockObject_MockObject /*extends Verifiable*/
{

View File

@@ -53,7 +53,7 @@ use SebastianBergmann\ObjectEnumerator\Enumerator;
use Text_Template;
use Throwable;
abstract class TestCase extends Assert implements Test, SelfDescribing
abstract class TestCase extends Assert implements SelfDescribing, Test
{
private const LOCALE_CATEGORIES = [\LC_ALL, \LC_COLLATE, \LC_CTYPE, \LC_MONETARY, \LC_NUMERIC, \LC_TIME];
@@ -118,12 +118,12 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
private $expectedException;
/**
* @var string
* @var null|string
*/
private $expectedExceptionMessage;
/**
* @var string
* @var null|string
*/
private $expectedExceptionMessageRegExp;
@@ -569,12 +569,12 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
return $this->expectedExceptionCode;
}
public function getExpectedExceptionMessage(): string
public function getExpectedExceptionMessage(): ?string
{
return $this->expectedExceptionMessage;
}
public function getExpectedExceptionMessageRegExp(): string
public function getExpectedExceptionMessageRegExp(): ?string
{
return $this->expectedExceptionMessageRegExp;
}
@@ -916,6 +916,7 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
$this->unregisterCustomComparators();
$this->cleanupIniSettings();
$this->cleanupLocaleSettings();
\libxml_clear_errors();
// Perform assertion on output.
if (!isset($e)) {
@@ -1123,6 +1124,11 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
return $this->data;
}
public function addWarning(string $warning): void
{
$this->warnings[] = $warning;
}
/**
* Override to run the test and assert its state.
*
@@ -1656,22 +1662,16 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
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());
} finally {
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;
}
}
}
@@ -1718,22 +1718,11 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
}
if (!isset($passedKeys[$dependency])) {
$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);
if (!\is_callable($dependency, false, $callableName) || $dependency !== $callableName) {
$this->markWarningForUncallableDependency($dependency);
} else {
$this->markSkippedForMissingDependecy($dependency);
}
return false;
}
@@ -1772,6 +1761,40 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
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.
*/
@@ -1987,13 +2010,7 @@ abstract class TestCase extends Assert implements Test, SelfDescribing
return true;
}
foreach ($enumerator->enumerate($this->testResult) as $object) {
if ($mock === $object) {
return false;
}
}
return true;
return !\in_array($mock, $enumerator->enumerate($this->testResult), true);
}
/**

View File

@@ -38,37 +38,37 @@ class TestResult implements Countable
protected $passed = [];
/**
* @var array
* @var TestFailure[]
*/
protected $errors = [];
/**
* @var array
* @var TestFailure[]
*/
protected $failures = [];
/**
* @var array
* @var TestFailure[]
*/
protected $warnings = [];
/**
* @var array
* @var TestFailure[]
*/
protected $notImplemented = [];
/**
* @var array
* @var TestFailure[]
*/
protected $risky = [];
/**
* @var array
* @var TestFailure[]
*/
protected $skipped = [];
/**
* @var array
* @var TestListener[]
*/
protected $listeners = [];
@@ -198,6 +198,12 @@ class TestResult implements Countable
{
$annotations = $test->getAnnotations();
// If there is a @coversNothing annotation on the test method then code
// coverage data does not need to be collected
if (isset($annotations['method']['coversNothing'])) {
return false;
}
// If any methods have covers, coverage must me generated
if (isset($annotations['method']['covers'])) {
return true;
@@ -461,7 +467,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the risky tests.
* Returns an array of TestFailure objects for the risky tests
*
* @return TestFailure[]
*/
public function risky(): array
{
@@ -469,7 +477,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the incomplete tests.
* Returns an array of TestFailure objects for the incomplete tests
*
* @return TestFailure[]
*/
public function notImplemented(): array
{
@@ -493,7 +503,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the skipped tests.
* Returns an array of TestFailure objects for the skipped tests
*
* @return TestFailure[]
*/
public function skipped(): array
{
@@ -509,7 +521,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the errors.
* Returns an array of TestFailure objects for the errors
*
* @return TestFailure[]
*/
public function errors(): array
{
@@ -525,7 +539,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the failures.
* Returns an array of TestFailure objects for the failures
*
* @return TestFailure[]
*/
public function failures(): array
{
@@ -541,7 +557,9 @@ class TestResult implements Countable
}
/**
* Returns an Enumeration for the warnings.
* Returns an array of TestFailure objects for the warnings
*
* @return TestFailure[]
*/
public function warnings(): array
{
@@ -845,13 +863,16 @@ class TestResult implements Countable
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()
)),
new RiskyTestError(
\sprintf(
"This test did not perform any assertions\n\n%s:%d",
$reflected->getFileName(),
$reflected->getStartLine()
)
),
$time
);
} elseif ($this->beStrictAboutTestsThatDoNotTestAnything &&
@@ -859,10 +880,12 @@ class TestResult implements Countable
$test->getNumAssertions() > 0) {
$this->addFailure(
$test,
new RiskyTestError(\sprintf(
'This test is annotated with "@doesNotPerformAssertions" but performed %d assertions',
$test->getNumAssertions()
)),
new RiskyTestError(
\sprintf(
'This test is annotated with "@doesNotPerformAssertions" but performed %d assertions',
$test->getNumAssertions()
)
),
$time
);
} elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) {
@@ -1068,7 +1091,12 @@ class TestResult implements Countable
*/
public function wasSuccessful(): bool
{
return empty($this->errors) && empty($this->failures) && empty($this->warnings);
return $this->wasSuccessfulIgnoringWarnings() && empty($this->warnings);
}
public function wasSuccessfulIgnoringWarnings(): bool
{
return empty($this->errors) && empty($this->failures);
}
/**

View File

@@ -23,7 +23,7 @@ use Throwable;
/**
* A TestSuite is a composite of Tests. It runs a collection of test cases.
*/
class TestSuite implements Test, SelfDescribing, IteratorAggregate
class TestSuite implements IteratorAggregate, SelfDescribing, Test
{
/**
* Enable or disable the backup and restoration of the $GLOBALS array.
@@ -61,7 +61,7 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
/**
* The tests in the test suite.
*
* @var TestCase[]
* @var Test[]
*/
protected $tests = [];
@@ -339,7 +339,7 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
$argumentsValid = true;
} elseif (\is_string($theClass) &&
$theClass !== '' &&
\class_exists($theClass, false)) {
\class_exists($theClass, true)) {
$argumentsValid = true;
if ($name == '') {
@@ -358,9 +358,9 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
}
if (!$theClass->isSubclassOf(TestCase::class)) {
throw new Exception(
'Class "' . $theClass->name . '" does not extend PHPUnit\Framework\TestCase.'
);
$this->setName($theClass);
return;
}
if ($name != '') {
@@ -703,13 +703,11 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
\call_user_func([$this->name, $beforeClassMethod]);
}
}
} catch (SkippedTestSuiteError $e) {
$numTests = \count($this);
for ($i = 0; $i < $numTests; $i++) {
$result->startTest($this);
$result->addFailure($this, $e, 0);
$result->endTest($this, 0);
} catch (SkippedTestSuiteError $error) {
foreach ($this->tests() as $test) {
$result->startTest($test);
$result->addFailure($test, $error, 0);
$result->endTest($test, 0);
}
$this->tearDown();
@@ -717,16 +715,14 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
return $result;
} catch (Throwable $t) {
$numTests = \count($this);
for ($i = 0; $i < $numTests; $i++) {
foreach ($this->tests() as $test) {
if ($result->shouldStop()) {
break;
}
$result->startTest($this);
$result->addError($this, $t, 0);
$result->endTest($this, 0);
$result->startTest($test);
$result->addError($test, $t, 0);
$result->endTest($test, 0);
}
$this->tearDown();
@@ -750,10 +746,25 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
$test->run($result);
}
foreach ($hookMethods['afterClass'] as $afterClassMethod) {
if ($this->testCase === true && \class_exists($this->name, false) && \method_exists($this->name, $afterClassMethod)) {
\call_user_func([$this->name, $afterClassMethod]);
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());
$placeholderTest = clone $test;
$placeholderTest->setName($afterClassMethod);
$result->startTest($placeholderTest);
$result->addFailure($placeholderTest, $error, 0);
$result->endTest($placeholderTest, 0);
}
$this->tearDown();
@@ -789,6 +800,8 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
/**
* Returns the tests as an enumeration.
*
* @return Test[]
*/
public function tests(): array
{
@@ -797,6 +810,8 @@ class TestSuite implements Test, SelfDescribing, IteratorAggregate
/**
* Set tests of the test suite
*
* @param Test[] $tests
*/
public function setTests(array $tests): void
{

View File

@@ -19,7 +19,7 @@ final class TestSuiteIterator implements RecursiveIterator
/**
* @var int
*/
private $position;
private $position = 0;
/**
* @var Test[]
@@ -58,7 +58,7 @@ final class TestSuiteIterator implements RecursiveIterator
/**
* Returns the current element.
*/
public function current(): Test
public function current(): ?Test
{
return $this->valid() ? $this->tests[$this->position] : null;
}
@@ -73,12 +73,22 @@ final class TestSuiteIterator implements RecursiveIterator
/**
* Returns the sub iterator for the current element.
*
* @throws \UnexpectedValueException if the current element is no TestSuite
*/
public function getChildren(): self
{
return new self(
$this->tests[$this->position]
);
if (!$this->hasChildren()) {
throw new UnexpectedValueException(
'The current item is no TestSuite instance and hence cannot have any children.',
1567849414
);
}
/** @var TestSuite $current */
$current = $this->current();
return new self($current);
}
/**
@@ -86,6 +96,6 @@ final class TestSuiteIterator implements RecursiveIterator
*/
public function hasChildren(): bool
{
return $this->tests[$this->position] instanceof TestSuite;
return $this->current() instanceof TestSuite;
}
}

View File

@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
@@ -7,5 +7,8 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework;
require __DIR__ . '/../../../../bootstrap.php';
final class UnexpectedValueException extends Exception
{
}

View File

@@ -21,22 +21,49 @@ use SebastianBergmann\FileIterator\Facade as FileIteratorFacade;
*/
abstract class BaseTestRunner
{
/**
* @var int
*/
public const STATUS_UNKNOWN = -1;
/**
* @var int
*/
public const STATUS_PASSED = 0;
/**
* @var int
*/
public const STATUS_SKIPPED = 1;
/**
* @var int
*/
public const STATUS_INCOMPLETE = 2;
/**
* @var int
*/
public const STATUS_FAILURE = 3;
/**
* @var int
*/
public const STATUS_ERROR = 4;
/**
* @var int
*/
public const STATUS_RISKY = 5;
/**
* @var int
*/
public const STATUS_WARNING = 6;
/**
* @var string
*/
public const SUITE_METHODNAME = 'suite';
/**
@@ -52,7 +79,7 @@ abstract class BaseTestRunner
* This is a template method, subclasses override
* the runFailed() and clearStatus() methods.
*
* @param array|string $suffixes
* @param string|string[] $suffixes
*
* @throws Exception
*/

View File

@@ -25,7 +25,7 @@ abstract class GroupFilterIterator extends RecursiveFilterIterator
parent::__construct($iterator);
foreach ($suite->getGroupDetails() as $group => $tests) {
if (\in_array($group, $groups, true)) {
if (\in_array((string) $group, $groups, true)) {
$testHashes = \array_map(
'spl_object_hash',
$tests

View File

@@ -0,0 +1,21 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\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;
}

View File

@@ -112,13 +112,17 @@ final class TestListenerAdapter implements TestListener
public function endTest(Test $test, float $time): void
{
if ($this->lastTestWasNotSuccessful === true) {
return;
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 AfterSuccessfulTestHook) {
$hook->executeAfterSuccessfulTest(TestUtil::describeAsString($test), $time);
if ($hook instanceof AfterTestHook) {
$hook->executeAfterTest(TestUtil::describeAsString($test), $time);
}
}
}

View File

@@ -24,7 +24,7 @@ use Throwable;
/**
* Runner for PHPT test cases.
*/
class PhptTestCase implements Test, SelfDescribing
class PhptTestCase implements SelfDescribing, Test
{
/**
* @var string[]
@@ -35,17 +35,17 @@ class PhptTestCase implements Test, SelfDescribing
'auto_prepend_file=',
'disable_functions=',
'display_errors=1',
'docref_root=',
'docref_ext=.html',
'docref_root=',
'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',
'output_handler=',
'report_memleaks=0',
'report_zend_debug=0',
'safe_mode=0',
@@ -62,6 +62,11 @@ class PhptTestCase implements Test, SelfDescribing
*/
private $phpUtil;
/**
* @var string
*/
private $output = '';
/**
* Constructs a test case with the given filename.
*
@@ -104,13 +109,21 @@ class PhptTestCase implements Test, SelfDescribing
*/
public function run(TestResult $result = null): TestResult
{
$sections = $this->parse();
$code = $this->render($sections['FILE']);
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);
@@ -155,15 +168,16 @@ class PhptTestCase implements Test, SelfDescribing
Timer::start();
$jobResult = $this->phpUtil->runJob($code, $this->stringifyIni($settings));
$time = Timer::stop();
$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']);
$this->assertPhptExpectation($sections, $this->output);
} catch (AssertionFailedError $e) {
$failure = $e;
@@ -202,6 +216,26 @@ class PhptTestCase implements Test, SelfDescribing
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.
*
@@ -332,20 +366,20 @@ class PhptTestCase implements Test, SelfDescribing
$section = '';
$unsupportedSections = [
'REDIRECTTEST',
'REQUEST',
'POST',
'PUT',
'POST_RAW',
'GZIP_POST',
'DEFLATE_POST',
'GET',
'COOKIE',
'HEADERS',
'CGI',
'COOKIE',
'DEFLATE_POST',
'EXPECTHEADERS',
'EXTENSIONS',
'GET',
'GZIP_POST',
'HEADERS',
'PHPDBG',
'POST',
'POST_RAW',
'PUT',
'REDIRECTTEST',
'REQUEST',
];
foreach (\file($this->filename) as $line) {
@@ -357,7 +391,7 @@ class PhptTestCase implements Test, SelfDescribing
}
if (empty($section)) {
throw new Exception('Invalid PHPT file');
throw new Exception('Invalid PHPT file: empty section header');
}
$sections[$section] .= $line;
@@ -377,7 +411,7 @@ class PhptTestCase implements Test, SelfDescribing
foreach ($unsupportedSections as $section) {
if (isset($sections[$section])) {
throw new Exception(
'PHPUnit does not support this PHPT file'
"PHPUnit does not support PHPT $section sections"
);
}
}
@@ -475,8 +509,8 @@ class PhptTestCase implements Test, SelfDescribing
private function getCoverageFiles(): array
{
$baseDir = \dirname(\realpath($this->filename)) . \DIRECTORY_SEPARATOR;
$basename = \basename($this->filename, 'phpt');
$baseDir = \dirname(\realpath($this->filename)) . \DIRECTORY_SEPARATOR;
$basename = \basename($this->filename, 'phpt');
return [
'coverage' => $baseDir . $basename . 'coverage',
@@ -507,7 +541,10 @@ class PhptTestCase implements Test, SelfDescribing
$globals = '';
if (!empty($GLOBALS['__PHPUNIT_BOOTSTRAP'])) {
$globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export($GLOBALS['__PHPUNIT_BOOTSTRAP'], true) . ";\n";
$globals = '$GLOBALS[\'__PHPUNIT_BOOTSTRAP\'] = ' . \var_export(
$GLOBALS['__PHPUNIT_BOOTSTRAP'],
true
) . ";\n";
}
$template->setVar(

View File

@@ -9,7 +9,7 @@
*/
namespace PHPUnit\Runner;
final class ResultCacheExtension implements AfterSuccessfulTestHook, AfterSkippedTestHook, AfterRiskyTestHook, AfterIncompleteTestHook, AfterTestErrorHook, AfterTestWarningHook, AfterTestFailureHook, AfterLastTestHook
final class ResultCacheExtension implements AfterIncompleteTestHook, AfterLastTestHook, AfterRiskyTestHook, AfterSkippedTestHook, AfterSuccessfulTestHook, AfterTestErrorHook, AfterTestFailureHook, AfterTestWarningHook
{
/**
* @var TestResultCacheInterface

View File

@@ -64,6 +64,35 @@ final class TestSuiteSorter
*/
private $cache;
/**
* @var array array<string> A list of normalized names of tests before reordering
*/
private $originalExecutionOrder = [];
/**
* @var array array<string> 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;
@@ -72,7 +101,7 @@ final class TestSuiteSorter
/**
* @throws Exception
*/
public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects): void
public function reorderTestsInSuite(Test $suite, int $order, bool $resolveDependencies, int $orderDefects, bool $isRootTestSuite = true): void
{
$allowedOrders = [
self::ORDER_DEFAULT,
@@ -98,9 +127,13 @@ final class TestSuiteSorter
);
}
if ($isRootTestSuite) {
$this->originalExecutionOrder = $this->calculateTestExecutionOrder($suite);
}
if ($suite instanceof TestSuite) {
foreach ($suite as $_suite) {
$this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects);
$this->reorderTestsInSuite($_suite, $order, $resolveDependencies, $orderDefects, false);
}
if ($orderDefects === self::ORDER_DEFECTS_FIRST) {
@@ -109,6 +142,20 @@ final class TestSuiteSorter
$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
@@ -130,7 +177,10 @@ final class TestSuiteSorter
}
if ($resolveDependencies && !($suite instanceof DataProviderTestSuite) && $this->suiteOnlyContainsTests($suite)) {
$suite->setTests($this->resolveDependencies($suite->tests()));
/** @var TestCase[] $tests */
$tests = $suite->tests();
$suite->setTests($this->resolveDependencies($tests));
}
}
@@ -139,7 +189,7 @@ final class TestSuiteSorter
$max = 0;
foreach ($suite->tests() as $test) {
$testname = $this->getNormalizedTestName($test);
$testname = self::getTestSorterUID($test);
if (!isset($this->defectSortOrder[$testname])) {
$this->defectSortOrder[$testname] = self::DEFECT_SORT_WEIGHT[$this->cache->getState($testname)];
@@ -205,8 +255,8 @@ final class TestSuiteSorter
*/
private function cmpDefectPriorityAndTime(Test $a, Test $b): int
{
$priorityA = $this->defectSortOrder[$this->getNormalizedTestName($a)] ?? 0;
$priorityB = $this->defectSortOrder[$this->getNormalizedTestName($b)] ?? 0;
$priorityA = $this->defectSortOrder[self::getTestSorterUID($a)] ?? 0;
$priorityB = $this->defectSortOrder[self::getTestSorterUID($b)] ?? 0;
if ($priorityB <=> $priorityA) {
// Sort defect weight descending
@@ -226,7 +276,7 @@ final class TestSuiteSorter
*/
private function cmpDuration(Test $a, Test $b): int
{
return $this->cache->getTime($this->getNormalizedTestName($a)) <=> $this->cache->getTime($this->getNormalizedTestName($b));
return $this->cache->getTime(self::getTestSorterUID($a)) <=> $this->cache->getTime(self::getTestSorterUID($b));
}
/**
@@ -252,7 +302,7 @@ final class TestSuiteSorter
do {
$todoNames = \array_map(
function ($test) {
return $this->getNormalizedTestName($test);
return self::getTestSorterUID($test);
},
$tests
);
@@ -268,28 +318,6 @@ final class TestSuiteSorter
return \array_merge($newTestOrder, $tests);
}
/**
* @param DataProviderTestSuite|TestCase $test
*
* @return string Full test name as "TestSuiteClassName::testMethodName"
*/
private function getNormalizedTestName($test): string
{
if ($test instanceof TestSuite && !($test instanceof DataProviderTestSuite)) {
return $test->getName();
}
if ($test instanceof PhptTestCase) {
return $test->getName();
}
if (\strpos($test->getName(), '::') !== false) {
return $test->getName(true);
}
return \get_class($test) . '::' . $test->getName(true);
}
/**
* @param DataProviderTestSuite|TestCase $test
*
@@ -312,4 +340,21 @@ final class TestSuiteSorter
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;
}
}

View File

@@ -30,7 +30,7 @@ class Version
}
if (self::$version === null) {
$version = new VersionId('7.4.5', \dirname(__DIR__, 2));
$version = new VersionId('7.5.20', \dirname(__DIR__, 2));
self::$version = $version->getVersion();
}

View File

@@ -778,7 +778,17 @@ class Command
}
if (isset($this->options[1][1])) {
$this->arguments['testFile'] = \realpath($this->options[1][1]);
$testFile = \realpath($this->options[1][1]);
if ($testFile === false) {
$this->exitWithErrorMessage(
\sprintf(
'Cannot open file "%s".',
$this->options[1][1]
)
);
}
$this->arguments['testFile'] = $testFile;
} else {
$this->arguments['testFile'] = '';
}

View File

@@ -36,9 +36,11 @@ 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;
@@ -186,12 +188,23 @@ class TestRunner extends BaseTestRunner
}
if ($arguments['cacheResult']) {
if (isset($arguments['cacheResultFile'])) {
$cache = new TestResultCache($arguments['cacheResultFile']);
} else {
$cache = new TestResultCache;
if (!isset($arguments['cacheResultFile'])) {
if ($arguments['configuration'] instanceof Configuration) {
$cacheLocation = $arguments['configuration']->getFilename();
} else {
$cacheLocation = $_SERVER['PHP_SELF'];
}
$arguments['cacheResultFile'] = null;
$cacheResultFile = \realpath($cacheLocation);
if ($cacheResultFile !== false) {
$arguments['cacheResultFile'] = \dirname($cacheResultFile);
}
}
$cache = new TestResultCache($arguments['cacheResultFile']);
$this->extensions[] = new ResultCacheExtension($cache);
}
@@ -203,6 +216,7 @@ class TestRunner extends BaseTestRunner
$sorter = new TestSuiteSorter($cache);
$sorter->reorderTestsInSuite($suite, $arguments['executionOrder'], $arguments['resolveDependencies'], $arguments['executionOrderDefects']);
$originalExecutionOrder = $sorter->getOriginalExecutionOrder();
unset($sorter);
}
@@ -309,6 +323,11 @@ class TestRunner extends BaseTestRunner
$arguments['columns'],
$arguments['reverseList']
);
if (isset($originalExecutionOrder) && ($this->printer instanceof CliTestDoxPrinter)) {
/* @var CliTestDoxPrinter */
$this->printer->setOriginalExecutionOrder($originalExecutionOrder);
}
}
}
@@ -330,13 +349,6 @@ class TestRunner extends BaseTestRunner
$this->writeMessage('Runtime', $runtime);
if ($arguments['executionOrder'] === TestSuiteSorter::ORDER_RANDOMIZED) {
$this->writeMessage(
'Random seed',
$arguments['randomOrderSeed']
);
}
if (isset($arguments['configuration'])) {
$this->writeMessage(
'Configuration',
@@ -359,6 +371,13 @@ class TestRunner extends BaseTestRunner
}
}
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');
}
@@ -470,6 +489,51 @@ class TestRunner extends BaseTestRunner
}
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
@@ -503,66 +567,14 @@ class TestRunner extends BaseTestRunner
$codeCoverage->setDisableIgnoredLines(true);
}
$whitelistFromConfigurationFile = false;
$whitelistFromOption = false;
if (!empty($filterConfiguration['whitelist'])) {
$codeCoverage->setAddUncoveredFilesFromWhitelist(
$filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist']
);
if (isset($arguments['whitelist'])) {
$this->codeCoverageFilter->addDirectoryToWhitelist($arguments['whitelist']);
$whitelistFromOption = true;
}
if (isset($arguments['configuration'])) {
$filterConfiguration = $arguments['configuration']->getFilterConfiguration();
if (!empty($filterConfiguration['whitelist'])) {
$whitelistFromConfigurationFile = true;
}
if (!empty($filterConfiguration['whitelist'])) {
$codeCoverage->setAddUncoveredFilesFromWhitelist(
$filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist']
);
$codeCoverage->setProcessUncoveredFilesFromWhitelist(
$filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist']
);
foreach ($filterConfiguration['whitelist']['include']['directory'] as $dir) {
$this->codeCoverageFilter->addDirectoryToWhitelist(
$dir['path'],
$dir['suffix'],
$dir['prefix']
);
}
foreach ($filterConfiguration['whitelist']['include']['file'] as $file) {
$this->codeCoverageFilter->addFileToWhitelist($file);
}
foreach ($filterConfiguration['whitelist']['exclude']['directory'] as $dir) {
$this->codeCoverageFilter->removeDirectoryFromWhitelist(
$dir['path'],
$dir['suffix'],
$dir['prefix']
);
}
foreach ($filterConfiguration['whitelist']['exclude']['file'] as $file) {
$this->codeCoverageFilter->removeFileFromWhitelist($file);
}
}
}
if (isset($arguments['xdebugFilterFile'], $filterConfiguration)) {
$filterScriptGenerator = new XdebugFilterScriptGenerator;
$script = $filterScriptGenerator->generate($filterConfiguration['whitelist']);
\file_put_contents($arguments['xdebugFilterFile'], $script);
$this->write("\n");
$this->write(\sprintf('Wrote Xdebug filter script to %s ' . \PHP_EOL, $arguments['xdebugFilterFile']));
exit(self::SUCCESS_EXIT);
$codeCoverage->setProcessUncoveredFilesFromWhitelist(
$filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist']
);
}
if (!$this->codeCoverageFilter->hasWhitelist()) {
@@ -578,6 +590,24 @@ class TestRunner extends BaseTestRunner
}
}
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)) {
@@ -755,7 +785,7 @@ class TestRunner extends BaseTestRunner
}
if ($exit) {
if ($result->wasSuccessful()) {
if ($result->wasSuccessfulIgnoringWarnings()) {
if ($arguments['failOnRisky'] && !$result->allHarmless()) {
exit(self::FAILURE_EXIT);
}

View File

@@ -12,13 +12,17 @@ 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 PHPUnit\Framework\MockObject\Generator;
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;
@@ -26,10 +30,14 @@ 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.
@@ -40,28 +48,89 @@ final class Blacklist
* @var array
*/
public static $blacklistedClassNames = [
FileIteratorFacade::class => 1,
Timer::class => 1,
PHP_Token::class => 1,
TestCase::class => 2,
'PHPUnit\DbUnit\TestCase' => 2,
Generator::class => 1,
Text_Template::class => 1,
'Symfony\Component\Yaml\Yaml' => 1,
CodeCoverage::class => 1,
Diff::class => 1,
Runtime::class => 1,
Comparator::class => 1,
Exporter::class => 1,
Snapshot::class => 1,
Invoker::class => 1,
Context::class => 1,
Version::class => 1,
ClassLoader::class => 1,
Instantiator::class => 1,
DocBlock::class => 1,
Prophet::class => 1,
DeepCopy::class => 1,
// 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,
];
/**

View File

@@ -27,4 +27,9 @@ final class Filesystem
$className
) . '.php';
}
public static function createDirectory(string $directory): bool
{
return !(!\is_dir($directory) && !@\mkdir($directory, 0777, true) && !\is_dir($directory));
}
}

View File

@@ -15,7 +15,6 @@ use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\ExceptionWrapper;
use PHPUnit\Framework\SelfDescribing;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestFailure;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestSuite;
@@ -46,7 +45,7 @@ class JUnit extends Printer implements TestListener
/**
* @var bool
*/
protected $reportUselessTests = false;
protected $reportRiskyTests = false;
/**
* @var bool
@@ -105,7 +104,7 @@ class JUnit extends Printer implements TestListener
*
* @throws \PHPUnit\Framework\Exception
*/
public function __construct($out = null, bool $reportUselessTests = false)
public function __construct($out = null, bool $reportRiskyTests = false)
{
$this->document = new DOMDocument('1.0', 'UTF-8');
$this->document->formatOutput = true;
@@ -115,7 +114,7 @@ class JUnit extends Printer implements TestListener
parent::__construct($out);
$this->reportUselessTests = $reportUselessTests;
$this->reportRiskyTests = $reportRiskyTests;
}
/**
@@ -176,7 +175,7 @@ class JUnit extends Printer implements TestListener
*/
public function addRiskyTest(Test $test, \Throwable $t, float $time): void
{
if (!$this->reportUselessTests || $this->currentTestCase === null) {
if (!$this->reportRiskyTests || $this->currentTestCase === null) {
return;
}
@@ -291,15 +290,17 @@ class JUnit extends Printer implements TestListener
*/
public function startTest(Test $test): void
{
if (!$test instanceof TestCase) {
return;
$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(!$test->usesDataProvider());
$methodName = $test->getName(!$usesDataprovider);
if ($class->hasMethod($methodName)) {
$method = $class->getMethod($methodName);
@@ -318,11 +319,12 @@ class JUnit extends Printer implements TestListener
*/
public function endTest(Test $test, float $time): void
{
if (!$test instanceof TestCase) {
return;
$numAssertions = 0;
if (\method_exists($test, 'getNumAssertions')) {
$numAssertions = $test->getNumAssertions();
}
$numAssertions = $test->getNumAssertions();
$this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;
$this->currentTestCase->setAttribute(
@@ -342,10 +344,16 @@ class JUnit extends Printer implements TestListener
$this->testSuiteTests[$this->testSuiteLevel]++;
$this->testSuiteTimes[$this->testSuiteLevel] += $time;
if ($test->hasOutput()) {
$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($test->getActualOutput())
Xml::prepareString($testOutput)
);
$this->currentTestCase->appendChild($systemOut);

View File

@@ -57,10 +57,6 @@ class TeamCity extends ResultPrinter
*/
public function addError(Test $test, \Throwable $t, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$this->printEvent(
'testFailed',
[
@@ -79,10 +75,6 @@ class TeamCity extends ResultPrinter
*/
public function addWarning(Test $test, Warning $e, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$this->printEvent(
'testFailed',
[
@@ -101,10 +93,6 @@ class TeamCity extends ResultPrinter
*/
public function addFailure(Test $test, AssertionFailedError $e, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$parameters = [
'name' => $test->getName(),
'message' => self::getMessage($e),
@@ -144,10 +132,6 @@ class TeamCity extends ResultPrinter
*/
public function addIncompleteTest(Test $test, \Throwable $t, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$this->printIgnoredTest($test->getName(), $t, $time);
}
@@ -158,10 +142,6 @@ class TeamCity extends ResultPrinter
*/
public function addRiskyTest(Test $test, \Throwable $t, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$this->addError($test, $t, $time);
}
@@ -172,10 +152,6 @@ class TeamCity extends ResultPrinter
*/
public function addSkippedTest(Test $test, \Throwable $t, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
$testName = $test->getName();
if ($this->startedTestName !== $testName) {
@@ -236,7 +212,7 @@ class TeamCity extends ResultPrinter
} else {
$split = \explode('::', $suiteName);
if (\count($split) === 2 && \method_exists($split[0], $split[1])) {
if (\count($split) === 2 && \class_exists($split[0]) && \method_exists($split[0], $split[1])) {
$fileName = self::getFileName($split[0]);
$parameters['locationHint'] = "php_qn://$fileName::\\$suiteName";
$parameters['name'] = $split[1];
@@ -262,7 +238,7 @@ class TeamCity extends ResultPrinter
if (!\class_exists($suiteName, false)) {
$split = \explode('::', $suiteName);
if (\count($split) === 2 && \method_exists($split[0], $split[1])) {
if (\count($split) === 2 && \class_exists($split[0]) && \method_exists($split[0], $split[1])) {
$parameters['name'] = $split[1];
}
}
@@ -277,10 +253,6 @@ class TeamCity extends ResultPrinter
*/
public function startTest(Test $test): void
{
if (!$test instanceof TestCase) {
return;
}
$testName = $test->getName();
$this->startedTestName = $testName;
$params = ['name' => $testName];
@@ -299,10 +271,6 @@ class TeamCity extends ResultPrinter
*/
public function endTest(Test $test, float $time): void
{
if (!$test instanceof TestCase) {
return;
}
parent::endTest($test, $time);
$this->printEvent(

View File

@@ -11,6 +11,7 @@ namespace PHPUnit\Util\PHP;
use __PHP_Incomplete_Class;
use ErrorException;
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\Exception;
use PHPUnit\Framework\SyntheticError;
use PHPUnit\Framework\Test;
@@ -248,6 +249,14 @@ abstract class AbstractPhpProcess
$childResult = \unserialize(\str_replace("#!/usr/bin/env php\n", '', $stdout));
\restore_error_handler();
if ($childResult === false) {
$result->addFailure(
$test,
new AssertionFailedError('Test was run in child process and ended unexpectedly'),
$time
);
}
} catch (ErrorException $e) {
\restore_error_handler();
$childResult = false;

View File

@@ -42,29 +42,33 @@ class Printer
*/
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 && !$this->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;
}
if ($out === null) {
return;
}
if (\is_string($out) === false) {
$this->out = $out;
return;
}
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;
}
/**
@@ -132,9 +136,4 @@ class Printer
{
$this->autoFlush = $autoFlush;
}
private function createDirectory(string $directory): bool
{
return !(!\is_dir($directory) && !@\mkdir($directory, 0777, true) && !\is_dir($directory));
}
}

View File

@@ -73,7 +73,7 @@ final class Test
/**
* @var string
*/
private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t -.|~^]+)[ \t]*\r?$/m';
private const REGEX_REQUIRES_VERSION_CONSTRAINT = '/@requires\s+(?P<name>PHP(?:Unit)?)\s+(?P<constraint>[\d\t \-.|~^]+)[ \t]*\r?$/m';
/**
* @var string
@@ -88,7 +88,7 @@ final class Test
/**
* @var string
*/
private const REGEX_REQUIRES = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^ ]+?))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m';
private const REGEX_REQUIRES = '/@requires\s+(?P<name>function|extension)\s+(?P<value>([^\s<>=!]+))\s*(?P<operator>[<>=!]{0,2})\s*(?P<version>[\d\.-]+[\d\.]?)?[ \t]*\r?$/m';
/**
* @var array
@@ -293,7 +293,7 @@ final class Test
foreach ($required['functions'] as $function) {
$pieces = \explode('::', $function);
if (\count($pieces) === 2 && \method_exists($pieces[0], $pieces[1])) {
if (\count($pieces) === 2 && \class_exists($pieces[0]) && \method_exists($pieces[0], $pieces[1])) {
continue;
}
@@ -414,7 +414,7 @@ final class Test
$data = self::getDataFromTestWithAnnotation($docComment);
}
if (\is_array($data) && empty($data)) {
if ($data === []) {
throw new SkippedTestError;
}
@@ -715,26 +715,30 @@ final class Test
continue;
}
if (self::isBeforeClassMethod($method)) {
\array_unshift(
self::$hookMethods[$className]['beforeClass'],
$method->getName()
);
}
if ($methodComment = $method->getDocComment()) {
if ($method->isStatic()) {
if (\strpos($methodComment, '@beforeClass') !== false) {
\array_unshift(
self::$hookMethods[$className]['beforeClass'],
$method->getName()
);
}
if (self::isBeforeMethod($method)) {
\array_unshift(
self::$hookMethods[$className]['before'],
$method->getName()
);
}
if (\strpos($methodComment, '@afterClass') !== false) {
self::$hookMethods[$className]['afterClass'][] = $method->getName();
}
}
if (self::isAfterMethod($method)) {
self::$hookMethods[$className]['after'][] = $method->getName();
}
if (\preg_match('/@before\b/', $methodComment) > 0) {
\array_unshift(
self::$hookMethods[$className]['before'],
$method->getName()
);
}
if (self::isAfterClassMethod($method)) {
self::$hookMethods[$className]['afterClass'][] = $method->getName();
if (\preg_match('/@after\b/', $methodComment) > 0) {
self::$hookMethods[$className]['after'][] = $method->getName();
}
}
}
} catch (ReflectionException $e) {
@@ -1085,26 +1089,6 @@ final class Test
return $result;
}
private static function isBeforeClassMethod(ReflectionMethod $method): bool
{
return $method->isStatic() && \strpos($method->getDocComment(), '@beforeClass') !== false;
}
private static function isBeforeMethod(ReflectionMethod $method): bool
{
return \preg_match('/@before\b/', $method->getDocComment()) > 0;
}
private static function isAfterClassMethod(ReflectionMethod $method): bool
{
return $method->isStatic() && \strpos($method->getDocComment(), '@afterClass') !== false;
}
private static function isAfterMethod(ReflectionMethod $method): bool
{
return \preg_match('/@after\b/', $method->getDocComment()) > 0;
}
/**
* Trims any extensions from version string that follows after
* the <major>.<minor>[.<patch>] format

View File

@@ -16,8 +16,8 @@ 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 PHPUnit\Util\TestDox\TestResult as TestDoxTestResult;
use SebastianBergmann\Timer\Timer;
/**
@@ -27,17 +27,7 @@ use SebastianBergmann\Timer\Timer;
class CliTestDoxPrinter extends ResultPrinter
{
/**
* @var TestDoxTestResult
*/
private $currentTestResult;
/**
* @var TestDoxTestResult
*/
private $previousTestResult;
/**
* @var TestDoxTestResult[]
* @var int[]
*/
private $nonSuccessfulTestResults = [];
@@ -46,42 +36,95 @@ class CliTestDoxPrinter extends ResultPrinter
*/
private $prettifier;
public function __construct($out = null, bool $verbose = false, $colors = self::COLOR_DEFAULT, bool $debug = false, $numberOfColumns = 80, bool $reverse = false)
{
/**
* @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<string>
*/
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;
}
$class = \get_class($test);
$this->lastTestFailed = false;
$this->lastClassName = $this->className;
$this->testResultMessage = '';
if ($test instanceof TestCase) {
$className = $this->prettifier->prettifyTestClass($class);
$className = $this->prettifier->prettifyTestClass(\get_class($test));
$testMethod = $this->prettifier->prettifyTestCase($test);
} elseif ($test instanceof TestSuite) {
$className = $test->getName();
$testMethod = \sprintf(
'Error bootstapping suite (most likely in %s::setUpBeforeClass)',
$test->getName()
);
} elseif ($test instanceof PhptTestCase) {
$className = $class;
$className = \get_class($test);
$testMethod = $test->getName();
}
$this->currentTestResult = new TestDoxTestResult(
function (string $color, string $buffer) {
return $this->formatWithColor($color, $buffer);
},
$className,
$testMethod
);
$this->className = $className;
$this->testMethod = $testMethod;
parent::startTest($test);
}
@@ -92,70 +135,120 @@ class CliTestDoxPrinter extends ResultPrinter
return;
}
parent::endTest($test, $time);
$this->currentTestResult->setRuntime($time);
$this->write($this->currentTestResult->toString($this->previousTestResult, $this->verbose));
$this->previousTestResult = $this->currentTestResult;
if (!$this->currentTestResult->isTestSuccessful()) {
$this->nonSuccessfulTestResults[] = $this->currentTestResult;
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->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-yellow', '✘'),
(string) $t
(string) $t,
$time,
true
);
}
public function addWarning(Test $test, Warning $e, float $time): void
{
$this->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-yellow', '✘'),
(string) $e
(string) $e,
$time,
true
);
}
public function addFailure(Test $test, AssertionFailedError $e, float $time): void
{
$this->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-red', '✘'),
(string) $e
(string) $e,
$time,
true
);
}
public function addIncompleteTest(Test $test, \Throwable $t, float $time): void
{
$this->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-yellow', '∅'),
(string) $t,
true
$time,
false
);
}
public function addRiskyTest(Test $test, \Throwable $t, float $time): void
{
$this->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-yellow', '☢'),
(string) $t,
true
$time,
false
);
}
public function addSkippedTest(Test $test, \Throwable $t, float $time): void
{
$this->currentTestResult->fail(
$this->lastTestFailed = true;
$this->testResultMessage = $this->formatTestResultMessage(
$this->formatWithColor('fg-yellow', '→'),
(string) $t,
true
$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
{
}
@@ -178,26 +271,159 @@ class CliTestDoxPrinter extends ResultPrinter
$this->write("\n" . Timer::resourceUsage() . "\n\n");
}
private function printNonSuccessfulTestsSummary(int $numberOfExecutedTests): void
private function flushOutputBuffer(): void
{
$numberOfNonSuccessfulTests = \count($this->nonSuccessfulTestResults);
if ($numberOfNonSuccessfulTests === 0) {
if ($this->testFlushIndex === $this->testIndex) {
return;
}
if (($numberOfNonSuccessfulTests / $numberOfExecutedTests) >= 0.7) {
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");
$previousTestResult = null;
$prevResult = $this->getEmptyTestResult();
foreach ($this->nonSuccessfulTestResults as $testResult) {
$this->write($testResult->toString($previousTestResult, $this->verbose));
$previousTestResult = $testResult;
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' => '',
];
}
}

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