24
24
from bzrlib.errors import BinaryFile, NoDiff
25
25
import bzrlib.osutils as osutils
26
26
import bzrlib.patiencediff
27
import bzrlib._patiencediff_py
27
28
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
28
29
TestCaseInTempDir, TestSkipped)
32
class _CompiledPatienceDiffFeature(Feature):
36
import bzrlib._patiencediff_c
41
def feature_name(self):
42
return 'bzrlib._patiencediff_c'
44
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
31
47
class _UnicodeFilename(Feature):
32
48
"""Does the filesystem support Unicode filenames?"""
531
547
class TestPatienceDiffLib(TestCase):
550
super(TestPatienceDiffLib, self).setUp()
551
self._unique_lcs = bzrlib._patiencediff_py.unique_lcs_py
552
self._recurse_matches = bzrlib._patiencediff_py.recurse_matches_py
553
self._PatienceSequenceMatcher = \
554
bzrlib._patiencediff_py.PatienceSequenceMatcher_py
533
556
def test_unique_lcs(self):
534
unique_lcs = bzrlib.patiencediff.unique_lcs
557
unique_lcs = self._unique_lcs
535
558
self.assertEquals(unique_lcs('', ''), [])
559
self.assertEquals(unique_lcs('', 'a'), [])
560
self.assertEquals(unique_lcs('a', ''), [])
536
561
self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
537
562
self.assertEquals(unique_lcs('a', 'b'), [])
538
563
self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
545
570
def test_recurse_matches(self):
546
571
def test_one(a, b, matches):
547
572
test_matches = []
548
bzrlib.patiencediff.recurse_matches(a, b, 0, 0, len(a), len(b),
573
self._recurse_matches(
574
a, b, 0, 0, len(a), len(b), test_matches, 10)
550
575
self.assertEquals(test_matches, matches)
552
577
test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
553
578
[(0, 0), (2, 2), (4, 4)])
554
579
test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
555
580
[(0, 0), (2, 1), (4, 2)])
581
# Even though 'bc' is not unique globally, and is surrounded by
582
# non-matching lines, we should still match, because they are locally
584
test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
585
(4, 6), (5, 7), (6, 8)])
557
587
# recurse_matches doesn't match non-unique
558
588
# lines surrounded by bogus text.
568
598
def chk_blocks(a, b, expected_blocks):
569
599
# difflib always adds a signature of the total
570
600
# length, with no matching entries at the end
571
s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
601
s = self._PatienceSequenceMatcher(None, a, b)
572
602
blocks = s.get_matching_blocks()
573
603
self.assertEquals((len(a), len(b), 0), blocks[-1])
574
604
self.assertEquals(expected_blocks, blocks[:-1])
576
606
# Some basic matching tests
577
607
chk_blocks('', '', [])
578
608
chk_blocks([], [], [])
609
chk_blocks('abc', '', [])
610
chk_blocks('', 'abc', [])
579
611
chk_blocks('abcd', 'abcd', [(0, 0, 4)])
580
612
chk_blocks('abcd', 'abce', [(0, 0, 3)])
581
613
chk_blocks('eabc', 'abce', [(1, 0, 3)])
621
653
def test_opcodes(self):
622
654
def chk_ops(a, b, expected_codes):
623
s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
655
s = self._PatienceSequenceMatcher(None, a, b)
624
656
self.assertEquals(expected_codes, s.get_opcodes())
626
658
chk_ops('', '', [])
627
659
chk_ops([], [], [])
660
chk_ops('abc', '', [('delete', 0,3, 0,0)])
661
chk_ops('', 'abc', [('insert', 0,0, 0,3)])
628
662
chk_ops('abcd', 'abcd', [('equal', 0,4, 0,4)])
629
663
chk_ops('abcd', 'abce', [('equal', 0,3, 0,3),
630
664
('replace', 3,4, 3,4)
692
726
('equal', 10,11, 8,9)
729
def test_grouped_opcodes(self):
730
def chk_ops(a, b, expected_codes, n=3):
731
s = self._PatienceSequenceMatcher(None, a, b)
732
self.assertEquals(expected_codes, list(s.get_grouped_opcodes(n)))
736
chk_ops('abc', '', [[('delete', 0,3, 0,0)]])
737
chk_ops('', 'abc', [[('insert', 0,0, 0,3)]])
738
chk_ops('abcd', 'abcd', [])
739
chk_ops('abcd', 'abce', [[('equal', 0,3, 0,3),
740
('replace', 3,4, 3,4)
742
chk_ops('eabc', 'abce', [[('delete', 0,1, 0,0),
746
chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
747
[[('equal', 3,6, 3,6),
748
('insert', 6,6, 6,11),
749
('equal', 6,9, 11,14)
751
chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
752
[[('equal', 2,6, 2,6),
753
('insert', 6,6, 6,11),
754
('equal', 6,10, 11,15)
756
chk_ops('Xabcdef', 'abcdef',
757
[[('delete', 0,1, 0,0),
760
chk_ops('abcdef', 'abcdefX',
761
[[('equal', 3,6, 3,6),
695
766
def test_multiple_ranges(self):
696
767
# There was an earlier bug where we used a bad set of ranges,
697
768
# this triggers that specific bug, to make sure it doesn't regress
698
769
def chk_blocks(a, b, expected_blocks):
699
770
# difflib always adds a signature of the total
700
771
# length, with no matching entries at the end
701
s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
772
s = self._PatienceSequenceMatcher(None, a, b)
702
773
blocks = s.get_matching_blocks()
704
775
self.assertEquals(x, (len(a), len(b), 0))
814
885
sequencematcher=psm)))
888
class TestPatienceDiffLib_c(TestPatienceDiffLib):
890
_test_needs_features = [CompiledPatienceDiffFeature]
893
super(TestPatienceDiffLib_c, self).setUp()
894
import bzrlib._patiencediff_c
895
self._unique_lcs = bzrlib._patiencediff_c.unique_lcs_c
896
self._recurse_matches = bzrlib._patiencediff_c.recurse_matches_c
897
self._PatienceSequenceMatcher = \
898
bzrlib._patiencediff_c.PatienceSequenceMatcher_c
817
901
class TestPatienceDiffLibFiles(TestCaseInTempDir):
904
super(TestPatienceDiffLibFiles, self).setUp()
905
self._PatienceSequenceMatcher = \
906
bzrlib._patiencediff_py.PatienceSequenceMatcher_py
819
908
def test_patience_unified_diff_files(self):
820
909
txt_a = ['hello there\n',
826
915
open('b1', 'wb').writelines(txt_b)
828
917
unified_diff_files = bzrlib.patiencediff.unified_diff_files
829
psm = bzrlib.patiencediff.PatienceSequenceMatcher
918
psm = self._PatienceSequenceMatcher
830
919
self.assertEquals(['--- a1 \n',
832
921
'@@ -1,3 +1,2 @@\n',
878
967
, list(unified_diff_files('a2', 'b2',
879
968
sequencematcher=psm)))
971
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
973
_test_needs_features = [CompiledPatienceDiffFeature]
976
super(TestPatienceDiffLibFiles_c, self).setUp()
977
import bzrlib._patiencediff_c
978
self._PatienceSequenceMatcher = \
979
bzrlib._patiencediff_c.PatienceSequenceMatcher_c
982
class TestUsingCompiledIfAvailable(TestCase):
984
def test_PatienceSequenceMatcher(self):
985
if CompiledPatienceDiffFeature.available():
986
from bzrlib._patiencediff_c import PatienceSequenceMatcher_c
987
self.assertIs(PatienceSequenceMatcher_c,
988
bzrlib.patiencediff.PatienceSequenceMatcher)
990
from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
991
self.assertIs(PatienceSequenceMatcher_py,
992
bzrlib.patiencediff.PatienceSequenceMatcher)
994
def test_unique_lcs(self):
995
if CompiledPatienceDiffFeature.available():
996
from bzrlib._patiencediff_c import unique_lcs_c
997
self.assertIs(unique_lcs_c,
998
bzrlib.patiencediff.unique_lcs)
1000
from bzrlib._patiencediff_py import unique_lcs_py
1001
self.assertIs(unique_lcs_py,
1002
bzrlib.patiencediff.unique_lcs)
1004
def test_recurse_matches(self):
1005
if CompiledPatienceDiffFeature.available():
1006
from bzrlib._patiencediff_c import recurse_matches_c
1007
self.assertIs(recurse_matches_c,
1008
bzrlib.patiencediff.recurse_matches)
1010
from bzrlib._patiencediff_py import recurse_matches_py
1011
self.assertIs(recurse_matches_py,
1012
bzrlib.patiencediff.recurse_matches)