ArrayComparator.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php declare(strict_types=1);
  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. use function array_key_exists;
  12. use function is_array;
  13. use function sort;
  14. use function sprintf;
  15. use function str_replace;
  16. use function trim;
  17. /**
  18. * Compares arrays for equality.
  19. *
  20. * Arrays are equal if they contain the same key-value pairs.
  21. * The order of the keys does not matter.
  22. * The types of key-value pairs do not matter.
  23. */
  24. class ArrayComparator extends Comparator
  25. {
  26. /**
  27. * Returns whether the comparator can compare two values.
  28. *
  29. * @param mixed $expected The first value to compare
  30. * @param mixed $actual The second value to compare
  31. *
  32. * @return bool
  33. */
  34. public function accepts($expected, $actual)
  35. {
  36. return is_array($expected) && is_array($actual);
  37. }
  38. /**
  39. * Asserts that two arrays are equal.
  40. *
  41. * @param mixed $expected First value to compare
  42. * @param mixed $actual Second value to compare
  43. * @param float $delta Allowed numerical distance between two values to consider them equal
  44. * @param bool $canonicalize Arrays are sorted before comparison when set to true
  45. * @param bool $ignoreCase Case is ignored when set to true
  46. * @param array $processed List of already processed elements (used to prevent infinite recursion)
  47. *
  48. * @throws ComparisonFailure
  49. */
  50. public function assertEquals($expected, $actual, $delta = 0.0, $canonicalize = false, $ignoreCase = false, array &$processed = [])/*: void*/
  51. {
  52. if ($canonicalize) {
  53. sort($expected);
  54. sort($actual);
  55. }
  56. $remaining = $actual;
  57. $actualAsString = "Array (\n";
  58. $expectedAsString = "Array (\n";
  59. $equal = true;
  60. foreach ($expected as $key => $value) {
  61. unset($remaining[$key]);
  62. if (!array_key_exists($key, $actual)) {
  63. $expectedAsString .= sprintf(
  64. " %s => %s\n",
  65. $this->exporter->export($key),
  66. $this->exporter->shortenedExport($value)
  67. );
  68. $equal = false;
  69. continue;
  70. }
  71. try {
  72. $comparator = $this->factory->getComparatorFor($value, $actual[$key]);
  73. $comparator->assertEquals($value, $actual[$key], $delta, $canonicalize, $ignoreCase, $processed);
  74. $expectedAsString .= sprintf(
  75. " %s => %s\n",
  76. $this->exporter->export($key),
  77. $this->exporter->shortenedExport($value)
  78. );
  79. $actualAsString .= sprintf(
  80. " %s => %s\n",
  81. $this->exporter->export($key),
  82. $this->exporter->shortenedExport($actual[$key])
  83. );
  84. } catch (ComparisonFailure $e) {
  85. $expectedAsString .= sprintf(
  86. " %s => %s\n",
  87. $this->exporter->export($key),
  88. $e->getExpectedAsString() ? $this->indent($e->getExpectedAsString()) : $this->exporter->shortenedExport($e->getExpected())
  89. );
  90. $actualAsString .= sprintf(
  91. " %s => %s\n",
  92. $this->exporter->export($key),
  93. $e->getActualAsString() ? $this->indent($e->getActualAsString()) : $this->exporter->shortenedExport($e->getActual())
  94. );
  95. $equal = false;
  96. }
  97. }
  98. foreach ($remaining as $key => $value) {
  99. $actualAsString .= sprintf(
  100. " %s => %s\n",
  101. $this->exporter->export($key),
  102. $this->exporter->shortenedExport($value)
  103. );
  104. $equal = false;
  105. }
  106. $expectedAsString .= ')';
  107. $actualAsString .= ')';
  108. if (!$equal) {
  109. throw new ComparisonFailure(
  110. $expected,
  111. $actual,
  112. $expectedAsString,
  113. $actualAsString,
  114. false,
  115. 'Failed asserting that two arrays are equal.'
  116. );
  117. }
  118. }
  119. protected function indent($lines)
  120. {
  121. return trim(str_replace("\n", "\n ", $lines));
  122. }
  123. }