LongestCommonSubsequenceTest.php 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of sebastian/diff.
  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\Diff;
  11. use PHPUnit\Framework\TestCase;
  12. /**
  13. * @coversNothing
  14. */
  15. abstract class LongestCommonSubsequenceTest extends TestCase
  16. {
  17. /**
  18. * @var LongestCommonSubsequenceCalculator
  19. */
  20. private $implementation;
  21. /**
  22. * @var string
  23. */
  24. private $memoryLimit;
  25. /**
  26. * @var int[]
  27. */
  28. private $stress_sizes = [1, 2, 3, 100, 500, 1000, 2000];
  29. protected function setUp(): void
  30. {
  31. $this->memoryLimit = \ini_get('memory_limit');
  32. \ini_set('memory_limit', '256M');
  33. $this->implementation = $this->createImplementation();
  34. }
  35. protected function tearDown(): void
  36. {
  37. \ini_set('memory_limit', $this->memoryLimit);
  38. }
  39. public function testBothEmpty(): void
  40. {
  41. $from = [];
  42. $to = [];
  43. $common = $this->implementation->calculate($from, $to);
  44. $this->assertSame([], $common);
  45. }
  46. public function testIsStrictComparison(): void
  47. {
  48. $from = [
  49. false, 0, 0.0, '', null, [],
  50. true, 1, 1.0, 'foo', ['foo', 'bar'], ['foo' => 'bar'],
  51. ];
  52. $to = $from;
  53. $common = $this->implementation->calculate($from, $to);
  54. $this->assertSame($from, $common);
  55. $to = [
  56. false, false, false, false, false, false,
  57. true, true, true, true, true, true,
  58. ];
  59. $expected = [
  60. false,
  61. true,
  62. ];
  63. $common = $this->implementation->calculate($from, $to);
  64. $this->assertSame($expected, $common);
  65. }
  66. public function testEqualSequences(): void
  67. {
  68. foreach ($this->stress_sizes as $size) {
  69. $range = \range(1, $size);
  70. $from = $range;
  71. $to = $range;
  72. $common = $this->implementation->calculate($from, $to);
  73. $this->assertSame($range, $common);
  74. }
  75. }
  76. public function testDistinctSequences(): void
  77. {
  78. $from = ['A'];
  79. $to = ['B'];
  80. $common = $this->implementation->calculate($from, $to);
  81. $this->assertSame([], $common);
  82. $from = ['A', 'B', 'C'];
  83. $to = ['D', 'E', 'F'];
  84. $common = $this->implementation->calculate($from, $to);
  85. $this->assertSame([], $common);
  86. foreach ($this->stress_sizes as $size) {
  87. $from = \range(1, $size);
  88. $to = \range($size + 1, $size * 2);
  89. $common = $this->implementation->calculate($from, $to);
  90. $this->assertSame([], $common);
  91. }
  92. }
  93. public function testCommonSubsequence(): void
  94. {
  95. $from = ['A', 'C', 'E', 'F', 'G'];
  96. $to = ['A', 'B', 'D', 'E', 'H'];
  97. $expected = ['A', 'E'];
  98. $common = $this->implementation->calculate($from, $to);
  99. $this->assertSame($expected, $common);
  100. $from = ['A', 'C', 'E', 'F', 'G'];
  101. $to = ['B', 'C', 'D', 'E', 'F', 'H'];
  102. $expected = ['C', 'E', 'F'];
  103. $common = $this->implementation->calculate($from, $to);
  104. $this->assertSame($expected, $common);
  105. foreach ($this->stress_sizes as $size) {
  106. $from = $size < 2 ? [1] : \range(1, $size + 1, 2);
  107. $to = $size < 3 ? [1] : \range(1, $size + 1, 3);
  108. $expected = $size < 6 ? [1] : \range(1, $size + 1, 6);
  109. $common = $this->implementation->calculate($from, $to);
  110. $this->assertSame($expected, $common);
  111. }
  112. }
  113. public function testSingleElementSubsequenceAtStart(): void
  114. {
  115. foreach ($this->stress_sizes as $size) {
  116. $from = \range(1, $size);
  117. $to = \array_slice($from, 0, 1);
  118. $common = $this->implementation->calculate($from, $to);
  119. $this->assertSame($to, $common);
  120. }
  121. }
  122. public function testSingleElementSubsequenceAtMiddle(): void
  123. {
  124. foreach ($this->stress_sizes as $size) {
  125. $from = \range(1, $size);
  126. $to = \array_slice($from, (int) ($size / 2), 1);
  127. $common = $this->implementation->calculate($from, $to);
  128. $this->assertSame($to, $common);
  129. }
  130. }
  131. public function testSingleElementSubsequenceAtEnd(): void
  132. {
  133. foreach ($this->stress_sizes as $size) {
  134. $from = \range(1, $size);
  135. $to = \array_slice($from, $size - 1, 1);
  136. $common = $this->implementation->calculate($from, $to);
  137. $this->assertSame($to, $common);
  138. }
  139. }
  140. public function testReversedSequences(): void
  141. {
  142. $from = ['A', 'B'];
  143. $to = ['B', 'A'];
  144. $expected = ['A'];
  145. $common = $this->implementation->calculate($from, $to);
  146. $this->assertSame($expected, $common);
  147. foreach ($this->stress_sizes as $size) {
  148. $from = \range(1, $size);
  149. $to = \array_reverse($from);
  150. $common = $this->implementation->calculate($from, $to);
  151. $this->assertSame([1], $common);
  152. }
  153. }
  154. public function testStrictTypeCalculate(): void
  155. {
  156. $diff = $this->implementation->calculate(['5'], ['05']);
  157. $this->assertIsArray($diff);
  158. $this->assertCount(0, $diff);
  159. }
  160. /**
  161. * @return LongestCommonSubsequenceCalculator
  162. */
  163. abstract protected function createImplementation(): LongestCommonSubsequenceCalculator;
  164. }