ArrayComparator.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /*
  3. * This file is part of sebastian/comparator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\Comparator;
  11. /**
  12. * Compares arrays for equality.
  13. */
  14. class ArrayComparator extends Comparator
  15. {
  16. /**
  17. * Returns whether the comparator can compare two values.
  18. *
  19. * @param mixed $expected The first value to compare
  20. * @param mixed $actual The second value to compare
  21. *
  22. * @return bool
  23. */
  24. public function accepts($expected, $actual)
  25. {
  26. return \is_array($expected) && \is_array($actual);
  27. }
  28. /**
  29. * Asserts that two values are equal.
  30. *
  31. * @param mixed $expected First value to compare
  32. * @param mixed $actual Second value to compare
  33. * @param float $delta Allowed numerical distance between two values to consider them equal
  34. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  35. * @param bool $ignoreCase Case is ignored when set to true
  36. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  37. *
  38. * @throws ComparisonFailure
  39. */
  40. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])
  41. {
  42. if ($canonicalize) {
  43. \sort($expected);
  44. \sort($actual);
  45. }
  46. $remaining = $actual;
  47. $actualAsString = "Array (\n";
  48. $expectedAsString = "Array (\n";
  49. $equal = true;
  50. foreach ($expected as $key => $value) {
  51. unset($remaining[$key]);
  52. if (!\array_key_exists($key, $actual)) {
  53. $expectedAsString .= \sprintf(
  54. " %s => %s\n",
  55. $this->exporter->export($key),
  56. $this->exporter->shortenedExport($value)
  57. );
  58. $equal = false;
  59. continue;
  60. }
  61. try {
  62. $comparator = $this->factory->getComparatorFor($value, $actual[$key]);
  63. $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
  64. $expectedAsString .= \sprintf(
  65. " %s => %s\n",
  66. $this->exporter->export($key),
  67. $this->exporter->shortenedExport($value)
  68. );
  69. $actualAsString .= \sprintf(
  70. " %s => %s\n",
  71. $this->exporter->export($key),
  72. $this->exporter->shortenedExport($actual[$key])
  73. );
  74. } catch (ComparisonFailure $e) {
  75. $expectedAsString .= \sprintf(
  76. " %s => %s\n",
  77. $this->exporter->export($key),
  78. $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected())
  79. );
  80. $actualAsString .= \sprintf(
  81. " %s => %s\n",
  82. $this->exporter->export($key),
  83. $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual())
  84. );
  85. $equal = false;
  86. }
  87. }
  88. foreach ($remaining as $key => $value) {
  89. $actualAsString .= \sprintf(
  90. " %s => %s\n",
  91. $this->exporter->export($key),
  92. $this->exporter->shortenedExport($value)
  93. );
  94. $equal = false;
  95. }
  96. $expectedAsString .= ')';
  97. $actualAsString .= ')';
  98. if (!$equal) {
  99. throw new ComparisonFailure(
  100. $expected,
  101. $actual,
  102. $expectedAsString,
  103. $actualAsString,
  104. false,
  105. 'Failed asserting that two arrays are equal.'
  106. );
  107. }
  108. }
  109. protected function indent($lines)
  110. {
  111. return \trim(\str_replace("\n", "\n ", $lines));
  112. }
  113. }