/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_conflicts.py

  • Committer: Jelmer Vernooij
  • Date: 2010-03-21 21:39:33 UTC
  • mfrom: (5102 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5143.
  • Revision ID: jelmer@samba.org-20100321213933-fexeh9zcoz8oaju2
merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
import os
19
19
 
20
20
from bzrlib import (
 
21
    branchbuilder,
21
22
    bzrdir,
22
23
    conflicts,
23
24
    errors,
 
25
    option,
24
26
    tests,
25
27
    workingtree,
26
28
    )
27
29
from bzrlib.tests import script
28
30
 
29
31
 
 
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((
 
37
                TestResolveContentConflicts,
 
38
                )))
 
39
    tests.multiply_tests(sp_tests, content_conflict_scenarios(), result)
 
40
 
 
41
    # No parametrization for the remaining tests
 
42
    result.addTests(remaining_tests)
 
43
 
 
44
    return result
 
45
 
 
46
 
30
47
# TODO: Test commit with some added, and added-but-missing files
31
48
# RBC 20060124 is that not tested in test_commit.py ?
32
49
 
69
86
                                  ('hello.sploo.OTHER', 'yellowworld2'),
70
87
                                  ])
71
88
        tree.lock_read()
72
 
        self.assertEqual(6, len(list(tree.list_files())))
 
89
        self.assertLength(6, list(tree.list_files()))
73
90
        tree.unlock()
74
91
        tree_conflicts = tree.conflicts()
75
 
        self.assertEqual(2, len(tree_conflicts))
 
92
        self.assertLength(2, tree_conflicts)
76
93
        self.assertTrue('hello' in tree_conflicts[0].path)
77
94
        self.assertTrue('hello.sploo' in tree_conflicts[1].path)
78
95
        conflicts.restore('hello')
79
96
        conflicts.restore('hello.sploo')
80
 
        self.assertEqual(0, len(tree.conflicts()))
 
97
        self.assertLength(0, tree.conflicts())
81
98
        self.assertFileEqual('hello world2', 'hello')
82
99
        self.assertFalse(os.path.lexists('hello.sploo'))
83
100
        self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
173
190
            if 'conflict_file_id' in stanza:
174
191
                self.assertStartsWith(stanza['conflict_file_id'], u'\xeed')
175
192
 
 
193
 
 
194
# FIXME: The shell-like tests should be converted to real whitebox tests... or
 
195
# moved to a blackbox module -- vila 20100205
 
196
 
 
197
# FIXME: Tests missing for DuplicateID conflict type
 
198
class TestResolveConflicts(script.TestCaseWithTransportAndScript):
 
199
 
 
200
    preamble = None # The setup script set by daughter classes
 
201
 
 
202
    def setUp(self):
 
203
        super(TestResolveConflicts, self).setUp()
 
204
        self.run_script(self.preamble)
 
205
 
 
206
 
 
207
class TestResolveTextConflicts(TestResolveConflicts):
 
208
    # TBC
 
209
    pass
 
210
 
 
211
 
 
212
def content_conflict_scenarios():
 
213
    return [('file,None', dict(_this_actions='modify_file',
 
214
                               _check_this='file_has_more_content',
 
215
                               _other_actions='delete_file',
 
216
                               _check_other='file_doesnt_exist',
 
217
                               )),
 
218
            ('None,file', dict(_this_actions='delete_file',
 
219
                               _check_this='file_doesnt_exist',
 
220
                               _other_actions='modify_file',
 
221
                               _check_other='file_has_more_content',
 
222
                               )),
 
223
            ]
 
224
 
 
225
 
 
226
class TestResolveContentConflicts(tests.TestCaseWithTransport):
 
227
 
 
228
    # Set by load_tests
 
229
    this_actions = None
 
230
    other_actions = None
 
231
 
 
232
    def setUp(self):
 
233
        super(TestResolveContentConflicts, self).setUp()
 
234
        builder = self.make_branch_builder('trunk')
 
235
        builder.start_series()
 
236
        # Create an empty trunk
 
237
        builder.build_snapshot('start', None, [
 
238
                ('add', ('', 'root-id', 'directory', ''))])
 
239
        # Add a minimal base content
 
240
        builder.build_snapshot('base', ['start'], [
 
241
                ('add', ('file', 'file-id', 'file', 'trunk content\n'))])
 
242
        # Modify the base content in branch
 
243
        other_actions = self._get_actions(self._other_actions)
 
244
        builder.build_snapshot('other', ['base'], other_actions())
 
245
        # Modify the base content in trunk
 
246
        this_actions = self._get_actions(self._this_actions)
 
247
        builder.build_snapshot('this', ['base'], this_actions())
 
248
        builder.finish_series()
 
249
        self.builder = builder
 
250
 
 
251
    def _get_actions(self, name):
 
252
        return getattr(self, 'do_%s' % name)
 
253
 
 
254
    def _get_check(self, name):
 
255
        return getattr(self, 'check_%s' % name)
 
256
 
 
257
    def do_modify_file(self):
 
258
        return [('modify', ('file-id', 'trunk content\nmore content\n'))]
 
259
 
 
260
    def check_file_has_more_content(self):
 
261
        self.assertFileEqual('trunk content\nmore content\n', 'branch/file')
 
262
 
 
263
    def do_delete_file(self):
 
264
        return [('unversion', 'file-id')]
 
265
 
 
266
    def check_file_doesnt_exist(self):
 
267
        self.failIfExists('branch/file')
 
268
 
 
269
    def _merge_other_into_this(self):
 
270
        b = self.builder.get_branch()
 
271
        wt = b.bzrdir.sprout('branch').open_workingtree()
 
272
        wt.merge_from_branch(b, 'other')
 
273
        return wt
 
274
 
 
275
    def assertConflict(self, wt, ctype, **kwargs):
 
276
        confs = wt.conflicts()
 
277
        self.assertLength(1, confs)
 
278
        c = confs[0]
 
279
        self.assertIsInstance(c, ctype)
 
280
        sentinel = object() # An impossible value
 
281
        for k, v in kwargs.iteritems():
 
282
            self.assertEqual(v, getattr(c, k, sentinel))
 
283
 
 
284
    def check_resolved(self, wt, item, action):
 
285
        conflicts.resolve(wt, [item], action=action)
 
286
        # Check that we don't have any conflicts nor unknown left
 
287
        self.assertLength(0, wt.conflicts())
 
288
        self.assertLength(0, list(wt.unknowns()))
 
289
 
 
290
    def test_resolve_taking_this(self):
 
291
        wt = self._merge_other_into_this()
 
292
        self.assertConflict(wt, conflicts.ContentsConflict,
 
293
                            path='file', file_id='file-id',)
 
294
        self.check_resolved(wt, 'file', 'take_this')
 
295
        check_this = self._get_check(self._check_this)
 
296
        check_this()
 
297
 
 
298
    def test_resolve_taking_other(self):
 
299
        wt = self._merge_other_into_this()
 
300
        self.assertConflict(wt, conflicts.ContentsConflict,
 
301
                            path='file', file_id='file-id',)
 
302
        self.check_resolved(wt, 'file', 'take_other')
 
303
        check_other = self._get_check(self._check_other)
 
304
        check_other()
 
305
 
 
306
 
 
307
class TestResolveDuplicateEntry(TestResolveConflicts):
 
308
 
 
309
    preamble = """
 
310
$ bzr init trunk
 
311
$ cd trunk
 
312
$ echo 'trunk content' >file
 
313
$ bzr add file
 
314
$ bzr commit -m 'Create trunk'
 
315
 
 
316
$ echo 'trunk content too' >file2
 
317
$ bzr add file2
 
318
$ bzr commit -m 'Add file2 in trunk'
 
319
 
 
320
$ bzr branch . -r 1 ../branch
 
321
$ cd ../branch
 
322
$ echo 'branch content' >file2
 
323
$ bzr add file2
 
324
$ bzr commit -m 'Add file2 in branch'
 
325
 
 
326
$ bzr merge ../trunk
 
327
2>+N  file2
 
328
2>R   file2 => file2.moved
 
329
2>Conflict adding file file2.  Moved existing file to file2.moved.
 
330
2>1 conflicts encountered.
 
331
"""
 
332
 
 
333
    def test_keep_this(self):
 
334
        self.run_script("""
 
335
$ bzr rm file2  --force
 
336
$ bzr mv file2.moved file2
 
337
$ bzr resolve file2
 
338
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
339
""")
 
340
 
 
341
    def test_keep_other(self):
 
342
        self.failIfExists('branch/file2.moved')
 
343
        self.run_script("""
 
344
$ bzr rm file2.moved --force
 
345
$ bzr resolve file2
 
346
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
347
""")
 
348
        self.failIfExists('branch/file2.moved')
 
349
 
 
350
    def test_resolve_taking_this(self):
 
351
        self.run_script("""
 
352
$ bzr resolve --take-this file2
 
353
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
354
""")
 
355
 
 
356
    def test_resolve_taking_other(self):
 
357
        self.run_script("""
 
358
$ bzr resolve --take-other file2
 
359
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
360
""")
 
361
 
 
362
 
 
363
class TestResolveUnversionedParent(TestResolveConflicts):
 
364
 
 
365
    # FIXME: Add the reverse tests: dir deleted in trunk, file added in branch
 
366
 
 
367
    # FIXME: While this *creates* UnversionedParent conflicts, this really only
 
368
    # tests MissingParent resolution :-/
 
369
    preamble = """
 
370
$ bzr init trunk
 
371
$ cd trunk
 
372
$ mkdir dir
 
373
$ bzr add dir
 
374
$ bzr commit -m 'Create trunk'
 
375
 
 
376
$ echo 'trunk content' >dir/file
 
377
$ bzr add dir/file
 
378
$ bzr commit -m 'Add dir/file in trunk'
 
379
 
 
380
$ bzr branch . -r 1 ../branch
 
381
$ cd ../branch
 
382
$ bzr rm dir
 
383
$ bzr commit -m 'Remove dir in branch'
 
384
 
 
385
$ bzr merge ../trunk
 
386
2>+N  dir/
 
387
2>+N  dir/file
 
388
2>Conflict adding files to dir.  Created directory.
 
389
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
390
2>2 conflicts encountered.
 
391
"""
 
392
 
 
393
    def test_take_this(self):
 
394
        self.run_script("""
 
395
$ bzr rm dir  --force
 
396
$ bzr resolve dir
 
397
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
398
""")
 
399
 
 
400
    def test_take_other(self):
 
401
        self.run_script("""
 
402
$ bzr resolve dir
 
403
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
404
""")
 
405
 
 
406
 
 
407
class TestResolveMissingParent(TestResolveConflicts):
 
408
 
 
409
    preamble = """
 
410
$ bzr init trunk
 
411
$ cd trunk
 
412
$ mkdir dir
 
413
$ echo 'trunk content' >dir/file
 
414
$ bzr add
 
415
$ bzr commit -m 'Create trunk'
 
416
 
 
417
$ echo 'trunk content' >dir/file2
 
418
$ bzr add dir/file2
 
419
$ bzr commit -m 'Add dir/file2 in branch'
 
420
 
 
421
$ bzr branch . -r 1 ../branch
 
422
$ cd ../branch
 
423
$ bzr rm dir/file --force
 
424
$ bzr rm dir
 
425
$ bzr commit -m 'Remove dir/file'
 
426
 
 
427
$ bzr merge ../trunk
 
428
2>+N  dir/
 
429
2>+N  dir/file2
 
430
2>Conflict adding files to dir.  Created directory.
 
431
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
432
2>2 conflicts encountered.
 
433
"""
 
434
 
 
435
    def test_keep_them_all(self):
 
436
        self.run_script("""
 
437
$ bzr resolve dir
 
438
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
439
""")
 
440
 
 
441
    def test_adopt_child(self):
 
442
        self.run_script("""
 
443
$ bzr mv dir/file2 file2
 
444
$ bzr rm dir --force
 
445
$ bzr resolve dir
 
446
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
447
""")
 
448
 
 
449
    def test_kill_them_all(self):
 
450
        self.run_script("""
 
451
$ bzr rm dir --force
 
452
$ bzr resolve dir
 
453
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
454
""")
 
455
 
 
456
    def test_resolve_taking_this(self):
 
457
        self.run_script("""
 
458
$ bzr resolve --take-this dir
 
459
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
460
""")
 
461
 
 
462
    def test_resolve_taking_other(self):
 
463
        self.run_script("""
 
464
$ bzr resolve --take-other dir
 
465
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
466
""")
 
467
 
 
468
 
 
469
class TestResolveDeletingParent(TestResolveConflicts):
 
470
 
 
471
    preamble = """
 
472
$ bzr init trunk
 
473
$ cd trunk
 
474
$ mkdir dir
 
475
$ echo 'trunk content' >dir/file
 
476
$ bzr add
 
477
$ bzr commit -m 'Create trunk'
 
478
 
 
479
$ bzr rm dir/file --force
 
480
$ bzr rm dir --force
 
481
$ bzr commit -m 'Remove dir/file'
 
482
 
 
483
$ bzr branch . -r 1 ../branch
 
484
$ cd ../branch
 
485
$ echo 'branch content' >dir/file2
 
486
$ bzr add dir/file2
 
487
$ bzr commit -m 'Add dir/file2 in branch'
 
488
 
 
489
$ bzr merge ../trunk
 
490
2>-D  dir/file
 
491
2>Conflict: can't delete dir because it is not empty.  Not deleting.
 
492
2>Conflict because dir is not versioned, but has versioned children.  Versioned directory.
 
493
2>2 conflicts encountered.
 
494
"""
 
495
 
 
496
    def test_keep_them_all(self):
 
497
        self.run_script("""
 
498
$ bzr resolve dir
 
499
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
500
""")
 
501
 
 
502
    def test_adopt_child(self):
 
503
        self.run_script("""
 
504
$ bzr mv dir/file2 file2
 
505
$ bzr rm dir --force
 
506
$ bzr resolve dir
 
507
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
508
""")
 
509
 
 
510
    def test_kill_them_all(self):
 
511
        self.run_script("""
 
512
$ bzr rm dir --force
 
513
$ bzr resolve dir
 
514
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
515
""")
 
516
 
 
517
    def test_resolve_taking_this(self):
 
518
        self.run_script("""
 
519
$ bzr resolve --take-this dir
 
520
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
521
""")
 
522
 
 
523
    def test_resolve_taking_other(self):
 
524
        self.run_script("""
 
525
$ bzr resolve --take-other dir
 
526
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
527
""")
 
528
 
 
529
 
 
530
class TestResolvePathConflict(TestResolveConflicts):
 
531
 
 
532
    preamble = """
 
533
$ bzr init trunk
 
534
$ cd trunk
 
535
$ echo 'Boo!' >file
 
536
$ bzr add
 
537
$ bzr commit -m 'Create trunk'
 
538
 
 
539
$ bzr mv file file-in-trunk
 
540
$ bzr commit -m 'Renamed to file-in-trunk'
 
541
 
 
542
$ bzr branch . -r 1 ../branch
 
543
$ cd ../branch
 
544
$ bzr mv file file-in-branch
 
545
$ bzr commit -m 'Renamed to file-in-branch'
 
546
 
 
547
$ bzr merge ../trunk
 
548
2>R   file-in-branch => file-in-trunk
 
549
2>Path conflict: file-in-branch / file-in-trunk
 
550
2>1 conflicts encountered.
 
551
"""
 
552
 
 
553
    def test_keep_source(self):
 
554
        self.run_script("""
 
555
$ bzr resolve file-in-trunk
 
556
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
557
""")
 
558
 
 
559
    def test_keep_target(self):
 
560
        self.run_script("""
 
561
$ bzr mv file-in-trunk file-in-branch
 
562
$ bzr resolve file-in-branch
 
563
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
564
""")
 
565
 
 
566
    def test_resolve_taking_this(self):
 
567
        self.run_script("""
 
568
$ bzr resolve --take-this file-in-branch
 
569
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
570
""")
 
571
 
 
572
    def test_resolve_taking_other(self):
 
573
        self.run_script("""
 
574
$ bzr resolve --take-other file-in-branch
 
575
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
576
""")
 
577
 
 
578
 
 
579
class TestResolveParentLoop(TestResolveConflicts):
 
580
 
 
581
    preamble = """
 
582
$ bzr init trunk
 
583
$ cd trunk
 
584
$ bzr mkdir dir1
 
585
$ bzr mkdir dir2
 
586
$ bzr commit -m 'Create trunk'
 
587
 
 
588
$ bzr mv dir2 dir1
 
589
$ bzr commit -m 'Moved dir2 into dir1'
 
590
 
 
591
$ bzr branch . -r 1 ../branch
 
592
$ cd ../branch
 
593
$ bzr mv dir1 dir2
 
594
$ bzr commit -m 'Moved dir1 into dir2'
 
595
 
 
596
$ bzr merge ../trunk
 
597
2>Conflict moving dir2/dir1 into dir2.  Cancelled move.
 
598
2>1 conflicts encountered.
 
599
"""
 
600
 
 
601
    def test_take_this(self):
 
602
        self.run_script("""
 
603
$ bzr resolve dir2
 
604
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
605
""")
 
606
 
 
607
    def test_take_other(self):
 
608
        self.run_script("""
 
609
$ bzr mv dir2/dir1 dir1
 
610
$ bzr mv dir2 dir1
 
611
$ bzr resolve dir2
 
612
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
613
""")
 
614
 
 
615
    def test_resolve_taking_this(self):
 
616
        self.run_script("""
 
617
$ bzr resolve --take-this dir2
 
618
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
619
""")
 
620
        self.failUnlessExists('dir2')
 
621
 
 
622
    def test_resolve_taking_other(self):
 
623
        self.run_script("""
 
624
$ bzr resolve --take-other dir2
 
625
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
626
""")
 
627
        self.failUnlessExists('dir1')
 
628
 
 
629
 
 
630
class TestResolveNonDirectoryParent(TestResolveConflicts):
 
631
 
 
632
    preamble = """
 
633
$ bzr init trunk
 
634
$ cd trunk
 
635
$ bzr mkdir foo
 
636
$ bzr commit -m 'Create trunk'
 
637
$ echo "Boing" >foo/bar
 
638
$ bzr add foo/bar
 
639
$ bzr commit -m 'Add foo/bar'
 
640
 
 
641
$ bzr branch . -r 1 ../branch
 
642
$ cd ../branch
 
643
$ rm -r foo
 
644
$ echo "Boo!" >foo
 
645
$ bzr commit -m 'foo is now a file'
 
646
 
 
647
$ bzr merge ../trunk
 
648
2>+N  foo.new/bar
 
649
2>RK  foo => foo.new/
 
650
# FIXME: The message is misleading, foo.new *is* a directory when the message
 
651
# is displayed -- vila 090916
 
652
2>Conflict: foo.new is not a directory, but has files in it.  Created directory.
 
653
2>1 conflicts encountered.
 
654
"""
 
655
 
 
656
    def test_take_this(self):
 
657
        self.run_script("""
 
658
$ bzr rm foo.new --force
 
659
# FIXME: Isn't it weird that foo is now unkown even if foo.new has been put
 
660
# aside ? -- vila 090916
 
661
$ bzr add foo
 
662
$ bzr resolve foo.new
 
663
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
664
""")
 
665
 
 
666
    def test_take_other(self):
 
667
        self.run_script("""
 
668
$ bzr rm foo --force
 
669
$ bzr mv foo.new foo
 
670
$ bzr resolve foo
 
671
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
672
""")
 
673
 
 
674
    def test_resolve_taking_this(self):
 
675
        self.run_script("""
 
676
$ bzr resolve --take-this foo.new
 
677
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
678
""")
 
679
 
 
680
    def test_resolve_taking_other(self):
 
681
        self.run_script("""
 
682
$ bzr resolve --take-other foo.new
 
683
$ bzr commit --strict -m 'No more conflicts nor unknown files'
 
684
""")
 
685
 
 
686
 
 
687
class TestMalformedTransform(script.TestCaseWithTransportAndScript):
 
688
 
 
689
    def test_bug_430129(self):
 
690
        # This is nearly like TestResolveNonDirectoryParent but with branch and
 
691
        # trunk switched. As such it should certainly produce the same
 
692
        # conflict.
 
693
        self.run_script("""
 
694
$ bzr init trunk
 
695
$ cd trunk
 
696
$ bzr mkdir foo
 
697
$ bzr commit -m 'Create trunk'
 
698
$ rm -r foo
 
699
$ echo "Boo!" >foo
 
700
$ bzr commit -m 'foo is now a file'
 
701
 
 
702
$ bzr branch . -r 1 ../branch
 
703
$ cd ../branch
 
704
$ echo "Boing" >foo/bar
 
705
$ bzr add foo/bar
 
706
$ bzr commit -m 'Add foo/bar'
 
707
 
 
708
$ bzr merge ../trunk
 
709
2>bzr: ERROR: Tree transform is malformed [('unversioned executability', 'new-1')]
 
710
""")
 
711
 
 
712
 
 
713
class TestResolveActionOption(tests.TestCase):
 
714
 
 
715
    def setUp(self):
 
716
        super(TestResolveActionOption, self).setUp()
 
717
        self.options = [conflicts.ResolveActionOption()]
 
718
        self.parser = option.get_optparser(dict((o.name, o)
 
719
                                                for o in self.options))
 
720
 
 
721
    def parse(self, args):
 
722
        return self.parser.parse_args(args)
 
723
 
 
724
    def test_unknown_action(self):
 
725
        self.assertRaises(errors.BadOptionValue,
 
726
                          self.parse, ['--action', 'take-me-to-the-moon'])
 
727
 
 
728
    def test_done(self):
 
729
        opts, args = self.parse(['--action', 'done'])
 
730
        self.assertEqual({'action':'done'}, opts)
 
731
 
 
732
    def test_take_this(self):
 
733
        opts, args = self.parse(['--action', 'take-this'])
 
734
        self.assertEqual({'action': 'take_this'}, opts)
 
735
        opts, args = self.parse(['--take-this'])
 
736
        self.assertEqual({'action': 'take_this'}, opts)
 
737
 
 
738
    def test_take_other(self):
 
739
        opts, args = self.parse(['--action', 'take-other'])
 
740
        self.assertEqual({'action': 'take_other'}, opts)
 
741
        opts, args = self.parse(['--take-other'])
 
742
        self.assertEqual({'action': 'take_other'}, opts)