blob: 977cb3928ba3e03c2110c62b3a0704cfa4336b1f [file] [log] [blame]
Victor Stinner024e37a2011-03-31 01:31:06 +02001from contextlib import contextmanager
Victor Stinnerc790a532011-04-08 13:39:59 +02002import datetime
Victor Stinner024e37a2011-03-31 01:31:06 +02003import faulthandler
Victor Stinner7e32f3a2011-06-29 13:44:05 +02004import os
Victor Stinner024e37a2011-03-31 01:31:06 +02005import re
6import signal
7import subprocess
8import sys
9from test import support, script_helper
10import tempfile
11import unittest
12
Victor Stinnerff4cd882011-04-07 11:50:25 +020013try:
14 import threading
15 HAVE_THREADS = True
16except ImportError:
17 HAVE_THREADS = False
18
Victor Stinner44378d42011-04-01 15:37:12 +020019TIMEOUT = 0.5
20
Victor Stinner024e37a2011-03-31 01:31:06 +020021try:
22 from resource import setrlimit, RLIMIT_CORE, error as resource_error
23except ImportError:
24 prepare_subprocess = None
25else:
26 def prepare_subprocess():
27 # don't create core file
28 try:
29 setrlimit(RLIMIT_CORE, (0, 0))
30 except (ValueError, resource_error):
31 pass
32
Victor Stinner301f3f02011-06-01 13:49:12 +020033def expected_traceback(lineno1, lineno2, header, min_count=1):
Victor Stinner024e37a2011-03-31 01:31:06 +020034 regex = header
Victor Stinner7ad24e92011-03-31 22:35:49 +020035 regex += ' File "<string>", line %s in func\n' % lineno1
36 regex += ' File "<string>", line %s in <module>' % lineno2
Victor Stinner301f3f02011-06-01 13:49:12 +020037 if 1 < min_count:
38 return '^' + (regex + '\n') * (min_count - 1) + regex
39 else:
40 return '^' + regex + '$'
Victor Stinner024e37a2011-03-31 01:31:06 +020041
42@contextmanager
43def temporary_filename():
44 filename = tempfile.mktemp()
45 try:
46 yield filename
47 finally:
48 support.unlink(filename)
49
50class FaultHandlerTests(unittest.TestCase):
Victor Stinner05585cb2011-03-31 13:29:56 +020051 def get_output(self, code, filename=None):
Victor Stinner024e37a2011-03-31 01:31:06 +020052 """
53 Run the specified code in Python (in a new child process) and read the
54 output from the standard error or from a file (if filename is set).
55 Return the output lines as a list.
56
57 Strip the reference count from the standard error for Python debug
58 build, and replace "Current thread 0x00007f8d8fbd9700" by "Current
59 thread XXX".
60 """
61 options = {}
62 if prepare_subprocess:
63 options['preexec_fn'] = prepare_subprocess
64 process = script_helper.spawn_python('-c', code, **options)
65 stdout, stderr = process.communicate()
66 exitcode = process.wait()
Victor Stinner19402332011-03-31 18:15:52 +020067 output = support.strip_python_stderr(stdout)
68 output = output.decode('ascii', 'backslashreplace')
Victor Stinner024e37a2011-03-31 01:31:06 +020069 if filename:
Victor Stinner19402332011-03-31 18:15:52 +020070 self.assertEqual(output, '')
Victor Stinner024e37a2011-03-31 01:31:06 +020071 with open(filename, "rb") as fp:
72 output = fp.read()
Victor Stinner19402332011-03-31 18:15:52 +020073 output = output.decode('ascii', 'backslashreplace')
Victor Stinner024e37a2011-03-31 01:31:06 +020074 output = re.sub('Current thread 0x[0-9a-f]+',
75 'Current thread XXX',
76 output)
Victor Stinner05585cb2011-03-31 13:29:56 +020077 return output.splitlines(), exitcode
Victor Stinner024e37a2011-03-31 01:31:06 +020078
79 def check_fatal_error(self, code, line_number, name_regex,
Victor Stinner7bba62f2011-05-07 12:43:00 +020080 filename=None, all_threads=True, other_regex=None):
Victor Stinner024e37a2011-03-31 01:31:06 +020081 """
82 Check that the fault handler for fatal errors is enabled and check the
83 traceback from the child process output.
84
85 Raise an error if the output doesn't match the expected format.
86 """
87 if all_threads:
88 header = 'Current thread XXX'
89 else:
90 header = 'Traceback (most recent call first)'
91 regex = """
92^Fatal Python error: {name}
93
94{header}:
95 File "<string>", line {lineno} in <module>$
96""".strip()
97 regex = regex.format(
98 lineno=line_number,
99 name=name_regex,
100 header=re.escape(header))
Victor Stinnerf0480752011-03-31 11:34:08 +0200101 if other_regex:
102 regex += '|' + other_regex
Victor Stinner05585cb2011-03-31 13:29:56 +0200103 output, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200104 output = '\n'.join(output)
105 self.assertRegex(output, regex)
Victor Stinner05585cb2011-03-31 13:29:56 +0200106 self.assertNotEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200107
108 def test_read_null(self):
109 self.check_fatal_error("""
110import faulthandler
111faulthandler.enable()
112faulthandler._read_null()
113""".strip(),
114 3,
Victor Stinnera8db3782011-08-08 22:43:45 +0200115 # Issue #12700: Read NULL raises SIGILL on Mac OS X Lion
116 '(?:Segmentation fault|Bus error|Illegal instruction)')
Victor Stinner024e37a2011-03-31 01:31:06 +0200117
118 def test_sigsegv(self):
119 self.check_fatal_error("""
120import faulthandler
121faulthandler.enable()
122faulthandler._sigsegv()
123""".strip(),
124 3,
125 'Segmentation fault')
126
Victor Stinnerd727e232011-04-01 12:13:55 +0200127 def test_sigabrt(self):
128 self.check_fatal_error("""
129import faulthandler
130faulthandler.enable()
131faulthandler._sigabrt()
132""".strip(),
133 3,
134 'Aborted')
135
Victor Stinner024e37a2011-03-31 01:31:06 +0200136 @unittest.skipIf(sys.platform == 'win32',
137 "SIGFPE cannot be caught on Windows")
138 def test_sigfpe(self):
139 self.check_fatal_error("""
140import faulthandler
141faulthandler.enable()
142faulthandler._sigfpe()
143""".strip(),
144 3,
145 'Floating point exception')
146
147 @unittest.skipIf(not hasattr(faulthandler, '_sigbus'),
148 "need faulthandler._sigbus()")
149 def test_sigbus(self):
150 self.check_fatal_error("""
151import faulthandler
152faulthandler.enable()
153faulthandler._sigbus()
154""".strip(),
155 3,
156 'Bus error')
157
158 @unittest.skipIf(not hasattr(faulthandler, '_sigill'),
159 "need faulthandler._sigill()")
160 def test_sigill(self):
161 self.check_fatal_error("""
162import faulthandler
163faulthandler.enable()
164faulthandler._sigill()
165""".strip(),
166 3,
167 'Illegal instruction')
168
169 def test_fatal_error(self):
170 self.check_fatal_error("""
171import faulthandler
172faulthandler._fatal_error(b'xyz')
173""".strip(),
174 2,
175 'xyz')
176
Charles-François Natali3391e642011-09-01 23:08:21 +0200177 @unittest.skipIf(sys.platform.startswith('openbsd') and HAVE_THREADS,
178 "Issue #12868: sigaltstack() doesn't work on "
179 "OpenBSD if Python is compiled with pthread")
Victor Stinner024e37a2011-03-31 01:31:06 +0200180 @unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'),
181 'need faulthandler._stack_overflow()')
182 def test_stack_overflow(self):
183 self.check_fatal_error("""
184import faulthandler
185faulthandler.enable()
186faulthandler._stack_overflow()
187""".strip(),
188 3,
Victor Stinnerf0480752011-03-31 11:34:08 +0200189 '(?:Segmentation fault|Bus error)',
190 other_regex='unable to raise a stack overflow')
Victor Stinner024e37a2011-03-31 01:31:06 +0200191
192 def test_gil_released(self):
193 self.check_fatal_error("""
194import faulthandler
195faulthandler.enable()
196faulthandler._read_null(True)
197""".strip(),
198 3,
Victor Stinnera8db3782011-08-08 22:43:45 +0200199 '(?:Segmentation fault|Bus error|Illegal instruction)')
Victor Stinner024e37a2011-03-31 01:31:06 +0200200
201 def test_enable_file(self):
202 with temporary_filename() as filename:
203 self.check_fatal_error("""
204import faulthandler
205output = open({filename}, 'wb')
206faulthandler.enable(output)
Victor Stinner44378d42011-04-01 15:37:12 +0200207faulthandler._read_null()
Victor Stinner024e37a2011-03-31 01:31:06 +0200208""".strip().format(filename=repr(filename)),
209 4,
Victor Stinnera8db3782011-08-08 22:43:45 +0200210 '(?:Segmentation fault|Bus error|Illegal instruction)',
Victor Stinner024e37a2011-03-31 01:31:06 +0200211 filename=filename)
212
Victor Stinner7bba62f2011-05-07 12:43:00 +0200213 def test_enable_single_thread(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200214 self.check_fatal_error("""
215import faulthandler
Victor Stinner7bba62f2011-05-07 12:43:00 +0200216faulthandler.enable(all_threads=False)
Victor Stinner44378d42011-04-01 15:37:12 +0200217faulthandler._read_null()
Victor Stinner024e37a2011-03-31 01:31:06 +0200218""".strip(),
219 3,
Victor Stinnera8db3782011-08-08 22:43:45 +0200220 '(?:Segmentation fault|Bus error|Illegal instruction)',
Victor Stinner7bba62f2011-05-07 12:43:00 +0200221 all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200222
223 def test_disable(self):
224 code = """
225import faulthandler
226faulthandler.enable()
227faulthandler.disable()
228faulthandler._read_null()
229""".strip()
230 not_expected = 'Fatal Python error'
Victor Stinner05585cb2011-03-31 13:29:56 +0200231 stderr, exitcode = self.get_output(code)
Victor Stinner024e37a2011-03-31 01:31:06 +0200232 stder = '\n'.join(stderr)
233 self.assertTrue(not_expected not in stderr,
234 "%r is present in %r" % (not_expected, stderr))
Victor Stinner05585cb2011-03-31 13:29:56 +0200235 self.assertNotEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200236
237 def test_is_enabled(self):
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200238 orig_stderr = sys.stderr
Victor Stinner024e37a2011-03-31 01:31:06 +0200239 try:
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200240 # regrtest may replace sys.stderr by io.StringIO object, but
241 # faulthandler.enable() requires that sys.stderr has a fileno()
242 # method
Victor Stinner72488502011-06-29 23:24:31 +0200243 sys.stderr = sys.__stderr__
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200244
245 was_enabled = faulthandler.is_enabled()
246 try:
Victor Stinner024e37a2011-03-31 01:31:06 +0200247 faulthandler.enable()
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200248 self.assertTrue(faulthandler.is_enabled())
Victor Stinner024e37a2011-03-31 01:31:06 +0200249 faulthandler.disable()
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200250 self.assertFalse(faulthandler.is_enabled())
251 finally:
252 if was_enabled:
253 faulthandler.enable()
254 else:
255 faulthandler.disable()
256 finally:
257 sys.stderr = orig_stderr
Victor Stinner024e37a2011-03-31 01:31:06 +0200258
259 def check_dump_traceback(self, filename):
260 """
261 Explicitly call dump_traceback() function and check its output.
262 Raise an error if the output doesn't match the expected format.
263 """
264 code = """
265import faulthandler
266
267def funcB():
268 if {has_filename}:
269 with open({filename}, "wb") as fp:
Victor Stinner7bba62f2011-05-07 12:43:00 +0200270 faulthandler.dump_traceback(fp, all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200271 else:
Victor Stinner7bba62f2011-05-07 12:43:00 +0200272 faulthandler.dump_traceback(all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200273
274def funcA():
275 funcB()
276
277funcA()
278""".strip()
279 code = code.format(
280 filename=repr(filename),
281 has_filename=bool(filename),
282 )
283 if filename:
284 lineno = 6
285 else:
286 lineno = 8
287 expected = [
288 'Traceback (most recent call first):',
289 ' File "<string>", line %s in funcB' % lineno,
290 ' File "<string>", line 11 in funcA',
291 ' File "<string>", line 13 in <module>'
292 ]
Victor Stinner05585cb2011-03-31 13:29:56 +0200293 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200294 self.assertEqual(trace, expected)
Victor Stinner05585cb2011-03-31 13:29:56 +0200295 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200296
297 def test_dump_traceback(self):
298 self.check_dump_traceback(None)
Victor Stinner19402332011-03-31 18:15:52 +0200299
300 def test_dump_traceback_file(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200301 with temporary_filename() as filename:
302 self.check_dump_traceback(filename)
303
Victor Stinnerff4cd882011-04-07 11:50:25 +0200304 @unittest.skipIf(not HAVE_THREADS, 'need threads')
Victor Stinner024e37a2011-03-31 01:31:06 +0200305 def check_dump_traceback_threads(self, filename):
306 """
307 Call explicitly dump_traceback(all_threads=True) and check the output.
308 Raise an error if the output doesn't match the expected format.
309 """
310 code = """
311import faulthandler
312from threading import Thread, Event
313import time
314
315def dump():
316 if {filename}:
317 with open({filename}, "wb") as fp:
318 faulthandler.dump_traceback(fp, all_threads=True)
319 else:
320 faulthandler.dump_traceback(all_threads=True)
321
322class Waiter(Thread):
323 # avoid blocking if the main thread raises an exception.
324 daemon = True
325
326 def __init__(self):
327 Thread.__init__(self)
328 self.running = Event()
329 self.stop = Event()
330
331 def run(self):
332 self.running.set()
333 self.stop.wait()
334
335waiter = Waiter()
336waiter.start()
337waiter.running.wait()
338dump()
339waiter.stop.set()
340waiter.join()
341""".strip()
342 code = code.format(filename=repr(filename))
Victor Stinner05585cb2011-03-31 13:29:56 +0200343 output, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200344 output = '\n'.join(output)
345 if filename:
346 lineno = 8
347 else:
348 lineno = 10
349 regex = """
350^Thread 0x[0-9a-f]+:
Victor Stinner1b3241f2011-04-03 18:41:22 +0200351(?: File ".*threading.py", line [0-9]+ in [_a-z]+
352){{1,3}} File "<string>", line 23 in run
Victor Stinner024e37a2011-03-31 01:31:06 +0200353 File ".*threading.py", line [0-9]+ in _bootstrap_inner
354 File ".*threading.py", line [0-9]+ in _bootstrap
355
356Current thread XXX:
357 File "<string>", line {lineno} in dump
358 File "<string>", line 28 in <module>$
359""".strip()
360 regex = regex.format(lineno=lineno)
361 self.assertRegex(output, regex)
Victor Stinner05585cb2011-03-31 13:29:56 +0200362 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200363
364 def test_dump_traceback_threads(self):
365 self.check_dump_traceback_threads(None)
Victor Stinner19402332011-03-31 18:15:52 +0200366
367 def test_dump_traceback_threads_file(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200368 with temporary_filename() as filename:
369 self.check_dump_traceback_threads(filename)
370
Victor Stinnerde10f402011-04-08 12:57:06 +0200371 def _check_dump_tracebacks_later(self, repeat, cancel, filename, loops):
Victor Stinner024e37a2011-03-31 01:31:06 +0200372 """
373 Check how many times the traceback is written in timeout x 2.5 seconds,
374 or timeout x 3.5 seconds if cancel is True: 1, 2 or 3 times depending
375 on repeat and cancel options.
376
377 Raise an error if the output doesn't match the expect format.
378 """
Victor Stinnerc790a532011-04-08 13:39:59 +0200379 timeout_str = str(datetime.timedelta(seconds=TIMEOUT))
Victor Stinner024e37a2011-03-31 01:31:06 +0200380 code = """
381import faulthandler
382import time
383
Victor Stinnerde10f402011-04-08 12:57:06 +0200384def func(timeout, repeat, cancel, file, loops):
385 for loop in range(loops):
386 faulthandler.dump_tracebacks_later(timeout, repeat=repeat, file=file)
387 if cancel:
388 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner301f3f02011-06-01 13:49:12 +0200389 time.sleep(timeout * 5)
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200390 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner024e37a2011-03-31 01:31:06 +0200391
Victor Stinner44378d42011-04-01 15:37:12 +0200392timeout = {timeout}
Victor Stinner024e37a2011-03-31 01:31:06 +0200393repeat = {repeat}
394cancel = {cancel}
Victor Stinnerde10f402011-04-08 12:57:06 +0200395loops = {loops}
Victor Stinner024e37a2011-03-31 01:31:06 +0200396if {has_filename}:
397 file = open({filename}, "wb")
398else:
399 file = None
Victor Stinnerde10f402011-04-08 12:57:06 +0200400func(timeout, repeat, cancel, file, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200401if file is not None:
402 file.close()
403""".strip()
404 code = code.format(
Victor Stinnerde10f402011-04-08 12:57:06 +0200405 timeout=TIMEOUT,
Victor Stinner024e37a2011-03-31 01:31:06 +0200406 repeat=repeat,
407 cancel=cancel,
Victor Stinnerde10f402011-04-08 12:57:06 +0200408 loops=loops,
409 has_filename=bool(filename),
410 filename=repr(filename),
Victor Stinner024e37a2011-03-31 01:31:06 +0200411 )
Victor Stinner05585cb2011-03-31 13:29:56 +0200412 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200413 trace = '\n'.join(trace)
414
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200415 if not cancel:
Victor Stinnerde10f402011-04-08 12:57:06 +0200416 count = loops
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200417 if repeat:
Victor Stinnerde10f402011-04-08 12:57:06 +0200418 count *= 2
Victor Stinnerc790a532011-04-08 13:39:59 +0200419 header = r'Timeout \(%s\)!\nThread 0x[0-9a-f]+:\n' % timeout_str
Victor Stinner301f3f02011-06-01 13:49:12 +0200420 regex = expected_traceback(9, 20, header, min_count=count)
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200421 self.assertRegex(trace, regex)
Victor Stinner024e37a2011-03-31 01:31:06 +0200422 else:
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200423 self.assertEqual(trace, '')
Victor Stinner05585cb2011-03-31 13:29:56 +0200424 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200425
426 @unittest.skipIf(not hasattr(faulthandler, 'dump_tracebacks_later'),
427 'need faulthandler.dump_tracebacks_later()')
428 def check_dump_tracebacks_later(self, repeat=False, cancel=False,
Victor Stinnerde10f402011-04-08 12:57:06 +0200429 file=False, twice=False):
430 if twice:
431 loops = 2
432 else:
433 loops = 1
Victor Stinner024e37a2011-03-31 01:31:06 +0200434 if file:
435 with temporary_filename() as filename:
Victor Stinnerde10f402011-04-08 12:57:06 +0200436 self._check_dump_tracebacks_later(repeat, cancel,
437 filename, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200438 else:
Victor Stinnerde10f402011-04-08 12:57:06 +0200439 self._check_dump_tracebacks_later(repeat, cancel, None, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200440
441 def test_dump_tracebacks_later(self):
442 self.check_dump_tracebacks_later()
443
444 def test_dump_tracebacks_later_repeat(self):
445 self.check_dump_tracebacks_later(repeat=True)
446
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200447 def test_dump_tracebacks_later_cancel(self):
448 self.check_dump_tracebacks_later(cancel=True)
Victor Stinner024e37a2011-03-31 01:31:06 +0200449
450 def test_dump_tracebacks_later_file(self):
451 self.check_dump_tracebacks_later(file=True)
452
Victor Stinnerde10f402011-04-08 12:57:06 +0200453 def test_dump_tracebacks_later_twice(self):
454 self.check_dump_tracebacks_later(twice=True)
455
Victor Stinner024e37a2011-03-31 01:31:06 +0200456 @unittest.skipIf(not hasattr(faulthandler, "register"),
457 "need faulthandler.register")
Victor Stinnera01ca122011-04-01 12:56:17 +0200458 def check_register(self, filename=False, all_threads=False,
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200459 unregister=False, chain=False):
Victor Stinner024e37a2011-03-31 01:31:06 +0200460 """
461 Register a handler displaying the traceback on a user signal. Raise the
462 signal and check the written traceback.
463
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200464 If chain is True, check that the previous signal handler is called.
465
Victor Stinner024e37a2011-03-31 01:31:06 +0200466 Raise an error if the output doesn't match the expected format.
467 """
Victor Stinnera01ca122011-04-01 12:56:17 +0200468 signum = signal.SIGUSR1
Victor Stinner024e37a2011-03-31 01:31:06 +0200469 code = """
470import faulthandler
471import os
472import signal
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200473import sys
Victor Stinner024e37a2011-03-31 01:31:06 +0200474
475def func(signum):
476 os.kill(os.getpid(), signum)
477
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200478def handler(signum, frame):
479 handler.called = True
480handler.called = False
481
482exitcode = 0
Victor Stinnera01ca122011-04-01 12:56:17 +0200483signum = {signum}
484unregister = {unregister}
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200485chain = {chain}
486
Victor Stinner024e37a2011-03-31 01:31:06 +0200487if {has_filename}:
488 file = open({filename}, "wb")
489else:
490 file = None
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200491if chain:
492 signal.signal(signum, handler)
493faulthandler.register(signum, file=file,
494 all_threads={all_threads}, chain={chain})
Victor Stinnera01ca122011-04-01 12:56:17 +0200495if unregister:
496 faulthandler.unregister(signum)
Victor Stinner024e37a2011-03-31 01:31:06 +0200497func(signum)
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200498if chain and not handler.called:
499 if file is not None:
500 output = file
501 else:
502 output = sys.stderr
503 print("Error: signal handler not called!", file=output)
504 exitcode = 1
Victor Stinner024e37a2011-03-31 01:31:06 +0200505if file is not None:
506 file.close()
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200507sys.exit(exitcode)
Victor Stinner024e37a2011-03-31 01:31:06 +0200508""".strip()
509 code = code.format(
510 filename=repr(filename),
511 has_filename=bool(filename),
512 all_threads=all_threads,
Victor Stinnera01ca122011-04-01 12:56:17 +0200513 signum=signum,
514 unregister=unregister,
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200515 chain=chain,
Victor Stinner024e37a2011-03-31 01:31:06 +0200516 )
Victor Stinner05585cb2011-03-31 13:29:56 +0200517 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200518 trace = '\n'.join(trace)
Victor Stinnera01ca122011-04-01 12:56:17 +0200519 if not unregister:
520 if all_threads:
521 regex = 'Current thread XXX:\n'
522 else:
523 regex = 'Traceback \(most recent call first\):\n'
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200524 regex = expected_traceback(7, 28, regex)
Victor Stinnera01ca122011-04-01 12:56:17 +0200525 self.assertRegex(trace, regex)
Victor Stinner024e37a2011-03-31 01:31:06 +0200526 else:
Victor Stinnera01ca122011-04-01 12:56:17 +0200527 self.assertEqual(trace, '')
528 if unregister:
529 self.assertNotEqual(exitcode, 0)
530 else:
531 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200532
533 def test_register(self):
534 self.check_register()
535
Victor Stinnera01ca122011-04-01 12:56:17 +0200536 def test_unregister(self):
537 self.check_register(unregister=True)
538
Victor Stinner024e37a2011-03-31 01:31:06 +0200539 def test_register_file(self):
540 with temporary_filename() as filename:
541 self.check_register(filename=filename)
542
543 def test_register_threads(self):
544 self.check_register(all_threads=True)
545
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200546 def test_register_chain(self):
547 self.check_register(chain=True)
548
Victor Stinner024e37a2011-03-31 01:31:06 +0200549
550def test_main():
551 support.run_unittest(FaultHandlerTests)
552
553if __name__ == "__main__":
554 test_main()