1<?php declare(strict_types=1);
2
3namespace PhpParser\Internal;
4
5class DifferTest extends \PHPUnit\Framework\TestCase {
6    private function formatDiffString(array $diff) {
7        $diffStr = '';
8        foreach ($diff as $diffElem) {
9            switch ($diffElem->type) {
10                case DiffElem::TYPE_KEEP:
11                    $diffStr .= $diffElem->old;
12                    break;
13                case DiffElem::TYPE_REMOVE:
14                    $diffStr .= '-' . $diffElem->old;
15                    break;
16                case DiffElem::TYPE_ADD:
17                    $diffStr .= '+' . $diffElem->new;
18                    break;
19                case DiffElem::TYPE_REPLACE:
20                    $diffStr .= '/' . $diffElem->old . $diffElem->new;
21                    break;
22                default:
23                    assert(false);
24                    break;
25            }
26        }
27        return $diffStr;
28    }
29
30    /** @dataProvider provideTestDiff */
31    public function testDiff($oldStr, $newStr, $expectedDiffStr): void {
32        $differ = new Differ(function ($a, $b) {
33            return $a === $b;
34        });
35        $diff = $differ->diff(str_split($oldStr), str_split($newStr));
36        $this->assertSame($expectedDiffStr, $this->formatDiffString($diff));
37    }
38
39    public static function provideTestDiff() {
40        return [
41            ['abc', 'abc', 'abc'],
42            ['abc', 'abcdef', 'abc+d+e+f'],
43            ['abcdef', 'abc', 'abc-d-e-f'],
44            ['abcdef', 'abcxyzdef', 'abc+x+y+zdef'],
45            ['axyzb', 'ab', 'a-x-y-zb'],
46            ['abcdef', 'abxyef', 'ab-c-d+x+yef'],
47            ['abcdef', 'cdefab', '-a-bcdef+a+b'],
48        ];
49    }
50
51    /** @dataProvider provideTestDiffWithReplacements */
52    public function testDiffWithReplacements($oldStr, $newStr, $expectedDiffStr): void {
53        $differ = new Differ(function ($a, $b) {
54            return $a === $b;
55        });
56        $diff = $differ->diffWithReplacements(str_split($oldStr), str_split($newStr));
57        $this->assertSame($expectedDiffStr, $this->formatDiffString($diff));
58    }
59
60    public static function provideTestDiffWithReplacements() {
61        return [
62            ['abcde', 'axyze', 'a/bx/cy/dze'],
63            ['abcde', 'xbcdy', '/axbcd/ey'],
64            ['abcde', 'axye', 'a-b-c-d+x+ye'],
65            ['abcde', 'axyzue', 'a-b-c-d+x+y+z+ue'],
66        ];
67    }
68
69    public function testNonContiguousIndices(): void {
70        $differ = new Differ(function ($a, $b) {
71            return $a === $b;
72        });
73        $diff = $differ->diff([0 => 'a', 2 => 'b'], [0 => 'a', 3 => 'b']);
74        $this->assertEquals([
75            new DiffElem(DiffElem::TYPE_KEEP, 'a', 'a'),
76            new DiffElem(DiffElem::TYPE_KEEP, 'b', 'b'),
77        ], $diff);
78    }
79}
80