/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2006-2012, 2016 Canonical Ltd
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
16
17
"""Tests for the formatting and construction of errors."""
18
5050.8.1 by Parth Malwankar
added test to ensure that BzrError subclasses dont use "message" as a name
19
import inspect
20
import re
4634.1.2 by Martin Pool
Add test for CannotBindAddress
21
import socket
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
22
import sys
4634.1.2 by Martin Pool
Add test for CannotBindAddress
23
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
24
from .. import (
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
25
    controldir,
1948.1.6 by John Arbash Meinel
Make BzrNewError always return a str object
26
    errors,
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
27
    osutils,
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
28
    tests,
3200.2.1 by Robert Collins
* The ``register-branch`` command will now use the public url of the branch
29
    urlutils,
1948.1.6 by John Arbash Meinel
Make BzrNewError always return a str object
30
    )
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
31
from ..sixish import (
32
    text_type,
5579.3.1 by Jelmer Vernooij
Remove unused imports.
33
    )
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
34
35
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
36
class TestErrors(tests.TestCase):
1534.4.50 by Robert Collins
Got the bzrdir api straightened out, plenty of refactoring to use it pending, but the api is up and running.
37
5050.8.1 by Parth Malwankar
added test to ensure that BzrError subclasses dont use "message" as a name
38
    def test_no_arg_named_message(self):
39
        """Ensure the __init__ and _fmt in errors do not have "message" arg.
40
41
        This test fails if __init__ or _fmt in errors has an argument
42
        named "message" as this can cause errors in some Python versions.
43
        Python 2.5 uses a slot for StandardError.message.
44
        See bug #603461
45
        """
46
        fmt_pattern = re.compile("%\(message\)[sir]")
5050.8.3 by Parth Malwankar
use __subclasses__
47
        for c in errors.BzrError.__subclasses__():
48
            init = getattr(c, '__init__', None)
49
            fmt = getattr(c, '_fmt', None)
5050.8.1 by Parth Malwankar
added test to ensure that BzrError subclasses dont use "message" as a name
50
            if init:
51
                args = inspect.getargspec(init)[0]
52
                self.assertFalse('message' in args,
53
                    ('Argument name "message" not allowed for '
5050.8.3 by Parth Malwankar
use __subclasses__
54
                    '"errors.%s.__init__"' % c.__name__))
5050.8.1 by Parth Malwankar
added test to ensure that BzrError subclasses dont use "message" as a name
55
            if fmt and fmt_pattern.search(fmt):
56
                self.assertFalse(True, ('"message" not allowed in '
5050.8.3 by Parth Malwankar
use __subclasses__
57
                    '"errors.%s._fmt"' % c.__name__))
5050.8.1 by Parth Malwankar
added test to ensure that BzrError subclasses dont use "message" as a name
58
3287.20.2 by John Arbash Meinel
Raise a clear error about the offending filename when there is a filename with bad characters.
59
    def test_bad_filename_encoding(self):
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
60
        error = errors.BadFilenameEncoding(b'bad/filen\xe5me', 'UTF-8')
6670.3.2 by Martin
Avoid PendingDeprecationWarning from assertRegexpMatches
61
        self.assertContainsRe(
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
62
            str(error),
63
            "^Filename b?'bad/filen\\\\xe5me' is not valid in your current"
64
            " filesystem encoding UTF-8$")
3287.20.2 by John Arbash Meinel
Raise a clear error about the offending filename when there is a filename with bad characters.
65
2255.7.16 by John Arbash Meinel
Make sure adding a duplicate file_id raises DuplicateFileId.
66
    def test_duplicate_file_id(self):
67
        error = errors.DuplicateFileId('a_file_id', 'foo')
68
        self.assertEqualDiff('File id {a_file_id} already exists in inventory'
69
                             ' as foo', str(error))
70
2432.1.19 by Robert Collins
Ensure each HelpIndex has a unique prefix.
71
    def test_duplicate_help_prefix(self):
72
        error = errors.DuplicateHelpPrefix('foo')
73
        self.assertEqualDiff('The prefix foo is in the help search path twice.',
74
            str(error))
75
3445.1.1 by John Arbash Meinel
Start working on a new Graph api to make finding revision numbers faster.
76
    def test_ghost_revisions_have_no_revno(self):
77
        error = errors.GhostRevisionsHaveNoRevno('target', 'ghost_rev')
78
        self.assertEqualDiff("Could not determine revno for {target} because"
79
                             " its ancestry shows a ghost at {ghost_rev}",
80
                             str(error))
81
6672.1.2 by Jelmer Vernooij
Remove breezy.api.
82
    def test_incompatibleVersion(self):
83
        error = errors.IncompatibleVersion("module", [(4, 5, 6), (7, 8, 9)],
84
                (1, 2, 3))
2550.2.3 by Robert Collins
Add require_api API.
85
        self.assertEqualDiff(
6672.1.2 by Jelmer Vernooij
Remove breezy.api.
86
            'API module is not compatible; one of versions '
87
            '[(4, 5, 6), (7, 8, 9)] is required, but current version is '
88
            '(1, 2, 3).',
2550.2.3 by Robert Collins
Add require_api API.
89
            str(error))
90
3207.2.2 by John Arbash Meinel
Fix bug #187169, when an invalid delta is supplied to update_basis_by_delta
91
    def test_inconsistent_delta(self):
92
        error = errors.InconsistentDelta('path', 'file-id', 'reason for foo')
93
        self.assertEqualDiff(
3221.1.8 by Martin Pool
Update error format in test_inconsistent_delta
94
            "An inconsistent delta was supplied involving 'path', 'file-id'\n"
3207.2.2 by John Arbash Meinel
Fix bug #187169, when an invalid delta is supplied to update_basis_by_delta
95
            "reason: reason for foo",
96
            str(error))
97
4505.5.1 by Robert Collins
Add more generic InconsistentDeltaDelta error class for use when the exact cause of an inconsistent delta isn't trivially accessible.
98
    def test_inconsistent_delta_delta(self):
99
        error = errors.InconsistentDeltaDelta([], 'reason')
100
        self.assertEqualDiff(
101
            "An inconsistent delta was supplied: []\nreason: reason",
102
            str(error))
103
2634.1.1 by Robert Collins
(robertc) Reinstate the accidentally backed out external_url patch.
104
    def test_in_process_transport(self):
105
        error = errors.InProcessTransport('fpp')
106
        self.assertEqualDiff(
107
            "The transport 'fpp' is only accessible within this process.",
108
            str(error))
109
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
110
    def test_invalid_http_range(self):
111
        error = errors.InvalidHttpRange('path',
112
                                        'Content-Range: potatoes 0-00/o0oo0',
113
                                        'bad range')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
114
        self.assertEqual("Invalid http range"
115
                         " 'Content-Range: potatoes 0-00/o0oo0'"
116
                         " for path: bad range",
117
                         str(error))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
118
119
    def test_invalid_range(self):
120
        error = errors.InvalidRange('path', 12, 'bad range')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
121
        self.assertEqual("Invalid range access in path at 12: bad range",
122
                         str(error))
3059.2.12 by Vincent Ladeuil
Spiv review feedback.
123
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
124
    def test_inventory_modified(self):
125
        error = errors.InventoryModified("a tree to be repred")
126
        self.assertEqualDiff("The current inventory for the tree 'a tree to "
127
            "be repred' has been modified, so a clean inventory cannot be "
128
            "read without data loss.",
129
            str(error))
130
4294.2.8 by Robert Collins
Reduce round trips pushing new branches substantially.
131
    def test_jail_break(self):
132
        error = errors.JailBreak("some url")
133
        self.assertEqualDiff("An attempt to access a url outside the server"
134
            " jail was made: 'some url'.",
135
            str(error))
136
2255.2.145 by Robert Collins
Support unbreakable locks for trees.
137
    def test_lock_active(self):
138
        error = errors.LockActive("lock description")
139
        self.assertEqualDiff("The lock for 'lock description' is in use and "
140
            "cannot be broken.",
141
            str(error))
142
4634.161.1 by Andrew Bennetts
Add LockCorrupt error, and use it to provide nicer handling of unparseable lock/held/info files.
143
    def test_lock_corrupt(self):
144
        error = errors.LockCorrupt("corruption info")
145
        self.assertEqualDiff("Lock is apparently held, but corrupted: "
146
            "corruption info\n"
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
147
            "Use 'brz break-lock' to clear it",
4634.161.1 by Andrew Bennetts
Add LockCorrupt error, and use it to provide nicer handling of unparseable lock/held/info files.
148
            str(error))
149
2535.3.4 by Andrew Bennetts
Simple implementation of Knit.insert_data_stream.
150
    def test_knit_data_stream_incompatible(self):
151
        error = errors.KnitDataStreamIncompatible(
152
            'stream format', 'target format')
153
        self.assertEqual('Cannot insert knit data stream of format '
154
                         '"stream format" into knit of format '
155
                         '"target format".', str(error))
156
3052.2.1 by Robert Collins
Add a new KnitDataStreamUnknown error class for showing formats we can't understand.
157
    def test_knit_data_stream_unknown(self):
158
        error = errors.KnitDataStreamUnknown(
159
            'stream format')
160
        self.assertEqual('Cannot parse knit data stream of format '
161
                         '"stream format".', str(error))
162
2171.1.1 by John Arbash Meinel
Knit index files should ignore empty indexes rather than consider them corrupt.
163
    def test_knit_header_error(self):
164
        error = errors.KnitHeaderError('line foo\n', 'path/to/file')
165
        self.assertEqual("Knit header error: 'line foo\\n' unexpected"
2745.3.2 by Daniel Watkins
Updated tests to reflect new error text.
166
                         " for file \"path/to/file\".", str(error))
2171.1.1 by John Arbash Meinel
Knit index files should ignore empty indexes rather than consider them corrupt.
167
2196.2.5 by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it
168
    def test_knit_index_unknown_method(self):
169
        error = errors.KnitIndexUnknownMethod('http://host/foo.kndx',
170
                                              ['bad', 'no-eol'])
171
        self.assertEqual("Knit index http://host/foo.kndx does not have a"
172
                         " known method in options: ['bad', 'no-eol']",
173
                         str(error))
174
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
175
    def test_medium_not_connected(self):
176
        error = errors.MediumNotConnected("a medium")
177
        self.assertEqualDiff(
178
            "The medium 'a medium' is not connected.", str(error))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
179
2018.2.3 by Andrew Bennetts
Starting factoring out the smart server client "medium" from the protocol.
180
    def test_no_smart_medium(self):
181
        error = errors.NoSmartMedium("a transport")
182
        self.assertEqualDiff("The transport 'a transport' cannot tunnel the "
183
            "smart protocol.",
184
            str(error))
185
1988.2.1 by Robert Collins
WorkingTree has a new api ``unversion`` which allow the unversioning of
186
    def test_no_such_id(self):
187
        error = errors.NoSuchId("atree", "anid")
2745.3.2 by Daniel Watkins
Updated tests to reflect new error text.
188
        self.assertEqualDiff("The file id \"anid\" is not present in the tree "
2745.3.3 by Daniel Watkins
Changed to remove need for escaping of quotes.
189
            "atree.",
1988.2.1 by Robert Collins
WorkingTree has a new api ``unversion`` which allow the unversioning of
190
            str(error))
1534.5.7 by Robert Collins
Start factoring out the upgrade policy logic.
191
1908.11.1 by Robert Collins
Add a new method ``Tree.revision_tree`` which allows access to cached
192
    def test_no_such_revision_in_tree(self):
193
        error = errors.NoSuchRevisionInTree("atree", "anid")
2745.3.3 by Daniel Watkins
Changed to remove need for escaping of quotes.
194
        self.assertEqualDiff("The revision id {anid} is not present in the"
195
                             " tree atree.", str(error))
1908.11.1 by Robert Collins
Add a new method ``Tree.revision_tree`` which allows access to cached
196
        self.assertIsInstance(error, errors.NoSuchRevision)
197
3221.11.2 by Robert Collins
Create basic stackable branch facility.
198
    def test_not_stacked(self):
199
        error = errors.NotStacked('a branch')
200
        self.assertEqualDiff("The branch 'a branch' is not stacked.",
201
            str(error))
202
1986.5.3 by Robert Collins
New method ``WorkingTree.flush()`` which will write the current memory
203
    def test_not_write_locked(self):
204
        error = errors.NotWriteLocked('a thing to repr')
205
        self.assertEqualDiff("'a thing to repr' is not write locked but needs "
206
            "to be.",
207
            str(error))
208
2872.5.1 by Martin Pool
Avoid internal error tracebacks on failure to lock on readonly transport (#129701).
209
    def test_lock_failed(self):
210
        error = errors.LockFailed('http://canonical.com/', 'readonly transport')
211
        self.assertEqualDiff("Cannot lock http://canonical.com/: readonly transport",
212
            str(error))
213
        self.assertFalse(error.internal_error)
214
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
215
    def test_too_many_concurrent_requests(self):
216
        error = errors.TooManyConcurrentRequests("a medium")
217
        self.assertEqualDiff("The medium 'a medium' has reached its concurrent "
218
            "request limit. Be sure to finish_writing and finish_reading on "
2018.5.134 by Andrew Bennetts
Fix the TooManyConcurrentRequests error message.
219
            "the currently open request.",
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
220
            str(error))
221
3350.3.3 by Robert Collins
Functional get_record_stream interface tests covering full interface.
222
    def test_unavailable_representation(self):
223
        error = errors.UnavailableRepresentation(('key',), "mpdiff", "fulltext")
224
        self.assertEqualDiff("The encoding 'mpdiff' is not available for key "
225
            "('key',) which is encoded as 'fulltext'.",
226
            str(error))
227
4462.3.2 by Robert Collins
Do not stack on the same branch/repository anymore. This was never supported and would generally result in infinite recursion. Fixes bug 376243.
228
    def test_unstackable_location(self):
229
        error = errors.UnstackableLocationError('foo', 'bar')
230
        self.assertEqualDiff("The branch 'foo' cannot be stacked on 'bar'.",
231
            str(error))
232
3221.11.2 by Robert Collins
Create basic stackable branch facility.
233
    def test_unstackable_repository_format(self):
234
        format = u'foo'
235
        url = "/foo"
236
        error = errors.UnstackableRepositoryFormat(format, url)
237
        self.assertEqualDiff(
238
            "The repository '/foo'(foo) is not a stackable format. "
239
            "You will need to upgrade the repository to permit branch stacking.",
240
            str(error))
241
1534.5.7 by Robert Collins
Start factoring out the upgrade policy logic.
242
    def test_up_to_date(self):
5582.10.51 by Jelmer Vernooij
Remove use of BzrDirFormat4 in test_errors.
243
        error = errors.UpToDateFormat("someformat")
244
        self.assertEqualDiff(
245
            "The branch format someformat is already at the most "
246
            "recent format.", str(error))
1570.1.13 by Robert Collins
Check for incorrect revision parentage in the weave during revision access.
247
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
248
    def test_read_error(self):
249
        # a unicode path to check that %r is being used.
250
        path = u'a path'
251
        error = errors.ReadError(path)
6670.3.2 by Martin
Avoid PendingDeprecationWarning from assertRegexpMatches
252
        self.assertContainsRe(str(error), "^Error reading from u?'a path'.$")
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
253
2592.1.7 by Robert Collins
A validate that goes boom.
254
    def test_bad_index_format_signature(self):
255
        error = errors.BadIndexFormatSignature("foo", "bar")
256
        self.assertEqual("foo is not an index of type bar.",
257
            str(error))
2052.6.2 by Robert Collins
Merge bzr.dev.
258
2592.1.11 by Robert Collins
Detect truncated indices.
259
    def test_bad_index_data(self):
260
        error = errors.BadIndexData("foo")
261
        self.assertEqual("Error in data for index foo.",
262
            str(error))
263
2592.1.15 by Robert Collins
Detect duplicate key insertion.
264
    def test_bad_index_duplicate_key(self):
265
        error = errors.BadIndexDuplicateKey("foo", "bar")
266
        self.assertEqual("The key 'foo' is already in index 'bar'.",
267
            str(error))
268
2592.1.12 by Robert Collins
Handle basic node adds.
269
    def test_bad_index_key(self):
270
        error = errors.BadIndexKey("foo")
271
        self.assertEqual("The key 'foo' is not a valid key.",
272
            str(error))
273
2592.1.10 by Robert Collins
Make validate detect node reference parsing errors.
274
    def test_bad_index_options(self):
275
        error = errors.BadIndexOptions("foo")
276
        self.assertEqual("Could not parse options for index foo.",
277
            str(error))
278
2592.1.12 by Robert Collins
Handle basic node adds.
279
    def test_bad_index_value(self):
280
        error = errors.BadIndexValue("foo")
281
        self.assertEqual("The value 'foo' is not a valid value.",
282
            str(error))
283
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
284
    def test_bzrerror_from_literal_string(self):
285
        # Some code constructs BzrError from a literal string, in which case
286
        # no further formatting is done.  (I'm not sure raising the base class
287
        # is a great idea, but if the exception is not intended to be caught
288
        # perhaps no more is needed.)
289
        try:
290
            raise errors.BzrError('this is my errors; %d is not expanded')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
291
        except errors.BzrError as e:
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
292
            self.assertEqual('this is my errors; %d is not expanded', str(e))
293
2018.2.4 by Robert Collins
separate out the client medium from the client encoding protocol for the smart server.
294
    def test_reading_completed(self):
295
        error = errors.ReadingCompleted("a request")
296
        self.assertEqualDiff("The MediumRequest 'a request' has already had "
297
            "finish_reading called upon it - the request has been completed and"
298
            " no more data may be read.",
299
            str(error))
300
301
    def test_writing_completed(self):
302
        error = errors.WritingCompleted("a request")
303
        self.assertEqualDiff("The MediumRequest 'a request' has already had "
304
            "finish_writing called upon it - accept bytes may not be called "
305
            "anymore.",
306
            str(error))
307
308
    def test_writing_not_completed(self):
309
        error = errors.WritingNotComplete("a request")
310
        self.assertEqualDiff("The MediumRequest 'a request' has not has "
311
            "finish_writing called upon it - until the write phase is complete"
312
            " no data may be read.",
313
            str(error))
314
2052.6.1 by Robert Collins
``Transport.get`` has had its interface made more clear for ease of use.
315
    def test_transport_not_possible(self):
316
        error = errors.TransportNotPossible('readonly', 'original error')
317
        self.assertEqualDiff('Transport operation not possible:'
318
                         ' readonly original error', str(error))
2052.4.4 by John Arbash Meinel
Create a SocketConnectionError to make creating nice errors easier
319
320
    def assertSocketConnectionError(self, expected, *args, **kwargs):
321
        """Check the formatting of a SocketConnectionError exception"""
322
        e = errors.SocketConnectionError(*args, **kwargs)
323
        self.assertEqual(expected, str(e))
324
325
    def test_socket_connection_error(self):
326
        """Test the formatting of SocketConnectionError"""
327
328
        # There should be a default msg about failing to connect
329
        # we only require a host name.
330
        self.assertSocketConnectionError(
331
            'Failed to connect to ahost',
332
            'ahost')
333
334
        # If port is None, we don't put :None
335
        self.assertSocketConnectionError(
336
            'Failed to connect to ahost',
337
            'ahost', port=None)
338
        # But if port is supplied we include it
339
        self.assertSocketConnectionError(
340
            'Failed to connect to ahost:22',
341
            'ahost', port=22)
342
343
        # We can also supply extra information about the error
344
        # with or without a port
345
        self.assertSocketConnectionError(
346
            'Failed to connect to ahost:22; bogus error',
347
            'ahost', port=22, orig_error='bogus error')
348
        self.assertSocketConnectionError(
349
            'Failed to connect to ahost; bogus error',
350
            'ahost', orig_error='bogus error')
351
        # An exception object can be passed rather than a string
352
        orig_error = ValueError('bad value')
353
        self.assertSocketConnectionError(
354
            'Failed to connect to ahost; %s' % (str(orig_error),),
355
            host='ahost', orig_error=orig_error)
356
357
        # And we can supply a custom failure message
358
        self.assertSocketConnectionError(
359
            'Unable to connect to ssh host ahost:444; my_error',
360
            host='ahost', port=444, msg='Unable to connect to ssh host',
361
            orig_error='my_error')
362
3535.8.2 by James Westby
Incorporate spiv's feedback.
363
    def test_target_not_branch(self):
364
        """Test the formatting of TargetNotBranch."""
365
        error = errors.TargetNotBranch('foo')
366
        self.assertEqual(
367
            "Your branch does not have all of the revisions required in "
3535.8.4 by James Westby
Replace "however" with "and" at John's request.
368
            "order to merge this merge directive and the target "
3535.8.3 by James Westby
Use location instead of branch as suggested by Robert.
369
            "location specified in the merge directive is not a branch: "
3535.8.2 by James Westby
Incorporate spiv's feedback.
370
            "foo.", str(error))
371
2018.5.163 by Andrew Bennetts
Deal with various review comments from Robert.
372
    def test_unexpected_smart_server_response(self):
373
        e = errors.UnexpectedSmartServerResponse(('not yes',))
374
        self.assertEqual(
375
            "Could not understand response from smart server: ('not yes',)",
376
            str(e))
2052.4.4 by John Arbash Meinel
Create a SocketConnectionError to make creating nice errors easier
377
2506.2.1 by Andrew Bennetts
Start implementing container format reading and writing.
378
    def test_unknown_container_format(self):
379
        """Test the formatting of UnknownContainerFormatError."""
380
        e = errors.UnknownContainerFormatError('bad format string')
381
        self.assertEqual(
382
            "Unrecognised container format: 'bad format string'",
383
            str(e))
384
385
    def test_unexpected_end_of_container(self):
386
        """Test the formatting of UnexpectedEndOfContainerError."""
387
        e = errors.UnexpectedEndOfContainerError()
388
        self.assertEqual(
389
            "Unexpected end of container stream", str(e))
390
391
    def test_unknown_record_type(self):
392
        """Test the formatting of UnknownRecordTypeError."""
393
        e = errors.UnknownRecordTypeError("X")
394
        self.assertEqual(
395
            "Unknown record type: 'X'",
396
            str(e))
397
2506.3.1 by Andrew Bennetts
More progress:
398
    def test_invalid_record(self):
399
        """Test the formatting of InvalidRecordError."""
400
        e = errors.InvalidRecordError("xxx")
401
        self.assertEqual(
402
            "Invalid record: xxx",
403
            str(e))
404
2506.2.6 by Andrew Bennetts
Add validate method to ContainerReader and BytesRecordReader.
405
    def test_container_has_excess_data(self):
406
        """Test the formatting of ContainerHasExcessDataError."""
407
        e = errors.ContainerHasExcessDataError("excess bytes")
408
        self.assertEqual(
409
            "Container has data after end marker: 'excess bytes'",
410
            str(e))
411
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
412
    def test_duplicate_record_name_error(self):
413
        """Test the formatting of DuplicateRecordNameError."""
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
414
        e = errors.DuplicateRecordNameError(b"n\xc3\xa5me")
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
415
        self.assertEqual(
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
416
            u"Container has multiple records with the same name: n\xe5me",
417
            text_type(e))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
418
2854.1.1 by Martin Pool
Fix "unprintable error" message for BzrCheckError and others
419
    def test_check_error(self):
420
        e = errors.BzrCheckError('example check failure')
421
        self.assertEqual(
422
            "Internal check failed: example check failure",
423
            str(e))
424
        self.assertTrue(e.internal_error)
2506.6.1 by Andrew Bennetts
Return a callable instead of a str from read, and add more validation.
425
2535.3.40 by Andrew Bennetts
Tidy up more XXXs.
426
    def test_repository_data_stream_error(self):
427
        """Test the formatting of RepositoryDataStreamError."""
428
        e = errors.RepositoryDataStreamError(u"my reason")
429
        self.assertEqual(
430
            "Corrupt or incompatible data stream: my reason", str(e))
431
2978.2.1 by Alexander Belchenko
fix formatting of ImmortalPendingDeletion error message.
432
    def test_immortal_pending_deletion_message(self):
433
        err = errors.ImmortalPendingDeletion('foo')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
434
        self.assertEqual(
2978.2.1 by Alexander Belchenko
fix formatting of ImmortalPendingDeletion error message.
435
            "Unable to delete transform temporary directory foo.  "
436
            "Please examine foo to see if it contains any files "
437
            "you wish to keep, and delete it when you are done.",
438
            str(err))
439
3006.2.2 by Alexander Belchenko
tests added.
440
    def test_unable_create_symlink(self):
441
        err = errors.UnableCreateSymlink()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
442
        self.assertEqual(
3006.2.2 by Alexander Belchenko
tests added.
443
            "Unable to create symlink on this platform",
444
            str(err))
445
        err = errors.UnableCreateSymlink(path=u'foo')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
446
        self.assertEqual(
3006.2.2 by Alexander Belchenko
tests added.
447
            "Unable to create symlink 'foo' on this platform",
448
            str(err))
449
        err = errors.UnableCreateSymlink(path=u'\xb5')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
450
        self.assertEqual(
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
451
            "Unable to create symlink %s on this platform" % repr(u'\xb5'),
3006.2.2 by Alexander Belchenko
tests added.
452
            str(err))
453
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
454
    def test_invalid_url_join(self):
455
        """Test the formatting of InvalidURLJoin."""
6729.6.1 by Jelmer Vernooij
Move urlutils errors.
456
        e = urlutils.InvalidURLJoin('Reason', 'base path', ('args',))
2692.1.1 by Andrew Bennetts
Add translate_client_path method to SmartServerRequest.
457
        self.assertEqual(
458
            "Invalid URL join request: Reason: 'base path' + ('args',)",
459
            str(e))
460
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
461
    def test_unable_encode_path(self):
462
        err = errors.UnableEncodePath('foo', 'executable')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
463
        self.assertEqual("Unable to encode executable path 'foo' in "
464
                         "user encoding " + osutils.get_user_encoding(),
465
                         str(err))
3234.2.6 by Alexander Belchenko
because every mail client has different rules to compose command line we should encode arguments to 8 bit string only when needed.
466
3246.3.4 by Daniel Watkins
Added test.
467
    def test_unknown_format(self):
468
        err = errors.UnknownFormatError('bar', kind='foo')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
469
        self.assertEqual("Unknown foo format: 'bar'", str(err))
3246.3.4 by Daniel Watkins
Added test.
470
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
471
    def test_tip_change_rejected(self):
472
        err = errors.TipChangeRejected(u'Unicode message\N{INTERROBANG}')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
473
        self.assertEqual(
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
474
            u'Tip change rejected: Unicode message\N{INTERROBANG}',
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
475
            text_type(err))
3577.1.1 by Andrew Bennetts
Cherry-pick TipChangeRejected changes from pre-branch-tip-changed-hook loom.
476
3690.1.1 by Andrew Bennetts
Unexpected error responses from a smart server no longer cause the client to traceback.
477
    def test_error_from_smart_server(self):
478
        error_tuple = ('error', 'tuple')
479
        err = errors.ErrorFromSmartServer(error_tuple)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
480
        self.assertEqual(
3690.1.1 by Andrew Bennetts
Unexpected error responses from a smart server no longer cause the client to traceback.
481
            "Error received from smart server: ('error', 'tuple')", str(err))
482
483
    def test_untranslateable_error_from_smart_server(self):
484
        error_tuple = ('error', 'tuple')
485
        orig_err = errors.ErrorFromSmartServer(error_tuple)
3690.1.2 by Andrew Bennetts
Rename UntranslateableErrorFromSmartServer -> UnknownErrorFromSmartServer.
486
        err = errors.UnknownErrorFromSmartServer(orig_err)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
487
        self.assertEqual(
3690.1.1 by Andrew Bennetts
Unexpected error responses from a smart server no longer cause the client to traceback.
488
            "Server sent an unexpected error: ('error', 'tuple')", str(err))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
489
3883.2.3 by Andrew Bennetts
Add test, tweak traceback formatting.
490
    def test_smart_message_handler_error(self):
491
        # Make an exc_info tuple.
492
        try:
493
            raise Exception("example error")
494
        except Exception:
5340.15.2 by John Arbash Meinel
supercede 2.4-613247-cleanup-tests
495
            err = errors.SmartMessageHandlerError(sys.exc_info())
496
        # GZ 2010-11-08: Should not store exc_info in exception instances.
497
        try:
498
            self.assertStartsWith(
499
                str(err), "The message handler raised an exception:\n")
500
            self.assertEndsWith(str(err), "Exception: example error\n")
501
        finally:
502
            del err
3690.1.1 by Andrew Bennetts
Unexpected error responses from a smart server no longer cause the client to traceback.
503
4002.1.7 by Andrew Bennetts
Rename UnresumableWriteGroups to UnresumableWriteGroup.
504
    def test_unresumable_write_group(self):
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
505
        repo = "dummy repo"
506
        wg_tokens = ['token']
507
        reason = "a reason"
4002.1.7 by Andrew Bennetts
Rename UnresumableWriteGroups to UnresumableWriteGroup.
508
        err = errors.UnresumableWriteGroup(repo, wg_tokens, reason)
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
509
        self.assertEqual(
4002.1.7 by Andrew Bennetts
Rename UnresumableWriteGroups to UnresumableWriteGroup.
510
            "Repository dummy repo cannot resume write group "
4002.1.1 by Andrew Bennetts
Implement suspend_write_group/resume_write_group.
511
            "['token']: a reason", str(err))
512
513
    def test_unsuspendable_write_group(self):
514
        repo = "dummy repo"
515
        err = errors.UnsuspendableWriteGroup(repo)
516
        self.assertEqual(
517
            'Repository dummy repo cannot suspend a write group.', str(err))
518
4734.4.9 by Andrew Bennetts
More tests and comments.
519
    def test_not_branch_no_args(self):
520
        err = errors.NotBranchError('path')
521
        self.assertEqual('Not a branch: "path".', str(err))
522
5050.46.1 by Andrew Bennetts
Suppress unexpected errors during NotBranchError's call to open_repository.
523
    def test_not_branch_bzrdir_with_recursive_not_branch_error(self):
524
        class FakeBzrDir(object):
525
            def open_repository(self):
526
                # str() on the NotBranchError will trigger a call to this,
527
                # which in turn will another, identical NotBranchError.
6653.6.6 by Jelmer Vernooij
Fix remaining tests.
528
                raise errors.NotBranchError('path', controldir=FakeBzrDir())
529
        err = errors.NotBranchError('path', controldir=FakeBzrDir())
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
530
        self.assertEqual('Not a branch: "path": NotBranchError.', str(err))
4734.4.9 by Andrew Bennetts
More tests and comments.
531
5050.7.6 by Parth Malwankar
fixed test name
532
    def test_recursive_bind(self):
5050.7.5 by Parth Malwankar
better error message for RecursiveBind
533
        error = errors.RecursiveBind('foo_bar_branch')
534
        msg = ('Branch "foo_bar_branch" appears to be bound to itself. '
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
535
            'Please use `brz unbind` to fix.')
5050.7.5 by Parth Malwankar
better error message for RecursiveBind
536
        self.assertEqualDiff(msg, str(error))
537
5609.58.1 by Andrew Bennetts
Fix 'Unprintable exception' when displaying RetryWithNewPacks error.
538
    def test_retry_with_new_packs(self):
539
        fake_exc_info = ('{exc type}', '{exc value}', '{exc traceback}')
540
        error = errors.RetryWithNewPacks(
541
            '{context}', reload_occurred=False, exc_info=fake_exc_info)
542
        self.assertEqual(
543
            'Pack files have changed, reload and retry. context: '
544
            '{context} {exc value}', str(error))
545
2116.3.1 by John Arbash Meinel
Cleanup error tests
546
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
547
class PassThroughError(errors.BzrError):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
548
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
549
    _fmt = """Pass through %(foo)s and %(bar)s"""
2116.3.1 by John Arbash Meinel
Cleanup error tests
550
551
    def __init__(self, foo, bar):
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
552
        errors.BzrError.__init__(self, foo=foo, bar=bar)
553
554
555
class ErrorWithBadFormat(errors.BzrError):
556
557
    _fmt = """One format specifier: %(thing)s"""
558
559
560
class ErrorWithNoFormat(errors.BzrError):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
561
    __doc__ = """This class has a docstring but no format string."""
2116.3.1 by John Arbash Meinel
Cleanup error tests
562
563
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
564
class TestErrorFormatting(tests.TestCase):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
565
2116.3.1 by John Arbash Meinel
Cleanup error tests
566
    def test_always_str(self):
567
        e = PassThroughError(u'\xb5', 'bar')
568
        self.assertIsInstance(e.__str__(), str)
569
        # In Python str(foo) *must* return a real byte string
570
        # not a Unicode string. The following line would raise a
571
        # Unicode error, because it tries to call str() on the string
572
        # returned from e.__str__(), and it has non ascii characters
573
        s = str(e)
574
        self.assertEqual('Pass through \xc2\xb5 and bar', s)
575
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
576
    def test_missing_format_string(self):
577
        e = ErrorWithNoFormat(param='randomvalue')
6318.2.1 by Martin Packman
Remove deprecated classes and practices from bzrlib.errors
578
        self.assertStartsWith(str(e),
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
579
                              "Unprintable exception ErrorWithNoFormat")
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
580
2116.3.1 by John Arbash Meinel
Cleanup error tests
581
    def test_mismatched_format_args(self):
582
        # Even though ErrorWithBadFormat's format string does not match the
583
        # arguments we constructing it with, we can still stringify an instance
584
        # of this exception. The resulting string will say its unprintable.
585
        e = ErrorWithBadFormat(not_thing='x')
586
        self.assertStartsWith(
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
587
            str(e), 'Unprintable exception ErrorWithBadFormat')
4634.1.2 by Martin Pool
Add test for CannotBindAddress
588
589
    def test_cannot_bind_address(self):
5243.1.2 by Martin
Point launchpad links in comments at production server rather than edge
590
        # see <https://bugs.launchpad.net/bzr/+bug/286871>
4634.1.2 by Martin Pool
Add test for CannotBindAddress
591
        e = errors.CannotBindAddress('example.com', 22,
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
592
                                     socket.error(13, 'Permission denied'))
593
        self.assertContainsRe(
594
            str(e),
4634.1.2 by Martin Pool
Add test for CannotBindAddress
595
            r'Cannot bind address "example\.com:22":.*Permission denied')
4976.1.1 by Jelmer Vernooij
Add FileTimestampUnavailable exception.
596
5186.2.6 by Martin Pool
Add formatting test for TransformRenameFailed
597
    def test_transform_rename_failed(self):
5186.2.7 by Martin Pool
Update other cases where transform detects failure to rename
598
        e = errors.TransformRenameFailed(u"from", u"to", "readonly file", 2)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
599
        self.assertEqual(
5186.2.6 by Martin Pool
Add formatting test for TransformRenameFailed
600
            u"Failed to rename from to to: readonly file",
601
            str(e))
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
602
603
604
class TestErrorsUsingTransport(tests.TestCaseWithMemoryTransport):
605
    """Tests for errors that need to use a branch or repo."""
606
607
    def test_no_public_branch(self):
608
        b = self.make_branch('.')
609
        error = errors.NoPublicBranch(b)
610
        url = urlutils.unescape_for_display(b.base, 'ascii')
611
        self.assertEqualDiff(
612
            'There is no public branch set for "%s".' % url, str(error))
613
614
    def test_no_repo(self):
615
        dir = controldir.ControlDir.create(self.get_url())
616
        error = errors.NoRepositoryPresent(dir)
617
        self.assertNotEqual(-1, str(error).find((dir.transport.clone('..').base)))
618
        self.assertEqual(-1, str(error).find((dir.transport.base)))
619
620
    def test_corrupt_repository(self):
621
        repo = self.make_repository('.')
622
        error = errors.CorruptRepository(repo)
623
        self.assertEqualDiff("An error has been detected in the repository %s.\n"
624
                             "Please run brz reconcile on this repository." %
6653.6.6 by Jelmer Vernooij
Fix remaining tests.
625
                             repo.controldir.root_transport.base,
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
626
                             str(error))
627
628
    def test_not_branch_bzrdir_with_repo(self):
6653.6.6 by Jelmer Vernooij
Fix remaining tests.
629
        controldir = self.make_repository('repo').controldir
630
        err = errors.NotBranchError('path', controldir=controldir)
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
631
        self.assertEqual(
632
            'Not a branch: "path": location is a repository.', str(err))
633
634
    def test_not_branch_bzrdir_without_repo(self):
6653.6.6 by Jelmer Vernooij
Fix remaining tests.
635
        controldir = self.make_controldir('bzrdir')
636
        err = errors.NotBranchError('path', controldir=controldir)
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
637
        self.assertEqual('Not a branch: "path".', str(err))
638
639
    def test_not_branch_laziness(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
640
        real_bzrdir = self.make_controldir('path')
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
641
        class FakeBzrDir(object):
642
            def __init__(self):
643
                self.calls = []
644
            def open_repository(self):
645
                self.calls.append('open_repository')
646
                raise errors.NoRepositoryPresent(real_bzrdir)
647
        fake_bzrdir = FakeBzrDir()
6653.6.6 by Jelmer Vernooij
Fix remaining tests.
648
        err = errors.NotBranchError('path', controldir=fake_bzrdir)
6670.3.1 by Martin
Initial work to make errors module Python 3 compatible
649
        self.assertEqual([], fake_bzrdir.calls)
650
        str(err)
651
        self.assertEqual(['open_repository'], fake_bzrdir.calls)
652
        # Stringifying twice doesn't try to open a repository twice.
653
        str(err)
654
        self.assertEqual(['open_repository'], fake_bzrdir.calls)