/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_diff.py

  • Committer: Martin Pool
  • Date: 2007-09-14 06:31:28 UTC
  • mfrom: (2822 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2823.
  • Revision ID: mbp@sourcefrog.net-20070914063128-0p7mh6zfb4pzdg9p
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
from bzrlib.errors import BinaryFile, NoDiff
25
25
import bzrlib.osutils as osutils
26
26
import bzrlib.patiencediff
27
 
from bzrlib.tests import (TestCase, TestCaseWithTransport,
 
27
import bzrlib._patiencediff_py
 
28
from bzrlib.tests import (Feature, TestCase, TestCaseWithTransport,
28
29
                          TestCaseInTempDir, TestSkipped)
29
30
 
30
31
 
 
32
class _CompiledPatienceDiffFeature(Feature):
 
33
 
 
34
    def _probe(self):
 
35
        try:
 
36
            import bzrlib._patiencediff_c
 
37
        except ImportError:
 
38
            return False
 
39
        return True
 
40
 
 
41
    def feature_name(self):
 
42
        return 'bzrlib._patiencediff_c'
 
43
 
 
44
CompiledPatienceDiffFeature = _CompiledPatienceDiffFeature()
 
45
 
 
46
 
 
47
class _UnicodeFilename(Feature):
 
48
    """Does the filesystem support Unicode filenames?"""
 
49
 
 
50
    def _probe(self):
 
51
        try:
 
52
            os.stat(u'\u03b1')
 
53
        except UnicodeEncodeError:
 
54
            return False
 
55
        except (IOError, OSError):
 
56
            # The filesystem allows the Unicode filename but the file doesn't
 
57
            # exist.
 
58
            return True
 
59
        else:
 
60
            # The filesystem allows the Unicode filename and the file exists,
 
61
            # for some reason.
 
62
            return True
 
63
 
 
64
UnicodeFilename = _UnicodeFilename()
 
65
 
 
66
 
 
67
class TestUnicodeFilename(TestCase):
 
68
 
 
69
    def test_probe_passes(self):
 
70
        """UnicodeFilename._probe passes."""
 
71
        # We can't test much more than that because the behaviour depends
 
72
        # on the platform.
 
73
        UnicodeFilename._probe()
 
74
        
 
75
 
31
76
def udiff_lines(old, new, allow_binary=False):
32
77
    output = StringIO()
33
78
    internal_diff('old', old, 'new', new, output, allow_binary)
441
486
        self.assertContainsRe(diff, '-contents\n'
442
487
                                    '\\+new contents\n')
443
488
 
 
489
    def test_binary_unicode_filenames(self):
 
490
        """Test that contents of files are *not* encoded in UTF-8 when there
 
491
        is a binary file in the diff.
 
492
        """
 
493
        # See https://bugs.launchpad.net/bugs/110092.
 
494
        self.requireFeature(UnicodeFilename)
 
495
 
 
496
        # This bug isn't triggered with cStringIO.
 
497
        from StringIO import StringIO
 
498
        tree = self.make_branch_and_tree('tree')
 
499
        alpha, omega = u'\u03b1', u'\u03c9'
 
500
        alpha_utf8, omega_utf8 = alpha.encode('utf8'), omega.encode('utf8')
 
501
        self.build_tree_contents(
 
502
            [('tree/' + alpha, chr(0)),
 
503
             ('tree/' + omega,
 
504
              ('The %s and the %s\n' % (alpha_utf8, omega_utf8)))])
 
505
        tree.add([alpha], ['file-id'])
 
506
        tree.add([omega], ['file-id-2'])
 
507
        diff_content = StringIO()
 
508
        show_diff_trees(tree.basis_tree(), tree, diff_content)
 
509
        diff = diff_content.getvalue()
 
510
        self.assertContainsRe(diff, r"=== added file '%s'" % alpha_utf8)
 
511
        self.assertContainsRe(
 
512
            diff, "Binary files a/%s.*and b/%s.* differ\n" % (alpha_utf8, alpha_utf8))
 
513
        self.assertContainsRe(diff, r"=== added file '%s'" % omega_utf8)
 
514
        self.assertContainsRe(diff, r"--- a/%s" % (omega_utf8,))
 
515
        self.assertContainsRe(diff, r"\+\+\+ b/%s" % (omega_utf8,))
 
516
 
 
517
    def test_unicode_filename(self):
 
518
        """Test when the filename are unicode."""
 
519
        self.requireFeature(UnicodeFilename)
 
520
 
 
521
        alpha, omega = u'\u03b1', u'\u03c9'
 
522
        autf8, outf8 = alpha.encode('utf8'), omega.encode('utf8')
 
523
 
 
524
        tree = self.make_branch_and_tree('tree')
 
525
        self.build_tree_contents([('tree/ren_'+alpha, 'contents\n')])
 
526
        tree.add(['ren_'+alpha], ['file-id-2'])
 
527
        self.build_tree_contents([('tree/del_'+alpha, 'contents\n')])
 
528
        tree.add(['del_'+alpha], ['file-id-3'])
 
529
        self.build_tree_contents([('tree/mod_'+alpha, 'contents\n')])
 
530
        tree.add(['mod_'+alpha], ['file-id-4'])
 
531
 
 
532
        tree.commit('one', rev_id='rev-1')
 
533
 
 
534
        tree.rename_one('ren_'+alpha, 'ren_'+omega)
 
535
        tree.remove('del_'+alpha)
 
536
        self.build_tree_contents([('tree/add_'+alpha, 'contents\n')])
 
537
        tree.add(['add_'+alpha], ['file-id'])
 
538
        self.build_tree_contents([('tree/mod_'+alpha, 'contents_mod\n')])
 
539
 
 
540
        diff = self.get_diff(tree.basis_tree(), tree)
 
541
        self.assertContainsRe(diff,
 
542
                "=== renamed file 'ren_%s' => 'ren_%s'\n"%(autf8, outf8))
 
543
        self.assertContainsRe(diff, "=== added file 'add_%s'"%autf8)
 
544
        self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
 
545
        self.assertContainsRe(diff, "=== removed file 'del_%s'"%autf8)
444
546
 
445
547
class TestPatienceDiffLib(TestCase):
446
548
 
 
549
    def setUp(self):
 
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
 
555
 
447
556
    def test_unique_lcs(self):
448
 
        unique_lcs = bzrlib.patiencediff.unique_lcs
 
557
        unique_lcs = self._unique_lcs
449
558
        self.assertEquals(unique_lcs('', ''), [])
 
559
        self.assertEquals(unique_lcs('', 'a'), [])
 
560
        self.assertEquals(unique_lcs('a', ''), [])
450
561
        self.assertEquals(unique_lcs('a', 'a'), [(0,0)])
451
562
        self.assertEquals(unique_lcs('a', 'b'), [])
452
563
        self.assertEquals(unique_lcs('ab', 'ab'), [(0,0), (1,1)])
459
570
    def test_recurse_matches(self):
460
571
        def test_one(a, b, matches):
461
572
            test_matches = []
462
 
            bzrlib.patiencediff.recurse_matches(a, b, 0, 0, len(a), len(b),
463
 
                test_matches, 10)
 
573
            self._recurse_matches(
 
574
                a, b, 0, 0, len(a), len(b), test_matches, 10)
464
575
            self.assertEquals(test_matches, matches)
465
576
 
466
577
        test_one(['a', '', 'b', '', 'c'], ['a', 'a', 'b', 'c', 'c'],
467
578
                 [(0, 0), (2, 2), (4, 4)])
468
579
        test_one(['a', 'c', 'b', 'a', 'c'], ['a', 'b', 'c'],
469
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
 
583
        # unique
 
584
        test_one('abcdbce', 'afbcgdbce', [(0,0), (1, 2), (2, 3), (3, 5),
 
585
                                          (4, 6), (5, 7), (6, 8)])
470
586
 
471
587
        # recurse_matches doesn't match non-unique 
472
588
        # lines surrounded by bogus text.
482
598
        def chk_blocks(a, b, expected_blocks):
483
599
            # difflib always adds a signature of the total
484
600
            # length, with no matching entries at the end
485
 
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
 
601
            s = self._PatienceSequenceMatcher(None, a, b)
486
602
            blocks = s.get_matching_blocks()
487
603
            self.assertEquals((len(a), len(b), 0), blocks[-1])
488
604
            self.assertEquals(expected_blocks, blocks[:-1])
490
606
        # Some basic matching tests
491
607
        chk_blocks('', '', [])
492
608
        chk_blocks([], [], [])
 
609
        chk_blocks('abc', '', [])
 
610
        chk_blocks('', 'abc', [])
493
611
        chk_blocks('abcd', 'abcd', [(0, 0, 4)])
494
612
        chk_blocks('abcd', 'abce', [(0, 0, 3)])
495
613
        chk_blocks('eabc', 'abce', [(1, 0, 3)])
534
652
 
535
653
    def test_opcodes(self):
536
654
        def chk_ops(a, b, expected_codes):
537
 
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
 
655
            s = self._PatienceSequenceMatcher(None, a, b)
538
656
            self.assertEquals(expected_codes, s.get_opcodes())
539
657
 
540
658
        chk_ops('', '', [])
541
659
        chk_ops([], [], [])
 
660
        chk_ops('abc', '', [('delete', 0,3, 0,0)])
 
661
        chk_ops('', 'abc', [('insert', 0,0, 0,3)])
542
662
        chk_ops('abcd', 'abcd', [('equal',    0,4, 0,4)])
543
663
        chk_ops('abcd', 'abce', [('equal',   0,3, 0,3),
544
664
                                 ('replace', 3,4, 3,4)
606
726
                 ('equal',   10,11, 8,9)
607
727
                ])
608
728
 
 
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)))
 
733
 
 
734
        chk_ops('', '', [])
 
735
        chk_ops([], [], [])
 
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)
 
741
                                 ]])
 
742
        chk_ops('eabc', 'abce', [[('delete', 0,1, 0,0),
 
743
                                 ('equal',  1,4, 0,3),
 
744
                                 ('insert', 4,4, 3,4)
 
745
                                ]])
 
746
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
 
747
                [[('equal',  3,6, 3,6),
 
748
                  ('insert', 6,6, 6,11),
 
749
                  ('equal',  6,9, 11,14)
 
750
                  ]])
 
751
        chk_ops('abcdefghijklmnop', 'abcdefxydefghijklmnop',
 
752
                [[('equal',  2,6, 2,6),
 
753
                  ('insert', 6,6, 6,11),
 
754
                  ('equal',  6,10, 11,15)
 
755
                  ]], 4)
 
756
        chk_ops('Xabcdef', 'abcdef',
 
757
                [[('delete', 0,1, 0,0),
 
758
                  ('equal',  1,4, 0,3)
 
759
                  ]])
 
760
        chk_ops('abcdef', 'abcdefX',
 
761
                [[('equal',  3,6, 3,6),
 
762
                  ('insert', 6,6, 6,7)
 
763
                  ]])
 
764
 
 
765
 
609
766
    def test_multiple_ranges(self):
610
767
        # There was an earlier bug where we used a bad set of ranges,
611
768
        # this triggers that specific bug, to make sure it doesn't regress
612
769
        def chk_blocks(a, b, expected_blocks):
613
770
            # difflib always adds a signature of the total
614
771
            # length, with no matching entries at the end
615
 
            s = bzrlib.patiencediff.PatienceSequenceMatcher(None, a, b)
 
772
            s = self._PatienceSequenceMatcher(None, a, b)
616
773
            blocks = s.get_matching_blocks()
617
774
            x = blocks.pop()
618
775
            self.assertEquals(x, (len(a), len(b), 0))
680
837
        txt_b = ['hello there\n',
681
838
                 'how are you today?\n']
682
839
        unified_diff = bzrlib.patiencediff.unified_diff
683
 
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
 
840
        psm = self._PatienceSequenceMatcher
684
841
        self.assertEquals([ '---  \n',
685
842
                           '+++  \n',
686
843
                           '@@ -1,3 +1,2 @@\n',
728
885
                                 sequencematcher=psm)))
729
886
 
730
887
 
 
888
class TestPatienceDiffLib_c(TestPatienceDiffLib):
 
889
 
 
890
    _test_needs_features = [CompiledPatienceDiffFeature]
 
891
 
 
892
    def setUp(self):
 
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
 
899
 
 
900
 
731
901
class TestPatienceDiffLibFiles(TestCaseInTempDir):
732
902
 
 
903
    def setUp(self):
 
904
        super(TestPatienceDiffLibFiles, self).setUp()
 
905
        self._PatienceSequenceMatcher = \
 
906
            bzrlib._patiencediff_py.PatienceSequenceMatcher_py
 
907
 
733
908
    def test_patience_unified_diff_files(self):
734
909
        txt_a = ['hello there\n',
735
910
                 'world\n',
740
915
        open('b1', 'wb').writelines(txt_b)
741
916
 
742
917
        unified_diff_files = bzrlib.patiencediff.unified_diff_files
743
 
        psm = bzrlib.patiencediff.PatienceSequenceMatcher
 
918
        psm = self._PatienceSequenceMatcher
744
919
        self.assertEquals(['--- a1 \n',
745
920
                           '+++ b1 \n',
746
921
                           '@@ -1,3 +1,2 @@\n',
791
966
                          ]
792
967
                          , list(unified_diff_files('a2', 'b2',
793
968
                                 sequencematcher=psm)))
 
969
 
 
970
 
 
971
class TestPatienceDiffLibFiles_c(TestPatienceDiffLibFiles):
 
972
 
 
973
    _test_needs_features = [CompiledPatienceDiffFeature]
 
974
 
 
975
    def setUp(self):
 
976
        super(TestPatienceDiffLibFiles_c, self).setUp()
 
977
        import bzrlib._patiencediff_c
 
978
        self._PatienceSequenceMatcher = \
 
979
            bzrlib._patiencediff_c.PatienceSequenceMatcher_c
 
980
 
 
981
 
 
982
class TestUsingCompiledIfAvailable(TestCase):
 
983
 
 
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)
 
989
        else:
 
990
            from bzrlib._patiencediff_py import PatienceSequenceMatcher_py
 
991
            self.assertIs(PatienceSequenceMatcher_py,
 
992
                          bzrlib.patiencediff.PatienceSequenceMatcher)
 
993
 
 
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)
 
999
        else:
 
1000
            from bzrlib._patiencediff_py import unique_lcs_py
 
1001
            self.assertIs(unique_lcs_py,
 
1002
                          bzrlib.patiencediff.unique_lcs)
 
1003
 
 
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)
 
1009
        else:
 
1010
            from bzrlib._patiencediff_py import recurse_matches_py
 
1011
            self.assertIs(recurse_matches_py,
 
1012
                          bzrlib.patiencediff.recurse_matches)