/ */ class P4Cms_Diff_Test extends TestCase { /** * Test diff of assets where results have been manually inspected. */ public function testCompareAssetOne() { $left = file_get_contents(TEST_ASSETS_PATH . '/files/diff-left-1.txt'); $right = file_get_contents(TEST_ASSETS_PATH . '/files/diff-right-1.txt'); $left = str_replace("\r\n", "\n", $left); $right = str_replace("\r\n", "\n", $right); $diff = new P4Cms_Diff; $result = $diff->compare($left, $right); $this->assertTrue($result instanceof P4Cms_Diff_Result); // ensure we got the (previously manually inspected) expected result. $this->assertSame( unserialize(file_get_contents(TEST_ASSETS_PATH . '/files/diff-expected-1.txt')), $result->getRawResult(), "Unexpected diff result." ); // exercise result. $this->assertTrue($result instanceof P4Cms_Diff_Result); $this->assertTrue($result->hasDiffs()); $this->assertSame(4, $result->getDiffCount()); $this->assertSame(9, count($result->getChunks())); $this->assertSame(4, count($result->getDiffChunks())); // exercise chunks. $chunks = $result->getChunks(); $expected = array( array('same', 6), array('change', 39), array('same', 26), array('change', 2), array('same', 214), array('insert', 4), array('same', 120), array('insert', 16), array('same', 46) ); for ($i = 0; $i < count($chunks); $i++) { $chunk = $chunks[$i]; $this->assertSame($expected[$i][0], $chunk->getChunkType()); $this->assertSame($expected[$i][1], $chunk->getMaxValueCount()); $this->assertTrue( call_user_func(array($chunk, 'is' . ucfirst($expected[$i][0]))) ); } // rebuild left-hand from chunks. $lines = array(); foreach ($chunks as $chunk) { $lines = array_merge($lines, $chunk->getLeft()); } $this->assertSame($left, implode("\n", $lines)); // rebuild right-hand from chunks. $lines = array(); foreach ($chunks as $chunk) { $lines = array_merge($lines, $chunk->getRight()); } $this->assertSame($right, implode("\n", $lines)); } /** * Try to compare models with fields. */ public function testCompareModels() { $left = new P4Cms_Model( array( 'one' => "a", 'two' => "b", 'three' => "foo bar\n" . "baz bof\r" . "zig zag\n" ) ); $right = new P4Cms_Model( array( 'one' => "b", 'two' => "b", 'three' => "foo barnacle\r\n" . "baz bof\n" . "ziggery\n" ) ); $diff = new P4Cms_Diff; $result = $diff->compareModels($left, $right); $this->assertTrue($result instanceof P4Cms_Diff_ResultCollection); $keys = array(); foreach ($result as $field => $diffResult) { $keys[] = $field; } $this->assertEquals(array('one', 'two', 'three'), $keys, 'Expected fields in result.'); $this->assertEquals(3, $result->getDiffCount(), 'Expected diff count.'); $this->assertEquals(2, $result['three']->getDiffCount(), 'Expected diffs for three.'); $rawResult = $result['three']->getRawResult(); $this->assertEquals(1, count($rawResult[0]['i']), 'Expected raw result for three.'); // make sure we can skip fields $options = new P4Cms_Diff_OptionsCollection; $options['two'] = new P4Cms_Diff_Options; $options['two']->setSkipped(true); $result = $diff->compareModels($left, $right, $options); $this->assertTrue($result instanceof P4Cms_Diff_ResultCollection); $this->assertEquals(3, $result->getDiffCount(), 'Expected diff count.'); $keys = array(); foreach ($result as $field => $diffResult) { $keys[] = $field; } $this->assertEquals(array('one', 'three'), $keys, 'Expected fields in result.'); $this->assertEquals(2, $result['three']->getDiffCount(), 'Expected diffs for three.'); $rawResult = $result['three']->getRawResult(); $this->assertEquals(1, count($rawResult[0]['i']), 'Expected raw result for three.'); } /** * Test that diff behaves as expected with identical inputs */ public function testCompareIdentical() { $left = file_get_contents(TEST_ASSETS_PATH . '/files/diff-left-1.txt'); $right = $left; $diff = new P4Cms_Diff; $result = $diff->compare($left, $right); $this->assertTrue($result instanceof P4Cms_Diff_Result); $this->assertFalse($result->hasDiffs()); $this->assertSame(0, $result->getDiffCount()); $this->assertSame(1, count($result->getChunks())); $this->assertSame(0, count($result->getDiffChunks())); } /** * Test whitespace detection. */ public function testWhitespaceChanges() { $left = "this is a string"; $right = "this is a string"; $diff = new P4Cms_Diff; $result = $diff->compare($left, $right); $chunks = $result->getDiffChunks(); $this->assertTrue($result->isWhitespaceChange()); $this->assertTrue(current($chunks)->isWhitespaceChange()); $left .= "\nsecond line\nthird line"; $right .= "\nsecond line\ndifferent third line"; $diff = new P4Cms_Diff; $result = $diff->compare($left, $right); $chunks = $result->getDiffChunks(); $this->assertFalse($result->isWhitespaceChange()); $this->assertTrue(current($chunks)->isWhitespaceChange()); $this->assertFalse(end($chunks)->isWhitespaceChange()); // try semantic flag. $left = "this is a string"; $right = "this is astring"; $diff = new P4Cms_Diff; $result = $diff->compare($left, $right); $chunks = $result->getDiffChunks(); $this->assertFalse($result->isWhitespaceChange()); $this->assertTrue($result->isWhitespaceChange(false)); } /** * Test split arguments option. */ public function testSplitArgs() { $left = "foo bar\nzig\nzag"; $right = "foo baz\nzig\nzag"; $diff = new P4Cms_Diff; // default should be lines. $result = $diff->compare($left, $right); $chunks = $result->getChunks(); $this->assertSame(2, count($chunks)); // try with chars. $options = new P4Cms_Diff_Options; $options->setSplitArgs(P4Cms_Diff_Options::PATTERN_CHARS, PREG_SPLIT_NO_EMPTY); $result = $diff->compare($left, $right, $options); $chunks = $result->getChunks(); $this->assertSame(3, count($chunks)); $this->assertSame("foo ba", implode('', $chunks[0]->getLeft())); $this->assertSame("foo ba", implode('', $chunks[0]->getRight())); $this->assertSame("r", implode('', $chunks[1]->getLeft())); $this->assertSame("z", implode('', $chunks[1]->getRight())); $this->assertSame("\nzig\nzag", implode('', $chunks[2]->getLeft())); $this->assertSame("\nzig\nzag", implode('', $chunks[2]->getRight())); } /** * Test sub-diff feature of chunks */ public function testSubDiff() { $left = "foo bar\nzig\nzag"; $right = "foo baz\nzig\nzag"; $diff = new P4Cms_Diff; // initial compare on line boundaries. $result = $diff->compare($left, $right); $chunks = $result->getChunks(); $this->assertSame(2, count($chunks)); // do a sub-diff on first line (defaults to char boundary) $subResult = $chunks[0]->getSubDiff(0); $subChunks = $subResult->getChunks(); $this->assertTrue($subResult instanceof P4Cms_Diff_Result); $this->assertTrue(is_array($subChunks)); $this->assertSame(2, count($subChunks)); $this->assertSame('same', $subChunks[0]->getChunkType()); $this->assertSame("foo ba", implode('', $subChunks[0]->getLeft())); $this->assertSame("foo ba", implode('', $subChunks[0]->getRight())); $this->assertSame('change', $subChunks[1]->getChunkType()); $this->assertSame("r", implode('', $subChunks[1]->getLeft())); $this->assertSame("z", implode('', $subChunks[1]->getRight())); } /** * Test diffing of binaries. */ public function testBinaryDiff() { // two different files. $left = file_get_contents(TEST_ASSETS_PATH . '/files/test1.pdf'); $right = file_get_contents(TEST_ASSETS_PATH . '/files/test2.pdf'); $diff = new P4Cms_Diff; $result = $diff->compareBinaries($left, $right); $chunks = $result->getChunks(); $this->assertTrue($result->hasDiffs()); $this->assertSame(1, $result->getDiffCount()); $this->assertSame(1, count($result->getChunks())); $this->assertSame($left, $chunks[0]->getLeft(0)); $this->assertSame($right, $chunks[0]->getRight(0)); // ensure calling indirectly works. $options = new P4Cms_Diff_Options; $options->setBinaryDiff(true); $result = $diff->compare($left, $right, $options); $chunks = $result->getChunks(); $this->assertTrue($result->hasDiffs()); $this->assertSame(1, $result->getDiffCount()); $this->assertSame(1, count($result->getChunks())); $this->assertSame($left, $chunks[0]->getLeft(0)); $this->assertSame($right, $chunks[0]->getRight(0)); // two identical files. $left = file_get_contents(TEST_ASSETS_PATH . '/images/content-type-icon.png'); $right = $left; $result = $diff->compare($left, $right, $options); $chunks = $result->getChunks(); $this->assertFalse($result->hasDiffs()); $this->assertSame(0, $result->getDiffCount()); $this->assertSame(1, count($result->getChunks())); $this->assertSame($left, $chunks[0]->getLeft(0)); $this->assertSame($right, $chunks[0]->getRight(0)); // empty left (insertion) $left = null; $result = $diff->compare($left, $right, $options); $chunks = $result->getChunks(); $this->assertSame('insert', $chunks[0]->getChunkType()); // empty right (deletion) $left = $right; $right = ''; $result = $diff->compare($left, $right, $options); $chunks = $result->getChunks(); $this->assertSame('delete', $chunks[0]->getChunkType()); } }