pax_global_header00006660000000000000000000000064126315015410014510gustar00rootroot0000000000000052 comment=13edfd8706462032c2f52b4b862974dd46b71c9e diff-1.4.1/000077500000000000000000000000001263150154100124235ustar00rootroot00000000000000diff-1.4.1/.gitignore000066400000000000000000000002111263150154100144050ustar00rootroot00000000000000.idea phpunit.xml composer.lock composer.phar vendor/ cache.properties build/SebastianBergmann build/LICENSE build/README.md build/*.tgz diff-1.4.1/.php_cs000066400000000000000000000035571263150154100137120ustar00rootroot00000000000000files() ->in('src') ->in('tests') ->name('*.php'); return Symfony\CS\Config\Config::create() ->level(\Symfony\CS\FixerInterface::NONE_LEVEL) ->fixers( array( 'align_double_arrow', 'align_equals', 'braces', 'concat_with_spaces', 'duplicate_semicolon', 'elseif', 'empty_return', 'encoding', 'eof_ending', 'extra_empty_lines', 'function_call_space', 'function_declaration', 'indentation', 'join_function', 'line_after_namespace', 'linefeed', 'list_commas', 'lowercase_constants', 'lowercase_keywords', 'method_argument_space', 'multiple_use', 'namespace_no_leading_whitespace', 'no_blank_lines_after_class_opening', 'no_empty_lines_after_phpdocs', 'parenthesis', 'php_closing_tag', 'phpdoc_indent', 'phpdoc_no_access', 'phpdoc_no_empty_return', 'phpdoc_no_package', 'phpdoc_params', 'phpdoc_scalar', 'phpdoc_separation', 'phpdoc_to_comment', 'phpdoc_trim', 'phpdoc_types', 'phpdoc_var_without_name', 'remove_lines_between_uses', 'return', 'self_accessor', 'short_tag', 'single_line_after_imports', 'single_quote', 'spaces_before_semicolon', 'spaces_cast', 'ternary_spaces', 'trailing_spaces', 'trim_array_spaces', 'unused_use', 'visibility', 'whitespacy_lines' ) ) ->finder($finder); diff-1.4.1/.travis.yml000066400000000000000000000003251263150154100145340ustar00rootroot00000000000000language: php install: - travis_retry composer install --no-interaction --prefer-source php: - 5.3.3 - 5.3 - 5.4 - 5.5 - 5.6 - hhvm notifications: email: false irc: "irc.freenode.org#phpunit" diff-1.4.1/LICENSE000066400000000000000000000030031263150154100134240ustar00rootroot00000000000000Diff Copyright (c) 2002-2015, Sebastian Bergmann . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Sebastian Bergmann nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff-1.4.1/README.md000066400000000000000000000125451263150154100137110ustar00rootroot00000000000000# Diff Diff implementation for PHP, factored out of PHPUnit into a stand-alone component. ## Installation To add this package as a local, per-project dependency to your project, simply add a dependency on `sebastian/diff` to your project's `composer.json` file. Here is a minimal example of a `composer.json` file that just defines a dependency on Diff: { "require": { "sebastian/diff": "*" } } ### Usage The `Differ` class can be used to generate a textual representation of the difference between two strings: ```php use SebastianBergmann\Diff\Differ; $differ = new Differ; print $differ->diff('foo', 'bar'); ``` The code above yields the output below: --- Original +++ New @@ @@ -foo +bar The `Parser` class can be used to parse a unified diff into an object graph: ```php use SebastianBergmann\Diff\Parser; use SebastianBergmann\Git; $git = new Git('/usr/local/src/money'); $diff = $git->getDiff( '948a1a07768d8edd10dcefa8315c1cbeffb31833', 'c07a373d2399f3e686234c4f7f088d635eb9641b' ); $parser = new Parser; print_r($parser->parse($diff)); ``` The code above yields the output below: Array ( [0] => SebastianBergmann\Diff\Diff Object ( [from:SebastianBergmann\Diff\Diff:private] => a/tests/MoneyTest.php [to:SebastianBergmann\Diff\Diff:private] => b/tests/MoneyTest.php [chunks:SebastianBergmann\Diff\Diff:private] => Array ( [0] => SebastianBergmann\Diff\Chunk Object ( [start:SebastianBergmann\Diff\Chunk:private] => 87 [startRange:SebastianBergmann\Diff\Chunk:private] => 7 [end:SebastianBergmann\Diff\Chunk:private] => 87 [endRange:SebastianBergmann\Diff\Chunk:private] => 7 [lines:SebastianBergmann\Diff\Chunk:private] => Array ( [0] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::add ) [1] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => * @covers SebastianBergmann\Money\Money::newMoney ) [2] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => */ ) [3] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 2 [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyWithSameCurrencyObjectCanBeAdded() ) [4] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 1 [content:SebastianBergmann\Diff\Line:private] => public function testAnotherMoneyObjectWithSameCurrencyCanBeAdded() ) [5] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => { ) [6] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => $a = new Money(1, new Currency('EUR')); ) [7] => SebastianBergmann\Diff\Line Object ( [type:SebastianBergmann\Diff\Line:private] => 3 [content:SebastianBergmann\Diff\Line:private] => $b = new Money(2, new Currency('EUR')); ) ) ) ) ) ) diff-1.4.1/build.xml000066400000000000000000000014451263150154100142500ustar00rootroot00000000000000 diff-1.4.1/composer.json000066400000000000000000000013031263150154100151420ustar00rootroot00000000000000{ "name": "sebastian/diff", "description": "Diff implementation", "keywords": ["diff"], "homepage": "https://github.com/sebastianbergmann/diff", "license": "BSD-3-Clause", "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" } ], "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.8" }, "autoload": { "classmap": [ "src/" ] }, "extra": { "branch-alias": { "dev-master": "1.4-dev" } } } diff-1.4.1/phpunit.xml.dist000066400000000000000000000010231263150154100155720ustar00rootroot00000000000000 tests src diff-1.4.1/src/000077500000000000000000000000001263150154100132125ustar00rootroot00000000000000diff-1.4.1/src/Chunk.php000066400000000000000000000033161263150154100147760ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; /** */ class Chunk { /** * @var int */ private $start; /** * @var int */ private $startRange; /** * @var int */ private $end; /** * @var int */ private $endRange; /** * @var array */ private $lines; /** * @param int $start * @param int $startRange * @param int $end * @param int $endRange * @param array $lines */ public function __construct($start = 0, $startRange = 1, $end = 0, $endRange = 1, array $lines = array()) { $this->start = (int) $start; $this->startRange = (int) $startRange; $this->end = (int) $end; $this->endRange = (int) $endRange; $this->lines = $lines; } /** * @return int */ public function getStart() { return $this->start; } /** * @return int */ public function getStartRange() { return $this->startRange; } /** * @return int */ public function getEnd() { return $this->end; } /** * @return int */ public function getEndRange() { return $this->endRange; } /** * @return array */ public function getLines() { return $this->lines; } /** * @param array $lines */ public function setLines(array $lines) { $this->lines = $lines; } } diff-1.4.1/src/Diff.php000066400000000000000000000022611263150154100145740ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; /** */ class Diff { /** * @var string */ private $from; /** * @var string */ private $to; /** * @var Chunk[] */ private $chunks; /** * @param string $from * @param string $to * @param Chunk[] $chunks */ public function __construct($from, $to, array $chunks = array()) { $this->from = $from; $this->to = $to; $this->chunks = $chunks; } /** * @return string */ public function getFrom() { return $this->from; } /** * @return string */ public function getTo() { return $this->to; } /** * @return Chunk[] */ public function getChunks() { return $this->chunks; } /** * @param Chunk[] $chunks */ public function setChunks(array $chunks) { $this->chunks = $chunks; } } diff-1.4.1/src/Differ.php000066400000000000000000000157341263150154100151340ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; use SebastianBergmann\Diff\LCS\LongestCommonSubsequence; use SebastianBergmann\Diff\LCS\TimeEfficientImplementation; use SebastianBergmann\Diff\LCS\MemoryEfficientImplementation; /** * Diff implementation. */ class Differ { /** * @var string */ private $header; /** * @var bool */ private $showNonDiffLines; /** * @param string $header */ public function __construct($header = "--- Original\n+++ New\n", $showNonDiffLines = true) { $this->header = $header; $this->showNonDiffLines = $showNonDiffLines; } /** * Returns the diff between two arrays or strings as string. * * @param array|string $from * @param array|string $to * @param LongestCommonSubsequence $lcs * * @return string */ public function diff($from, $to, LongestCommonSubsequence $lcs = null) { if (!is_array($from) && !is_string($from)) { $from = (string) $from; } if (!is_array($to) && !is_string($to)) { $to = (string) $to; } $buffer = $this->header; $diff = $this->diffToArray($from, $to, $lcs); $inOld = false; $i = 0; $old = array(); foreach ($diff as $line) { if ($line[1] === 0 /* OLD */) { if ($inOld === false) { $inOld = $i; } } elseif ($inOld !== false) { if (($i - $inOld) > 5) { $old[$inOld] = $i - 1; } $inOld = false; } ++$i; } $start = isset($old[0]) ? $old[0] : 0; $end = count($diff); if ($tmp = array_search($end, $old)) { $end = $tmp; } $newChunk = true; for ($i = $start; $i < $end; $i++) { if (isset($old[$i])) { $buffer .= "\n"; $newChunk = true; $i = $old[$i]; } if ($newChunk) { if ($this->showNonDiffLines === true) { $buffer .= "@@ @@\n"; } $newChunk = false; } if ($diff[$i][1] === 1 /* ADDED */) { $buffer .= '+' . $diff[$i][0] . "\n"; } elseif ($diff[$i][1] === 2 /* REMOVED */) { $buffer .= '-' . $diff[$i][0] . "\n"; } elseif ($this->showNonDiffLines === true) { $buffer .= ' ' . $diff[$i][0] . "\n"; } } return $buffer; } /** * Returns the diff between two arrays or strings as array. * * Each array element contains two elements: * - [0] => string $token * - [1] => 2|1|0 * * - 2: REMOVED: $token was removed from $from * - 1: ADDED: $token was added to $from * - 0: OLD: $token is not changed in $to * * @param array|string $from * @param array|string $to * @param LongestCommonSubsequence $lcs * * @return array */ public function diffToArray($from, $to, LongestCommonSubsequence $lcs = null) { preg_match_all('(\r\n|\r|\n)', $from, $fromMatches); preg_match_all('(\r\n|\r|\n)', $to, $toMatches); if (is_string($from)) { $from = preg_split('(\r\n|\r|\n)', $from); } if (is_string($to)) { $to = preg_split('(\r\n|\r|\n)', $to); } $start = array(); $end = array(); $fromLength = count($from); $toLength = count($to); $length = min($fromLength, $toLength); for ($i = 0; $i < $length; ++$i) { if ($from[$i] === $to[$i]) { $start[] = $from[$i]; unset($from[$i], $to[$i]); } else { break; } } $length -= $i; for ($i = 1; $i < $length; ++$i) { if ($from[$fromLength - $i] === $to[$toLength - $i]) { array_unshift($end, $from[$fromLength - $i]); unset($from[$fromLength - $i], $to[$toLength - $i]); } else { break; } } if ($lcs === null) { $lcs = $this->selectLcsImplementation($from, $to); } $common = $lcs->calculate(array_values($from), array_values($to)); $diff = array(); if (isset($fromMatches[0]) && $toMatches[0] && count($fromMatches[0]) === count($toMatches[0]) && $fromMatches[0] !== $toMatches[0]) { $diff[] = array( '#Warning: Strings contain different line endings!', 0 ); } foreach ($start as $token) { $diff[] = array($token, 0 /* OLD */); } reset($from); reset($to); foreach ($common as $token) { while ((($fromToken = reset($from)) !== $token)) { $diff[] = array(array_shift($from), 2 /* REMOVED */); } while ((($toToken = reset($to)) !== $token)) { $diff[] = array(array_shift($to), 1 /* ADDED */); } $diff[] = array($token, 0 /* OLD */); array_shift($from); array_shift($to); } while (($token = array_shift($from)) !== null) { $diff[] = array($token, 2 /* REMOVED */); } while (($token = array_shift($to)) !== null) { $diff[] = array($token, 1 /* ADDED */); } foreach ($end as $token) { $diff[] = array($token, 0 /* OLD */); } return $diff; } /** * @param array $from * @param array $to * * @return LongestCommonSubsequence */ private function selectLcsImplementation(array $from, array $to) { // We do not want to use the time-efficient implementation if its memory // footprint will probably exceed this value. Note that the footprint // calculation is only an estimation for the matrix and the LCS method // will typically allocate a bit more memory than this. $memoryLimit = 100 * 1024 * 1024; if ($this->calculateEstimatedFootprint($from, $to) > $memoryLimit) { return new MemoryEfficientImplementation; } return new TimeEfficientImplementation; } /** * Calculates the estimated memory footprint for the DP-based method. * * @param array $from * @param array $to * * @return int */ private function calculateEstimatedFootprint(array $from, array $to) { $itemSize = PHP_INT_SIZE == 4 ? 76 : 144; return $itemSize * pow(min(count($from), count($to)), 2); } } diff-1.4.1/src/LCS/000077500000000000000000000000001263150154100136335ustar00rootroot00000000000000diff-1.4.1/src/LCS/LongestCommonSubsequence.php000066400000000000000000000011541263150154100213340ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff\LCS; /** * Interface for implementations of longest common subsequence calculation. */ interface LongestCommonSubsequence { /** * Calculates the longest common subsequence of two arrays. * * @param array $from * @param array $to * * @return array */ public function calculate(array $from, array $to); } diff-1.4.1/src/LCS/MemoryEfficientLongestCommonSubsequenceImplementation.php000066400000000000000000000046571263150154100272630ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff\LCS; /** * Memory-efficient implementation of longest common subsequence calculation. */ class MemoryEfficientImplementation implements LongestCommonSubsequence { /** * Calculates the longest common subsequence of two arrays. * * @param array $from * @param array $to * * @return array */ public function calculate(array $from, array $to) { $cFrom = count($from); $cTo = count($to); if ($cFrom == 0) { return array(); } elseif ($cFrom == 1) { if (in_array($from[0], $to)) { return array($from[0]); } else { return array(); } } else { $i = intval($cFrom / 2); $fromStart = array_slice($from, 0, $i); $fromEnd = array_slice($from, $i); $llB = $this->length($fromStart, $to); $llE = $this->length(array_reverse($fromEnd), array_reverse($to)); $jMax = 0; $max = 0; for ($j = 0; $j <= $cTo; $j++) { $m = $llB[$j] + $llE[$cTo - $j]; if ($m >= $max) { $max = $m; $jMax = $j; } } $toStart = array_slice($to, 0, $jMax); $toEnd = array_slice($to, $jMax); return array_merge( $this->calculate($fromStart, $toStart), $this->calculate($fromEnd, $toEnd) ); } } /** * @param array $from * @param array $to * * @return array */ private function length(array $from, array $to) { $current = array_fill(0, count($to) + 1, 0); $cFrom = count($from); $cTo = count($to); for ($i = 0; $i < $cFrom; $i++) { $prev = $current; for ($j = 0; $j < $cTo; $j++) { if ($from[$i] == $to[$j]) { $current[$j + 1] = $prev[$j] + 1; } else { $current[$j + 1] = max($current[$j], $prev[$j + 1]); } } } return $current; } } diff-1.4.1/src/LCS/TimeEfficientLongestCommonSubsequenceImplementation.php000066400000000000000000000036341263150154100267030ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff\LCS; /** * Time-efficient implementation of longest common subsequence calculation. */ class TimeEfficientImplementation implements LongestCommonSubsequence { /** * Calculates the longest common subsequence of two arrays. * * @param array $from * @param array $to * * @return array */ public function calculate(array $from, array $to) { $common = array(); $fromLength = count($from); $toLength = count($to); $width = $fromLength + 1; $matrix = new \SplFixedArray($width * ($toLength + 1)); for ($i = 0; $i <= $fromLength; ++$i) { $matrix[$i] = 0; } for ($j = 0; $j <= $toLength; ++$j) { $matrix[$j * $width] = 0; } for ($i = 1; $i <= $fromLength; ++$i) { for ($j = 1; $j <= $toLength; ++$j) { $o = ($j * $width) + $i; $matrix[$o] = max( $matrix[$o - 1], $matrix[$o - $width], $from[$i - 1] === $to[$j - 1] ? $matrix[$o - $width - 1] + 1 : 0 ); } } $i = $fromLength; $j = $toLength; while ($i > 0 && $j > 0) { if ($from[$i-1] === $to[$j-1]) { $common[] = $from[$i-1]; --$i; --$j; } else { $o = ($j * $width) + $i; if ($matrix[$o - $width] > $matrix[$o - 1]) { --$j; } else { --$i; } } } return array_reverse($common); } } diff-1.4.1/src/Line.php000066400000000000000000000016371263150154100146210ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; /** */ class Line { const ADDED = 1; const REMOVED = 2; const UNCHANGED = 3; /** * @var int */ private $type; /** * @var string */ private $content; /** * @param int $type * @param string $content */ public function __construct($type = self::UNCHANGED, $content = '') { $this->type = $type; $this->content = $content; } /** * @return string */ public function getContent() { return $this->content; } /** * @return int */ public function getType() { return $this->type; } } diff-1.4.1/src/Parser.php000066400000000000000000000054471263150154100151710ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; /** * Unified diff parser. */ class Parser { /** * @param string $string * * @return Diff[] */ public function parse($string) { $lines = preg_split('(\r\n|\r|\n)', $string); $lineCount = count($lines); $diffs = array(); $diff = null; $collected = array(); for ($i = 0; $i < $lineCount; ++$i) { if (preg_match('(^---\\s+(?P\\S+))', $lines[$i], $fromMatch) && preg_match('(^\\+\\+\\+\\s+(?P\\S+))', $lines[$i + 1], $toMatch)) { if ($diff !== null) { $this->parseFileDiff($diff, $collected); $diffs[] = $diff; $collected = array(); } $diff = new Diff($fromMatch['file'], $toMatch['file']); ++$i; } else { if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $lines[$i])) { continue; } $collected[] = $lines[$i]; } } if (count($collected) && ($diff !== null)) { $this->parseFileDiff($diff, $collected); $diffs[] = $diff; } return $diffs; } /** * @param Diff $diff * @param array $lines */ private function parseFileDiff(Diff $diff, array $lines) { $chunks = array(); foreach ($lines as $line) { if (preg_match('/^@@\s+-(?P\d+)(?:,\s*(?P\d+))?\s+\+(?P\d+)(?:,\s*(?P\d+))?\s+@@/', $line, $match)) { $chunk = new Chunk( $match['start'], isset($match['startrange']) ? max(1, $match['startrange']) : 1, $match['end'], isset($match['endrange']) ? max(1, $match['endrange']) : 1 ); $chunks[] = $chunk; $diffLines = array(); continue; } if (preg_match('/^(?P[+ -])?(?P.*)/', $line, $match)) { $type = Line::UNCHANGED; if ($match['type'] == '+') { $type = Line::ADDED; } elseif ($match['type'] == '-') { $type = Line::REMOVED; } $diffLines[] = new Line($type, $match['line']); if (isset($chunk)) { $chunk->setLines($diffLines); } } } $diff->setChunks($chunks); } } diff-1.4.1/tests/000077500000000000000000000000001263150154100135655ustar00rootroot00000000000000diff-1.4.1/tests/DifferTest.php000066400000000000000000000263441263150154100163460ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; use PHPUnit_Framework_TestCase; use SebastianBergmann\Diff\LCS\MemoryEfficientImplementation; use SebastianBergmann\Diff\LCS\TimeEfficientImplementation; class DifferTest extends PHPUnit_Framework_TestCase { const REMOVED = 2; const ADDED = 1; const OLD = 0; /** * @var Differ */ private $differ; protected function setUp() { $this->differ = new Differ; } /** * @param array $expected * @param string $from * @param string $to * @dataProvider arrayProvider * @covers SebastianBergmann\Diff\Differ::diffToArray * @covers SebastianBergmann\Diff\LCS\TimeEfficientImplementation */ public function testArrayRepresentationOfDiffCanBeRenderedUsingTimeEfficientLcsImplementation(array $expected, $from, $to) { $this->assertEquals($expected, $this->differ->diffToArray($from, $to, new TimeEfficientImplementation)); } /** * @param string $expected * @param string $from * @param string $to * @dataProvider textProvider * @covers SebastianBergmann\Diff\Differ::diff * @covers SebastianBergmann\Diff\LCS\TimeEfficientImplementation */ public function testTextRepresentationOfDiffCanBeRenderedUsingTimeEfficientLcsImplementation($expected, $from, $to) { $this->assertEquals($expected, $this->differ->diff($from, $to, new TimeEfficientImplementation)); } /** * @param array $expected * @param string $from * @param string $to * @dataProvider arrayProvider * @covers SebastianBergmann\Diff\Differ::diffToArray * @covers SebastianBergmann\Diff\LCS\MemoryEfficientImplementation */ public function testArrayRepresentationOfDiffCanBeRenderedUsingMemoryEfficientLcsImplementation(array $expected, $from, $to) { $this->assertEquals($expected, $this->differ->diffToArray($from, $to, new MemoryEfficientImplementation)); } /** * @param string $expected * @param string $from * @param string $to * @dataProvider textProvider * @covers SebastianBergmann\Diff\Differ::diff * @covers SebastianBergmann\Diff\LCS\MemoryEfficientImplementation */ public function testTextRepresentationOfDiffCanBeRenderedUsingMemoryEfficientLcsImplementation($expected, $from, $to) { $this->assertEquals($expected, $this->differ->diff($from, $to, new MemoryEfficientImplementation)); } /** * @covers SebastianBergmann\Diff\Differ::diff */ public function testCustomHeaderCanBeUsed() { $differ = new Differ('CUSTOM HEADER'); $this->assertEquals( "CUSTOM HEADER@@ @@\n-a\n+b\n", $differ->diff('a', 'b') ); } public function testTypesOtherThanArrayAndStringCanBePassed() { $this->assertEquals( "--- Original\n+++ New\n@@ @@\n-1\n+2\n", $this->differ->diff(1, 2) ); } /** * @param string $diff * @param array $expected * @dataProvider diffProvider * @covers SebastianBergmann\Diff\Parser::parse */ public function testParser($diff, $expected) { $parser = new Parser; $result = $parser->parse($diff); $this->assertEquals($expected, $result); } public function arrayProvider() { return array( array( array( array('a', self::REMOVED), array('b', self::ADDED) ), 'a', 'b' ), array( array( array('ba', self::REMOVED), array('bc', self::ADDED) ), 'ba', 'bc' ), array( array( array('ab', self::REMOVED), array('cb', self::ADDED) ), 'ab', 'cb' ), array( array( array('abc', self::REMOVED), array('adc', self::ADDED) ), 'abc', 'adc' ), array( array( array('ab', self::REMOVED), array('abc', self::ADDED) ), 'ab', 'abc' ), array( array( array('bc', self::REMOVED), array('abc', self::ADDED) ), 'bc', 'abc' ), array( array( array('abc', self::REMOVED), array('abbc', self::ADDED) ), 'abc', 'abbc' ), array( array( array('abcdde', self::REMOVED), array('abcde', self::ADDED) ), 'abcdde', 'abcde' ) ); } public function textProvider() { return array( array( "--- Original\n+++ New\n@@ @@\n-a\n+b\n", 'a', 'b' ), array( "--- Original\n+++ New\n@@ @@\n-ba\n+bc\n", 'ba', 'bc' ), array( "--- Original\n+++ New\n@@ @@\n-ab\n+cb\n", 'ab', 'cb' ), array( "--- Original\n+++ New\n@@ @@\n-abc\n+adc\n", 'abc', 'adc' ), array( "--- Original\n+++ New\n@@ @@\n-ab\n+abc\n", 'ab', 'abc' ), array( "--- Original\n+++ New\n@@ @@\n-bc\n+abc\n", 'bc', 'abc' ), array( "--- Original\n+++ New\n@@ @@\n-abc\n+abbc\n", 'abc', 'abbc' ), array( "--- Original\n+++ New\n@@ @@\n-abcdde\n+abcde\n", 'abcdde', 'abcde' ), ); } public function diffProvider() { $serialized_arr = << * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff\LCS; use PHPUnit_Framework_TestCase; /** * Some of these tests are volontary stressfull, in order to give some approximative benchmark hints. */ class TimeEfficientImplementationTest extends PHPUnit_Framework_TestCase { private $implementation; private $memory_limit; private $stress_sizes = array(1, 2, 3, 100, 500, 1000, 2000); protected function setUp() { $this->memory_limit = ini_get('memory_limit'); ini_set('memory_limit', '256M'); $this->implementation = new TimeEfficientImplementation; } protected function tearDown() { ini_set('memory_limit', $this->memory_limit); } public function testBothEmpty() { $from = array(); $to = array(); $common = $this->implementation->calculate($from, $to); $this->assertEquals(array(), $common); } public function testIsStrictComparison() { $from = array( false, 0, 0.0, '', null, array(), true, 1, 1.0, 'foo', array('foo', 'bar'), array('foo' => 'bar') ); $to = $from; $common = $this->implementation->calculate($from, $to); $this->assertEquals($from, $common); $to = array( false, false, false, false, false, false, true, true, true, true, true, true ); $expected = array( false, true, ); $common = $this->implementation->calculate($from, $to); $this->assertEquals($expected, $common); } public function testEqualSequences() { foreach ($this->stress_sizes as $size) { $range = range(1, $size); $from = $range; $to = $range; $common = $this->implementation->calculate($from, $to); $this->assertEquals($range, $common); } } public function testDistinctSequences() { $from = array('A'); $to = array('B'); $common = $this->implementation->calculate($from, $to); $this->assertEquals(array(), $common); $from = array('A', 'B', 'C'); $to = array('D', 'E', 'F'); $common = $this->implementation->calculate($from, $to); $this->assertEquals(array(), $common); foreach ($this->stress_sizes as $size) { $from = range(1, $size); $to = range($size + 1, $size * 2); $common = $this->implementation->calculate($from, $to); $this->assertEquals(array(), $common); } } public function testCommonSubsequence() { $from = array('A', 'C', 'E', 'F', 'G'); $to = array('A', 'B', 'D', 'E', 'H'); $expected = array('A', 'E'); $common = $this->implementation->calculate($from, $to); $this->assertEquals($expected, $common); $from = array('A', 'C', 'E', 'F', 'G'); $to = array('B', 'C', 'D', 'E', 'F', 'H'); $expected = array('C', 'E', 'F'); $common = $this->implementation->calculate($from, $to); $this->assertEquals($expected, $common); foreach ($this->stress_sizes as $size) { $from = $size < 2 ? array(1) : range(1, $size + 1, 2); $to = $size < 3 ? array(1) : range(1, $size + 1, 3); $expected = $size < 6 ? array(1) : range(1, $size + 1, 6); $common = $this->implementation->calculate($from, $to); $this->assertEquals($expected, $common); } } public function testSingleElementSubsequenceAtStart() { foreach ($this->stress_sizes as $size) { $from = range(1, $size); $to = array_slice($from, 0, 1); $common = $this->implementation->calculate($from, $to); $this->assertEquals($to, $common); } } public function testSingleElementSubsequenceAtMiddle() { foreach ($this->stress_sizes as $size) { $from = range(1, $size); $to = array_slice($from, (int) $size / 2, 1); $common = $this->implementation->calculate($from, $to); $this->assertEquals($to, $common); } } public function testSingleElementSubsequenceAtEnd() { foreach ($this->stress_sizes as $size) { $from = range(1, $size); $to = array_slice($from, $size - 1, 1); $common = $this->implementation->calculate($from, $to); $this->assertEquals($to, $common); } } public function testReversedSequences() { $from = array('A', 'B'); $to = array('B', 'A'); $expected = array('A'); $common = $this->implementation->calculate($from, $to); $this->assertEquals($expected, $common); foreach ($this->stress_sizes as $size) { $from = range(1, $size); $to = array_reverse($from); $common = $this->implementation->calculate($from, $to); $this->assertEquals(array(1), $common); } } } diff-1.4.1/tests/ParserTest.php000066400000000000000000000030151263150154100163710ustar00rootroot00000000000000 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace SebastianBergmann\Diff; use PHPUnit_Framework_TestCase; class ParserTest extends PHPUnit_Framework_TestCase { /** * @var Parser */ private $parser; protected function setUp() { $this->parser = new Parser; } public function testParse() { $content = file_get_contents(__DIR__ . '/fixtures/patch.txt'); $diffs = $this->parser->parse($content); $this->assertCount(1, $diffs); $chunks = $diffs[0]->getChunks(); $this->assertCount(1, $chunks); $this->assertEquals(20, $chunks[0]->getStart()); $this->assertCount(5, $chunks[0]->getLines()); } public function testParseWithMultipleChunks() { $content = file_get_contents(__DIR__ . '/fixtures/patch2.txt'); $diffs = $this->parser->parse($content); $this->assertCount(1, $diffs); $chunks = $diffs[0]->getChunks(); $this->assertCount(3, $chunks); $this->assertEquals(20, $chunks[0]->getStart()); $this->assertEquals(320, $chunks[1]->getStart()); $this->assertEquals(600, $chunks[2]->getStart()); $this->assertCount(5, $chunks[0]->getLines()); $this->assertCount(5, $chunks[1]->getLines()); $this->assertCount(5, $chunks[2]->getLines()); } } diff-1.4.1/tests/fixtures/000077500000000000000000000000001263150154100154365ustar00rootroot00000000000000diff-1.4.1/tests/fixtures/patch.txt000066400000000000000000000003101263150154100172700ustar00rootroot00000000000000diff --git a/Foo.php b/Foo.php index abcdefg..abcdefh 100644 --- a/Foo.php +++ b/Foo.php @@ -20,4 +20,5 @@ class Foo const ONE = 1; const TWO = 2; + const THREE = 3; const FOUR = 4; diff-1.4.1/tests/fixtures/patch2.txt000066400000000000000000000006321263150154100173610ustar00rootroot00000000000000diff --git a/Foo.php b/Foo.php index abcdefg..abcdefh 100644 --- a/Foo.php +++ b/Foo.php @@ -20,4 +20,5 @@ class Foo const ONE = 1; const TWO = 2; + const THREE = 3; const FOUR = 4; @@ -320,4 +320,5 @@ class Foo const A = 'A'; const B = 'B'; + const C = 'C'; const D = 'D'; @@ -600,4 +600,5 @@ class Foo public function doSomething() { + return 'foo'; }