~bzr-pqm/bzr/bzr.dev

4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.14.8 by Aaron Bentley
Added test_commit.py
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.14.8 by Aaron Bentley
Added test_commit.py
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.14.8 by Aaron Bentley
Added test_commit.py
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.14.8 by Aaron Bentley
Added test_commit.py
16
17
18
import os
19
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
20
from bzrlib import (
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
21
    branchbuilder,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
22
    bzrdir,
23
    conflicts,
24
    errors,
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
25
    option,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
26
    tests,
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
27
    workingtree,
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
28
    )
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
29
from bzrlib.tests import script
1185.14.8 by Aaron Bentley
Added test_commit.py
30
1534.10.4 by Aaron Bentley
Implemented conflict serialization
31
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
32
def load_tests(standard_tests, module, loader):
33
    result = loader.suiteClass()
34
35
    sp_tests, remaining_tests = tests.split_suite_by_condition(
36
        standard_tests, tests.condition_isinstance((
4597.7.4 by Vincent Ladeuil
Abstract the test class some more to address more conflict
37
                TestParametrizedResolveConflicts,
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
38
                )))
4597.7.16 by Vincent Ladeuil
Some cleanup.
39
    # Each test class defines its own scenarios. This is needed for
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
40
    # TestResolvePathConflictBefore531967 that verifies that the same tests as
41
    # TestResolvePathConflict still pass.
42
    for test in tests.iter_suite_tests(sp_tests):
43
        tests.apply_scenarios(test, test.scenarios(), result)
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
44
45
    # No parametrization for the remaining tests
46
    result.addTests(remaining_tests)
47
48
    return result
49
50
1185.14.8 by Aaron Bentley
Added test_commit.py
51
# TODO: Test commit with some added, and added-but-missing files
1534.4.26 by Robert Collins
Move working tree initialisation out from Branch.initialize, deprecated Branch.initialize to Branch.create.
52
# RBC 20060124 is that not tested in test_commit.py ?
1185.14.8 by Aaron Bentley
Added test_commit.py
53
1666.1.4 by Robert Collins
* 'Metadir' is now the default disk format. This improves behaviour in
54
# The order of 'path' here is important - do not let it
55
# be a sorted list.
2309.4.13 by John Arbash Meinel
Conflicts go through Stanza so the need to be aware of utf8 versus unicode file ids.
56
# u'\xe5' == a with circle
57
# '\xc3\xae' == u'\xee' == i with hat
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
58
# So these are u'path' and 'id' only with a circle and a hat. (shappo?)
59
example_conflicts = conflicts.ConflictList(
60
    [conflicts.MissingParent('Not deleting', u'p\xe5thg', '\xc3\xaedg'),
61
     conflicts.ContentsConflict(u'p\xe5tha', None, '\xc3\xaeda'),
62
     conflicts.TextConflict(u'p\xe5tha'),
63
     conflicts.PathConflict(u'p\xe5thb', u'p\xe5thc', '\xc3\xaedb'),
64
     conflicts.DuplicateID('Unversioned existing file',
65
                           u'p\xe5thc', u'p\xe5thc2',
66
                           '\xc3\xaedc', '\xc3\xaedc'),
67
    conflicts.DuplicateEntry('Moved existing file to',
68
                             u'p\xe5thdd.moved', u'p\xe5thd',
69
                             '\xc3\xaedd', None),
70
    conflicts.ParentLoop('Cancelled move', u'p\xe5the', u'p\xe5th2e',
71
                         None, '\xc3\xaed2e'),
72
    conflicts.UnversionedParent('Versioned directory',
73
                                u'p\xe5thf', '\xc3\xaedf'),
74
    conflicts.NonDirectoryParent('Created directory',
75
                                 u'p\xe5thg', '\xc3\xaedg'),
1534.10.22 by Aaron Bentley
Got ConflictList implemented
76
])
1534.10.4 by Aaron Bentley
Implemented conflict serialization
77
78
4597.2.2 by Vincent Ladeuil
Cleanup conflict tests.
79
class TestConflicts(tests.TestCaseWithTransport):
1185.14.8 by Aaron Bentley
Added test_commit.py
80
81
    def test_conflicts(self):
82
        """Conflicts are detected properly"""
4597.2.3 by Vincent Ladeuil
More cleanup.
83
        # Use BzrDirFormat6 so we can fake conflicts
84
        tree = self.make_branch_and_tree('.', format=bzrdir.BzrDirFormat6())
85
        self.build_tree_contents([('hello', 'hello world4'),
86
                                  ('hello.THIS', 'hello world2'),
87
                                  ('hello.BASE', 'hello world1'),
88
                                  ('hello.OTHER', 'hello world3'),
89
                                  ('hello.sploo.BASE', 'yellowworld'),
90
                                  ('hello.sploo.OTHER', 'yellowworld2'),
91
                                  ])
2255.2.61 by John Arbash Meinel
Find callers of list_files() and make sure the tree is always locked.
92
        tree.lock_read()
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
93
        self.assertLength(6, list(tree.list_files()))
2255.2.61 by John Arbash Meinel
Find callers of list_files() and make sure the tree is always locked.
94
        tree.unlock()
4597.2.3 by Vincent Ladeuil
More cleanup.
95
        tree_conflicts = tree.conflicts()
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
96
        self.assertLength(2, tree_conflicts)
4597.2.3 by Vincent Ladeuil
More cleanup.
97
        self.assertTrue('hello' in tree_conflicts[0].path)
98
        self.assertTrue('hello.sploo' in tree_conflicts[1].path)
99
        conflicts.restore('hello')
100
        conflicts.restore('hello.sploo')
4597.2.28 by Vincent Ladeuil
Use assertLength where appropriate.
101
        self.assertLength(0, tree.conflicts())
1185.35.1 by Aaron Bentley
Implemented conflicts.restore
102
        self.assertFileEqual('hello world2', 'hello')
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
103
        self.assertFalse(os.path.lexists('hello.sploo'))
4597.2.3 by Vincent Ladeuil
More cleanup.
104
        self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
105
        self.assertRaises(errors.NotConflicted,
106
                          conflicts.restore, 'hello.sploo')
1534.10.4 by Aaron Bentley
Implemented conflict serialization
107
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
108
    def test_resolve_conflict_dir(self):
109
        tree = self.make_branch_and_tree('.')
4597.2.3 by Vincent Ladeuil
More cleanup.
110
        self.build_tree_contents([('hello', 'hello world4'),
111
                                  ('hello.THIS', 'hello world2'),
112
                                  ('hello.BASE', 'hello world1'),
113
                                  ])
114
        os.mkdir('hello.OTHER')
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
115
        tree.add('hello', 'q')
4597.2.3 by Vincent Ladeuil
More cleanup.
116
        l = conflicts.ConflictList([conflicts.TextConflict('hello')])
1558.12.9 by Aaron Bentley
Handle resolving conflicts with directories properly
117
        l.remove_files(tree)
118
1551.15.58 by Aaron Bentley
Status honours selected paths for conflicts (#127606)
119
    def test_select_conflicts(self):
120
        tree = self.make_branch_and_tree('.')
4597.2.3 by Vincent Ladeuil
More cleanup.
121
        clist = conflicts.ConflictList
122
123
        def check_select(not_selected, selected, paths, **kwargs):
124
            self.assertEqual(
125
                (not_selected, selected),
126
                tree_conflicts.select_conflicts(tree, paths, **kwargs))
127
128
        foo = conflicts.ContentsConflict('foo')
129
        bar = conflicts.ContentsConflict('bar')
130
        tree_conflicts = clist([foo, bar])
131
132
        check_select(clist([bar]), clist([foo]), ['foo'])
133
        check_select(clist(), tree_conflicts,
134
                     [''], ignore_misses=True, recurse=True)
135
136
        foobaz  = conflicts.ContentsConflict('foo/baz')
137
        tree_conflicts = clist([foobaz, bar])
138
139
        check_select(clist([bar]), clist([foobaz]),
140
                     ['foo'], ignore_misses=True, recurse=True)
141
142
        qux = conflicts.PathConflict('qux', 'foo/baz')
143
        tree_conflicts = clist([qux])
144
145
        check_select(clist(), tree_conflicts,
146
                     ['foo'], ignore_misses=True, recurse=True)
147
        check_select (tree_conflicts, clist(), ['foo'], ignore_misses=True)
1551.15.58 by Aaron Bentley
Status honours selected paths for conflicts (#127606)
148
3017.2.1 by Aaron Bentley
Revert now resolves conflicts recursively (#102739)
149
    def test_resolve_conflicts_recursive(self):
150
        tree = self.make_branch_and_tree('.')
151
        self.build_tree(['dir/', 'dir/hello'])
152
        tree.add(['dir', 'dir/hello'])
4597.2.3 by Vincent Ladeuil
More cleanup.
153
154
        dirhello = conflicts.ConflictList([conflicts.TextConflict('dir/hello')])
155
        tree.set_conflicts(dirhello)
156
157
        conflicts.resolve(tree, ['dir'], recursive=False, ignore_misses=True)
158
        self.assertEqual(dirhello, tree.conflicts())
159
160
        conflicts.resolve(tree, ['dir'], recursive=True, ignore_misses=True)
161
        self.assertEqual(conflicts.ConflictList([]), tree.conflicts())
4773.1.1 by Vincent Ladeuil
Cleanup imports in test_conflicts
162
163
4597.3.43 by Vincent Ladeuil
Cleanups, ready to record.
164
class TestConflictStanzas(tests.TestCase):
165
166
    def test_stanza_roundtrip(self):
167
        # write and read our example stanza.
168
        stanza_iter = example_conflicts.to_stanzas()
169
        processed = conflicts.ConflictList.from_stanzas(stanza_iter)
170
        for o, p in zip(processed, example_conflicts):
171
            self.assertEqual(o, p)
172
173
            self.assertIsInstance(o.path, unicode)
174
175
            if o.file_id is not None:
176
                self.assertIsInstance(o.file_id, str)
177
178
            conflict_path = getattr(o, 'conflict_path', None)
179
            if conflict_path is not None:
180
                self.assertIsInstance(conflict_path, unicode)
181
182
            conflict_file_id = getattr(o, 'conflict_file_id', None)
183
            if conflict_file_id is not None:
184
                self.assertIsInstance(conflict_file_id, str)
185
186
    def test_stanzification(self):
187
        for stanza in example_conflicts.to_stanzas():
188
            if 'file_id' in stanza:
189
                # In Stanza form, the file_id has to be unicode.
190
                self.assertStartsWith(stanza['file_id'], u'\xeed')
191
            self.assertStartsWith(stanza['path'], u'p\xe5th')
192
            if 'conflict_path' in stanza:
193
                self.assertStartsWith(stanza['conflict_path'], u'p\xe5th')
194
            if 'conflict_file_id' in stanza:
195
                self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
196
197
4597.3.74 by Vincent Ladeuil
Add a FIXME about rewriting shell-like tests into real whitebox tests.
198
# FIXME: The shell-like tests should be converted to real whitebox tests... or
199
# moved to a blackbox module -- vila 20100205
200
4597.7.11 by Vincent Ladeuil
Fix #531967 by creating helpers for PathConflicts when a deletion
201
# FIXME: test missing for multiple conflicts
202
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
203
# FIXME: Tests missing for DuplicateID conflict type
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
204
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
205
206
    preamble = None # The setup script set by daughter classes
207
208
    def setUp(self):
209
        super(TestResolveConflicts, self).setUp()
210
        self.run_script(self.preamble)
211
212
213
class TestResolveTextConflicts(TestResolveConflicts):
214
    # TBC
215
    pass
216
217
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
218
def mirror_scenarios(base_scenarios):
219
    """Return a list of mirrored scenarios.
220
221
    Each scenario in base_scenarios is duplicated switching the roles of 'this'
222
    and 'other'
223
    """
224
    scenarios = []
4597.10.14 by Vincent Ladeuil
Some more cleanup and typos.
225
    for common, (lname, ldict), (rname, rdict) in base_scenarios:
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
226
        a = tests.multiply_scenarios([(lname, dict(_this=ldict))],
227
                                     [(rname, dict(_other=rdict))])
228
        b = tests.multiply_scenarios([(rname, dict(_this=rdict))],
229
                                     [(lname, dict(_other=ldict))])
230
        # Inject the common parameters in all scenarios
231
        for name, d in a + b:
232
            d.update(common)
233
        scenarios.extend(a + b)
234
    return scenarios
235
236
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
237
# FIXME: Get rid of parametrized (in the class name) once we delete
238
# TestResolveConflicts -- vila 20100308
4597.7.4 by Vincent Ladeuil
Abstract the test class some more to address more conflict
239
class TestParametrizedResolveConflicts(tests.TestCaseWithTransport):
4597.7.18 by Vincent Ladeuil
Start addressing Andrew's concerns.
240
    """This class provides a base to test single conflict resolution.
241
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
242
    Since all conflict objects are created with specific semantics for their
243
    attributes, each class should implement the necessary functions and
244
    attributes described below.
245
246
    Each class should define the scenarios that create the expected (single)
247
    conflict.
248
249
    Each scenario describes:
250
    * how to create 'base' tree (and revision)
251
    * how to create 'left' tree (and revision, parent rev 'base')
252
    * how to create 'right' tree (and revision, parent rev 'base')
253
    * how to check that changes in 'base'->'left' have been taken
254
    * how to check that changes in 'base'->'right' have been taken
255
256
    From each base scenario, we generate two concrete scenarios where:
257
    * this=left, other=right
258
    * this=right, other=left
259
260
    Then the test case verifies each concrete scenario by:
261
    * creating a branch containing the 'base', 'this' and 'other' revisions
262
    * creating a working tree for the 'this' revision
263
    * performing the merge of 'other' into 'this'
264
    * verifying the expected conflict was generated
265
    * resolving with --take-this or --take-other, and running the corresponding
266
      checks (for either 'base'->'this', or 'base'->'other')
267
268
    :cvar _conflict_type: The expected class of the generated conflict.
269
270
    :cvar _assert_conflict: A method receiving the working tree and the
271
        conflict object and checking its attributes.
272
4597.10.9 by Vincent Ladeuil
More doc.
273
    :cvar _base_actions: The branchbuilder actions to create the 'base'
274
        revision.
275
276
    :cvar _this: The dict related to 'base' -> 'this'. It contains at least:
277
      * 'actions': The branchbuilder actions to create the 'this'
278
          revision.
4597.10.10 by Vincent Ladeuil
Fix typo.
279
      * 'check': how to check the changes after resolution with --take-this.
4597.10.9 by Vincent Ladeuil
More doc.
280
281
    :cvar _other: The dict related to 'base' -> 'other'. It contains at least:
282
      * 'actions': The branchbuilder actions to create the 'other'
283
          revision.
4597.10.10 by Vincent Ladeuil
Fix typo.
284
      * 'check': how to check the changes after resolution with --take-other.
4597.7.18 by Vincent Ladeuil
Start addressing Andrew's concerns.
285
    """
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
286
4597.7.16 by Vincent Ladeuil
Some cleanup.
287
    # Set by daughter classes
288
    _conflict_type = None
289
    _assert_conflict = None
290
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
291
    # Set by load_tests
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
292
    _base_actions = None
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
293
    _this = None
294
    _other = None
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
295
4597.10.13 by Vincent Ladeuil
Turns scenarios() methods into static methods.
296
    @staticmethod
297
    def scenarios():
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
298
        """Return the scenario list for the conflict type defined by the class.
299
300
        Each scenario is of the form:
301
        (common, (left_name, left_dict), (right_name, right_dict))
302
303
        * common is a dict
304
305
        * left_name and right_name are the scenario names that will be combined
306
307
        * left_dict and right_dict are the attributes specific to each half of
308
          the scenario. They should include at least 'actions' and 'check' and
309
          will be available as '_this' and '_other' test instance attributes.
310
311
        Daughters classes are free to add their specific attributes as they see
4597.10.9 by Vincent Ladeuil
More doc.
312
        fit in any of the three dicts.
4597.10.12 by Vincent Ladeuil
Some more doc.
313
314
        This is a class method so that load_tests can find it.
315
4597.10.14 by Vincent Ladeuil
Some more cleanup and typos.
316
        '_base_actions' in the common dict, 'actions' and 'check' in the left
4597.10.12 by Vincent Ladeuil
Some more doc.
317
        and right dicts use names that map to methods in the test classes. Some
318
        prefixes are added to these names to get the correspong methods (see
319
        _get_actions() and _get_check()). The motivation here is to avoid
320
        collisions in the class namespace.
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
321
        """
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
322
        # Only concrete classes return actual scenarios
323
        return []
324
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
325
    def setUp(self):
4597.7.4 by Vincent Ladeuil
Abstract the test class some more to address more conflict
326
        super(TestParametrizedResolveConflicts, self).setUp()
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
327
        builder = self.make_branch_builder('trunk')
328
        builder.start_series()
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
329
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
330
        # Create an empty trunk
331
        builder.build_snapshot('start', None, [
332
                ('add', ('', 'root-id', 'directory', ''))])
333
        # Add a minimal base content
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
334
        base_actions = self._get_actions(self._base_actions)()
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
335
        builder.build_snapshot('base', ['start'], base_actions)
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
336
        # Modify the base content in branch
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
337
        actions_other = self._get_actions(self._other['actions'])()
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
338
        builder.build_snapshot('other', ['base'], actions_other)
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
339
        # Modify the base content in trunk
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
340
        actions_this = self._get_actions(self._this['actions'])()
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
341
        builder.build_snapshot('this', ['base'], actions_this)
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
342
        # builder.get_branch() tip is now 'this'
4597.7.6 by Vincent Ladeuil
Cleanup TestParametrizedResolveConflicts some more.
343
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
344
        builder.finish_series()
345
        self.builder = builder
346
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
347
    def _get_actions(self, name):
348
        return getattr(self, 'do_%s' % name)
349
350
    def _get_check(self, name):
351
        return getattr(self, 'check_%s' % name)
352
4597.2.24 by Vincent Ladeuil
Translate one more test.
353
    def _merge_other_into_this(self):
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
354
        b = self.builder.get_branch()
355
        wt = b.bzrdir.sprout('branch').open_workingtree()
356
        wt.merge_from_branch(b, 'other')
4597.2.24 by Vincent Ladeuil
Translate one more test.
357
        return wt
358
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
359
    def assertConflict(self, wt):
360
        confs = wt.conflicts()
361
        self.assertLength(1, confs)
362
        c = confs[0]
363
        self.assertIsInstance(c, self._conflict_type)
364
        self._assert_conflict(wt, c)
365
366
    def _get_resolve_path_arg(self, wt, action):
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
367
        raise NotImplementedError(self._get_resolve_path_arg)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
368
369
    def check_resolved(self, wt, action):
370
        path = self._get_resolve_path_arg(wt, action)
371
        conflicts.resolve(wt, [path], action=action)
372
        # Check that we don't have any conflicts nor unknown left
373
        self.assertLength(0, wt.conflicts())
374
        self.assertLength(0, list(wt.unknowns()))
375
4597.2.24 by Vincent Ladeuil
Translate one more test.
376
    def test_resolve_taking_this(self):
377
        wt = self._merge_other_into_this()
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
378
        self.assertConflict(wt)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
379
        self.check_resolved(wt, 'take_this')
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
380
        check_this = self._get_check(self._this['check'])
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
381
        check_this()
4597.2.24 by Vincent Ladeuil
Translate one more test.
382
383
    def test_resolve_taking_other(self):
384
        wt = self._merge_other_into_this()
4597.7.7 by Vincent Ladeuil
Reproduce bug #531967 on various aspects.
385
        self.assertConflict(wt)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
386
        self.check_resolved(wt, 'take_other')
4597.10.7 by Vincent Ladeuil
Simplify scenarios mirroring and give a better docstring for TestParametrizedResolveConflicts.
387
        check_other = self._get_check(self._other['check'])
4597.2.26 by Vincent Ladeuil
Fix bug #529968 by renaming the kept file on content conflicts.
388
        check_other()
4597.3.28 by Vincent Ladeuil
Implement --interactive for ContentsConflict.
389
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
390
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
391
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
392
4597.7.16 by Vincent Ladeuil
Some cleanup.
393
    _conflict_type = conflicts.ContentsConflict,
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
394
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
395
    # Set by load_tests from scenarios()
396
    # path and file-id for the file involved in the conflict
397
    _path = None
398
    _file_id = None
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
399
4597.10.13 by Vincent Ladeuil
Turns scenarios() methods into static methods.
400
    @staticmethod
401
    def scenarios():
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
402
        base_scenarios = [
4597.10.12 by Vincent Ladeuil
Some more doc.
403
            # File modified/deleted
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
404
            (dict(_base_actions='create_file',
405
                  _path='file', _file_id='file-id'),
4597.10.12 by Vincent Ladeuil
Some more doc.
406
             ('file_modified',
407
              dict(actions='modify_file', check='file_has_more_content')),
408
             ('file_deleted',
409
              dict(actions='delete_file', check='file_doesnt_exist')),),
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
410
            ]
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
411
        return mirror_scenarios(base_scenarios)
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
412
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
413
    def do_create_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
414
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
415
416
    def do_modify_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
417
        return [('modify', ('file-id', 'trunk content\nmore content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
418
419
    def check_file_has_more_content(self):
420
        self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
421
422
    def do_delete_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
423
        return [('unversion', 'file-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
424
425
    def check_file_doesnt_exist(self):
426
        self.failIfExists('branch/file')
427
428
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
429
        return self._path
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
430
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
431
    def assertContentsConflict(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
432
        self.assertEqual(self._file_id, c.file_id)
433
        self.assertEqual(self._path, c.path)
4597.7.16 by Vincent Ladeuil
Some cleanup.
434
    _assert_conflict = assertContentsConflict
435
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
436
437
class TestResolvePathConflict(TestParametrizedResolveConflicts):
438
4597.7.16 by Vincent Ladeuil
Some cleanup.
439
    _conflict_type = conflicts.PathConflict,
440
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
441
    def do_nothing(self):
442
        return []
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
443
4597.10.13 by Vincent Ladeuil
Turns scenarios() methods into static methods.
444
    @staticmethod
445
    def scenarios():
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
446
        # Each side dict additionally defines:
447
        # - path path involved (can be '<deleted>')
448
        # - file-id involved
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
449
        base_scenarios = [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
450
            # File renamed/deleted
451
            (dict(_base_actions='create_file'),
452
             ('file_renamed',
453
              dict(actions='rename_file', check='file_renamed',
454
                   path='new-file', file_id='file-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
455
             ('file_deleted',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
456
              dict(actions='delete_file', check='file_doesnt_exist',
457
                   # PathConflicts deletion handling requires a special
458
                   # hard-coded value
459
                   path='<deleted>', file_id='file-id')),),
460
            # File renamed/renamed differently
461
            (dict(_base_actions='create_file'),
462
             ('file_renamed',
463
              dict(actions='rename_file', check='file_renamed',
464
                   path='new-file', file_id='file-id')),
4597.8.4 by Vincent Ladeuil
Delete PathConflict bloackbox tests.
465
             ('file_renamed2',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
466
              dict(actions='rename_file2', check='file_renamed2',
467
                   path='new-file2', file_id='file-id')),),
468
            # Dir renamed/deleted
469
            (dict(_base_actions='create_dir'),
470
             ('dir_renamed',
471
              dict(actions='rename_dir', check='dir_renamed',
472
                   path='new-dir', file_id='dir-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
473
             ('dir_deleted',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
474
              dict(actions='delete_dir', check='dir_doesnt_exist',
475
                   # PathConflicts deletion handling requires a special
476
                   # hard-coded value
477
                   path='<deleted>', file_id='dir-id')),),
478
            # Dir renamed/renamed differently
479
            (dict(_base_actions='create_dir'),
480
             ('dir_renamed',
481
              dict(actions='rename_dir', check='dir_renamed',
482
                   path='new-dir', file_id='dir-id')),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
483
             ('dir_renamed2',
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
484
              dict(actions='rename_dir2', check='dir_renamed2',
485
                   path='new-dir2', file_id='dir-id')),),
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
486
        ]
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
487
        return mirror_scenarios(base_scenarios)
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
488
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
489
    def do_create_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
490
        return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
491
492
    def do_create_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
493
        return [('add', ('dir', 'dir-id', 'directory', ''))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
494
495
    def do_rename_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
496
        return [('rename', ('file', 'new-file'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
497
498
    def check_file_renamed(self):
499
        self.failIfExists('branch/file')
500
        self.failUnlessExists('branch/new-file')
501
502
    def do_rename_file2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
503
        return [('rename', ('file', 'new-file2'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
504
505
    def check_file_renamed2(self):
506
        self.failIfExists('branch/file')
507
        self.failUnlessExists('branch/new-file2')
508
509
    def do_rename_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
510
        return [('rename', ('dir', 'new-dir'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
511
512
    def check_dir_renamed(self):
513
        self.failIfExists('branch/dir')
514
        self.failUnlessExists('branch/new-dir')
515
516
    def do_rename_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
517
        return [('rename', ('dir', 'new-dir2'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
518
519
    def check_dir_renamed2(self):
520
        self.failIfExists('branch/dir')
521
        self.failUnlessExists('branch/new-dir2')
522
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
523
    def do_delete_file(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
524
        return [('unversion', 'file-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
525
526
    def check_file_doesnt_exist(self):
527
        self.failIfExists('branch/file')
528
529
    def do_delete_dir(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
530
        return [('unversion', 'dir-id')]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
531
532
    def check_dir_doesnt_exist(self):
533
        self.failIfExists('branch/dir')
534
535
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
536
        tpath = self._this['path']
537
        opath = self._other['path']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
538
        if tpath == '<deleted>':
539
            path = opath
540
        else:
541
            path = tpath
542
        return path
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
543
544
    def assertPathConflict(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
545
        tpath = self._this['path']
546
        tfile_id = self._this['file_id']
547
        opath = self._other['path']
548
        ofile_id = self._other['file_id']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
549
        self.assertEqual(tfile_id, ofile_id) # Sanity check
550
        self.assertEqual(tfile_id, c.file_id)
551
        self.assertEqual(tpath, c.path)
552
        self.assertEqual(opath, c.conflict_path)
4597.7.16 by Vincent Ladeuil
Some cleanup.
553
    _assert_conflict = assertPathConflict
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
554
555
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
556
class TestResolvePathConflictBefore531967(TestResolvePathConflict):
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
557
    """Same as TestResolvePathConflict but a specific conflict object.
558
    """
559
4597.7.16 by Vincent Ladeuil
Some cleanup.
560
    def assertPathConflict(self, c):
4597.7.17 by Vincent Ladeuil
Add a scenario and activate the compatibility tests.
561
        # We create a conflict object as it was created before the fix and
562
        # inject it into the working tree, the test will exercise the
563
        # compatibility code.
564
        old_c = conflicts.PathConflict('<deleted>', self._item_path,
565
                                       file_id=None)
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
566
        wt.set_conflicts(conflicts.ConflictList([old_c]))
4597.7.10 by Vincent Ladeuil
Define scenarios by test classes.
567
568
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
569
class TestResolveDuplicateEntry(TestParametrizedResolveConflicts):
570
571
    _conflict_type = conflicts.DuplicateEntry,
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
572
4597.10.13 by Vincent Ladeuil
Turns scenarios() methods into static methods.
573
    @staticmethod
574
    def scenarios():
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
575
        # Each side dict additionally defines:
576
        # - path involved
577
        # - file-id involved
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
578
        base_scenarios = [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
579
            # File created with different file-ids
580
            (dict(_base_actions='nothing'),
581
             ('filea_created',
582
              dict(actions='create_file_a', check='file_content_a',
583
                   path='file', file_id='file-a-id')),
584
             ('fileb_created',
585
              dict(actions='create_file_b', check='file_content_b',
586
                   path='file', file_id='file-b-id')),),
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
587
            ]
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
588
        return mirror_scenarios(base_scenarios)
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
589
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
590
    def do_nothing(self):
591
        return []
592
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
593
    def do_create_file_a(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
594
        return [('add', ('file', 'file-a-id', 'file', 'file a content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
595
596
    def check_file_content_a(self):
597
        self.assertFileEqual('file a content\n', 'branch/file')
598
599
    def do_create_file_b(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
600
        return [('add', ('file', 'file-b-id', 'file', 'file b content\n'))]
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
601
602
    def check_file_content_b(self):
603
        self.assertFileEqual('file b content\n', 'branch/file')
604
605
    def _get_resolve_path_arg(self, wt, action):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
606
        return self._this['path']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
607
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
608
    def assertDuplicateEntry(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
609
        tpath = self._this['path']
610
        tfile_id = self._this['file_id']
611
        opath = self._other['path']
612
        ofile_id = self._other['file_id']
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
613
        self.assertEqual(tpath, opath) # Sanity check
614
        self.assertEqual(tfile_id, c.file_id)
615
        self.assertEqual(tpath + '.moved', c.path)
616
        self.assertEqual(tpath, c.conflict_path)
4597.8.5 by Vincent Ladeuil
Replace DuplicateEntry blackbox tests by whitebox ones.
617
    _assert_conflict = assertDuplicateEntry
4597.3.19 by Vincent Ladeuil
Some failing tests.
618
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
619
620
class TestResolveUnversionedParent(TestResolveConflicts):
621
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
622
    # FIXME: Add the reverse tests: dir deleted in trunk, file added in branch
623
4597.3.30 by Vincent Ladeuil
Light changes learned while starting to understand multiple conflicts on
624
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
625
    # tests MissingParent resolution :-/
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
626
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
627
$ bzr init trunk
628
$ cd trunk
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
629
$ mkdir dir
630
$ bzr add dir
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
631
$ bzr commit -m 'Create trunk'
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
632
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
633
$ echo 'trunk content' >dir/file
634
$ bzr add dir/file
635
$ bzr commit -m 'Add dir/file in trunk'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
636
637
$ bzr branch . -r 1 ../branch
638
$ cd ../branch
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
639
$ bzr rm dir
640
$ bzr commit -m 'Remove dir in branch'
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
641
642
$ bzr merge ../trunk
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
643
2>+N  dir/
644
2>+N  dir/file
645
2>Conflict adding files to dir.  Created directory.
646
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
647
2>2 conflicts encountered.
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
648
"""
649
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
650
    def test_take_this(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
651
        self.run_script("""
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
652
$ bzr rm dir  --force
653
$ bzr resolve dir
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
654
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
655
""")
656
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
657
    def test_take_other(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
658
        self.run_script("""
4597.3.29 by Vincent Ladeuil
Fix bogus tests.
659
$ bzr resolve dir
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
660
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
661
""")
662
663
664
class TestResolveMissingParent(TestResolveConflicts):
665
666
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
667
$ bzr init trunk
668
$ cd trunk
669
$ mkdir dir
670
$ echo 'trunk content' >dir/file
671
$ bzr add
672
$ bzr commit -m 'Create trunk'
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
673
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
674
$ echo 'trunk content' >dir/file2
675
$ bzr add dir/file2
676
$ bzr commit -m 'Add dir/file2 in branch'
677
678
$ bzr branch . -r 1 ../branch
679
$ cd ../branch
680
$ bzr rm dir/file --force
681
$ bzr rm dir
682
$ bzr commit -m 'Remove dir/file'
683
684
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
685
2>+N  dir/
686
2>+N  dir/file2
687
2>Conflict adding files to dir.  Created directory.
688
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
689
2>2 conflicts encountered.
690
"""
691
692
    def test_keep_them_all(self):
693
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
694
$ bzr resolve dir
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
696
""")
697
698
    def test_adopt_child(self):
699
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
700
$ bzr mv dir/file2 file2
701
$ bzr rm dir --force
702
$ bzr resolve dir
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
704
""")
705
706
    def test_kill_them_all(self):
707
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
708
$ bzr rm dir --force
709
$ bzr resolve dir
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
711
""")
712
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
713
    def test_resolve_taking_this(self):
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
714
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
715
$ bzr resolve --take-this dir
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
717
""")
718
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
719
    def test_resolve_taking_other(self):
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
720
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
721
$ bzr resolve --take-other dir
4597.3.31 by Vincent Ladeuil
Implement --interactive for MissingParent.
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
723
""")
724
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
725
726
class TestResolveDeletingParent(TestResolveConflicts):
727
728
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
729
$ bzr init trunk
730
$ cd trunk
731
$ mkdir dir
732
$ echo 'trunk content' >dir/file
733
$ bzr add
734
$ bzr commit -m 'Create trunk'
4597.2.23 by Vincent Ladeuil
Start translating blackbox tests into whitebox ones.
735
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
736
$ bzr rm dir/file --force
737
$ bzr rm dir --force
738
$ bzr commit -m 'Remove dir/file'
739
740
$ bzr branch . -r 1 ../branch
741
$ cd ../branch
742
$ echo 'branch content' >dir/file2
743
$ bzr add dir/file2
744
$ bzr commit -m 'Add dir/file2 in branch'
745
746
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
747
2>-D  dir/file
748
2>Conflict: can't delete dir because it is not empty.  Not deleting.
749
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
750
2>2 conflicts encountered.
751
"""
752
753
    def test_keep_them_all(self):
754
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
755
$ bzr resolve dir
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
757
""")
758
759
    def test_adopt_child(self):
760
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
761
$ bzr mv dir/file2 file2
762
$ bzr rm dir --force
763
$ bzr resolve dir
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
765
""")
766
767
    def test_kill_them_all(self):
768
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
769
$ bzr rm dir --force
770
$ bzr resolve dir
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
772
""")
773
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
774
    def test_resolve_taking_this(self):
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
775
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
776
$ bzr resolve --take-this dir
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
778
""")
779
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
780
    def test_resolve_taking_other(self):
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
781
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
782
$ bzr resolve --take-other dir
4597.3.32 by Vincent Ladeuil
Implement --interactive for DeletingParent noting the inconsistency.
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
784
""")
785
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
786
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
787
class TestResolveParentLoop(TestParametrizedResolveConflicts):
788
789
    _conflict_type = conflicts.ParentLoop,
4597.10.1 by Vincent Ladeuil
Refactor to better handle various conflict types.
790
791
    _this_args = None
792
    _other_args = None
793
4597.10.13 by Vincent Ladeuil
Turns scenarios() methods into static methods.
794
    @staticmethod
795
    def scenarios():
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
796
        # Each side dict additionally defines:
797
        # - dir_id: the directory being moved
798
        # - target_id: The target directory
799
        # - xfail: whether the test is expected to fail if the action is
800
        #     involved as 'other'
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
801
        base_scenarios = [
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
802
            # Dirs moved into each other
803
            (dict(_base_actions='create_dir1_dir2'),
804
             ('dir1_into_dir2',
805
              dict(actions='move_dir1_into_dir2', check='dir1_moved',
806
                   dir_id='dir1-id', target_id='dir2-id', xfail=False)),
807
             ('dir2_into_dir1',
808
              dict(actions='move_dir2_into_dir1', check='dir2_moved',
809
                   dir_id='dir2-id', target_id='dir1-id', xfail=False))),
810
            # Subdirs moved into each other
811
            (dict(_base_actions='create_dir1_4'),
812
             ('dir1_into_dir4',
813
              dict(actions='move_dir1_into_dir4', check='dir1_2_moved',
814
                   dir_id='dir1-id', target_id='dir4-id', xfail=True)),
815
             ('dir3_into_dir2',
816
              dict(actions='move_dir3_into_dir2', check='dir3_4_moved',
817
                   dir_id='dir3-id', target_id='dir2-id', xfail=True))),
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
818
            ]
4597.10.11 by Vincent Ladeuil
Turn mirror_scenarios into a simple function.
819
        return mirror_scenarios(base_scenarios)
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
820
821
    def do_create_dir1_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
822
        return [('add', ('dir1', 'dir1-id', 'directory', '')),
823
                ('add', ('dir2', 'dir2-id', 'directory', '')),]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
824
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
825
    def do_move_dir1_into_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
826
        return [('rename', ('dir1', 'dir2/dir1'))]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
827
828
    def check_dir1_moved(self):
829
        self.failIfExists('branch/dir1')
830
        self.failUnlessExists('branch/dir2/dir1')
831
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
832
    def do_move_dir2_into_dir1(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
833
        return [('rename', ('dir2', 'dir1/dir2'))]
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
834
835
    def check_dir2_moved(self):
836
        self.failIfExists('branch/dir2')
837
        self.failUnlessExists('branch/dir1/dir2')
838
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
839
    def do_create_dir1_4(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
840
        return [('add', ('dir1', 'dir1-id', 'directory', '')),
841
                ('add', ('dir1/dir2', 'dir2-id', 'directory', '')),
842
                ('add', ('dir3', 'dir3-id', 'directory', '')),
843
                ('add', ('dir3/dir4', 'dir4-id', 'directory', '')),]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
844
845
    def do_move_dir1_into_dir4(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
846
        return [('rename', ('dir1', 'dir3/dir4/dir1'))]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
847
848
    def check_dir1_2_moved(self):
849
        self.failIfExists('branch/dir1')
850
        self.failUnlessExists('branch/dir3/dir4/dir1')
851
        self.failUnlessExists('branch/dir3/dir4/dir1/dir2')
852
853
    def do_move_dir3_into_dir2(self):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
854
        return [('rename', ('dir3', 'dir1/dir2/dir3'))]
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
855
856
    def check_dir3_4_moved(self):
857
        self.failIfExists('branch/dir3')
858
        self.failUnlessExists('branch/dir1/dir2/dir3')
859
        self.failUnlessExists('branch/dir1/dir2/dir3/dir4')
860
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
861
    def _get_resolve_path_arg(self, wt, action):
4597.10.9 by Vincent Ladeuil
More doc.
862
        # ParentLoop says: moving <conflict_path> into <path>. Cancelled move.
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
863
        # But since <path> doesn't exist in the working tree, we need to use
4597.10.9 by Vincent Ladeuil
More doc.
864
        # <conflict_path> instead, and that, in turn, is given by dir_id. Pfew.
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
865
        return wt.id2path(self._other['dir_id'])
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
866
867
    def assertParentLoop(self, wt, c):
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
868
        self.assertEqual(self._other['dir_id'], c.file_id)
869
        self.assertEqual(self._other['target_id'], c.conflict_file_id)
4597.8.8 by Vincent Ladeuil
Exhibit bug #537956.
870
        # The conflict paths are irrelevant (they are deterministic but not
871
        # worth checking since they don't provide the needed information
872
        # anyway)
4597.10.8 by Vincent Ladeuil
Separate actions and conflict attributes.
873
        if self._other['xfail']:
874
            # It's a bit hackish to raise from here relying on being called for
875
            # both tests but this avoid overriding test_resolve_taking_other
4597.10.4 by Vincent Ladeuil
Handle TestResolveParentLoop expected failures more precisely.
876
            raise tests.KnownFailure(
877
                "ParentLoop doesn't carry enough info to resolve --take-other")
4597.8.7 by Vincent Ladeuil
Add whitebox tests for ParentLoop.
878
    _assert_conflict = assertParentLoop
879
880
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
881
class TestResolveNonDirectoryParent(TestResolveConflicts):
882
883
    preamble = """
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
884
$ bzr init trunk
885
$ cd trunk
886
$ bzr mkdir foo
887
$ bzr commit -m 'Create trunk'
888
$ echo "Boing" >foo/bar
889
$ bzr add foo/bar
890
$ bzr commit -m 'Add foo/bar'
891
892
$ bzr branch . -r 1 ../branch
893
$ cd ../branch
894
$ rm -r foo
895
$ echo "Boo!" >foo
896
$ bzr commit -m 'foo is now a file'
897
898
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
899
2>+N  foo.new/bar
900
2>RK  foo => foo.new/
901
# FIXME: The message is misleading, foo.new *is* a directory when the message
902
# is displayed -- vila 090916
903
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
904
2>1 conflicts encountered.
905
"""
906
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
907
    def test_take_this(self):
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
908
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
909
$ bzr rm foo.new --force
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
910
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
911
# aside ? -- vila 090916
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
912
$ bzr add foo
913
$ bzr resolve foo.new
914
$ bzr commit --strict -m 'No more conflicts nor unknown files'
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
915
""")
916
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
917
    def test_take_other(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
918
        self.run_script("""
919
$ bzr rm foo --force
920
$ bzr mv foo.new foo
921
$ bzr resolve foo
922
$ bzr commit --strict -m 'No more conflicts nor unknown files'
923
""")
924
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
925
    def test_resolve_taking_this(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
926
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
927
$ bzr resolve --take-this foo.new
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
928
$ bzr commit --strict -m 'No more conflicts nor unknown files'
929
""")
930
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
931
    def test_resolve_taking_other(self):
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
932
        self.run_script("""
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
933
$ bzr resolve --take-other foo.new
4597.3.35 by Vincent Ladeuil
Implement --interactive for NonDirectoryParent, sort of.
934
$ bzr commit --strict -m 'No more conflicts nor unknown files'
935
""")
936
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
937
938
class TestMalformedTransform(script.TestCaseWithTransportAndScript):
939
940
    def test_bug_430129(self):
941
        # This is nearly like TestResolveNonDirectoryParent but with branch and
942
        # trunk switched. As such it should certainly produce the same
943
        # conflict.
944
        self.run_script("""
4597.3.15 by Vincent Ladeuil
Update to new shell-like tests syntax.
945
$ bzr init trunk
946
$ cd trunk
947
$ bzr mkdir foo
948
$ bzr commit -m 'Create trunk'
949
$ rm -r foo
950
$ echo "Boo!" >foo
951
$ bzr commit -m 'foo is now a file'
952
953
$ bzr branch . -r 1 ../branch
954
$ cd ../branch
955
$ echo "Boing" >foo/bar
956
$ bzr add foo/bar
957
$ bzr commit -m 'Add foo/bar'
958
959
$ bzr merge ../trunk
4597.3.12 by Vincent Ladeuil
Start writing tests for all expected conflict resolution actions.
960
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
961
""")
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
962
963
964
class TestResolveActionOption(tests.TestCase):
965
966
    def setUp(self):
967
        super(TestResolveActionOption, self).setUp()
968
        self.options = [conflicts.ResolveActionOption()]
969
        self.parser = option.get_optparser(dict((o.name, o)
970
                                                for o in self.options))
971
972
    def parse(self, args):
973
        return self.parser.parse_args(args)
974
975
    def test_unknown_action(self):
976
        self.assertRaises(errors.BadOptionValue,
977
                          self.parse, ['--action', 'take-me-to-the-moon'])
978
979
    def test_done(self):
980
        opts, args = self.parse(['--action', 'done'])
981
        self.assertEqual({'action':'done'}, opts)
982
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
983
    def test_take_this(self):
984
        opts, args = self.parse(['--action', 'take-this'])
985
        self.assertEqual({'action': 'take_this'}, opts)
986
        opts, args = self.parse(['--take-this'])
987
        self.assertEqual({'action': 'take_this'}, opts)
4597.3.51 by Vincent Ladeuil
Implement conflicts.ResolveActionOption.
988
4597.3.67 by Vincent Ladeuil
Settle with --take-this and --take-other as action names.
989
    def test_take_other(self):
990
        opts, args = self.parse(['--action', 'take-other'])
991
        self.assertEqual({'action': 'take_other'}, opts)
992
        opts, args = self.parse(['--take-other'])
993
        self.assertEqual({'action': 'take_other'}, opts)