~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_errors.py

  • Committer: Vincent Ladeuil
  • Date: 2011-09-09 13:30:12 UTC
  • mfrom: (5609.48.11 2.3)
  • mto: (6015.33.3 2.4)
  • mto: This revision was merged to the branch mainline in revision 6134.
  • Revision ID: v.ladeuil+lp@free.fr-20110909133012-jc1d1zyqgak57123
Merge 2.3 into 2.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
2
 
#   Authors: Robert Collins <robert.collins@canonical.com>
3
 
#            and others
 
1
# Copyright (C) 2006-2011 Canonical Ltd
4
2
#
5
3
# This program is free software; you can redistribute it and/or modify
6
4
# it under the terms of the GNU General Public License as published by
18
16
 
19
17
"""Tests for the formatting and construction of errors."""
20
18
 
 
19
import inspect
 
20
import re
 
21
import socket
21
22
import sys
 
23
 
22
24
from bzrlib import (
23
25
    bzrdir,
24
26
    errors,
25
27
    osutils,
26
 
    symbol_versioning,
27
28
    urlutils,
28
29
    )
29
 
from bzrlib.tests import TestCase, TestCaseWithTransport
 
30
from bzrlib.tests import (
 
31
    TestCase,
 
32
    TestCaseWithTransport,
 
33
    TestSkipped,
 
34
    )
30
35
 
31
36
 
32
37
class TestErrors(TestCaseWithTransport):
33
38
 
 
39
    def test_no_arg_named_message(self):
 
40
        """Ensure the __init__ and _fmt in errors do not have "message" arg.
 
41
 
 
42
        This test fails if __init__ or _fmt in errors has an argument
 
43
        named "message" as this can cause errors in some Python versions.
 
44
        Python 2.5 uses a slot for StandardError.message.
 
45
        See bug #603461
 
46
        """
 
47
        fmt_pattern = re.compile("%\(message\)[sir]")
 
48
        subclasses_present = getattr(errors.BzrError, '__subclasses__', None)
 
49
        if not subclasses_present:
 
50
            raise TestSkipped('__subclasses__ attribute required for classes. '
 
51
                'Requires Python 2.5 or later.')
 
52
        for c in errors.BzrError.__subclasses__():
 
53
            init = getattr(c, '__init__', None)
 
54
            fmt = getattr(c, '_fmt', None)
 
55
            if init:
 
56
                args = inspect.getargspec(init)[0]
 
57
                self.assertFalse('message' in args,
 
58
                    ('Argument name "message" not allowed for '
 
59
                    '"errors.%s.__init__"' % c.__name__))
 
60
            if fmt and fmt_pattern.search(fmt):
 
61
                self.assertFalse(True, ('"message" not allowed in '
 
62
                    '"errors.%s._fmt"' % c.__name__))
 
63
 
34
64
    def test_bad_filename_encoding(self):
35
65
        error = errors.BadFilenameEncoding('bad/filen\xe5me', 'UTF-8')
36
66
        self.assertEqualDiff(
132
162
            "cannot be broken.",
133
163
            str(error))
134
164
 
 
165
    def test_lock_corrupt(self):
 
166
        error = errors.LockCorrupt("corruption info")
 
167
        self.assertEqualDiff("Lock is apparently held, but corrupted: "
 
168
            "corruption info\n"
 
169
            "Use 'bzr break-lock' to clear it",
 
170
            str(error))
 
171
 
135
172
    def test_knit_data_stream_incompatible(self):
136
173
        error = errors.KnitDataStreamIncompatible(
137
174
            'stream format', 'target format')
263
300
            str(error))
264
301
 
265
302
    def test_up_to_date(self):
266
 
        error = errors.UpToDateFormat(bzrdir.BzrDirFormat4())
267
 
        self.assertEqualDiff("The branch format All-in-one "
268
 
                             "format 4 is already at the most "
269
 
                             "recent format.",
270
 
                             str(error))
 
303
        error = errors.UpToDateFormat("someformat")
 
304
        self.assertEqualDiff(
 
305
            "The branch format someformat is already at the most "
 
306
            "recent format.", str(error))
271
307
 
272
308
    def test_corrupt_repository(self):
273
309
        repo = self.make_repository('.')
541
577
        try:
542
578
            1/0
543
579
        except ZeroDivisionError:
544
 
            exc_info = sys.exc_info()
545
 
        err = errors.HookFailed('hook stage', 'hook name', exc_info)
546
 
        self.assertStartsWith(
547
 
            str(err), 'Hook \'hook name\' during hook stage failed:\n')
548
 
        self.assertEndsWith(
549
 
            str(err), 'integer division or modulo by zero')
 
580
            err = errors.HookFailed('hook stage', 'hook name', sys.exc_info(),
 
581
                warn=False)
 
582
        # GZ 2010-11-08: Should not store exc_info in exception instances, but
 
583
        #                HookFailed is deprecated anyway and could maybe go.
 
584
        try:
 
585
            self.assertStartsWith(
 
586
                str(err), 'Hook \'hook name\' during hook stage failed:\n')
 
587
            self.assertEndsWith(
 
588
                str(err), 'integer division or modulo by zero')
 
589
        finally:
 
590
            del err
550
591
 
551
592
    def test_tip_change_rejected(self):
552
593
        err = errors.TipChangeRejected(u'Unicode message\N{INTERROBANG}')
575
616
        try:
576
617
            raise Exception("example error")
577
618
        except Exception:
578
 
            exc_info = sys.exc_info()
579
 
        err = errors.SmartMessageHandlerError(exc_info)
580
 
        self.assertStartsWith(
581
 
            str(err), "The message handler raised an exception:\n")
582
 
        self.assertEndsWith(str(err), "Exception: example error\n")
 
619
            err = errors.SmartMessageHandlerError(sys.exc_info())
 
620
        # GZ 2010-11-08: Should not store exc_info in exception instances.
 
621
        try:
 
622
            self.assertStartsWith(
 
623
                str(err), "The message handler raised an exception:\n")
 
624
            self.assertEndsWith(str(err), "Exception: example error\n")
 
625
        finally:
 
626
            del err
583
627
 
584
628
    def test_must_have_working_tree(self):
585
629
        err = errors.MustHaveWorkingTree('foo', 'bar')
623
667
        self.assertEqual(
624
668
            'Repository dummy repo cannot suspend a write group.', str(err))
625
669
 
 
670
    def test_not_branch_no_args(self):
 
671
        err = errors.NotBranchError('path')
 
672
        self.assertEqual('Not a branch: "path".', str(err))
 
673
 
 
674
    def test_not_branch_bzrdir_with_repo(self):
 
675
        bzrdir = self.make_repository('repo').bzrdir
 
676
        err = errors.NotBranchError('path', bzrdir=bzrdir)
 
677
        self.assertEqual(
 
678
            'Not a branch: "path": location is a repository.', str(err))
 
679
 
 
680
    def test_not_branch_bzrdir_without_repo(self):
 
681
        bzrdir = self.make_bzrdir('bzrdir')
 
682
        err = errors.NotBranchError('path', bzrdir=bzrdir)
 
683
        self.assertEqual('Not a branch: "path".', str(err))
 
684
 
 
685
    def test_not_branch_bzrdir_with_recursive_not_branch_error(self):
 
686
        class FakeBzrDir(object):
 
687
            def open_repository(self):
 
688
                # str() on the NotBranchError will trigger a call to this,
 
689
                # which in turn will another, identical NotBranchError.
 
690
                raise errors.NotBranchError('path', bzrdir=FakeBzrDir())
 
691
        err = errors.NotBranchError('path', bzrdir=FakeBzrDir())
 
692
        self.assertEqual('Not a branch: "path".', str(err))
 
693
 
 
694
    def test_not_branch_laziness(self):
 
695
        real_bzrdir = self.make_bzrdir('path')
 
696
        class FakeBzrDir(object):
 
697
            def __init__(self):
 
698
                self.calls = []
 
699
            def open_repository(self):
 
700
                self.calls.append('open_repository')
 
701
                raise errors.NoRepositoryPresent(real_bzrdir)
 
702
        fake_bzrdir = FakeBzrDir()
 
703
        err = errors.NotBranchError('path', bzrdir=fake_bzrdir)
 
704
        self.assertEqual([], fake_bzrdir.calls)
 
705
        str(err)
 
706
        self.assertEqual(['open_repository'], fake_bzrdir.calls)
 
707
        # Stringifying twice doesn't try to open a repository twice.
 
708
        str(err)
 
709
        self.assertEqual(['open_repository'], fake_bzrdir.calls)
 
710
 
 
711
    def test_invalid_pattern(self):
 
712
        error = errors.InvalidPattern('Bad pattern msg.')
 
713
        self.assertEqualDiff("Invalid pattern(s) found. Bad pattern msg.",
 
714
            str(error))
 
715
 
 
716
    def test_recursive_bind(self):
 
717
        error = errors.RecursiveBind('foo_bar_branch')
 
718
        msg = ('Branch "foo_bar_branch" appears to be bound to itself. '
 
719
            'Please use `bzr unbind` to fix.')
 
720
        self.assertEqualDiff(msg, str(error))
 
721
 
626
722
 
627
723
class PassThroughError(errors.BzrError):
628
724
 
638
734
 
639
735
 
640
736
class ErrorWithNoFormat(errors.BzrError):
641
 
    """This class has a docstring but no format string."""
 
737
    __doc__ = """This class has a docstring but no format string."""
642
738
 
643
739
 
644
740
class TestErrorFormatting(TestCase):
669
765
        e = ErrorWithBadFormat(not_thing='x')
670
766
        self.assertStartsWith(
671
767
            str(e), 'Unprintable exception ErrorWithBadFormat')
 
768
 
 
769
    def test_cannot_bind_address(self):
 
770
        # see <https://bugs.launchpad.net/bzr/+bug/286871>
 
771
        e = errors.CannotBindAddress('example.com', 22,
 
772
            socket.error(13, 'Permission denied'))
 
773
        self.assertContainsRe(str(e),
 
774
            r'Cannot bind address "example\.com:22":.*Permission denied')
 
775
 
 
776
    def test_file_timestamp_unavailable(self):            
 
777
        e = errors.FileTimestampUnavailable("/path/foo")
 
778
        self.assertEquals("The filestamp for /path/foo is not available.",
 
779
            str(e))
 
780
            
 
781
    def test_transform_rename_failed(self):
 
782
        e = errors.TransformRenameFailed(u"from", u"to", "readonly file", 2)
 
783
        self.assertEquals(
 
784
            u"Failed to rename from to to: readonly file",
 
785
            str(e))