/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/tests/test_trace.py

  • Committer: Jelmer Vernooij
  • Date: 2017-07-23 22:06:41 UTC
  • mfrom: (6738 trunk)
  • mto: This revision was merged to the branch mainline in revision 6739.
  • Revision ID: jelmer@jelmer.uk-20170723220641-69eczax9bmv8d6kk
Merge trunk, address review comments.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
"""Tests for trace library"""
20
20
 
21
21
import errno
22
 
from io import StringIO
23
22
import logging
24
23
import os
25
24
import re
31
30
    errors,
32
31
    trace,
33
32
    )
34
 
from . import features, TestCaseInTempDir, TestCase, TestSkipped
 
33
from ..sixish import (
 
34
    PY3,
 
35
    StringIO,
 
36
    )
 
37
from . import features, TestCaseInTempDir, TestCase
35
38
from ..trace import (
36
39
    mutter, mutter_callsite, report_exception,
37
40
    set_verbosity_level, get_verbosity_level, is_quiet, is_verbose, be_quiet,
61
64
        except NotImplementedError:
62
65
            err = _format_exception()
63
66
        self.assertContainsRe(err,
64
 
                              '^brz: ERROR: NotImplementedError: time travel')
 
67
                '^brz: ERROR: NotImplementedError: time travel')
65
68
        self.assertContainsRe(err,
66
 
                              'Bazaar has encountered an internal error.')
 
69
            'Bazaar has encountered an internal error.')
67
70
 
68
71
    def test_format_interrupt_exception(self):
69
72
        try:
78
81
            raise MemoryError()
79
82
        except MemoryError:
80
83
            msg = _format_exception()
81
 
        self.assertEqual(
82
 
            msg,
 
84
        self.assertEqual(msg,
83
85
            "brz: out of memory\nUse -Dmem_dump to dump memory to a file.\n")
84
86
 
85
87
    def test_format_mem_dump(self):
90
92
        except MemoryError:
91
93
            msg = _format_exception()
92
94
        self.assertStartsWith(msg,
93
 
                              "brz: out of memory\nMemory dumped to ")
 
95
            "brz: out of memory\nMemory dumped to ")
94
96
 
95
97
    def test_format_os_error(self):
96
98
        try:
109
111
            msg = _format_exception()
110
112
        # Even though Windows and Linux differ for 'os.rmdir', they both give
111
113
        # 'No such file' for open()
112
 
        # However it now gets translated so we can not test for a specific
113
 
        # message
 
114
        # However it now gets translated so we can not test for a specific message
114
115
        self.assertContainsRe(msg,
115
 
                              '^brz: ERROR: \\[Errno .*\\] .*nosuchfile')
 
116
            '^brz: ERROR: \\[Errno .*\\] .*nosuchfile')
116
117
 
117
118
    def test_format_pywintypes_error(self):
118
119
        self.requireFeature(features.pywintypes)
119
 
        import pywintypes
120
 
        import win32file
 
120
        import pywintypes, win32file
121
121
        try:
122
122
            win32file.RemoveDirectory('nosuchfile22222')
123
123
        except pywintypes.error:
124
124
            msg = _format_exception()
125
125
        # GZ 2010-05-03: Formatting for pywintypes.error is basic, a 3-tuple
126
126
        #                with errno, function name, and locale error message
127
 
        self.assertContainsRe(
128
 
            msg, "^brz: ERROR: \\(2, 'RemoveDirectory[AW]?', .*\\)")
 
127
        self.assertContainsRe(msg,
 
128
            "^brz: ERROR: \\(2, 'RemoveDirectory[AW]?', .*\\)")
129
129
 
130
130
    def test_format_sockets_error(self):
131
131
        try:
136
136
            msg = _format_exception()
137
137
 
138
138
        self.assertNotContainsRe(msg,
139
 
                                 "Traceback \\(most recent call last\\):")
 
139
            "Traceback \\(most recent call last\\):")
140
140
 
141
141
    def test_format_unicode_error(self):
142
142
        try:
143
 
            raise errors.CommandError(u'argument foo\xb5 does not exist')
144
 
        except errors.CommandError:
 
143
            raise errors.BzrCommandError(u'argument foo\xb5 does not exist')
 
144
        except errors.BzrCommandError:
145
145
            msg = _format_exception()
146
 
        expected = 'brz: ERROR: argument foo\xb5 does not exist\n'
 
146
        if PY3:
 
147
            expected = 'brz: ERROR: argument foo\xb5 does not exist\n'
 
148
        else:
 
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'
147
151
        self.assertEqual(msg, expected)
148
152
 
149
153
    def test_format_exception(self):
158
162
        """Short friendly message for missing system modules."""
159
163
        try:
160
164
            import ImaginaryModule
161
 
        except ImportError:
 
165
        except ImportError as e:
162
166
            msg = _format_exception()
163
167
        else:
164
168
            self.fail("somehow succeeded in importing %r" % ImaginaryModule)
165
 
        self.assertContainsRe(
166
 
            msg,
 
169
        self.assertContainsRe(msg,
167
170
            "^brz: ERROR: No module named '?ImaginaryModule'?\n"
168
171
            "You may need to install this Python library separately.\n$")
169
172
 
170
173
    def test_report_import_syntax_error(self):
171
174
        try:
172
175
            raise ImportError("syntax error")
173
 
        except ImportError:
 
176
        except ImportError as e:
174
177
            msg = _format_exception()
175
178
        self.assertContainsRe(msg,
176
 
                              'Bazaar has encountered an internal error')
 
179
            'Bazaar has encountered an internal error')
177
180
 
178
181
    def test_trace_unicode(self):
179
182
        """Write Unicode to trace log"""
194
197
        log = self.get_log()
195
198
        self.assertContainsRe(log, 'the unicode character')
196
199
 
197
 
    def test_trace_argument_exception(self):
198
 
        err = Exception('an error')
199
 
        mutter(u'can format stringable classes %s', err)
200
 
        log = self.get_log()
201
 
        self.assertContainsRe(log, 'can format stringable classes an error')
202
 
 
203
200
    def test_report_broken_pipe(self):
204
201
        try:
205
202
            raise IOError(errno.EPIPE, 'broken pipe foofofo')
206
 
        except IOError:
 
203
        except IOError as e:
207
204
            msg = _format_exception()
208
205
            self.assertEqual(msg, "brz: broken pipe\n")
209
206
        else:
213
210
        """Assert log contains a line including log timestamp."""
214
211
        # Does not check absolute position in log as there may be kipple.
215
212
        self.assertContainsRe(log,
216
 
                              '(?m)^\\d+\\.\\d+  ' + re.escape(string))
 
213
            '(?m)^\\d+\\.\\d+  ' + re.escape(string))
217
214
 
218
215
    def test_mutter_callsite_1(self):
219
216
        """mutter_callsite can capture 1 level of stack frame."""
222
219
        # begin with the message
223
220
        self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
224
221
        # should show two frame: this frame and the one above
225
 
        self.assertContainsRe(
226
 
            log, 'test_trace\\.py", line \\d+, in test_mutter_callsite_1\n')
 
222
        self.assertContainsRe(log,
 
223
            'test_trace\\.py", line \\d+, in test_mutter_callsite_1\n')
227
224
        # this frame should be the final one
228
225
        self.assertEndsWith(log, ' "a string")\n')
229
226
 
234
231
        # begin with the message
235
232
        self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
236
233
        # should show two frame: this frame and the one above
237
 
        self.assertContainsRe(
238
 
            log, 'test_trace.py", line \\d+, in test_mutter_callsite_2\n')
 
234
        self.assertContainsRe(log,
 
235
            'test_trace.py", line \d+, in test_mutter_callsite_2\n')
239
236
        # this frame should be the final one
240
237
        self.assertEndsWith(log, ' "a string")\n')
241
238
 
242
239
    def test_mutter_never_fails(self):
243
 
        """Even with unencodable input mutter should not raise errors."""
244
 
        mutter(u'can write unicode \xa7')
245
 
        mutter('can interpolate unicode %s', u'\xa7')
246
 
        mutter(b'can write bytes \xa7')
247
 
        mutter('can repr bytes %r', b'\xa7')
248
 
        mutter('can interpolate bytes %s', b'\xa7')
249
 
        # Log will always be written as utf-8
 
240
        # Even if the decode/encode stage fails, mutter should not
 
241
        # raise an exception
 
242
        # This test checks that mutter doesn't fail; the current behaviour
 
243
        # is that it doesn't fail *and writes non-utf8*.
 
244
        mutter(u'Writing a greek mu (\xb5) works in a unicode string')
 
245
        mutter(b'But fails in an ascii string \xb5')
 
246
        mutter(b'and in an ascii argument: %s', b'\xb5')
250
247
        log = self.get_log()
251
 
        self.assertContainsRe(
252
 
            log,
253
 
            u'.* +can write unicode \xa7\n'
254
 
            u'.* +can interpolate unicode \xa7\n'
255
 
            u'.* +can write bytes \ufffd\n'
256
 
            u'.* +can repr bytes b\'\\\\xa7\'\n'
257
 
            u'.* +can interpolate bytes (?:\ufffd|b\'\\\\xa7\')\n')
 
248
        self.assertContainsRe(log, 'Writing a greek mu')
 
249
        self.assertContainsRe(log, "But fails in an ascii string")
 
250
        # However, the log content object does unicode replacement on reading
 
251
        # to let it get unicode back where good data has been written. So we
 
252
        # have to do a replaceent here as well.
 
253
        self.assertContainsRe(log, b"ascii argument: \xb5".decode('utf8',
 
254
            'replace'))
258
255
 
259
256
    def test_show_error(self):
260
257
        show_error('error1')
261
258
        show_error(u'error2 \xb5 blah')
262
259
        show_error('arg: %s', 'blah')
263
 
        show_error('arg2: %(key)s', {'key': 'stuff'})
 
260
        show_error('arg2: %(key)s', {'key':'stuff'})
264
261
        try:
265
262
            raise Exception("oops")
266
 
        except BaseException:
 
263
        except:
267
264
            show_error('kwarg', exc_info=True)
268
265
        log = self.get_log()
269
266
        self.assertContainsRe(log, 'error1')
272
269
        self.assertContainsRe(log, 'arg2: stuff')
273
270
        self.assertContainsRe(log, 'kwarg')
274
271
        self.assertContainsRe(log, 'Traceback \\(most recent call last\\):')
275
 
        self.assertContainsRe(
276
 
            log, 'File ".*test_trace.py", line .*, in test_show_error')
 
272
        self.assertContainsRe(log, 'File ".*test_trace.py", line .*, in test_show_error')
277
273
        self.assertContainsRe(log, 'raise Exception\\("oops"\\)')
278
274
        self.assertContainsRe(log, 'Exception: oops')
279
275
 
302
298
            # as there's a timestamp at the front.
303
299
            tmp1.seek(0)
304
300
            self.assertContainsRe(tmp1.read(),
305
 
                                  b"\\d+\\.\\d+  comment to file1\n"
306
 
                                  b"\\d+\\.\\d+  again to file1\n")
 
301
                b"\\d+\\.\\d+  comment to file1\n"
 
302
                b"\\d+\\.\\d+  again to file1\n")
307
303
            tmp2.seek(0)
308
304
            self.assertContainsRe(tmp2.read(),
309
 
                                  b"\\d+\\.\\d+  comment to file2\n")
 
305
                b"\\d+\\.\\d+  comment to file2\n")
310
306
        finally:
311
307
            tmp1.close()
312
308
            tmp2.close()
320
316
        self.overrideEnv('BRZ_LOG', '/no-such-dir/brz.log')
321
317
        self.overrideAttr(trace, '_brz_log_filename')
322
318
        logf = trace._open_brz_log()
323
 
        if os.path.isdir('/no-such-dir'):
324
 
            raise TestSkipped('directory creation succeeded')
325
319
        self.assertIs(None, logf)
326
320
        self.assertContainsRe(
327
321
            sys.stderr.getvalue(),
328
322
            "failed to open trace file: .* '/no-such-dir/brz.log'$")
329
323
 
330
 
    def test__open_brz_log_ignores_cache_dir_error(self):
331
 
        # If the cache directory can not be created and _open_brz_log can thus
332
 
        # not open the file, then we should write the warning to stderr. Since
333
 
        # this is normally happening before logging is set up.
334
 
        self.overrideAttr(sys, 'stderr', StringIO())
335
 
        # Set the cache directory to something that cannot exist
336
 
        self.overrideEnv('BRZ_LOG', None)
337
 
        self.overrideEnv('BRZ_HOME', '/no-such-dir')
338
 
        self.overrideEnv('XDG_CACHE_HOME', '/no-such-dir')
339
 
        self.overrideAttr(trace, '_brz_log_filename')
340
 
        logf = trace._open_brz_log()
341
 
        if os.path.isdir('/no-such-dir'):
342
 
            raise TestSkipped('directory creation succeeded')
343
 
        self.assertIs(None, logf)
344
 
        self.assertContainsRe(
345
 
            sys.stderr.getvalue(),
346
 
            "failed to open trace file: .* '/no-such-dir'$")
347
 
 
348
324
 
349
325
class TestVerbosityLevel(TestCase):
350
326
 
403
379
 
404
380
    def test_log_utf8_arg(self):
405
381
        logging.getLogger("brz").debug(b"%s", b"\xc2\xa7")
406
 
        expected = u"   DEBUG  b'\\xc2\\xa7'\n"
 
382
        if PY3:
 
383
            expected = u"   DEBUG  b'\\xc2\\xa7'\n"
 
384
        else:
 
385
            expected = u"   DEBUG  \xa7\n"
407
386
        self.assertEqual(expected, self.get_log())
408
387
 
409
388
    def test_log_bytes_msg(self):
410
389
        logging.getLogger("brz").debug(b"\xa7")
411
390
        log = self.get_log()
412
391
        self.assertContainsString(log, "UnicodeDecodeError: ")
413
 
        self.assertContainsRe(
414
 
            log, "Logging record unformattable: b?'\\\\xa7' % \\(\\)\n")
 
392
        self.assertContainsRe(log,
 
393
            "Logging record unformattable: b?'\\\\xa7' % \\(\\)\n")
415
394
 
416
395
    def test_log_bytes_arg(self):
417
396
        logging.getLogger("brz").debug(b"%s", b"\xa7")
418
397
        log = self.get_log()
419
 
        self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
398
        if PY3:
 
399
            self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
400
        else:
 
401
            self.assertContainsString(log, "UnicodeDecodeError: ")
 
402
            self.assertContainsRe(log,
 
403
                "Logging record unformattable: ?'%s' % \\(b?'\\\\xa7',\\)\n")
420
404
 
421
405
    def test_log_mixed_strings(self):
422
406
        logging.getLogger("brz").debug(u"%s", b"\xa7")
423
407
        log = self.get_log()
424
 
        self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
408
        if PY3:
 
409
            self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
410
        else:
 
411
            self.assertContainsString(log, "UnicodeDecodeError: ")
 
412
            self.assertContainsRe(log,
 
413
                "Logging record unformattable: u'%s' % \\('\\\\xa7',\\)\n")
425
414
 
426
415
    def test_log_repr_broken(self):
427
416
        class BadRepr(object):