/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: 2018-07-08 14:45:27 UTC
  • mto: This revision was merged to the branch mainline in revision 7036.
  • Revision ID: jelmer@jelmer.uk-20180708144527-codhlvdcdg9y0nji
Fix a bunch of merge tests.

Show diffs side-by-side

added added

removed removed

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