~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_errors.py

  • Committer: Robert Collins
  • Date: 2009-04-24 05:08:51 UTC
  • mto: This revision was merged to the branch mainline in revision 4304.
  • Revision ID: robertc@robertcollins.net-20090424050851-sdfonaqerfs386t0
Reduce round trips pushing new branches substantially.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
 
3
#            and others
2
4
#
3
5
# This program is free software; you can redistribute it and/or modify
4
6
# it under the terms of the GNU General Public License as published by
16
18
 
17
19
"""Tests for the formatting and construction of errors."""
18
20
 
19
 
import inspect
20
 
import re
21
 
import socket
22
21
import sys
23
 
 
24
22
from bzrlib import (
25
23
    bzrdir,
26
24
    errors,
27
25
    osutils,
 
26
    symbol_versioning,
28
27
    urlutils,
29
28
    )
30
 
from bzrlib.tests import (
31
 
    TestCase,
32
 
    TestCaseWithTransport,
33
 
    TestSkipped,
34
 
    )
 
29
from bzrlib.tests import TestCase, TestCaseWithTransport
35
30
 
36
31
 
37
32
class TestErrors(TestCaseWithTransport):
38
33
 
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
 
 
64
34
    def test_bad_filename_encoding(self):
65
35
        error = errors.BadFilenameEncoding('bad/filen\xe5me', 'UTF-8')
66
36
        self.assertEqualDiff(
117
87
            "reason: reason for foo",
118
88
            str(error))
119
89
 
120
 
    def test_inconsistent_delta_delta(self):
121
 
        error = errors.InconsistentDeltaDelta([], 'reason')
122
 
        self.assertEqualDiff(
123
 
            "An inconsistent delta was supplied: []\nreason: reason",
124
 
            str(error))
125
 
 
126
90
    def test_in_process_transport(self):
127
91
        error = errors.InProcessTransport('fpp')
128
92
        self.assertEqualDiff(
150
114
            "read without data loss.",
151
115
            str(error))
152
116
 
 
117
    def test_install_failed(self):
 
118
        error = errors.InstallFailed(['rev-one'])
 
119
        self.assertEqual("Could not install revisions:\nrev-one", str(error))
 
120
        error = errors.InstallFailed(['rev-one', 'rev-two'])
 
121
        self.assertEqual("Could not install revisions:\nrev-one, rev-two",
 
122
                         str(error))
 
123
        error = errors.InstallFailed([None])
 
124
        self.assertEqual("Could not install revisions:\nNone", str(error))
 
125
 
153
126
    def test_jail_break(self):
154
127
        error = errors.JailBreak("some url")
155
128
        self.assertEqualDiff("An attempt to access a url outside the server"
162
135
            "cannot be broken.",
163
136
            str(error))
164
137
 
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
 
 
172
138
    def test_knit_data_stream_incompatible(self):
173
139
        error = errors.KnitDataStreamIncompatible(
174
140
            'stream format', 'target format')
285
251
            "You will need to upgrade the branch to permit branch stacking.",
286
252
            str(error))
287
253
 
288
 
    def test_unstackable_location(self):
289
 
        error = errors.UnstackableLocationError('foo', 'bar')
290
 
        self.assertEqualDiff("The branch 'foo' cannot be stacked on 'bar'.",
291
 
            str(error))
292
 
 
293
254
    def test_unstackable_repository_format(self):
294
255
        format = u'foo'
295
256
        url = "/foo"
300
261
            str(error))
301
262
 
302
263
    def test_up_to_date(self):
303
 
        error = errors.UpToDateFormat("someformat")
304
 
        self.assertEqualDiff(
305
 
            "The branch format someformat is already at the most "
306
 
            "recent format.", str(error))
 
264
        error = errors.UpToDateFormat(bzrdir.BzrDirFormat4())
 
265
        self.assertEqualDiff("The branch format All-in-one "
 
266
                             "format 4 is already at the most "
 
267
                             "recent format.",
 
268
                             str(error))
307
269
 
308
270
    def test_corrupt_repository(self):
309
271
        repo = self.make_repository('.')
577
539
        try:
578
540
            1/0
579
541
        except ZeroDivisionError:
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
 
542
            exc_info = sys.exc_info()
 
543
        err = errors.HookFailed('hook stage', 'hook name', exc_info)
 
544
        self.assertStartsWith(
 
545
            str(err), 'Hook \'hook name\' during hook stage failed:\n')
 
546
        self.assertEndsWith(
 
547
            str(err), 'integer division or modulo by zero')
591
548
 
592
549
    def test_tip_change_rejected(self):
593
550
        err = errors.TipChangeRejected(u'Unicode message\N{INTERROBANG}')
616
573
        try:
617
574
            raise Exception("example error")
618
575
        except Exception:
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
 
576
            exc_info = sys.exc_info()
 
577
        err = errors.SmartMessageHandlerError(exc_info)
 
578
        self.assertStartsWith(
 
579
            str(err), "The message handler raised an exception:\n")
 
580
        self.assertEndsWith(str(err), "Exception: example error\n")
627
581
 
628
582
    def test_must_have_working_tree(self):
629
583
        err = errors.MustHaveWorkingTree('foo', 'bar')
667
621
        self.assertEqual(
668
622
            'Repository dummy repo cannot suspend a write group.', str(err))
669
623
 
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
 
 
722
624
 
723
625
class PassThroughError(errors.BzrError):
724
626
 
734
636
 
735
637
 
736
638
class ErrorWithNoFormat(errors.BzrError):
737
 
    __doc__ = """This class has a docstring but no format string."""
 
639
    """This class has a docstring but no format string."""
738
640
 
739
641
 
740
642
class TestErrorFormatting(TestCase):
765
667
        e = ErrorWithBadFormat(not_thing='x')
766
668
        self.assertStartsWith(
767
669
            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))