~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_errors.py

  • Committer: Andrew Bennetts
  • Date: 2009-12-03 02:24:54 UTC
  • mfrom: (4634.101.4 2.0)
  • mto: This revision was merged to the branch mainline in revision 4857.
  • Revision ID: andrew.bennetts@canonical.com-20091203022454-m2gyhbcdqi1t7ujz
Merge lp:bzr/2.0 into lp:bzr.

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, 2009 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
16
16
 
17
17
"""Tests for the formatting and construction of errors."""
18
18
 
19
 
import inspect
20
 
import re
21
19
import socket
22
20
import sys
23
21
 
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(
162
132
            "cannot be broken.",
163
133
            str(error))
164
134
 
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
135
    def test_knit_data_stream_incompatible(self):
173
136
        error = errors.KnitDataStreamIncompatible(
174
137
            'stream format', 'target format')
300
263
            str(error))
301
264
 
302
265
    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))
 
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))
307
271
 
308
272
    def test_corrupt_repository(self):
309
273
        repo = self.make_repository('.')
349
313
        self.assertEqual("The value 'foo' is not a valid value.",
350
314
            str(error))
351
315
 
 
316
    def test_bzrnewerror_is_deprecated(self):
 
317
        class DeprecatedError(errors.BzrNewError):
 
318
            pass
 
319
        self.callDeprecated(['BzrNewError was deprecated in bzr 0.13; '
 
320
             'please convert DeprecatedError to use BzrError instead'],
 
321
            DeprecatedError)
 
322
 
352
323
    def test_bzrerror_from_literal_string(self):
353
324
        # Some code constructs BzrError from a literal string, in which case
354
325
        # no further formatting is done.  (I'm not sure raising the base class
565
536
        err = errors.UnknownRules(['foo', 'bar'])
566
537
        self.assertEquals("Unknown rules detected: foo, bar.", str(err))
567
538
 
 
539
    def test_hook_failed(self):
 
540
        # Create an exc_info tuple by raising and catching an exception.
 
541
        try:
 
542
            1/0
 
543
        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')
 
550
 
568
551
    def test_tip_change_rejected(self):
569
552
        err = errors.TipChangeRejected(u'Unicode message\N{INTERROBANG}')
570
553
        self.assertEquals(
592
575
        try:
593
576
            raise Exception("example error")
594
577
        except Exception:
595
 
            err = errors.SmartMessageHandlerError(sys.exc_info())
596
 
        # GZ 2010-11-08: Should not store exc_info in exception instances.
597
 
        try:
598
 
            self.assertStartsWith(
599
 
                str(err), "The message handler raised an exception:\n")
600
 
            self.assertEndsWith(str(err), "Exception: example error\n")
601
 
        finally:
602
 
            del err
 
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")
603
583
 
604
584
    def test_must_have_working_tree(self):
605
585
        err = errors.MustHaveWorkingTree('foo', 'bar')
643
623
        self.assertEqual(
644
624
            'Repository dummy repo cannot suspend a write group.', str(err))
645
625
 
646
 
    def test_not_branch_no_args(self):
647
 
        err = errors.NotBranchError('path')
648
 
        self.assertEqual('Not a branch: "path".', str(err))
649
 
 
650
 
    def test_not_branch_bzrdir_with_repo(self):
651
 
        bzrdir = self.make_repository('repo').bzrdir
652
 
        err = errors.NotBranchError('path', bzrdir=bzrdir)
653
 
        self.assertEqual(
654
 
            'Not a branch: "path": location is a repository.', str(err))
655
 
 
656
 
    def test_not_branch_bzrdir_without_repo(self):
657
 
        bzrdir = self.make_bzrdir('bzrdir')
658
 
        err = errors.NotBranchError('path', bzrdir=bzrdir)
659
 
        self.assertEqual('Not a branch: "path".', str(err))
660
 
 
661
 
    def test_not_branch_bzrdir_with_recursive_not_branch_error(self):
662
 
        class FakeBzrDir(object):
663
 
            def open_repository(self):
664
 
                # str() on the NotBranchError will trigger a call to this,
665
 
                # which in turn will another, identical NotBranchError.
666
 
                raise errors.NotBranchError('path', bzrdir=FakeBzrDir())
667
 
        err = errors.NotBranchError('path', bzrdir=FakeBzrDir())
668
 
        self.assertEqual('Not a branch: "path".', str(err))
669
 
 
670
 
    def test_not_branch_laziness(self):
671
 
        real_bzrdir = self.make_bzrdir('path')
672
 
        class FakeBzrDir(object):
673
 
            def __init__(self):
674
 
                self.calls = []
675
 
            def open_repository(self):
676
 
                self.calls.append('open_repository')
677
 
                raise errors.NoRepositoryPresent(real_bzrdir)
678
 
        fake_bzrdir = FakeBzrDir()
679
 
        err = errors.NotBranchError('path', bzrdir=fake_bzrdir)
680
 
        self.assertEqual([], fake_bzrdir.calls)
681
 
        str(err)
682
 
        self.assertEqual(['open_repository'], fake_bzrdir.calls)
683
 
        # Stringifying twice doesn't try to open a repository twice.
684
 
        str(err)
685
 
        self.assertEqual(['open_repository'], fake_bzrdir.calls)
686
 
 
687
 
    def test_invalid_pattern(self):
688
 
        error = errors.InvalidPattern('Bad pattern msg.')
689
 
        self.assertEqualDiff("Invalid pattern(s) found. Bad pattern msg.",
690
 
            str(error))
691
 
 
692
 
    def test_recursive_bind(self):
693
 
        error = errors.RecursiveBind('foo_bar_branch')
694
 
        msg = ('Branch "foo_bar_branch" appears to be bound to itself. '
695
 
            'Please use `bzr unbind` to fix.')
696
 
        self.assertEqualDiff(msg, str(error))
697
 
 
698
 
    def test_retry_with_new_packs(self):
699
 
        fake_exc_info = ('{exc type}', '{exc value}', '{exc traceback}')
700
 
        error = errors.RetryWithNewPacks(
701
 
            '{context}', reload_occurred=False, exc_info=fake_exc_info)
702
 
        self.assertEqual(
703
 
            'Pack files have changed, reload and retry. context: '
704
 
            '{context} {exc value}', str(error))
705
 
 
706
626
 
707
627
class PassThroughError(errors.BzrError):
708
628
 
718
638
 
719
639
 
720
640
class ErrorWithNoFormat(errors.BzrError):
721
 
    __doc__ = """This class has a docstring but no format string."""
 
641
    """This class has a docstring but no format string."""
722
642
 
723
643
 
724
644
class TestErrorFormatting(TestCase):
735
655
 
736
656
    def test_missing_format_string(self):
737
657
        e = ErrorWithNoFormat(param='randomvalue')
738
 
        self.assertStartsWith(str(e),
739
 
            "Unprintable exception ErrorWithNoFormat")
 
658
        s = self.callDeprecated(
 
659
                ['ErrorWithNoFormat uses its docstring as a format, it should use _fmt instead'],
 
660
                lambda x: str(x), e)
 
661
        ## s = str(e)
 
662
        self.assertEqual(s,
 
663
                "This class has a docstring but no format string.")
740
664
 
741
665
    def test_mismatched_format_args(self):
742
666
        # Even though ErrorWithBadFormat's format string does not match the
747
671
            str(e), 'Unprintable exception ErrorWithBadFormat')
748
672
 
749
673
    def test_cannot_bind_address(self):
750
 
        # see <https://bugs.launchpad.net/bzr/+bug/286871>
 
674
        # see <https://bugs.edge.launchpad.net/bzr/+bug/286871>
751
675
        e = errors.CannotBindAddress('example.com', 22,
752
676
            socket.error(13, 'Permission denied'))
753
677
        self.assertContainsRe(str(e),
754
678
            r'Cannot bind address "example\.com:22":.*Permission denied')
755
 
 
756
 
    def test_file_timestamp_unavailable(self):            
757
 
        e = errors.FileTimestampUnavailable("/path/foo")
758
 
        self.assertEquals("The filestamp for /path/foo is not available.",
759
 
            str(e))
760
 
            
761
 
    def test_transform_rename_failed(self):
762
 
        e = errors.TransformRenameFailed(u"from", u"to", "readonly file", 2)
763
 
        self.assertEquals(
764
 
            u"Failed to rename from to to: readonly file",
765
 
            str(e))