/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 brzlib/tests/test_trace.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-21 12:41:27 UTC
  • mto: This revision was merged to the branch mainline in revision 6623.
  • Revision ID: jelmer@jelmer.uk-20170521124127-iv8etg0vwymyai6y
s/bzr/brz/ in apport config.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
"""Tests for trace library"""
20
20
 
 
21
from cStringIO import StringIO
21
22
import errno
22
 
from io import StringIO
23
23
import logging
24
24
import os
25
25
import re
26
26
import sys
27
27
import tempfile
28
28
 
29
 
from .. import (
 
29
from brzlib import (
30
30
    debug,
31
31
    errors,
32
32
    trace,
33
33
    )
34
 
from . import features, TestCaseInTempDir, TestCase, TestSkipped
35
 
from ..trace import (
 
34
from brzlib.tests import features, TestCaseInTempDir, TestCase
 
35
from brzlib.trace import (
36
36
    mutter, mutter_callsite, report_exception,
37
37
    set_verbosity_level, get_verbosity_level, is_quiet, is_verbose, be_quiet,
38
38
    pop_log_file,
53
53
 
54
54
    def test_format_sys_exception(self):
55
55
        # Test handling of an internal/unexpected error that probably
56
 
        # indicates a bug in brz.  The details of the message may vary
 
56
        # indicates a bug in bzr.  The details of the message may vary
57
57
        # depending on whether apport is available or not.  See test_crash for
58
58
        # more.
59
59
        try:
60
 
            raise NotImplementedError("time travel")
 
60
            raise NotImplementedError, "time travel"
61
61
        except NotImplementedError:
62
 
            err = _format_exception()
63
 
        self.assertContainsRe(err,
64
 
                              '^brz: ERROR: NotImplementedError: time travel')
65
 
        self.assertContainsRe(err,
66
 
                              'Bazaar has encountered an internal error.')
 
62
            pass
 
63
        err = _format_exception()
 
64
        self.assertEqualDiff(err.splitlines()[0],
 
65
                'bzr: ERROR: exceptions.NotImplementedError: time travel')
 
66
        self.assertContainsRe(err,
 
67
            'Bazaar has encountered an internal error.')
67
68
 
68
69
    def test_format_interrupt_exception(self):
69
70
        try:
70
71
            raise KeyboardInterrupt()
71
72
        except KeyboardInterrupt:
72
73
            # XXX: Some risk that a *real* keyboard interrupt won't be seen
73
 
            msg = _format_exception()
74
 
        self.assertEqual(msg, 'brz: interrupted\n')
 
74
            pass
 
75
        msg = _format_exception()
 
76
        self.assertTrue(len(msg) > 0)
 
77
        self.assertEqualDiff(msg, 'bzr: interrupted\n')
75
78
 
76
79
    def test_format_memory_error(self):
77
80
        try:
78
81
            raise MemoryError()
79
82
        except MemoryError:
80
 
            msg = _format_exception()
81
 
        self.assertEqual(
82
 
            msg,
83
 
            "brz: out of memory\nUse -Dmem_dump to dump memory to a file.\n")
 
83
            pass
 
84
        msg = _format_exception()
 
85
        self.assertEqual(msg,
 
86
            "bzr: out of memory\nUse -Dmem_dump to dump memory to a file.\n")
84
87
 
85
88
    def test_format_mem_dump(self):
86
89
        self.requireFeature(features.meliae)
88
91
        try:
89
92
            raise MemoryError()
90
93
        except MemoryError:
91
 
            msg = _format_exception()
 
94
            pass
 
95
        msg = _format_exception()
92
96
        self.assertStartsWith(msg,
93
 
                              "brz: out of memory\nMemory dumped to ")
 
97
            "bzr: out of memory\nMemory dumped to ")
94
98
 
95
99
    def test_format_os_error(self):
96
100
        try:
97
101
            os.rmdir('nosuchfile22222')
98
 
        except OSError as e:
 
102
        except OSError, e:
99
103
            e_str = str(e)
100
 
            msg = _format_exception()
 
104
        msg = _format_exception()
101
105
        # Linux seems to give "No such file" but Windows gives "The system
102
106
        # cannot find the file specified".
103
 
        self.assertEqual('brz: ERROR: %s\n' % (e_str,), msg)
 
107
        self.assertEqual('bzr: ERROR: %s\n' % (e_str,), msg)
104
108
 
105
109
    def test_format_io_error(self):
106
110
        try:
107
 
            open('nosuchfile22222')
 
111
            file('nosuchfile22222')
108
112
        except IOError:
109
 
            msg = _format_exception()
 
113
            pass
 
114
        msg = _format_exception()
110
115
        # Even though Windows and Linux differ for 'os.rmdir', they both give
111
116
        # 'No such file' for open()
112
 
        # However it now gets translated so we can not test for a specific
113
 
        # message
 
117
        # However it now gets translated so we can not test for a specific message
114
118
        self.assertContainsRe(msg,
115
 
                              '^brz: ERROR: \\[Errno .*\\] .*nosuchfile')
 
119
            r'^bzr: ERROR: \[Errno .*\] .*nosuchfile')
116
120
 
117
121
    def test_format_pywintypes_error(self):
118
122
        self.requireFeature(features.pywintypes)
119
 
        import pywintypes
120
 
        import win32file
 
123
        import pywintypes, win32file
121
124
        try:
122
125
            win32file.RemoveDirectory('nosuchfile22222')
123
126
        except pywintypes.error:
124
 
            msg = _format_exception()
 
127
            pass
 
128
        msg = _format_exception()
125
129
        # GZ 2010-05-03: Formatting for pywintypes.error is basic, a 3-tuple
126
130
        #                with errno, function name, and locale error message
127
 
        self.assertContainsRe(
128
 
            msg, "^brz: ERROR: \\(2, 'RemoveDirectory[AW]?', .*\\)")
129
 
 
 
131
        self.assertContainsRe(msg,
 
132
            r"^bzr: ERROR: \(2, 'RemoveDirectory[AW]?', .*\)")
 
133
            
130
134
    def test_format_sockets_error(self):
131
135
        try:
132
136
            import socket
133
137
            sock = socket.socket()
134
 
            sock.send(b"This should fail.")
 
138
            sock.send("This should fail.")
135
139
        except socket.error:
136
 
            msg = _format_exception()
137
 
 
 
140
            pass
 
141
        msg = _format_exception()
 
142
        
138
143
        self.assertNotContainsRe(msg,
139
 
                                 "Traceback \\(most recent call last\\):")
 
144
            r"Traceback (most recent call last):")
140
145
 
141
146
    def test_format_unicode_error(self):
142
147
        try:
143
148
            raise errors.BzrCommandError(u'argument foo\xb5 does not exist')
144
149
        except errors.BzrCommandError:
145
 
            msg = _format_exception()
146
 
        expected = 'brz: ERROR: argument foo\xb5 does not exist\n'
147
 
        self.assertEqual(msg, expected)
 
150
            pass
 
151
        msg = _format_exception()
148
152
 
149
153
    def test_format_exception(self):
150
 
        """Short formatting of brz exceptions"""
 
154
        """Short formatting of bzr exceptions"""
151
155
        try:
152
156
            raise errors.NotBranchError('wibble')
153
157
        except errors.NotBranchError:
154
 
            msg = _format_exception()
155
 
        self.assertEqual(msg, 'brz: ERROR: Not a branch: \"wibble\".\n')
 
158
            pass
 
159
        msg = _format_exception()
 
160
        self.assertTrue(len(msg) > 0)
 
161
        self.assertEqualDiff(msg, 'bzr: ERROR: Not a branch: \"wibble\".\n')
156
162
 
157
163
    def test_report_external_import_error(self):
158
164
        """Short friendly message for missing system modules."""
159
165
        try:
160
166
            import ImaginaryModule
161
 
        except ImportError:
162
 
            msg = _format_exception()
 
167
        except ImportError, e:
 
168
            pass
163
169
        else:
164
170
            self.fail("somehow succeeded in importing %r" % ImaginaryModule)
165
 
        self.assertContainsRe(
166
 
            msg,
167
 
            "^brz: ERROR: No module named '?ImaginaryModule'?\n"
168
 
            "You may need to install this Python library separately.\n$")
 
171
        msg = _format_exception()
 
172
        self.assertEqual(msg,
 
173
            'bzr: ERROR: No module named ImaginaryModule\n'
 
174
            'You may need to install this Python library separately.\n')
169
175
 
170
176
    def test_report_import_syntax_error(self):
171
177
        try:
172
178
            raise ImportError("syntax error")
173
 
        except ImportError:
174
 
            msg = _format_exception()
 
179
        except ImportError, e:
 
180
            pass
 
181
        msg = _format_exception()
175
182
        self.assertContainsRe(msg,
176
 
                              'Bazaar has encountered an internal error')
 
183
            r'Bazaar has encountered an internal error')
177
184
 
178
185
    def test_trace_unicode(self):
179
186
        """Write Unicode to trace log"""
194
201
        log = self.get_log()
195
202
        self.assertContainsRe(log, 'the unicode character')
196
203
 
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
204
    def test_report_broken_pipe(self):
204
205
        try:
205
206
            raise IOError(errno.EPIPE, 'broken pipe foofofo')
206
 
        except IOError:
 
207
        except IOError as e:
207
208
            msg = _format_exception()
208
 
            self.assertEqual(msg, "brz: broken pipe\n")
 
209
            self.assertEqual(msg, "bzr: broken pipe\n")
209
210
        else:
210
211
            self.fail("expected error not raised")
211
212
 
212
 
    def assertLogContainsLine(self, log, string):
213
 
        """Assert log contains a line including log timestamp."""
214
 
        # Does not check absolute position in log as there may be kipple.
 
213
    def assertLogStartsWith(self, log, string):
 
214
        """Like assertStartsWith, but skips the log timestamp."""
215
215
        self.assertContainsRe(log,
216
 
                              '(?m)^\\d+\\.\\d+  ' + re.escape(string))
 
216
            '^\\d+\\.\\d+  ' + re.escape(string))
217
217
 
218
218
    def test_mutter_callsite_1(self):
219
219
        """mutter_callsite can capture 1 level of stack frame."""
220
220
        mutter_callsite(1, "foo %s", "a string")
221
221
        log = self.get_log()
222
222
        # begin with the message
223
 
        self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
 
223
        self.assertLogStartsWith(log, 'foo a string\nCalled from:\n')
224
224
        # 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')
 
225
        self.assertContainsRe(log,
 
226
            'test_trace\\.py", line \\d+, in test_mutter_callsite_1\n')
227
227
        # this frame should be the final one
228
228
        self.assertEndsWith(log, ' "a string")\n')
229
229
 
232
232
        mutter_callsite(2, "foo %s", "a string")
233
233
        log = self.get_log()
234
234
        # begin with the message
235
 
        self.assertLogContainsLine(log, 'foo a string\nCalled from:\n')
 
235
        self.assertLogStartsWith(log, 'foo a string\nCalled from:\n')
236
236
        # 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')
 
237
        self.assertContainsRe(log,
 
238
            'test_trace.py", line \d+, in test_mutter_callsite_2\n')
239
239
        # this frame should be the final one
240
240
        self.assertEndsWith(log, ' "a string")\n')
241
241
 
242
242
    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
 
243
        # Even if the decode/encode stage fails, mutter should not
 
244
        # raise an exception
 
245
        # This test checks that mutter doesn't fail; the current behaviour
 
246
        # is that it doesn't fail *and writes non-utf8*.
 
247
        mutter(u'Writing a greek mu (\xb5) works in a unicode string')
 
248
        mutter('But fails in an ascii string \xb5')
 
249
        mutter('and in an ascii argument: %s', '\xb5')
250
250
        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')
 
251
        self.assertContainsRe(log, 'Writing a greek mu')
 
252
        self.assertContainsRe(log, "But fails in an ascii string")
 
253
        # However, the log content object does unicode replacement on reading
 
254
        # to let it get unicode back where good data has been written. So we
 
255
        # have to do a replaceent here as well.
 
256
        self.assertContainsRe(log, "ascii argument: \xb5".decode('utf8',
 
257
            'replace'))
258
258
 
259
259
    def test_show_error(self):
260
260
        show_error('error1')
261
261
        show_error(u'error2 \xb5 blah')
262
262
        show_error('arg: %s', 'blah')
263
 
        show_error('arg2: %(key)s', {'key': 'stuff'})
 
263
        show_error('arg2: %(key)s', {'key':'stuff'})
264
264
        try:
265
265
            raise Exception("oops")
266
 
        except BaseException:
 
266
        except:
267
267
            show_error('kwarg', exc_info=True)
268
268
        log = self.get_log()
269
269
        self.assertContainsRe(log, 'error1')
272
272
        self.assertContainsRe(log, 'arg2: stuff')
273
273
        self.assertContainsRe(log, 'kwarg')
274
274
        self.assertContainsRe(log, 'Traceback \\(most recent call last\\):')
275
 
        self.assertContainsRe(
276
 
            log, 'File ".*test_trace.py", line .*, in test_show_error')
 
275
        self.assertContainsRe(log, 'File ".*test_trace.py", line .*, in test_show_error')
277
276
        self.assertContainsRe(log, 'raise Exception\\("oops"\\)')
278
277
        self.assertContainsRe(log, 'Exception: oops')
279
278
 
302
301
            # as there's a timestamp at the front.
303
302
            tmp1.seek(0)
304
303
            self.assertContainsRe(tmp1.read(),
305
 
                                  b"\\d+\\.\\d+  comment to file1\n"
306
 
                                  b"\\d+\\.\\d+  again to file1\n")
 
304
                r"\d+\.\d+  comment to file1\n\d+\.\d+  again to file1\n")
307
305
            tmp2.seek(0)
308
306
            self.assertContainsRe(tmp2.read(),
309
 
                                  b"\\d+\\.\\d+  comment to file2\n")
 
307
                r"\d+\.\d+  comment to file2\n")
310
308
        finally:
311
309
            tmp1.close()
312
310
            tmp2.close()
313
311
 
314
 
    def test__open_brz_log_uses_stderr_for_failures(self):
315
 
        # If _open_brz_log cannot open the file, then we should write the
 
312
    def test__open_bzr_log_uses_stderr_for_failures(self):
 
313
        # If _open_bzr_log cannot open the file, then we should write the
316
314
        # warning to stderr. Since this is normally happening before logging is
317
315
        # set up.
318
316
        self.overrideAttr(sys, 'stderr', StringIO())
319
317
        # Set the log file to something that cannot exist
320
 
        self.overrideEnv('BRZ_LOG', '/no-such-dir/brz.log')
321
 
        self.overrideAttr(trace, '_brz_log_filename')
322
 
        logf = trace._open_brz_log()
323
 
        if os.path.isdir('/no-such-dir'):
324
 
            raise TestSkipped('directory creation succeeded')
325
 
        self.assertIs(None, logf)
326
 
        self.assertContainsRe(
327
 
            sys.stderr.getvalue(),
328
 
            "failed to open trace file: .* '/no-such-dir/brz.log'$")
329
 
 
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'$")
 
318
        self.overrideEnv('BZR_LOG', os.getcwd() + '/no-dir/bzr.log')
 
319
        self.overrideAttr(trace, '_bzr_log_filename')
 
320
        logf = trace._open_bzr_log()
 
321
        self.assertIs(None, logf)
 
322
        self.assertContainsRe(sys.stderr.getvalue(),
 
323
                              'failed to open trace file: .*/no-dir/bzr.log')
347
324
 
348
325
 
349
326
class TestVerbosityLevel(TestCase):
382
359
        self.assertEqual(" WARNING  Warned\n", self.get_log())
383
360
 
384
361
    def test_log(self):
385
 
        logging.getLogger("brz").error("Errored")
 
362
        logging.getLogger("bzr").error("Errored")
386
363
        self.assertEqual("   ERROR  Errored\n", self.get_log())
387
364
 
388
365
    def test_log_sub(self):
389
 
        logging.getLogger("brz.test_log_sub").debug("Whispered")
 
366
        logging.getLogger("bzr.test_log_sub").debug("Whispered")
390
367
        self.assertEqual("   DEBUG  Whispered\n", self.get_log())
391
368
 
392
369
    def test_log_unicode_msg(self):
393
 
        logging.getLogger("brz").debug(u"\xa7")
 
370
        logging.getLogger("bzr").debug(u"\xa7")
394
371
        self.assertEqual(u"   DEBUG  \xa7\n", self.get_log())
395
372
 
396
373
    def test_log_unicode_arg(self):
397
 
        logging.getLogger("brz").debug("%s", u"\xa7")
 
374
        logging.getLogger("bzr").debug("%s", u"\xa7")
398
375
        self.assertEqual(u"   DEBUG  \xa7\n", self.get_log())
399
376
 
400
377
    def test_log_utf8_msg(self):
401
 
        logging.getLogger("brz").debug(b"\xc2\xa7")
 
378
        logging.getLogger("bzr").debug("\xc2\xa7")
402
379
        self.assertEqual(u"   DEBUG  \xa7\n", self.get_log())
403
380
 
404
381
    def test_log_utf8_arg(self):
405
 
        logging.getLogger("brz").debug(b"%s", b"\xc2\xa7")
406
 
        expected = u"   DEBUG  b'\\xc2\\xa7'\n"
407
 
        self.assertEqual(expected, self.get_log())
 
382
        logging.getLogger("bzr").debug("%s", "\xc2\xa7")
 
383
        self.assertEqual(u"   DEBUG  \xa7\n", self.get_log())
408
384
 
409
385
    def test_log_bytes_msg(self):
410
 
        logging.getLogger("brz").debug(b"\xa7")
 
386
        logging.getLogger("bzr").debug("\xa7")
411
387
        log = self.get_log()
412
388
        self.assertContainsString(log, "UnicodeDecodeError: ")
413
 
        self.assertContainsRe(
414
 
            log, "Logging record unformattable: b?'\\\\xa7' % \\(\\)\n")
 
389
        self.assertContainsString(log,
 
390
            "Logging record unformattable: '\\xa7' % ()\n")
415
391
 
416
392
    def test_log_bytes_arg(self):
417
 
        logging.getLogger("brz").debug(b"%s", b"\xa7")
 
393
        logging.getLogger("bzr").debug("%s", "\xa7")
418
394
        log = self.get_log()
419
 
        self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
395
        self.assertContainsString(log, "UnicodeDecodeError: ")
 
396
        self.assertContainsString(log,
 
397
            "Logging record unformattable: '%s' % ('\\xa7',)\n")
420
398
 
421
399
    def test_log_mixed_strings(self):
422
 
        logging.getLogger("brz").debug(u"%s", b"\xa7")
 
400
        logging.getLogger("bzr").debug(u"%s", "\xa7")
423
401
        log = self.get_log()
424
 
        self.assertEqual(u"   DEBUG  b'\\xa7'\n", self.get_log())
 
402
        self.assertContainsString(log, "UnicodeDecodeError: ")
 
403
        self.assertContainsString(log,
 
404
            "Logging record unformattable: u'%s' % ('\\xa7',)\n")
425
405
 
426
406
    def test_log_repr_broken(self):
427
407
        class BadRepr(object):
428
408
            def __repr__(self):
429
409
                raise ValueError("Broken object")
430
 
        logging.getLogger("brz").debug("%s", BadRepr())
 
410
        logging.getLogger("bzr").debug("%s", BadRepr())
431
411
        log = self.get_log()
432
412
        self.assertContainsRe(log, "ValueError: Broken object\n")
433
413
        self.assertContainsRe(log, "Logging record unformattable: '%s' % .*\n")
449
429
 
450
430
    def test_default_config(self):
451
431
        config = trace.DefaultConfig()
452
 
        self.overrideAttr(trace, "_brz_log_filename", None)
453
 
        trace._brz_log_filename = None
454
 
        expected_filename = trace._get_brz_log_filename()
455
 
        self.assertEqual(None, trace._brz_log_filename)
 
432
        self.overrideAttr(trace, "_bzr_log_filename", None)
 
433
        trace._bzr_log_filename = None
 
434
        expected_filename = trace._get_bzr_log_filename()
 
435
        self.assertEqual(None, trace._bzr_log_filename)
456
436
        config.__enter__()
457
437
        try:
458
438
            # Should have entered and setup a default filename.
459
 
            self.assertEqual(expected_filename, trace._brz_log_filename)
 
439
            self.assertEqual(expected_filename, trace._bzr_log_filename)
460
440
        finally:
461
441
            config.__exit__(None, None, None)
462
442
            # Should have exited and cleaned up.
463
 
            self.assertEqual(None, trace._brz_log_filename)
 
443
            self.assertEqual(None, trace._bzr_log_filename)