20250203
This commit is contained in:
131
vendor/sebastian/comparator/src/ArrayComparator.php
vendored
Normal file
131
vendor/sebastian/comparator/src/ArrayComparator.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function array_key_exists;
|
||||
use function assert;
|
||||
use function is_array;
|
||||
use function sort;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function trim;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
/**
|
||||
* Arrays are equal if they contain the same key-value pairs.
|
||||
* The order of the keys does not matter.
|
||||
* The types of key-value pairs do not matter.
|
||||
*/
|
||||
class ArrayComparator extends Comparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return is_array($expected) && is_array($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $processed
|
||||
*
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
|
||||
{
|
||||
assert(is_array($expected));
|
||||
assert(is_array($actual));
|
||||
|
||||
if ($canonicalize) {
|
||||
sort($expected);
|
||||
sort($actual);
|
||||
}
|
||||
|
||||
$remaining = $actual;
|
||||
$actualAsString = "Array (\n";
|
||||
$expectedAsString = "Array (\n";
|
||||
$equal = true;
|
||||
$exporter = new Exporter;
|
||||
|
||||
foreach ($expected as $key => $value) {
|
||||
unset($remaining[$key]);
|
||||
|
||||
if (!array_key_exists($key, $actual)) {
|
||||
$expectedAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$exporter->shortenedExport($value),
|
||||
);
|
||||
|
||||
$equal = false;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$comparator = $this->factory()->getComparatorFor($value, $actual[$key]);
|
||||
|
||||
/** @phpstan-ignore arguments.count */
|
||||
$comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
|
||||
|
||||
$expectedAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$exporter->shortenedExport($value),
|
||||
);
|
||||
|
||||
$actualAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$exporter->shortenedExport($actual[$key]),
|
||||
);
|
||||
} catch (ComparisonFailure $e) {
|
||||
$expectedAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $exporter->shortenedExport($e->getExpected()),
|
||||
);
|
||||
|
||||
$actualAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$e->getActualAsString() ? $this->indent($e->getActualAsString()) : $exporter->shortenedExport($e->getActual()),
|
||||
);
|
||||
|
||||
$equal = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($remaining as $key => $value) {
|
||||
$actualAsString .= sprintf(
|
||||
" %s => %s\n",
|
||||
$exporter->export($key),
|
||||
$exporter->shortenedExport($value),
|
||||
);
|
||||
|
||||
$equal = false;
|
||||
}
|
||||
|
||||
$expectedAsString .= ')';
|
||||
$actualAsString .= ')';
|
||||
|
||||
if (!$equal) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$expectedAsString,
|
||||
$actualAsString,
|
||||
'Failed asserting that two arrays are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function indent(string $lines): string
|
||||
{
|
||||
return trim(str_replace("\n", "\n ", $lines));
|
||||
}
|
||||
}
|
32
vendor/sebastian/comparator/src/Comparator.php
vendored
Normal file
32
vendor/sebastian/comparator/src/Comparator.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
abstract class Comparator
|
||||
{
|
||||
private Factory $factory;
|
||||
|
||||
public function setFactory(Factory $factory): void
|
||||
{
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
abstract public function accepts(mixed $expected, mixed $actual): bool;
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
abstract public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void;
|
||||
|
||||
protected function factory(): Factory
|
||||
{
|
||||
return $this->factory;
|
||||
}
|
||||
}
|
68
vendor/sebastian/comparator/src/ComparisonFailure.php
vendored
Normal file
68
vendor/sebastian/comparator/src/ComparisonFailure.php
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use RuntimeException;
|
||||
use SebastianBergmann\Diff\Differ;
|
||||
use SebastianBergmann\Diff\Output\UnifiedDiffOutputBuilder;
|
||||
|
||||
final class ComparisonFailure extends RuntimeException
|
||||
{
|
||||
private mixed $expected;
|
||||
private mixed $actual;
|
||||
private string $expectedAsString;
|
||||
private string $actualAsString;
|
||||
|
||||
public function __construct(mixed $expected, mixed $actual, string $expectedAsString, string $actualAsString, string $message = '')
|
||||
{
|
||||
parent::__construct($message);
|
||||
|
||||
$this->expected = $expected;
|
||||
$this->actual = $actual;
|
||||
$this->expectedAsString = $expectedAsString;
|
||||
$this->actualAsString = $actualAsString;
|
||||
}
|
||||
|
||||
public function getActual(): mixed
|
||||
{
|
||||
return $this->actual;
|
||||
}
|
||||
|
||||
public function getExpected(): mixed
|
||||
{
|
||||
return $this->expected;
|
||||
}
|
||||
|
||||
public function getActualAsString(): string
|
||||
{
|
||||
return $this->actualAsString;
|
||||
}
|
||||
|
||||
public function getExpectedAsString(): string
|
||||
{
|
||||
return $this->expectedAsString;
|
||||
}
|
||||
|
||||
public function getDiff(): string
|
||||
{
|
||||
if (!$this->actualAsString && !$this->expectedAsString) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$differ = new Differ(new UnifiedDiffOutputBuilder("\n--- Expected\n+++ Actual\n"));
|
||||
|
||||
return $differ->diff($this->expectedAsString, $this->actualAsString);
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return $this->getMessage() . $this->getDiff();
|
||||
}
|
||||
}
|
98
vendor/sebastian/comparator/src/DOMNodeComparator.php
vendored
Normal file
98
vendor/sebastian/comparator/src/DOMNodeComparator.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use function mb_strtolower;
|
||||
use function sprintf;
|
||||
use DOMDocument;
|
||||
use DOMNode;
|
||||
use ValueError;
|
||||
|
||||
final class DOMNodeComparator extends ObjectComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return $expected instanceof DOMNode && $actual instanceof DOMNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $processed
|
||||
*
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
|
||||
{
|
||||
assert($expected instanceof DOMNode);
|
||||
assert($actual instanceof DOMNode);
|
||||
|
||||
$expectedAsString = $this->nodeToText($expected, true, $ignoreCase);
|
||||
$actualAsString = $this->nodeToText($actual, true, $ignoreCase);
|
||||
|
||||
if ($expectedAsString !== $actualAsString) {
|
||||
$type = $expected instanceof DOMDocument ? 'documents' : 'nodes';
|
||||
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$expectedAsString,
|
||||
$actualAsString,
|
||||
sprintf("Failed asserting that two DOM %s are equal.\n", $type),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized, whitespace-cleaned, and indented textual
|
||||
* representation of a DOMNode.
|
||||
*/
|
||||
private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string
|
||||
{
|
||||
if ($canonicalize) {
|
||||
$document = new DOMDocument;
|
||||
|
||||
try {
|
||||
$c14n = $node->C14N();
|
||||
|
||||
assert(!empty($c14n));
|
||||
|
||||
@$document->loadXML($c14n);
|
||||
} catch (ValueError) {
|
||||
}
|
||||
|
||||
$node = $document;
|
||||
}
|
||||
|
||||
if ($node instanceof DOMDocument) {
|
||||
$document = $node;
|
||||
} else {
|
||||
$document = $node->ownerDocument;
|
||||
}
|
||||
|
||||
assert($document instanceof DOMDocument);
|
||||
|
||||
$document->formatOutput = true;
|
||||
$document->normalizeDocument();
|
||||
|
||||
if ($node instanceof DOMDocument) {
|
||||
$text = $node->saveXML();
|
||||
} else {
|
||||
$text = $document->saveXML($node);
|
||||
}
|
||||
|
||||
assert($text !== false);
|
||||
|
||||
if ($ignoreCase) {
|
||||
return mb_strtolower($text, 'UTF-8');
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
64
vendor/sebastian/comparator/src/DateTimeComparator.php
vendored
Normal file
64
vendor/sebastian/comparator/src/DateTimeComparator.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function abs;
|
||||
use function assert;
|
||||
use function floor;
|
||||
use function sprintf;
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
|
||||
final class DateTimeComparator extends ObjectComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return ($expected instanceof DateTime || $expected instanceof DateTimeImmutable) &&
|
||||
($actual instanceof DateTime || $actual instanceof DateTimeImmutable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $processed
|
||||
*
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
|
||||
{
|
||||
assert($expected instanceof DateTime || $expected instanceof DateTimeImmutable);
|
||||
assert($actual instanceof DateTime || $actual instanceof DateTimeImmutable);
|
||||
|
||||
$absDelta = abs($delta);
|
||||
$delta = new DateInterval(sprintf('PT%dS', $absDelta));
|
||||
$delta->f = $absDelta - floor($absDelta);
|
||||
|
||||
$actualClone = (clone $actual)
|
||||
->setTimezone(new DateTimeZone('UTC'));
|
||||
|
||||
$expectedLower = (clone $expected)
|
||||
->setTimezone(new DateTimeZone('UTC'))
|
||||
->sub($delta);
|
||||
|
||||
$expectedUpper = (clone $expected)
|
||||
->setTimezone(new DateTimeZone('UTC'))
|
||||
->add($delta);
|
||||
|
||||
if ($actualClone < $expectedLower || $actualClone > $expectedUpper) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$expected->format('Y-m-d\TH:i:s.uO'),
|
||||
$actual->format('Y-m-d\TH:i:s.uO'),
|
||||
'Failed asserting that two DateTime objects are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
50
vendor/sebastian/comparator/src/EnumerationComparator.php
vendored
Normal file
50
vendor/sebastian/comparator/src/EnumerationComparator.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use function sprintf;
|
||||
use UnitEnum;
|
||||
|
||||
final class EnumerationComparator extends Comparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return $expected instanceof UnitEnum &&
|
||||
$actual instanceof UnitEnum &&
|
||||
$expected::class === $actual::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
assert($expected instanceof UnitEnum);
|
||||
assert($actual instanceof UnitEnum);
|
||||
|
||||
if ($expected === $actual) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
'',
|
||||
'',
|
||||
sprintf(
|
||||
'Failed asserting that two values of enumeration %s are equal, %s does not match expected %s.',
|
||||
$expected::class,
|
||||
$actual->name,
|
||||
$expected->name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
44
vendor/sebastian/comparator/src/ExceptionComparator.php
vendored
Normal file
44
vendor/sebastian/comparator/src/ExceptionComparator.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Compares Exception instances for equality.
|
||||
*/
|
||||
final class ExceptionComparator extends ObjectComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return $expected instanceof Exception && $actual instanceof Exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
protected function toArray(object $object): array
|
||||
{
|
||||
assert($object instanceof Exception);
|
||||
|
||||
$array = parent::toArray($object);
|
||||
|
||||
unset(
|
||||
$array['file'],
|
||||
$array['line'],
|
||||
$array['trace'],
|
||||
$array['string'],
|
||||
$array['xdebug_message'],
|
||||
);
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
123
vendor/sebastian/comparator/src/Factory.php
vendored
Normal file
123
vendor/sebastian/comparator/src/Factory.php
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use const PHP_VERSION;
|
||||
use function array_unshift;
|
||||
use function extension_loaded;
|
||||
use function version_compare;
|
||||
|
||||
final class Factory
|
||||
{
|
||||
private static ?Factory $instance = null;
|
||||
|
||||
/**
|
||||
* @var array<non-negative-int, Comparator>
|
||||
*/
|
||||
private array $customComparators = [];
|
||||
|
||||
/**
|
||||
* @var list<Comparator>
|
||||
*/
|
||||
private array $defaultComparators = [];
|
||||
|
||||
public static function getInstance(): self
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->registerDefaultComparators();
|
||||
}
|
||||
|
||||
public function getComparatorFor(mixed $expected, mixed $actual): Comparator
|
||||
{
|
||||
foreach ($this->customComparators as $comparator) {
|
||||
if ($comparator->accepts($expected, $actual)) {
|
||||
return $comparator;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->defaultComparators as $comparator) {
|
||||
if ($comparator->accepts($expected, $actual)) {
|
||||
return $comparator;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException('No suitable Comparator implementation found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new comparator.
|
||||
*
|
||||
* This comparator will be returned by getComparatorFor() if its accept() method
|
||||
* returns TRUE for the compared values. It has higher priority than the
|
||||
* existing comparators, meaning that its accept() method will be invoked
|
||||
* before those of the other comparators.
|
||||
*/
|
||||
public function register(Comparator $comparator): void
|
||||
{
|
||||
array_unshift($this->customComparators, $comparator);
|
||||
|
||||
$comparator->setFactory($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a comparator.
|
||||
*
|
||||
* This comparator will no longer be considered by getComparatorFor().
|
||||
*/
|
||||
public function unregister(Comparator $comparator): void
|
||||
{
|
||||
foreach ($this->customComparators as $key => $_comparator) {
|
||||
if ($comparator === $_comparator) {
|
||||
unset($this->customComparators[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->customComparators = [];
|
||||
}
|
||||
|
||||
private function registerDefaultComparators(): void
|
||||
{
|
||||
$this->registerDefaultComparator(new MockObjectComparator);
|
||||
$this->registerDefaultComparator(new DateTimeComparator);
|
||||
$this->registerDefaultComparator(new DOMNodeComparator);
|
||||
$this->registerDefaultComparator(new SplObjectStorageComparator);
|
||||
$this->registerDefaultComparator(new ExceptionComparator);
|
||||
$this->registerDefaultComparator(new EnumerationComparator);
|
||||
|
||||
if (extension_loaded('bcmath') && version_compare(PHP_VERSION, '8.4.0', '>=')) {
|
||||
$this->registerDefaultComparator(new NumberComparator);
|
||||
}
|
||||
|
||||
$this->registerDefaultComparator(new ObjectComparator);
|
||||
$this->registerDefaultComparator(new ResourceComparator);
|
||||
$this->registerDefaultComparator(new ArrayComparator);
|
||||
$this->registerDefaultComparator(new NumericComparator);
|
||||
$this->registerDefaultComparator(new ScalarComparator);
|
||||
$this->registerDefaultComparator(new TypeComparator);
|
||||
}
|
||||
|
||||
private function registerDefaultComparator(Comparator $comparator): void
|
||||
{
|
||||
$this->defaultComparators[] = $comparator;
|
||||
|
||||
$comparator->setFactory($this);
|
||||
}
|
||||
}
|
46
vendor/sebastian/comparator/src/MockObjectComparator.php
vendored
Normal file
46
vendor/sebastian/comparator/src/MockObjectComparator.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function array_keys;
|
||||
use function assert;
|
||||
use function str_starts_with;
|
||||
use PHPUnit\Framework\MockObject\Stub;
|
||||
|
||||
/**
|
||||
* Compares PHPUnit\Framework\MockObject\MockObject instances for equality.
|
||||
*/
|
||||
final class MockObjectComparator extends ObjectComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return $expected instanceof Stub && $actual instanceof Stub;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
protected function toArray(object $object): array
|
||||
{
|
||||
assert($object instanceof Stub);
|
||||
|
||||
$array = parent::toArray($object);
|
||||
|
||||
foreach (array_keys($array) as $key) {
|
||||
if (!str_starts_with($key, '__phpunit_')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($array[$key]);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
60
vendor/sebastian/comparator/src/NumberComparator.php
vendored
Normal file
60
vendor/sebastian/comparator/src/NumberComparator.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use function is_int;
|
||||
use function is_numeric;
|
||||
use function is_string;
|
||||
use function max;
|
||||
use function number_format;
|
||||
use BcMath\Number;
|
||||
|
||||
final class NumberComparator extends ObjectComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return ($expected instanceof Number || $actual instanceof Number) &&
|
||||
($expected instanceof Number || is_int($expected) || is_string($expected) && is_numeric($expected)) &&
|
||||
($actual instanceof Number || is_int($actual) || is_string($actual) && is_numeric($actual));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $processed
|
||||
*
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
|
||||
{
|
||||
if (!$expected instanceof Number) {
|
||||
assert(is_string($expected) || is_int($expected));
|
||||
|
||||
$expected = new Number($expected);
|
||||
}
|
||||
|
||||
if (!$actual instanceof Number) {
|
||||
assert(is_string($actual) || is_int($actual));
|
||||
|
||||
$actual = new Number($actual);
|
||||
}
|
||||
|
||||
$deltaNumber = new Number(number_format($delta, max($expected->scale, $actual->scale)));
|
||||
|
||||
if ($actual < $expected - $deltaNumber || $actual > $expected + $deltaNumber) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
(string) $expected,
|
||||
(string) $actual,
|
||||
'Failed asserting that two Number objects are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
71
vendor/sebastian/comparator/src/NumericComparator.php
vendored
Normal file
71
vendor/sebastian/comparator/src/NumericComparator.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function abs;
|
||||
use function assert;
|
||||
use function is_float;
|
||||
use function is_infinite;
|
||||
use function is_nan;
|
||||
use function is_numeric;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
final class NumericComparator extends ScalarComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
// all numerical values, but not if both of them are strings
|
||||
return is_numeric($expected) && is_numeric($actual) &&
|
||||
!(is_string($expected) && is_string($actual));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
assert(is_numeric($expected));
|
||||
assert(is_numeric($actual));
|
||||
|
||||
if ($this->isInfinite($actual) && $this->isInfinite($expected)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (($this->isInfinite($actual) xor $this->isInfinite($expected)) ||
|
||||
($this->isNan($actual) || $this->isNan($expected)) ||
|
||||
abs($actual - $expected) > $delta) {
|
||||
$exporter = new Exporter;
|
||||
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
'',
|
||||
'',
|
||||
sprintf(
|
||||
'Failed asserting that %s matches expected %s.',
|
||||
$exporter->export($actual),
|
||||
$exporter->export($expected),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function isInfinite(mixed $value): bool
|
||||
{
|
||||
return is_float($value) && is_infinite($value);
|
||||
}
|
||||
|
||||
private function isNan(mixed $value): bool
|
||||
{
|
||||
return is_float($value) && is_nan($value);
|
||||
}
|
||||
}
|
93
vendor/sebastian/comparator/src/ObjectComparator.php
vendored
Normal file
93
vendor/sebastian/comparator/src/ObjectComparator.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use function in_array;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
use function substr_replace;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
class ObjectComparator extends ArrayComparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return is_object($expected) && is_object($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $processed
|
||||
*
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
|
||||
{
|
||||
assert(is_object($expected));
|
||||
assert(is_object($actual));
|
||||
|
||||
if ($actual::class !== $expected::class) {
|
||||
$exporter = new Exporter;
|
||||
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$exporter->export($expected),
|
||||
$exporter->export($actual),
|
||||
sprintf(
|
||||
'%s is not instance of expected class "%s".',
|
||||
$exporter->export($actual),
|
||||
$expected::class,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// don't compare twice to allow for cyclic dependencies
|
||||
if (in_array([$actual, $expected], $processed, true) ||
|
||||
in_array([$expected, $actual], $processed, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$processed[] = [$actual, $expected];
|
||||
|
||||
// don't compare objects if they are identical
|
||||
// this helps to avoid the error "maximum function nesting level reached"
|
||||
// CAUTION: this conditional clause is not tested
|
||||
if ($actual !== $expected) {
|
||||
try {
|
||||
parent::assertEquals(
|
||||
$this->toArray($expected),
|
||||
$this->toArray($actual),
|
||||
$delta,
|
||||
$canonicalize,
|
||||
$ignoreCase,
|
||||
$processed,
|
||||
);
|
||||
} catch (ComparisonFailure $e) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
// replace "Array" with "MyClass object"
|
||||
substr_replace($e->getExpectedAsString(), $expected::class . ' Object', 0, 5),
|
||||
substr_replace($e->getActualAsString(), $actual::class . ' Object', 0, 5),
|
||||
'Failed asserting that two objects are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
protected function toArray(object $object): array
|
||||
{
|
||||
return (new Exporter)->toArray($object);
|
||||
}
|
||||
}
|
42
vendor/sebastian/comparator/src/ResourceComparator.php
vendored
Normal file
42
vendor/sebastian/comparator/src/ResourceComparator.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use function is_resource;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
final class ResourceComparator extends Comparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return is_resource($expected) && is_resource($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
assert(is_resource($expected));
|
||||
assert(is_resource($actual));
|
||||
|
||||
$exporter = new Exporter;
|
||||
|
||||
if ($actual != $expected) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$exporter->export($expected),
|
||||
$exporter->export($actual),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
158
vendor/sebastian/comparator/src/ScalarComparator.php
vendored
Normal file
158
vendor/sebastian/comparator/src/ScalarComparator.php
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function is_bool;
|
||||
use function is_object;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function mb_strtolower;
|
||||
use function method_exists;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
/**
|
||||
* Compares scalar or NULL values for equality.
|
||||
*/
|
||||
class ScalarComparator extends Comparator
|
||||
{
|
||||
private const int OVERLONG_THRESHOLD = 40;
|
||||
private const int KEEP_CONTEXT_CHARS = 25;
|
||||
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return ((is_scalar($expected) xor null === $expected) &&
|
||||
(is_scalar($actual) xor null === $actual)) ||
|
||||
// allow comparison between strings and objects featuring __toString()
|
||||
(is_string($expected) && is_object($actual) && method_exists($actual, '__toString')) ||
|
||||
(is_object($expected) && method_exists($expected, '__toString') && is_string($actual));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
$expectedToCompare = $expected;
|
||||
$actualToCompare = $actual;
|
||||
$exporter = new Exporter;
|
||||
|
||||
// always compare as strings to avoid strange behaviour
|
||||
// otherwise 0 == 'Foobar'
|
||||
if ((is_string($expected) && !is_bool($actual)) || (is_string($actual) && !is_bool($expected))) {
|
||||
/** @phpstan-ignore cast.string */
|
||||
$expectedToCompare = (string) $expectedToCompare;
|
||||
|
||||
/** @phpstan-ignore cast.string */
|
||||
$actualToCompare = (string) $actualToCompare;
|
||||
|
||||
if ($ignoreCase) {
|
||||
$expectedToCompare = mb_strtolower($expectedToCompare, 'UTF-8');
|
||||
$actualToCompare = mb_strtolower($actualToCompare, 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
if ($expectedToCompare !== $actualToCompare && is_string($expected) && is_string($actual)) {
|
||||
[$cutExpected, $cutActual] = self::removeOverlongCommonPrefix($expected, $actual);
|
||||
[$cutExpected, $cutActual] = self::removeOverlongCommonSuffix($cutExpected, $cutActual);
|
||||
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$exporter->export($cutExpected),
|
||||
$exporter->export($cutActual),
|
||||
'Failed asserting that two strings are equal.',
|
||||
);
|
||||
}
|
||||
|
||||
if ($expectedToCompare != $actualToCompare) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
// no diff is required
|
||||
'',
|
||||
'',
|
||||
sprintf(
|
||||
'Failed asserting that %s matches expected %s.',
|
||||
$exporter->export($actual),
|
||||
$exporter->export($expected),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, string}
|
||||
*/
|
||||
private static function removeOverlongCommonPrefix(string $string1, string $string2): array
|
||||
{
|
||||
$commonPrefix = self::findCommonPrefix($string1, $string2);
|
||||
|
||||
if (strlen($commonPrefix) > self::OVERLONG_THRESHOLD) {
|
||||
$string1 = '...' . substr($string1, strlen($commonPrefix) - self::KEEP_CONTEXT_CHARS);
|
||||
$string2 = '...' . substr($string2, strlen($commonPrefix) - self::KEEP_CONTEXT_CHARS);
|
||||
}
|
||||
|
||||
return [$string1, $string2];
|
||||
}
|
||||
|
||||
private static function findCommonPrefix(string $string1, string $string2): string
|
||||
{
|
||||
for ($i = 0; $i < strlen($string1); $i++) {
|
||||
if (!isset($string2[$i]) || $string1[$i] != $string2[$i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return substr($string1, 0, $i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{string, string}
|
||||
*/
|
||||
private static function removeOverlongCommonSuffix(string $string1, string $string2): array
|
||||
{
|
||||
$commonSuffix = self::findCommonSuffix($string1, $string2);
|
||||
|
||||
if (strlen($commonSuffix) > self::OVERLONG_THRESHOLD) {
|
||||
$string1 = substr($string1, 0, -(strlen($commonSuffix) - self::KEEP_CONTEXT_CHARS)) . '...';
|
||||
$string2 = substr($string2, 0, -(strlen($commonSuffix) - self::KEEP_CONTEXT_CHARS)) . '...';
|
||||
}
|
||||
|
||||
return [$string1, $string2];
|
||||
}
|
||||
|
||||
private static function findCommonSuffix(string $string1, string $string2): string
|
||||
{
|
||||
if ($string1 === '' || $string2 === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$lastCharIndex1 = strlen($string1) - 1;
|
||||
$lastCharIndex2 = strlen($string2) - 1;
|
||||
|
||||
if ($string1[$lastCharIndex1] != $string2[$lastCharIndex2]) {
|
||||
return '';
|
||||
}
|
||||
|
||||
while (
|
||||
$lastCharIndex1 > 0 &&
|
||||
$lastCharIndex2 > 0 &&
|
||||
$string1[$lastCharIndex1] == $string2[$lastCharIndex2]
|
||||
) {
|
||||
$lastCharIndex1--;
|
||||
$lastCharIndex2--;
|
||||
}
|
||||
|
||||
return substr($string1, $lastCharIndex1 - strlen($string1) + 1);
|
||||
}
|
||||
}
|
57
vendor/sebastian/comparator/src/SplObjectStorageComparator.php
vendored
Normal file
57
vendor/sebastian/comparator/src/SplObjectStorageComparator.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function assert;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
use SplObjectStorage;
|
||||
|
||||
final class SplObjectStorageComparator extends Comparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return $expected instanceof SplObjectStorage && $actual instanceof SplObjectStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
assert($expected instanceof SplObjectStorage);
|
||||
assert($actual instanceof SplObjectStorage);
|
||||
|
||||
$exporter = new Exporter;
|
||||
|
||||
foreach ($actual as $object) {
|
||||
if (!$expected->contains($object)) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$exporter->export($expected),
|
||||
$exporter->export($actual),
|
||||
'Failed asserting that two objects are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($expected as $object) {
|
||||
if (!$actual->contains($object)) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
$exporter->export($expected),
|
||||
$exporter->export($actual),
|
||||
'Failed asserting that two objects are equal.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
vendor/sebastian/comparator/src/TypeComparator.php
vendored
Normal file
43
vendor/sebastian/comparator/src/TypeComparator.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use function gettype;
|
||||
use function sprintf;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
final class TypeComparator extends Comparator
|
||||
{
|
||||
public function accepts(mixed $expected, mixed $actual): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ComparisonFailure
|
||||
*/
|
||||
public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false): void
|
||||
{
|
||||
if (gettype($expected) != gettype($actual)) {
|
||||
throw new ComparisonFailure(
|
||||
$expected,
|
||||
$actual,
|
||||
// we don't need a diff
|
||||
'',
|
||||
'',
|
||||
sprintf(
|
||||
'%s does not match expected type "%s".',
|
||||
(new Exporter)->shortenedExport($actual),
|
||||
gettype($expected),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
16
vendor/sebastian/comparator/src/exceptions/Exception.php
vendored
Normal file
16
vendor/sebastian/comparator/src/exceptions/Exception.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface Exception extends Throwable
|
||||
{
|
||||
}
|
14
vendor/sebastian/comparator/src/exceptions/RuntimeException.php
vendored
Normal file
14
vendor/sebastian/comparator/src/exceptions/RuntimeException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php declare(strict_types=1);
|
||||
/*
|
||||
* This file is part of sebastian/comparator.
|
||||
*
|
||||
* (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 SebastianBergmann\Comparator;
|
||||
|
||||
final class RuntimeException extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
Reference in New Issue
Block a user