~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_merge.py

  • Committer: Mark Hammond
  • Date: 2009-01-12 01:55:34 UTC
  • mto: (3995.8.2 prepare-1.12)
  • mto: This revision was merged to the branch mainline in revision 4007.
  • Revision ID: mhammond@skippinet.com.au-20090112015534-yfxg50p7mpds9j4v
Include all .html files from the tortoise doc directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
import os
18
18
from StringIO import StringIO
29
29
    transform,
30
30
    versionedfile,
31
31
    )
 
32
from bzrlib.branch import Branch
32
33
from bzrlib.conflicts import ConflictList, TextConflict
33
 
from bzrlib.errors import UnrelatedBranches, NoCommits
 
34
from bzrlib.errors import UnrelatedBranches, NoCommits, BzrCommandError
34
35
from bzrlib.merge import transform_tree, merge_inner, _PlanMerge
35
36
from bzrlib.osutils import pathjoin, file_kind
36
37
from bzrlib.tests import TestCaseWithTransport, TestCaseWithMemoryTransport
 
38
from bzrlib.trace import (enable_test_log, disable_test_log)
37
39
from bzrlib.workingtree import WorkingTree
38
40
 
39
41
 
87
89
        self.failIfExists('bar')
88
90
        wt2 = WorkingTree.open('.') # opens branch2
89
91
        self.assertEqual([tip], wt2.get_parent_ids())
90
 
 
 
92
        
91
93
    def test_pending_with_null(self):
92
94
        """When base is forced to revno 0, parent_ids are set"""
93
95
        wt2 = self.test_unrelated()
94
96
        wt1 = WorkingTree.open('.')
95
97
        br1 = wt1.branch
96
98
        br1.fetch(wt2.branch)
97
 
        # merge all of branch 2 into branch 1 even though they
 
99
        # merge all of branch 2 into branch 1 even though they 
98
100
        # are not related.
99
101
        wt1.merge_from_branch(wt2.branch, wt2.last_revision(), 'null:')
100
102
        self.assertEqual([br1.last_revision(), wt2.branch.last_revision()],
148
150
        self.addCleanup(tree_b.unlock)
149
151
        tree_a.commit(message="hello again")
150
152
        log = StringIO()
151
 
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(),
 
153
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
152
154
                    this_tree=tree_b, ignore_zero=True)
153
 
        self.failUnless('All changes applied successfully.\n' not in
154
 
            self.get_log())
 
155
        log = self._get_log(keep_log_file=True)
 
156
        self.failUnless('All changes applied successfully.\n' not in log)
155
157
        tree_b.revert()
156
 
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(),
 
158
        merge_inner(tree_b.branch, tree_a, tree_b.basis_tree(), 
157
159
                    this_tree=tree_b, ignore_zero=False)
158
 
        self.failUnless('All changes applied successfully.\n' in self.get_log())
 
160
        log = self._get_log(keep_log_file=True)
 
161
        self.failUnless('All changes applied successfully.\n' in log)
159
162
 
160
163
    def test_merge_inner_conflicts(self):
161
164
        tree_a = self.make_branch_and_tree('a')
216
219
        tree_a.add('file')
217
220
        tree_a.commit('commit base')
218
221
        # basis_tree() is only guaranteed to be valid as long as it is actually
219
 
        # the basis tree. This test commits to the tree after grabbing basis,
220
 
        # so we go to the repository.
 
222
        # the basis tree. This mutates the tree after grabbing basis, so go to
 
223
        # the repository.
221
224
        base_tree = tree_a.branch.repository.revision_tree(tree_a.last_revision())
222
225
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
223
226
        self.build_tree_contents([('tree_a/file', 'content_2')])
224
227
        tree_a.commit('commit other')
225
228
        other_tree = tree_a.basis_tree()
226
 
        # 'file' is now missing but isn't altered in any commit in b so no
227
 
        # change should be applied.
228
229
        os.unlink('tree_b/file')
229
230
        merge_inner(tree_b.branch, other_tree, base_tree, this_tree=tree_b)
230
231
 
247
248
        self.assertEqual(tree_b.conflicts(),
248
249
                         [conflicts.ContentsConflict('file',
249
250
                          file_id='file-id')])
250
 
 
 
251
    
251
252
    def test_merge_type_registry(self):
252
253
        merge_type_option = option.Option.OPTIONS['merge-type']
253
 
        self.assertFalse('merge4' in [x[0] for x in
 
254
        self.assertFalse('merge4' in [x[0] for x in 
254
255
                        merge_type_option.iter_switches()])
255
256
        registry = _mod_merge.get_merge_type_registry()
256
257
        registry.register_lazy('merge4', 'bzrlib.merge', 'Merge4Merger',
257
258
                               'time-travelling merge')
258
 
        self.assertTrue('merge4' in [x[0] for x in
 
259
        self.assertTrue('merge4' in [x[0] for x in 
259
260
                        merge_type_option.iter_switches()])
260
261
        registry.remove('merge4')
261
 
        self.assertFalse('merge4' in [x[0] for x in
 
262
        self.assertFalse('merge4' in [x[0] for x in 
262
263
                        merge_type_option.iter_switches()])
263
264
 
264
265
    def test_merge_other_moves_we_deleted(self):
312
313
        merger.do_merge()
313
314
        self.assertEqual(tree_a.get_parent_ids(), [tree_b.last_revision()])
314
315
 
315
 
    def test_Merger_defaults_to_DummyProgress(self):
316
 
        branch = self.make_branch('branch')
317
 
        merger = _mod_merge.Merger(branch, pb=None)
318
 
        self.assertIsInstance(merger._pb, progress.DummyProgress)
319
 
 
320
316
    def prepare_cherrypick(self):
321
317
        """Prepare a pair of trees for cherrypicking tests.
322
318
 
522
518
        self.add_uncommitted_version(('root', 'C:'), [('root', 'A')], 'fabg')
523
519
        return _PlanMerge('B:', 'C:', self.plan_merge_vf, ('root',))
524
520
 
525
 
    def test_base_from_plan(self):
526
 
        self.setup_plan_merge()
527
 
        plan = self.plan_merge_vf.plan_merge('B', 'C')
528
 
        pwm = versionedfile.PlanWeaveMerge(plan)
529
 
        self.assertEqual(['a\n', 'b\n', 'c\n'], pwm.base_from_plan())
530
 
 
531
521
    def test_unique_lines(self):
532
522
        plan = self.setup_plan_merge()
533
523
        self.assertEqual(plan._unique_lines(
728
718
 
729
719
    def test_plan_merge_insert_order(self):
730
720
        """Weave merges are sensitive to the order of insertion.
731
 
 
 
721
        
732
722
        Specifically for overlapping regions, it effects which region gets put
733
723
        'first'. And when a user resolves an overlapping merge, if they use the
734
724
        same ordering, then the lines match the parents, if they don't only
831
821
                          ('unchanged', 'f\n'),
832
822
                          ('unchanged', 'g\n')],
833
823
                         list(plan))
834
 
        plan = self.plan_merge_vf.plan_lca_merge('F', 'G')
835
 
        # This is one of the main differences between plan_merge and
836
 
        # plan_lca_merge. plan_lca_merge generates a conflict for 'x => z',
837
 
        # because 'x' was not present in one of the bases. However, in this
838
 
        # case it is spurious because 'x' does not exist in the global base A.
839
 
        self.assertEqual([
840
 
                          ('unchanged', 'h\n'),
841
 
                          ('unchanged', 'a\n'),
842
 
                          ('conflicted-a', 'x\n'),
843
 
                          ('new-b', 'z\n'),
844
 
                          ('unchanged', 'c\n'),
845
 
                          ('unchanged', 'd\n'),
846
 
                          ('unchanged', 'y\n'),
847
 
                          ('unchanged', 'f\n'),
848
 
                          ('unchanged', 'g\n')],
849
 
                         list(plan))
850
 
 
851
 
    def test_criss_cross_flip_flop(self):
852
 
        # This is specificly trying to trigger problems when using limited
853
 
        # ancestry and weaves. The ancestry graph looks like:
854
 
        #       XX      unused ancestor, should not show up in the weave
855
 
        #       |
856
 
        #       A       Unique LCA
857
 
        #      / \  
858
 
        #     B   C     B & C both introduce a new line
859
 
        #     |\ /|  
860
 
        #     | X |  
861
 
        #     |/ \| 
862
 
        #     D   E     B & C are both merged, so both are common ancestors
863
 
        #               In the process of merging, both sides order the new
864
 
        #               lines differently
865
 
        #
866
 
        self.add_rev('root', 'XX', [], 'qrs')
867
 
        self.add_rev('root', 'A', ['XX'], 'abcdef')
868
 
        self.add_rev('root', 'B', ['A'], 'abcdgef')
869
 
        self.add_rev('root', 'C', ['A'], 'abcdhef')
870
 
        self.add_rev('root', 'D', ['B', 'C'], 'abcdghef')
871
 
        self.add_rev('root', 'E', ['C', 'B'], 'abcdhgef')
872
 
        plan = list(self.plan_merge_vf.plan_merge('D', 'E'))
873
 
        self.assertEqual([
874
 
                          ('unchanged', 'a\n'),
875
 
                          ('unchanged', 'b\n'),
876
 
                          ('unchanged', 'c\n'),
877
 
                          ('unchanged', 'd\n'),
878
 
                          ('new-b', 'h\n'),
879
 
                          ('unchanged', 'g\n'),
880
 
                          ('killed-b', 'h\n'),
881
 
                          ('unchanged', 'e\n'),
882
 
                          ('unchanged', 'f\n'),
883
 
                         ], plan)
884
 
        pwm = versionedfile.PlanWeaveMerge(plan)
885
 
        self.assertEqualDiff('\n'.join('abcdghef') + '\n',
886
 
                             ''.join(pwm.base_from_plan()))
887
 
        # Reversing the order reverses the merge plan, and final order of 'hg'
888
 
        # => 'gh'
889
 
        plan = list(self.plan_merge_vf.plan_merge('E', 'D'))
890
 
        self.assertEqual([
891
 
                          ('unchanged', 'a\n'),
892
 
                          ('unchanged', 'b\n'),
893
 
                          ('unchanged', 'c\n'),
894
 
                          ('unchanged', 'd\n'),
895
 
                          ('new-b', 'g\n'),
896
 
                          ('unchanged', 'h\n'),
897
 
                          ('killed-b', 'g\n'),
898
 
                          ('unchanged', 'e\n'),
899
 
                          ('unchanged', 'f\n'),
900
 
                         ], plan)
901
 
        pwm = versionedfile.PlanWeaveMerge(plan)
902
 
        self.assertEqualDiff('\n'.join('abcdhgef') + '\n',
903
 
                             ''.join(pwm.base_from_plan()))
904
 
        # This is where lca differs, in that it (fairly correctly) determines
905
 
        # that there is a conflict because both sides resolved the merge
906
 
        # differently
907
 
        plan = list(self.plan_merge_vf.plan_lca_merge('D', 'E'))
908
 
        self.assertEqual([
909
 
                          ('unchanged', 'a\n'),
910
 
                          ('unchanged', 'b\n'),
911
 
                          ('unchanged', 'c\n'),
912
 
                          ('unchanged', 'd\n'),
913
 
                          ('conflicted-b', 'h\n'),
914
 
                          ('unchanged', 'g\n'),
915
 
                          ('conflicted-a', 'h\n'),
916
 
                          ('unchanged', 'e\n'),
917
 
                          ('unchanged', 'f\n'),
918
 
                         ], plan)
919
 
        pwm = versionedfile.PlanWeaveMerge(plan)
920
 
        self.assertEqualDiff('\n'.join('abcdgef') + '\n',
921
 
                             ''.join(pwm.base_from_plan()))
922
 
        # Reversing it changes what line is doubled, but still gives a
923
 
        # double-conflict
924
 
        plan = list(self.plan_merge_vf.plan_lca_merge('E', 'D'))
925
 
        self.assertEqual([
926
 
                          ('unchanged', 'a\n'),
927
 
                          ('unchanged', 'b\n'),
928
 
                          ('unchanged', 'c\n'),
929
 
                          ('unchanged', 'd\n'),
930
 
                          ('conflicted-b', 'g\n'),
931
 
                          ('unchanged', 'h\n'),
932
 
                          ('conflicted-a', 'g\n'),
933
 
                          ('unchanged', 'e\n'),
934
 
                          ('unchanged', 'f\n'),
935
 
                         ], plan)
936
 
        pwm = versionedfile.PlanWeaveMerge(plan)
937
 
        self.assertEqualDiff('\n'.join('abcdhef') + '\n',
938
 
                             ''.join(pwm.base_from_plan()))
939
824
 
940
825
    def assertRemoveExternalReferences(self, filtered_parent_map,
941
826
                                       child_map, tails, parent_map):
1141
1026
                         ], list(plan))
1142
1027
 
1143
1028
 
 
1029
class TestMergeImplementation(object):
 
1030
 
 
1031
    def do_merge(self, target_tree, source_tree, **kwargs):
 
1032
        merger = _mod_merge.Merger.from_revision_ids(progress.DummyProgress(),
 
1033
            target_tree, source_tree.last_revision(),
 
1034
            other_branch=source_tree.branch)
 
1035
        merger.merge_type=self.merge_type
 
1036
        for name, value in kwargs.items():
 
1037
            setattr(merger, name, value)
 
1038
        merger.do_merge()
 
1039
 
 
1040
    def test_merge_specific_file(self):
 
1041
        this_tree = self.make_branch_and_tree('this')
 
1042
        this_tree.lock_write()
 
1043
        self.addCleanup(this_tree.unlock)
 
1044
        self.build_tree_contents([
 
1045
            ('this/file1', 'a\nb\n'),
 
1046
            ('this/file2', 'a\nb\n')
 
1047
        ])
 
1048
        this_tree.add(['file1', 'file2'])
 
1049
        this_tree.commit('Added files')
 
1050
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
 
1051
        self.build_tree_contents([
 
1052
            ('other/file1', 'a\nb\nc\n'),
 
1053
            ('other/file2', 'a\nb\nc\n')
 
1054
        ])
 
1055
        other_tree.commit('modified both')
 
1056
        self.build_tree_contents([
 
1057
            ('this/file1', 'd\na\nb\n'),
 
1058
            ('this/file2', 'd\na\nb\n')
 
1059
        ])
 
1060
        this_tree.commit('modified both')
 
1061
        self.do_merge(this_tree, other_tree, interesting_files=['file1'])
 
1062
        self.assertFileEqual('d\na\nb\nc\n', 'this/file1')
 
1063
        self.assertFileEqual('d\na\nb\n', 'this/file2')
 
1064
 
 
1065
    def test_merge_move_and_change(self):
 
1066
        this_tree = self.make_branch_and_tree('this')
 
1067
        this_tree.lock_write()
 
1068
        self.addCleanup(this_tree.unlock)
 
1069
        self.build_tree_contents([
 
1070
            ('this/file1', 'line 1\nline 2\nline 3\nline 4\n'),
 
1071
        ])
 
1072
        this_tree.add('file1',)
 
1073
        this_tree.commit('Added file')
 
1074
        other_tree = this_tree.bzrdir.sprout('other').open_workingtree()
 
1075
        self.build_tree_contents([
 
1076
            ('other/file1', 'line 1\nline 2 to 2.1\nline 3\nline 4\n'),
 
1077
        ])
 
1078
        other_tree.commit('Changed 2 to 2.1')
 
1079
        self.build_tree_contents([
 
1080
            ('this/file1', 'line 1\nline 3\nline 2\nline 4\n'),
 
1081
        ])
 
1082
        this_tree.commit('Swapped 2 & 3')
 
1083
        self.do_merge(this_tree, other_tree)
 
1084
        self.assertFileEqual('line 1\n'
 
1085
            '<<<<<<< TREE\n'
 
1086
            'line 3\n'
 
1087
            'line 2\n'
 
1088
            '=======\n'
 
1089
            'line 2 to 2.1\n'
 
1090
            'line 3\n'
 
1091
            '>>>>>>> MERGE-SOURCE\n'
 
1092
            'line 4\n', 'this/file1')
 
1093
 
 
1094
 
 
1095
class TestMerge3Merge(TestCaseWithTransport, TestMergeImplementation):
 
1096
 
 
1097
    merge_type = _mod_merge.Merge3Merger
 
1098
 
 
1099
 
 
1100
class TestWeaveMerge(TestCaseWithTransport, TestMergeImplementation):
 
1101
 
 
1102
    merge_type = _mod_merge.WeaveMerger
 
1103
 
 
1104
 
 
1105
class TestLCAMerge(TestCaseWithTransport, TestMergeImplementation):
 
1106
 
 
1107
    merge_type = _mod_merge.LCAMerger
 
1108
 
 
1109
    def test_merge_move_and_change(self):
 
1110
        self.expectFailure("lca merge doesn't conflict for move and change",
 
1111
            super(TestLCAMerge, self).test_merge_move_and_change)
 
1112
 
 
1113
 
1144
1114
class LoggingMerger(object):
1145
1115
    # These seem to be the required attributes
1146
1116
    requires_base = False
1212
1182
 
1213
1183
class TestMergerInMemory(TestMergerBase):
1214
1184
 
1215
 
    def test_cache_trees_with_revision_ids_None(self):
1216
 
        merger = self.make_Merger(self.setup_simple_graph(), 'C-id')
1217
 
        original_cache = dict(merger._cached_trees)
1218
 
        merger.cache_trees_with_revision_ids([None])
1219
 
        self.assertEqual(original_cache, merger._cached_trees)
1220
 
 
1221
 
    def test_cache_trees_with_revision_ids_no_revision_id(self):
1222
 
        merger = self.make_Merger(self.setup_simple_graph(), 'C-id')
1223
 
        original_cache = dict(merger._cached_trees)
1224
 
        tree = self.make_branch_and_memory_tree('tree')
1225
 
        merger.cache_trees_with_revision_ids([tree])
1226
 
        self.assertEqual(original_cache, merger._cached_trees)
1227
 
 
1228
 
    def test_cache_trees_with_revision_ids_having_revision_id(self):
1229
 
        merger = self.make_Merger(self.setup_simple_graph(), 'C-id')
1230
 
        original_cache = dict(merger._cached_trees)
1231
 
        tree = merger.this_branch.repository.revision_tree('B-id')
1232
 
        original_cache['B-id'] = tree
1233
 
        merger.cache_trees_with_revision_ids([tree])
1234
 
        self.assertEqual(original_cache, merger._cached_trees)
1235
 
 
1236
1185
    def test_find_base(self):
1237
1186
        merger = self.make_Merger(self.setup_simple_graph(), 'C-id')
1238
1187
        self.assertEqual('A-id', merger.base_rev_id)
1432
1381
        self.assertEqual('A-id', merge_obj.base_tree.get_revision_id())
1433
1382
 
1434
1383
        entries = list(merge_obj._entries_lca())
 
1384
        root_id = 'a-root-id'
1435
1385
        self.assertEqual([], entries)
1436
1386
 
1437
1387
    def test_not_in_other(self):
1460
1410
        #       B C  B nothing, C deletes foo
1461
1411
        #       |X|
1462
1412
        #       D E  D restores foo (same as B), E leaves it deleted
1463
 
        # Analysis:
1464
 
        #   A => B, no changes
1465
 
        #   A => C, delete foo (C should supersede B)
1466
 
        #   C => D, restore foo
1467
 
        #   C => E, no changes
1468
 
        # D would then win 'cleanly' and no record would be given
 
1413
        # We should emit an entry for this
1469
1414
        builder = self.get_builder()
1470
1415
        builder.build_snapshot('A-id', None,
1471
1416
            [('add', (u'', 'a-root-id', 'directory', None)),
1478
1423
        merge_obj = self.make_merge_obj(builder, 'E-id')
1479
1424
 
1480
1425
        entries = list(merge_obj._entries_lca())
1481
 
        self.assertEqual([], entries)
1482
 
 
1483
 
    def test_not_in_other_mod_in_lca1_not_in_lca2(self):
1484
 
        #       A    base, introduces 'foo'
1485
 
        #       |\
1486
 
        #       B C  B changes 'foo', C deletes foo
1487
 
        #       |X|
1488
 
        #       D E  D restores foo (same as B), E leaves it deleted (as C)
1489
 
        # Analysis:
1490
 
        #   A => B, modified foo
1491
 
        #   A => C, delete foo, C does not supersede B
1492
 
        #   B => D, no changes
1493
 
        #   C => D, resolve in favor of B
1494
 
        #   B => E, resolve in favor of E
1495
 
        #   C => E, no changes
1496
 
        # In this case, we have a conflict of how the changes were resolved. E
1497
 
        # picked C and D picked B, so we should issue a conflict
1498
 
        builder = self.get_builder()
1499
 
        builder.build_snapshot('A-id', None,
1500
 
            [('add', (u'', 'a-root-id', 'directory', None)),
1501
 
             ('add', (u'foo', 'foo-id', 'file', 'content\n'))])
1502
 
        builder.build_snapshot('B-id', ['A-id'], [
1503
 
            ('modify', ('foo-id', 'new-content\n'))])
1504
 
        builder.build_snapshot('C-id', ['A-id'],
1505
 
            [('unversion', 'foo-id')])
1506
 
        builder.build_snapshot('E-id', ['C-id', 'B-id'], [])
1507
 
        builder.build_snapshot('D-id', ['B-id', 'C-id'], [])
1508
 
        merge_obj = self.make_merge_obj(builder, 'E-id')
1509
 
 
1510
 
        entries = list(merge_obj._entries_lca())
1511
1426
        root_id = 'a-root-id'
1512
1427
        self.assertEqual([('foo-id', True,
1513
1428
                           ((root_id, [root_id, None]), None, root_id),
1516
1431
                         ], entries)
1517
1432
 
1518
1433
    def test_only_in_one_lca(self):
1519
 
        #   A   add only root
1520
 
        #   |\
1521
 
        #   B C B nothing, C add file
1522
 
        #   |X|
1523
 
        #   D E D still has nothing, E removes file
1524
 
        # Analysis:
1525
 
        #   B => D, no change
1526
 
        #   C => D, removed the file
1527
 
        #   B => E, no change
1528
 
        #   C => E, removed the file
1529
 
        # Thus D & E have identical changes, and this is a no-op
1530
 
        # Alternatively:
1531
 
        #   A => B, no change
1532
 
        #   A => C, add file, thus C supersedes B
1533
 
        #   w/ C=BASE, D=THIS, E=OTHER we have 'happy convergence'
1534
1434
        builder = self.get_builder()
1535
1435
        builder.build_snapshot('A-id', None,
1536
1436
            [('add', (u'', 'a-root-id', 'directory', None))])
1543
1443
        merge_obj = self.make_merge_obj(builder, 'E-id')
1544
1444
 
1545
1445
        entries = list(merge_obj._entries_lca())
1546
 
        self.assertEqual([], entries)
 
1446
        root_id = 'a-root-id'
 
1447
        self.assertEqual([('a-id', True,
 
1448
                           ((None, [None, root_id]), None, None),
 
1449
                           ((None, [None, u'a']), None, None),
 
1450
                           ((None, [None, False]), None, None)),
 
1451
                         ], entries)
1547
1452
 
1548
1453
    def test_only_in_other(self):
1549
1454
        builder = self.get_builder()
1773
1678
        merge_obj = self.make_merge_obj(builder, 'E-id')
1774
1679
 
1775
1680
        entries = list(merge_obj._entries_lca())
 
1681
        root_id = 'a-root-id'
1776
1682
        self.expectFailure("We don't detect that LCA resolution was the"
1777
1683
                           " same on both sides",
1778
1684
            self.assertEqual, [], entries)
1833
1739
             ('add', (u'a', 'a-id', 'directory', None))])
1834
1740
        merge_obj = self.make_merge_obj(builder, 'E-id')
1835
1741
        entries = list(merge_obj._entries_lca())
 
1742
        root_id = 'a-root-id'
1836
1743
        # Only the kind was changed (content)
1837
1744
        self.assertEqual([], entries)
1838
1745
 
2204
2111
        wt.merge_from_branch(wt.branch, 'C-id')
2205
2112
        wt.commit('D merges B & C', rev_id='D-id')
2206
2113
        conflicts = wt.merge_from_branch(wt.branch, to_revision='F-id')
2207
 
        self.assertEqual(0, conflicts)
 
2114
        self.expectFailure("Merge3Merger doesn't use lcas for symlink content",
 
2115
            self.assertEqual, 0, conflicts)
2208
2116
        self.assertEqual('bing', wt.get_symlink_target('foo-id'))
2209
2117
 
2210
2118
    def test_renamed_symlink(self):
2471
2379
        # TODO: We need to use the per-file graph to properly select a BASE
2472
2380
        #       before this will work. Or at least use the LCA trees to find
2473
2381
        #       the appropriate content base. (which is B, not A).
2474
 
        self.assertEqual('base content\n', wt.get_file_text('foo-id'))
 
2382
        self.expectFailure("Merge3Merger doesn't recognize reverted content",
 
2383
            self.assertEqual, 'base content\n', wt.get_file_text('foo-id'))
2475
2384
 
2476
2385
    def test_other_modified_content(self):
2477
2386
        builder = self.get_builder()
2487
2396
            [('modify', ('foo-id', 'F content\n'))]) # Override B content
2488
2397
        builder.build_snapshot('D-id', ['B-id', 'C-id'], [])
2489
2398
        wt, conflicts = self.do_merge(builder, 'F-id')
 
2399
        self.expectFailure("Merge3Merger only uses BASE for content",
 
2400
            self.assertEqual, 'F content\n', wt.get_file_text('foo-id'))
2490
2401
        self.assertEqual(0, conflicts)
2491
2402
        self.assertEqual('F content\n', wt.get_file_text('foo-id'))
2492
2403