62
63
raise NotImplementedError("time travel")
63
64
except NotImplementedError:
65
err = _format_exception()
66
self.assertEqualDiff(err.splitlines()[0],
67
'brz: ERROR: exceptions.NotImplementedError: time travel')
65
err = _format_exception()
66
self.assertContainsRe(err,
67
'^brz: ERROR: NotImplementedError: time travel')
68
68
self.assertContainsRe(err,
69
69
'Bazaar has encountered an internal error.')
73
73
raise KeyboardInterrupt()
74
74
except KeyboardInterrupt:
75
75
# XXX: Some risk that a *real* keyboard interrupt won't be seen
77
msg = _format_exception()
78
self.assertTrue(len(msg) > 0)
79
self.assertEqualDiff(msg, 'brz: interrupted\n')
76
msg = _format_exception()
77
self.assertEqual(msg, 'brz: interrupted\n')
81
79
def test_format_memory_error(self):
83
81
raise MemoryError()
84
82
except MemoryError:
86
msg = _format_exception()
83
msg = _format_exception()
87
84
self.assertEqual(msg,
88
85
"brz: out of memory\nUse -Dmem_dump to dump memory to a file.\n")
103
99
os.rmdir('nosuchfile22222')
104
100
except OSError as e:
106
msg = _format_exception()
102
msg = _format_exception()
107
103
# Linux seems to give "No such file" but Windows gives "The system
108
104
# cannot find the file specified".
109
105
self.assertEqual('brz: ERROR: %s\n' % (e_str,), msg)
111
107
def test_format_io_error(self):
113
file('nosuchfile22222')
109
open('nosuchfile22222')
116
msg = _format_exception()
111
msg = _format_exception()
117
112
# Even though Windows and Linux differ for 'os.rmdir', they both give
118
113
# 'No such file' for open()
119
114
# However it now gets translated so we can not test for a specific message
120
115
self.assertContainsRe(msg,
121
r'^brz: ERROR: \[Errno .*\] .*nosuchfile')
116
'^brz: ERROR: \\[Errno .*\\] .*nosuchfile')
123
118
def test_format_pywintypes_error(self):
124
119
self.requireFeature(features.pywintypes)
127
122
win32file.RemoveDirectory('nosuchfile22222')
128
123
except pywintypes.error:
130
msg = _format_exception()
124
msg = _format_exception()
131
125
# GZ 2010-05-03: Formatting for pywintypes.error is basic, a 3-tuple
132
126
# with errno, function name, and locale error message
133
127
self.assertContainsRe(msg,
134
r"^brz: ERROR: \(2, 'RemoveDirectory[AW]?', .*\)")
128
"^brz: ERROR: \\(2, 'RemoveDirectory[AW]?', .*\\)")
136
130
def test_format_sockets_error(self):
139
133
sock = socket.socket()
140
sock.send("This should fail.")
134
sock.send(b"This should fail.")
141
135
except socket.error:
143
msg = _format_exception()
136
msg = _format_exception()
145
138
self.assertNotContainsRe(msg,
146
r"Traceback (most recent call last):")
139
"Traceback \\(most recent call last\\):")
148
141
def test_format_unicode_error(self):
150
143
raise errors.BzrCommandError(u'argument foo\xb5 does not exist')
151
144
except errors.BzrCommandError:
153
msg = _format_exception()
145
msg = _format_exception()
147
expected = 'brz: ERROR: argument foo\xb5 does not exist\n'
149
# GZ 2017-06-10: Pretty bogus, should encode per the output stream
150
expected = 'brz: ERROR: argument foo\xc2\xb5 does not exist\n'
151
self.assertEqual(msg, expected)
155
153
def test_format_exception(self):
156
154
"""Short formatting of brz exceptions"""
158
156
raise errors.NotBranchError('wibble')
159
157
except errors.NotBranchError:
161
msg = _format_exception()
162
self.assertTrue(len(msg) > 0)
163
self.assertEqualDiff(msg, 'brz: ERROR: Not a branch: \"wibble\".\n')
158
msg = _format_exception()
159
self.assertEqual(msg, 'brz: ERROR: Not a branch: \"wibble\".\n')
165
161
def test_report_external_import_error(self):
166
162
"""Short friendly message for missing system modules."""
168
164
import ImaginaryModule
169
165
except ImportError as e:
166
msg = _format_exception()
172
168
self.fail("somehow succeeded in importing %r" % ImaginaryModule)
173
msg = _format_exception()
174
self.assertEqual(msg,
175
'brz: ERROR: No module named ImaginaryModule\n'
176
'You may need to install this Python library separately.\n')
169
self.assertContainsRe(msg,
170
"^brz: ERROR: No module named '?ImaginaryModule'?\n"
171
"You may need to install this Python library separately.\n$")
178
173
def test_report_import_syntax_error(self):
180
175
raise ImportError("syntax error")
181
176
except ImportError as e:
183
msg = _format_exception()
177
msg = _format_exception()
184
178
self.assertContainsRe(msg,
185
r'Bazaar has encountered an internal error')
179
'Bazaar has encountered an internal error')
187
181
def test_trace_unicode(self):
188
182
"""Write Unicode to trace log"""
213
207
self.fail("expected error not raised")
215
def assertLogStartsWith(self, log, string):
216
"""Like assertStartsWith, but skips the log timestamp."""
209
def assertLogContainsLine(self, log, string):
210
"""Assert log contains a line including log timestamp."""
211
# Does not check absolute position in log as there may be kipple.
217
212
self.assertContainsRe(log,
218
'^\\d+\\.\\d+ ' + re.escape(string))
213
'(?m)^\\d+\\.\\d+ ' + re.escape(string))
220
215
def test_mutter_callsite_1(self):
221
216
"""mutter_callsite can capture 1 level of stack frame."""
222
217
mutter_callsite(1, "foo %s", "a string")
223
218
log = self.get_log()
224
219
# begin with the message
225
self.assertLogStartsWith(log, 'foo a string\nCalled from:\n')
220
self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
226
221
# should show two frame: this frame and the one above
227
222
self.assertContainsRe(log,
228
223
'test_trace\\.py", line \\d+, in test_mutter_callsite_1\n')
234
229
mutter_callsite(2, "foo %s", "a string")
235
230
log = self.get_log()
236
231
# begin with the message
237
self.assertLogStartsWith(log, 'foo a string\nCalled from:\n')
232
self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
238
233
# should show two frame: this frame and the one above
239
234
self.assertContainsRe(log,
240
235
'test_trace.py", line \d+, in test_mutter_callsite_2\n')
247
242
# This test checks that mutter doesn't fail; the current behaviour
248
243
# is that it doesn't fail *and writes non-utf8*.
249
244
mutter(u'Writing a greek mu (\xb5) works in a unicode string')
250
mutter('But fails in an ascii string \xb5')
251
mutter('and in an ascii argument: %s', '\xb5')
245
mutter(b'But fails in an ascii string \xb5')
246
mutter(b'and in an ascii argument: %s', b'\xb5')
252
247
log = self.get_log()
253
248
self.assertContainsRe(log, 'Writing a greek mu')
254
249
self.assertContainsRe(log, "But fails in an ascii string")
255
250
# However, the log content object does unicode replacement on reading
256
251
# to let it get unicode back where good data has been written. So we
257
252
# have to do a replaceent here as well.
258
self.assertContainsRe(log, "ascii argument: \xb5".decode('utf8',
253
self.assertContainsRe(log, b"ascii argument: \xb5".decode('utf8',
261
256
def test_show_error(self):
303
298
# as there's a timestamp at the front.
305
300
self.assertContainsRe(tmp1.read(),
306
r"\d+\.\d+ comment to file1\n\d+\.\d+ again to file1\n")
301
b"\\d+\\.\\d+ comment to file1\n"
302
b"\\d+\\.\\d+ again to file1\n")
308
304
self.assertContainsRe(tmp2.read(),
309
r"\d+\.\d+ comment to file2\n")
305
b"\\d+\\.\\d+ comment to file2\n")
315
311
# If _open_brz_log cannot open the file, then we should write the
316
312
# warning to stderr. Since this is normally happening before logging is
318
self.overrideAttr(sys, 'stderr', BytesIO())
314
self.overrideAttr(sys, 'stderr', StringIO())
319
315
# Set the log file to something that cannot exist
320
316
self.overrideEnv('BRZ_LOG', '/no-such-dir/brz.log')
321
317
self.overrideAttr(trace, '_brz_log_filename')
378
374
self.assertEqual(u" DEBUG \xa7\n", self.get_log())
380
376
def test_log_utf8_msg(self):
381
logging.getLogger("brz").debug("\xc2\xa7")
377
logging.getLogger("brz").debug(b"\xc2\xa7")
382
378
self.assertEqual(u" DEBUG \xa7\n", self.get_log())
384
380
def test_log_utf8_arg(self):
385
logging.getLogger("brz").debug("%s", "\xc2\xa7")
386
self.assertEqual(u" DEBUG \xa7\n", self.get_log())
381
logging.getLogger("brz").debug(b"%s", b"\xc2\xa7")
383
expected = u" DEBUG b'\\xc2\\xa7'\n"
385
expected = u" DEBUG \xa7\n"
386
self.assertEqual(expected, self.get_log())
388
388
def test_log_bytes_msg(self):
389
logging.getLogger("brz").debug("\xa7")
389
logging.getLogger("brz").debug(b"\xa7")
390
390
log = self.get_log()
391
391
self.assertContainsString(log, "UnicodeDecodeError: ")
392
self.assertContainsString(log,
393
"Logging record unformattable: '\\xa7' % ()\n")
392
self.assertContainsRe(log,
393
"Logging record unformattable: b?'\\\\xa7' % \\(\\)\n")
395
395
def test_log_bytes_arg(self):
396
logging.getLogger("brz").debug("%s", "\xa7")
396
logging.getLogger("brz").debug(b"%s", b"\xa7")
397
397
log = self.get_log()
398
self.assertContainsString(log, "UnicodeDecodeError: ")
399
self.assertContainsString(log,
400
"Logging record unformattable: '%s' % ('\\xa7',)\n")
399
self.assertEqual(u" DEBUG b'\\xa7'\n", self.get_log())
401
self.assertContainsString(log, "UnicodeDecodeError: ")
402
self.assertContainsRe(log,
403
"Logging record unformattable: ?'%s' % \\(b?'\\\\xa7',\\)\n")
402
405
def test_log_mixed_strings(self):
403
logging.getLogger("brz").debug(u"%s", "\xa7")
406
logging.getLogger("brz").debug(u"%s", b"\xa7")
404
407
log = self.get_log()
405
self.assertContainsString(log, "UnicodeDecodeError: ")
406
self.assertContainsString(log,
407
"Logging record unformattable: u'%s' % ('\\xa7',)\n")
409
self.assertEqual(u" DEBUG b'\\xa7'\n", self.get_log())
411
self.assertContainsString(log, "UnicodeDecodeError: ")
412
self.assertContainsRe(log,
413
"Logging record unformattable: u'%s' % \\('\\\\xa7',\\)\n")
409
415
def test_log_repr_broken(self):
410
416
class BadRepr(object):