Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace SebastianBergmann\Comparator; Chris@0: Chris@0: /** Chris@0: * Compares arrays for equality. Chris@0: */ Chris@0: class ArrayComparator extends Comparator Chris@0: { Chris@0: /** Chris@0: * Returns whether the comparator can compare two values. Chris@0: * Chris@14: * @param mixed $expected The first value to compare Chris@14: * @param mixed $actual The second value to compare Chris@14: * Chris@0: * @return bool Chris@0: */ Chris@0: public function accepts($expected, $actual) Chris@0: { Chris@14: return \is_array($expected) && \is_array($actual); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Asserts that two values are equal. Chris@0: * Chris@0: * @param mixed $expected First value to compare Chris@0: * @param mixed $actual Second value to compare Chris@0: * @param float $delta Allowed numerical distance between two values to consider them equal Chris@0: * @param bool $canonicalize Arrays are sorted before comparison when set to true Chris@0: * @param bool $ignoreCase Case is ignored when set to true Chris@0: * @param array $processed List of already processed elements (used to prevent infinite recursion) Chris@0: * Chris@0: * @throws ComparisonFailure Chris@0: */ Chris@14: public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = []) Chris@0: { Chris@0: if ($canonicalize) { Chris@14: \sort($expected); Chris@14: \sort($actual); Chris@0: } Chris@0: Chris@14: $remaining = $actual; Chris@14: $actualAsString = "Array (\n"; Chris@14: $expectedAsString = "Array (\n"; Chris@14: $equal = true; Chris@0: Chris@0: foreach ($expected as $key => $value) { Chris@0: unset($remaining[$key]); Chris@0: Chris@14: if (!\array_key_exists($key, $actual)) { Chris@14: $expectedAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@0: $this->exporter->shortenedExport($value) Chris@0: ); Chris@0: Chris@0: $equal = false; Chris@0: Chris@0: continue; Chris@0: } Chris@0: Chris@0: try { Chris@0: $comparator = $this->factory->getComparatorFor($value, $actual[$key]); Chris@0: $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed); Chris@0: Chris@14: $expectedAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@0: $this->exporter->shortenedExport($value) Chris@0: ); Chris@14: Chris@14: $actualAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@0: $this->exporter->shortenedExport($actual[$key]) Chris@0: ); Chris@0: } catch (ComparisonFailure $e) { Chris@14: $expectedAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@14: $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected()) Chris@0: ); Chris@0: Chris@14: $actualAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@14: $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual()) Chris@0: ); Chris@0: Chris@0: $equal = false; Chris@0: } Chris@0: } Chris@0: Chris@0: foreach ($remaining as $key => $value) { Chris@14: $actualAsString .= \sprintf( Chris@0: " %s => %s\n", Chris@0: $this->exporter->export($key), Chris@0: $this->exporter->shortenedExport($value) Chris@0: ); Chris@0: Chris@0: $equal = false; Chris@0: } Chris@0: Chris@14: $expectedAsString .= ')'; Chris@14: $actualAsString .= ')'; Chris@0: Chris@0: if (!$equal) { Chris@0: throw new ComparisonFailure( Chris@0: $expected, Chris@0: $actual, Chris@14: $expectedAsString, Chris@14: $actualAsString, Chris@0: false, Chris@0: 'Failed asserting that two arrays are equal.' Chris@0: ); Chris@0: } Chris@0: } Chris@0: Chris@0: protected function indent($lines) Chris@0: { Chris@14: return \trim(\str_replace("\n", "\n ", $lines)); Chris@0: } Chris@0: }