20
20
from bzrlib import (
29
from bzrlib.tests import script
32
def load_tests(standard_tests, module, loader):
33
result = loader.suiteClass()
35
sp_tests, remaining_tests = tests.split_suite_by_condition(
36
standard_tests, tests.condition_isinstance((
37
TestParametrizedResolveConflicts,
39
# Each test class defines its own scenarios. This is needed for
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)
45
# No parametrization for the remaining tests
46
result.addTests(remaining_tests)
28
from bzrlib.tests import (
34
load_tests = scenarios.load_tests_apply_scenarios
51
37
# TODO: Test commit with some added, and added-but-missing files
79
65
class TestConflicts(tests.TestCaseWithTransport):
81
def test_conflicts(self):
82
"""Conflicts are detected properly"""
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'),
93
self.assertLength(6, list(tree.list_files()))
95
tree_conflicts = tree.conflicts()
96
self.assertLength(2, tree_conflicts)
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')
101
self.assertLength(0, tree.conflicts())
102
self.assertFileEqual('hello world2', 'hello')
103
self.assertFalse(os.path.lexists('hello.sploo'))
104
self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
105
self.assertRaises(errors.NotConflicted,
106
conflicts.restore, 'hello.sploo')
108
67
def test_resolve_conflict_dir(self):
109
68
tree = self.make_branch_and_tree('.')
110
69
self.build_tree_contents([('hello', 'hello world4'),
298
"""Return the scenario list for the conflict type defined by the class.
300
Each scenario is of the form:
301
(common, (left_name, left_dict), (right_name, right_dict))
305
* left_name and right_name are the scenario names that will be combined
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.
311
Daughters classes are free to add their specific attributes as they see
312
fit in any of the three dicts.
314
This is a class method so that load_tests can find it.
316
'_base_actions' in the common dict, 'actions' and 'check' in the left
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.
322
# Only concrete classes return actual scenarios
251
"""The scenario list for the conflict type defined by the class.
253
Each scenario is of the form:
254
(common, (left_name, left_dict), (right_name, right_dict))
258
* left_name and right_name are the scenario names that will be combined
260
* left_dict and right_dict are the attributes specific to each half of
261
the scenario. They should include at least 'actions' and 'check' and
262
will be available as '_this' and '_other' test instance attributes.
264
Daughters classes are free to add their specific attributes as they see
265
fit in any of the three dicts.
267
This is a class method so that load_tests can find it.
269
'_base_actions' in the common dict, 'actions' and 'check' in the left
270
and right dicts use names that map to methods in the test classes. Some
271
prefixes are added to these names to get the correspong methods (see
272
_get_actions() and _get_check()). The motivation here is to avoid
273
collisions in the class namespace.
326
277
super(TestParametrizedResolveConflicts, self).setUp()
342
class TestResolveTextConflicts(TestParametrizedResolveConflicts):
344
_conflict_type = conflicts.TextConflict
346
# Set by the scenarios
347
# path and file-id for the file involved in the conflict
351
scenarios = mirror_scenarios(
353
# File modified on both sides
354
(dict(_base_actions='create_file',
355
_path='file', _file_id='file-id'),
357
dict(actions='modify_file_A', check='file_has_content_A')),
359
dict(actions='modify_file_B', check='file_has_content_B')),),
360
# File modified on both sides in dir
361
(dict(_base_actions='create_file_in_dir',
362
_path='dir/file', _file_id='file-id'),
363
('filed_modified_A_in_dir',
364
dict(actions='modify_file_A',
365
check='file_in_dir_has_content_A')),
367
dict(actions='modify_file_B',
368
check='file_in_dir_has_content_B')),),
371
def do_create_file(self, path='file'):
372
return [('add', (path, 'file-id', 'file', 'trunk content\n'))]
374
def do_modify_file_A(self):
375
return [('modify', ('file-id', 'trunk content\nfeature A\n'))]
377
def do_modify_file_B(self):
378
return [('modify', ('file-id', 'trunk content\nfeature B\n'))]
380
def check_file_has_content_A(self, path='file'):
381
self.assertFileEqual('trunk content\nfeature A\n',
382
osutils.pathjoin('branch', path))
384
def check_file_has_content_B(self, path='file'):
385
self.assertFileEqual('trunk content\nfeature B\n',
386
osutils.pathjoin('branch', path))
388
def do_create_file_in_dir(self):
389
return [('add', ('dir', 'dir-id', 'directory', '')),
390
] + self.do_create_file('dir/file')
392
def check_file_in_dir_has_content_A(self):
393
self.check_file_has_content_A('dir/file')
395
def check_file_in_dir_has_content_B(self):
396
self.check_file_has_content_B('dir/file')
398
def _get_resolve_path_arg(self, wt, action):
401
def assertTextConflict(self, wt, c):
402
self.assertEqual(self._file_id, c.file_id)
403
self.assertEqual(self._path, c.path)
404
_assert_conflict = assertTextConflict
391
407
class TestResolveContentsConflict(TestParametrizedResolveConflicts):
393
_conflict_type = conflicts.ContentsConflict,
409
_conflict_type = conflicts.ContentsConflict
395
# Set by load_tests from scenarios()
411
# Set by the scenarios
396
412
# path and file-id for the file involved in the conflict
416
scenarios = mirror_scenarios(
403
418
# File modified/deleted
404
419
(dict(_base_actions='create_file',
405
420
_path='file', _file_id='file-id'),
407
422
dict(actions='modify_file', check='file_has_more_content')),
409
424
dict(actions='delete_file', check='file_doesnt_exist')),),
411
return mirror_scenarios(base_scenarios)
425
# File modified/deleted in dir
426
(dict(_base_actions='create_file_in_dir',
427
_path='dir/file', _file_id='file-id'),
428
('file_modified_in_dir',
429
dict(actions='modify_file_in_dir',
430
check='file_in_dir_has_more_content')),
431
('file_deleted_in_dir',
432
dict(actions='delete_file',
433
check='file_in_dir_doesnt_exist')),),
413
436
def do_create_file(self):
414
437
return [('add', ('file', 'file-id', 'file', 'trunk content\n'))]
425
448
def check_file_doesnt_exist(self):
426
449
self.failIfExists('branch/file')
451
def do_create_file_in_dir(self):
452
return [('add', ('dir', 'dir-id', 'directory', '')),
453
('add', ('dir/file', 'file-id', 'file', 'trunk content\n'))]
455
def do_modify_file_in_dir(self):
456
return [('modify', ('file-id', 'trunk content\nmore content\n'))]
458
def check_file_in_dir_has_more_content(self):
459
self.assertFileEqual('trunk content\nmore content\n', 'branch/dir/file')
461
def check_file_in_dir_doesnt_exist(self):
462
self.failIfExists('branch/dir/file')
428
464
def _get_resolve_path_arg(self, wt, action):
429
465
return self._path
457
492
# PathConflicts deletion handling requires a special
458
493
# hard-coded value
459
494
path='<deleted>', file_id='file-id')),),
495
# File renamed/deleted in dir
496
(dict(_base_actions='create_file_in_dir'),
497
('file_renamed_in_dir',
498
dict(actions='rename_file_in_dir', check='file_in_dir_renamed',
499
path='dir/new-file', file_id='file-id')),
501
dict(actions='delete_file', check='file_in_dir_doesnt_exist',
502
# PathConflicts deletion handling requires a special
504
path='<deleted>', file_id='file-id')),),
460
505
# File renamed/renamed differently
461
506
(dict(_base_actions='create_file'),
532
576
def check_dir_doesnt_exist(self):
533
577
self.failIfExists('branch/dir')
579
def do_create_file_in_dir(self):
580
return [('add', ('dir', 'dir-id', 'directory', '')),
581
('add', ('dir/file', 'file-id', 'file', 'trunk content\n'))]
583
def do_rename_file_in_dir(self):
584
return [('rename', ('dir/file', 'dir/new-file'))]
586
def check_file_in_dir_renamed(self):
587
self.failIfExists('branch/dir/file')
588
self.failUnlessExists('branch/dir/new-file')
590
def check_file_in_dir_doesnt_exist(self):
591
self.failIfExists('branch/dir/file')
535
593
def _get_resolve_path_arg(self, wt, action):
536
594
tpath = self._this['path']
537
595
opath = self._other['path']
670
724
$ echo 'trunk content' >dir/file
672
$ bzr commit -m 'Create trunk'
726
$ bzr commit -m 'Create trunk' -q
674
727
$ echo 'trunk content' >dir/file2
676
$ bzr commit -m 'Add dir/file2 in branch'
678
$ bzr branch . -r 1 ../branch
728
$ bzr add -q dir/file2
729
$ bzr commit -q -m 'Add dir/file2 in branch'
730
$ bzr branch -q . -r 1 ../branch
680
$ bzr rm dir/file --force
682
$ bzr commit -m 'Remove dir/file'
732
$ bzr rm -q dir/file --force
734
$ bzr commit -q -m 'Remove dir/file'
684
735
$ bzr merge ../trunk
692
743
def test_keep_them_all(self):
693
744
self.run_script("""
694
745
$ bzr resolve dir
695
$ bzr commit --strict -m 'No more conflicts nor unknown files'
746
2>2 conflict(s) resolved, 0 remaining
747
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
698
750
def test_adopt_child(self):
699
751
self.run_script("""
700
$ bzr mv dir/file2 file2
752
$ bzr mv -q dir/file2 file2
753
$ bzr rm -q dir --force
702
754
$ bzr resolve dir
703
$ bzr commit --strict -m 'No more conflicts nor unknown files'
755
2>2 conflict(s) resolved, 0 remaining
756
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
706
759
def test_kill_them_all(self):
707
760
self.run_script("""
761
$ bzr rm -q dir --force
709
762
$ bzr resolve dir
710
$ bzr commit --strict -m 'No more conflicts nor unknown files'
763
2>2 conflict(s) resolved, 0 remaining
764
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
713
767
def test_resolve_taking_this(self):
714
768
self.run_script("""
715
769
$ bzr resolve --take-this dir
716
$ bzr commit --strict -m 'No more conflicts nor unknown files'
771
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
719
774
def test_resolve_taking_other(self):
720
775
self.run_script("""
721
776
$ bzr resolve --take-other dir
722
$ bzr commit --strict -m 'No more conflicts nor unknown files'
778
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
732
789
$ echo 'trunk content' >dir/file
734
$ bzr commit -m 'Create trunk'
736
$ bzr rm dir/file --force
738
$ bzr commit -m 'Remove dir/file'
740
$ bzr branch . -r 1 ../branch
791
$ bzr commit -m 'Create trunk' -q
792
$ bzr rm -q dir/file --force
793
$ bzr rm -q dir --force
794
$ bzr commit -q -m 'Remove dir/file'
795
$ bzr branch -q . -r 1 ../branch
742
797
$ echo 'branch content' >dir/file2
744
$ bzr commit -m 'Add dir/file2 in branch'
798
$ bzr add -q dir/file2
799
$ bzr commit -q -m 'Add dir/file2 in branch'
746
800
$ bzr merge ../trunk
748
802
2>Conflict: can't delete dir because it is not empty. Not deleting.
753
807
def test_keep_them_all(self):
754
808
self.run_script("""
755
809
$ bzr resolve dir
756
$ bzr commit --strict -m 'No more conflicts nor unknown files'
810
2>2 conflict(s) resolved, 0 remaining
811
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
759
814
def test_adopt_child(self):
760
815
self.run_script("""
761
$ bzr mv dir/file2 file2
816
$ bzr mv -q dir/file2 file2
817
$ bzr rm -q dir --force
763
818
$ bzr resolve dir
764
$ bzr commit --strict -m 'No more conflicts nor unknown files'
819
2>2 conflict(s) resolved, 0 remaining
820
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
767
823
def test_kill_them_all(self):
768
824
self.run_script("""
825
$ bzr rm -q dir --force
770
826
$ bzr resolve dir
771
$ bzr commit --strict -m 'No more conflicts nor unknown files'
827
2>2 conflict(s) resolved, 0 remaining
828
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
774
831
def test_resolve_taking_this(self):
775
832
self.run_script("""
776
833
$ bzr resolve --take-this dir
777
$ bzr commit --strict -m 'No more conflicts nor unknown files'
834
2>2 conflict(s) resolved, 0 remaining
835
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
780
838
def test_resolve_taking_other(self):
781
839
self.run_script("""
782
840
$ bzr resolve --take-other dir
783
$ bzr commit --strict -m 'No more conflicts nor unknown files'
843
2>2 conflict(s) resolved, 0 remaining
844
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
787
848
class TestResolveParentLoop(TestParametrizedResolveConflicts):
789
_conflict_type = conflicts.ParentLoop,
850
_conflict_type = conflicts.ParentLoop
791
852
_this_args = None
792
853
_other_args = None
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'
855
# Each side dict additionally defines:
856
# - dir_id: the directory being moved
857
# - target_id: The target directory
858
# - xfail: whether the test is expected to fail if the action is
859
# involved as 'other'
860
scenarios = mirror_scenarios(
802
862
# Dirs moved into each other
803
863
(dict(_base_actions='create_dir1_dir2'),
804
864
('dir1_into_dir2',
907
966
def test_take_this(self):
908
967
self.run_script("""
909
$ bzr rm foo.new --force
968
$ bzr rm -q foo.new --force
910
969
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
911
970
# aside ? -- vila 090916
913
972
$ bzr resolve foo.new
914
$ bzr commit --strict -m 'No more conflicts nor unknown files'
973
2>1 conflict(s) resolved, 0 remaining
974
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
917
977
def test_take_other(self):
918
978
self.run_script("""
979
$ bzr rm -q foo --force
980
$ bzr mv -q foo.new foo
921
981
$ bzr resolve foo
922
$ bzr commit --strict -m 'No more conflicts nor unknown files'
982
2>1 conflict(s) resolved, 0 remaining
983
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
925
986
def test_resolve_taking_this(self):
926
987
self.run_script("""
927
988
$ bzr resolve --take-this foo.new
928
$ bzr commit --strict -m 'No more conflicts nor unknown files'
990
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'
931
993
def test_resolve_taking_other(self):
932
994
self.run_script("""
933
995
$ bzr resolve --take-other foo.new
934
$ bzr commit --strict -m 'No more conflicts nor unknown files'
997
$ bzr commit -q --strict -m 'No more conflicts nor unknown files'