/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: Breezy landing bot
  • Author(s): Martin
  • Date: 2017-06-10 23:10:27 UTC
  • mfrom: (6677.1.6 py3_crash_debug_trace)
  • Revision ID: breezy.the.bot@gmail.com-20170610231027-rmnb6npg1qb049fx
Make tests pass on Python 3 for crash, debug, and trace modules

Merged from https://code.launchpad.net/~gz/brz/py3_crash_debug_trace/+merge/325445

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
    trace,
32
32
    )
33
33
from ..sixish import (
34
 
    BytesIO,
 
34
    PY3,
 
35
    StringIO,
35
36
    )
36
37
from . import features, TestCaseInTempDir, TestCase
37
38
from ..trace import (
46
47
 
47
48
def _format_exception():
48
49
    """Format an exception as it would normally be displayed to the user"""
49
 
    buf = BytesIO()
 
50
    buf = StringIO()
50
51
    report_exception(sys.exc_info(), buf)
51
52
    return buf.getvalue()
52
53
 
61
62
        try:
62
63
            raise NotImplementedError("time travel")
63
64
        except NotImplementedError:
64
 
            pass
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.')
70
70
 
73
73
            raise KeyboardInterrupt()
74
74
        except KeyboardInterrupt:
75
75
            # XXX: Some risk that a *real* keyboard interrupt won't be seen
76
 
            pass
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')
80
78
 
81
79
    def test_format_memory_error(self):
82
80
        try:
83
81
            raise MemoryError()
84
82
        except MemoryError:
85
 
            pass
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")
89
86
 
93
90
        try:
94
91
            raise MemoryError()
95
92
        except MemoryError:
96
 
            pass
97
 
        msg = _format_exception()
 
93
            msg = _format_exception()
98
94
        self.assertStartsWith(msg,
99
95
            "brz: out of memory\nMemory dumped to ")
100
96
 
103
99
            os.rmdir('nosuchfile22222')
104
100
        except OSError as e:
105
101
            e_str = str(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)
110
106
 
111
107
    def test_format_io_error(self):
112
108
        try:
113
 
            file('nosuchfile22222')
 
109
            open('nosuchfile22222')
114
110
        except IOError:
115
 
            pass
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')
122
117
 
123
118
    def test_format_pywintypes_error(self):
124
119
        self.requireFeature(features.pywintypes)
126
121
        try:
127
122
            win32file.RemoveDirectory('nosuchfile22222')
128
123
        except pywintypes.error:
129
 
            pass
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]?', .*\)")
135
 
            
 
128
            "^brz: ERROR: \\(2, 'RemoveDirectory[AW]?', .*\\)")
 
129
 
136
130
    def test_format_sockets_error(self):
137
131
        try:
138
132
            import socket
139
133
            sock = socket.socket()
140
 
            sock.send("This should fail.")
 
134
            sock.send(b"This should fail.")
141
135
        except socket.error:
142
 
            pass
143
 
        msg = _format_exception()
144
 
        
 
136
            msg = _format_exception()
 
137
 
145
138
        self.assertNotContainsRe(msg,
146
 
            r"Traceback (most recent call last):")
 
139
            "Traceback \\(most recent call last\\):")
147
140
 
148
141
    def test_format_unicode_error(self):
149
142
        try:
150
143
            raise errors.BzrCommandError(u'argument foo\xb5 does not exist')
151
144
        except errors.BzrCommandError:
152
 
            pass
153
 
        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)
154
152
 
155
153
    def test_format_exception(self):
156
154
        """Short formatting of brz exceptions"""
157
155
        try:
158
156
            raise errors.NotBranchError('wibble')
159
157
        except errors.NotBranchError:
160
 
            pass
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')
164
160
 
165
161
    def test_report_external_import_error(self):
166
162
        """Short friendly message for missing system modules."""
167
163
        try:
168
164
            import ImaginaryModule
169
165
        except ImportError as e:
170
 
            pass
 
166
            msg = _format_exception()
171
167
        else:
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$")
177
172
 
178
173
    def test_report_import_syntax_error(self):
179
174
        try:
180
175
            raise ImportError("syntax error")
181
176
        except ImportError as e:
182
 
            pass
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')
186
180
 
187
181
    def test_trace_unicode(self):
188
182
        """Write Unicode to trace log"""
212
206
        else:
213
207
            self.fail("expected error not raised")
214
208
 
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))
219
214
 
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',
259
254
            'replace'))
260
255
 
261
256
    def test_show_error(self):
303
298
            # as there's a timestamp at the front.
304
299
            tmp1.seek(0)
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")
307
303
            tmp2.seek(0)
308
304
            self.assertContainsRe(tmp2.read(),
309
 
                r"\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()
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
317
313
        # set up.
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())
379
375
 
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())
383
379
 
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")
 
382
        if PY3:
 
383
            expected = u"   DEBUG  b'\\xc2\\xa7'\n"
 
384
        else:
 
385
            expected = u"   DEBUG  \xa7\n"
 
386
        self.assertEqual(expected, self.get_log())
387
387
 
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")
394
394
 
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")
 
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")
401
404
 
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")
 
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")
408
414
 
409
415
    def test_log_repr_broken(self):
410
416
        class BadRepr(object):