blob: 331dd2ec86e12bb6b53e2788fffaf2e045a6da41 [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
Victor Stinner024e37a2011-03-31 01:31:06 +0200177 @unittest.skipIf(not hasattr(faulthandler, '_stack_overflow'),
178 'need faulthandler._stack_overflow()')
179 def test_stack_overflow(self):
180 self.check_fatal_error("""
181import faulthandler
182faulthandler.enable()
183faulthandler._stack_overflow()
184""".strip(),
185 3,
Victor Stinnerf0480752011-03-31 11:34:08 +0200186 '(?:Segmentation fault|Bus error)',
187 other_regex='unable to raise a stack overflow')
Victor Stinner024e37a2011-03-31 01:31:06 +0200188
189 def test_gil_released(self):
190 self.check_fatal_error("""
191import faulthandler
192faulthandler.enable()
193faulthandler._read_null(True)
194""".strip(),
195 3,
Victor Stinnera8db3782011-08-08 22:43:45 +0200196 '(?:Segmentation fault|Bus error|Illegal instruction)')
Victor Stinner024e37a2011-03-31 01:31:06 +0200197
198 def test_enable_file(self):
199 with temporary_filename() as filename:
200 self.check_fatal_error("""
201import faulthandler
202output = open({filename}, 'wb')
203faulthandler.enable(output)
Victor Stinner44378d42011-04-01 15:37:12 +0200204faulthandler._read_null()
Victor Stinner024e37a2011-03-31 01:31:06 +0200205""".strip().format(filename=repr(filename)),
206 4,
Victor Stinnera8db3782011-08-08 22:43:45 +0200207 '(?:Segmentation fault|Bus error|Illegal instruction)',
Victor Stinner024e37a2011-03-31 01:31:06 +0200208 filename=filename)
209
Victor Stinner7bba62f2011-05-07 12:43:00 +0200210 def test_enable_single_thread(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200211 self.check_fatal_error("""
212import faulthandler
Victor Stinner7bba62f2011-05-07 12:43:00 +0200213faulthandler.enable(all_threads=False)
Victor Stinner44378d42011-04-01 15:37:12 +0200214faulthandler._read_null()
Victor Stinner024e37a2011-03-31 01:31:06 +0200215""".strip(),
216 3,
Victor Stinnera8db3782011-08-08 22:43:45 +0200217 '(?:Segmentation fault|Bus error|Illegal instruction)',
Victor Stinner7bba62f2011-05-07 12:43:00 +0200218 all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200219
220 def test_disable(self):
221 code = """
222import faulthandler
223faulthandler.enable()
224faulthandler.disable()
225faulthandler._read_null()
226""".strip()
227 not_expected = 'Fatal Python error'
Victor Stinner05585cb2011-03-31 13:29:56 +0200228 stderr, exitcode = self.get_output(code)
Victor Stinner024e37a2011-03-31 01:31:06 +0200229 stder = '\n'.join(stderr)
230 self.assertTrue(not_expected not in stderr,
231 "%r is present in %r" % (not_expected, stderr))
Victor Stinner05585cb2011-03-31 13:29:56 +0200232 self.assertNotEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200233
234 def test_is_enabled(self):
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200235 orig_stderr = sys.stderr
Victor Stinner024e37a2011-03-31 01:31:06 +0200236 try:
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200237 # regrtest may replace sys.stderr by io.StringIO object, but
238 # faulthandler.enable() requires that sys.stderr has a fileno()
239 # method
Victor Stinner72488502011-06-29 23:24:31 +0200240 sys.stderr = sys.__stderr__
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200241
242 was_enabled = faulthandler.is_enabled()
243 try:
Victor Stinner024e37a2011-03-31 01:31:06 +0200244 faulthandler.enable()
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200245 self.assertTrue(faulthandler.is_enabled())
Victor Stinner024e37a2011-03-31 01:31:06 +0200246 faulthandler.disable()
Victor Stinner7e32f3a2011-06-29 13:44:05 +0200247 self.assertFalse(faulthandler.is_enabled())
248 finally:
249 if was_enabled:
250 faulthandler.enable()
251 else:
252 faulthandler.disable()
253 finally:
254 sys.stderr = orig_stderr
Victor Stinner024e37a2011-03-31 01:31:06 +0200255
256 def check_dump_traceback(self, filename):
257 """
258 Explicitly call dump_traceback() function and check its output.
259 Raise an error if the output doesn't match the expected format.
260 """
261 code = """
262import faulthandler
263
264def funcB():
265 if {has_filename}:
266 with open({filename}, "wb") as fp:
Victor Stinner7bba62f2011-05-07 12:43:00 +0200267 faulthandler.dump_traceback(fp, all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200268 else:
Victor Stinner7bba62f2011-05-07 12:43:00 +0200269 faulthandler.dump_traceback(all_threads=False)
Victor Stinner024e37a2011-03-31 01:31:06 +0200270
271def funcA():
272 funcB()
273
274funcA()
275""".strip()
276 code = code.format(
277 filename=repr(filename),
278 has_filename=bool(filename),
279 )
280 if filename:
281 lineno = 6
282 else:
283 lineno = 8
284 expected = [
285 'Traceback (most recent call first):',
286 ' File "<string>", line %s in funcB' % lineno,
287 ' File "<string>", line 11 in funcA',
288 ' File "<string>", line 13 in <module>'
289 ]
Victor Stinner05585cb2011-03-31 13:29:56 +0200290 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200291 self.assertEqual(trace, expected)
Victor Stinner05585cb2011-03-31 13:29:56 +0200292 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200293
294 def test_dump_traceback(self):
295 self.check_dump_traceback(None)
Victor Stinner19402332011-03-31 18:15:52 +0200296
297 def test_dump_traceback_file(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200298 with temporary_filename() as filename:
299 self.check_dump_traceback(filename)
300
Victor Stinnerff4cd882011-04-07 11:50:25 +0200301 @unittest.skipIf(not HAVE_THREADS, 'need threads')
Victor Stinner024e37a2011-03-31 01:31:06 +0200302 def check_dump_traceback_threads(self, filename):
303 """
304 Call explicitly dump_traceback(all_threads=True) and check the output.
305 Raise an error if the output doesn't match the expected format.
306 """
307 code = """
308import faulthandler
309from threading import Thread, Event
310import time
311
312def dump():
313 if {filename}:
314 with open({filename}, "wb") as fp:
315 faulthandler.dump_traceback(fp, all_threads=True)
316 else:
317 faulthandler.dump_traceback(all_threads=True)
318
319class Waiter(Thread):
320 # avoid blocking if the main thread raises an exception.
321 daemon = True
322
323 def __init__(self):
324 Thread.__init__(self)
325 self.running = Event()
326 self.stop = Event()
327
328 def run(self):
329 self.running.set()
330 self.stop.wait()
331
332waiter = Waiter()
333waiter.start()
334waiter.running.wait()
335dump()
336waiter.stop.set()
337waiter.join()
338""".strip()
339 code = code.format(filename=repr(filename))
Victor Stinner05585cb2011-03-31 13:29:56 +0200340 output, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200341 output = '\n'.join(output)
342 if filename:
343 lineno = 8
344 else:
345 lineno = 10
346 regex = """
347^Thread 0x[0-9a-f]+:
Victor Stinner1b3241f2011-04-03 18:41:22 +0200348(?: File ".*threading.py", line [0-9]+ in [_a-z]+
349){{1,3}} File "<string>", line 23 in run
Victor Stinner024e37a2011-03-31 01:31:06 +0200350 File ".*threading.py", line [0-9]+ in _bootstrap_inner
351 File ".*threading.py", line [0-9]+ in _bootstrap
352
353Current thread XXX:
354 File "<string>", line {lineno} in dump
355 File "<string>", line 28 in <module>$
356""".strip()
357 regex = regex.format(lineno=lineno)
358 self.assertRegex(output, regex)
Victor Stinner05585cb2011-03-31 13:29:56 +0200359 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200360
361 def test_dump_traceback_threads(self):
362 self.check_dump_traceback_threads(None)
Victor Stinner19402332011-03-31 18:15:52 +0200363
364 def test_dump_traceback_threads_file(self):
Victor Stinner024e37a2011-03-31 01:31:06 +0200365 with temporary_filename() as filename:
366 self.check_dump_traceback_threads(filename)
367
Victor Stinnerde10f402011-04-08 12:57:06 +0200368 def _check_dump_tracebacks_later(self, repeat, cancel, filename, loops):
Victor Stinner024e37a2011-03-31 01:31:06 +0200369 """
370 Check how many times the traceback is written in timeout x 2.5 seconds,
371 or timeout x 3.5 seconds if cancel is True: 1, 2 or 3 times depending
372 on repeat and cancel options.
373
374 Raise an error if the output doesn't match the expect format.
375 """
Victor Stinnerc790a532011-04-08 13:39:59 +0200376 timeout_str = str(datetime.timedelta(seconds=TIMEOUT))
Victor Stinner024e37a2011-03-31 01:31:06 +0200377 code = """
378import faulthandler
379import time
380
Victor Stinnerde10f402011-04-08 12:57:06 +0200381def func(timeout, repeat, cancel, file, loops):
382 for loop in range(loops):
383 faulthandler.dump_tracebacks_later(timeout, repeat=repeat, file=file)
384 if cancel:
385 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner301f3f02011-06-01 13:49:12 +0200386 time.sleep(timeout * 5)
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200387 faulthandler.cancel_dump_tracebacks_later()
Victor Stinner024e37a2011-03-31 01:31:06 +0200388
Victor Stinner44378d42011-04-01 15:37:12 +0200389timeout = {timeout}
Victor Stinner024e37a2011-03-31 01:31:06 +0200390repeat = {repeat}
391cancel = {cancel}
Victor Stinnerde10f402011-04-08 12:57:06 +0200392loops = {loops}
Victor Stinner024e37a2011-03-31 01:31:06 +0200393if {has_filename}:
394 file = open({filename}, "wb")
395else:
396 file = None
Victor Stinnerde10f402011-04-08 12:57:06 +0200397func(timeout, repeat, cancel, file, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200398if file is not None:
399 file.close()
400""".strip()
401 code = code.format(
Victor Stinnerde10f402011-04-08 12:57:06 +0200402 timeout=TIMEOUT,
Victor Stinner024e37a2011-03-31 01:31:06 +0200403 repeat=repeat,
404 cancel=cancel,
Victor Stinnerde10f402011-04-08 12:57:06 +0200405 loops=loops,
406 has_filename=bool(filename),
407 filename=repr(filename),
Victor Stinner024e37a2011-03-31 01:31:06 +0200408 )
Victor Stinner05585cb2011-03-31 13:29:56 +0200409 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200410 trace = '\n'.join(trace)
411
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200412 if not cancel:
Victor Stinnerde10f402011-04-08 12:57:06 +0200413 count = loops
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200414 if repeat:
Victor Stinnerde10f402011-04-08 12:57:06 +0200415 count *= 2
Victor Stinnerc790a532011-04-08 13:39:59 +0200416 header = r'Timeout \(%s\)!\nThread 0x[0-9a-f]+:\n' % timeout_str
Victor Stinner301f3f02011-06-01 13:49:12 +0200417 regex = expected_traceback(9, 20, header, min_count=count)
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200418 self.assertRegex(trace, regex)
Victor Stinner024e37a2011-03-31 01:31:06 +0200419 else:
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200420 self.assertEqual(trace, '')
Victor Stinner05585cb2011-03-31 13:29:56 +0200421 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200422
423 @unittest.skipIf(not hasattr(faulthandler, 'dump_tracebacks_later'),
424 'need faulthandler.dump_tracebacks_later()')
425 def check_dump_tracebacks_later(self, repeat=False, cancel=False,
Victor Stinnerde10f402011-04-08 12:57:06 +0200426 file=False, twice=False):
427 if twice:
428 loops = 2
429 else:
430 loops = 1
Victor Stinner024e37a2011-03-31 01:31:06 +0200431 if file:
432 with temporary_filename() as filename:
Victor Stinnerde10f402011-04-08 12:57:06 +0200433 self._check_dump_tracebacks_later(repeat, cancel,
434 filename, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200435 else:
Victor Stinnerde10f402011-04-08 12:57:06 +0200436 self._check_dump_tracebacks_later(repeat, cancel, None, loops)
Victor Stinner024e37a2011-03-31 01:31:06 +0200437
438 def test_dump_tracebacks_later(self):
439 self.check_dump_tracebacks_later()
440
441 def test_dump_tracebacks_later_repeat(self):
442 self.check_dump_tracebacks_later(repeat=True)
443
Victor Stinnerf77ccc62011-04-03 18:45:42 +0200444 def test_dump_tracebacks_later_cancel(self):
445 self.check_dump_tracebacks_later(cancel=True)
Victor Stinner024e37a2011-03-31 01:31:06 +0200446
447 def test_dump_tracebacks_later_file(self):
448 self.check_dump_tracebacks_later(file=True)
449
Victor Stinnerde10f402011-04-08 12:57:06 +0200450 def test_dump_tracebacks_later_twice(self):
451 self.check_dump_tracebacks_later(twice=True)
452
Victor Stinner024e37a2011-03-31 01:31:06 +0200453 @unittest.skipIf(not hasattr(faulthandler, "register"),
454 "need faulthandler.register")
Victor Stinnera01ca122011-04-01 12:56:17 +0200455 def check_register(self, filename=False, all_threads=False,
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200456 unregister=False, chain=False):
Victor Stinner024e37a2011-03-31 01:31:06 +0200457 """
458 Register a handler displaying the traceback on a user signal. Raise the
459 signal and check the written traceback.
460
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200461 If chain is True, check that the previous signal handler is called.
462
Victor Stinner024e37a2011-03-31 01:31:06 +0200463 Raise an error if the output doesn't match the expected format.
464 """
Victor Stinnera01ca122011-04-01 12:56:17 +0200465 signum = signal.SIGUSR1
Victor Stinner024e37a2011-03-31 01:31:06 +0200466 code = """
467import faulthandler
468import os
469import signal
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200470import sys
Victor Stinner024e37a2011-03-31 01:31:06 +0200471
472def func(signum):
473 os.kill(os.getpid(), signum)
474
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200475def handler(signum, frame):
476 handler.called = True
477handler.called = False
478
479exitcode = 0
Victor Stinnera01ca122011-04-01 12:56:17 +0200480signum = {signum}
481unregister = {unregister}
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200482chain = {chain}
483
Victor Stinner024e37a2011-03-31 01:31:06 +0200484if {has_filename}:
485 file = open({filename}, "wb")
486else:
487 file = None
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200488if chain:
489 signal.signal(signum, handler)
490faulthandler.register(signum, file=file,
491 all_threads={all_threads}, chain={chain})
Victor Stinnera01ca122011-04-01 12:56:17 +0200492if unregister:
493 faulthandler.unregister(signum)
Victor Stinner024e37a2011-03-31 01:31:06 +0200494func(signum)
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200495if chain and not handler.called:
496 if file is not None:
497 output = file
498 else:
499 output = sys.stderr
500 print("Error: signal handler not called!", file=output)
501 exitcode = 1
Victor Stinner024e37a2011-03-31 01:31:06 +0200502if file is not None:
503 file.close()
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200504sys.exit(exitcode)
Victor Stinner024e37a2011-03-31 01:31:06 +0200505""".strip()
506 code = code.format(
507 filename=repr(filename),
508 has_filename=bool(filename),
509 all_threads=all_threads,
Victor Stinnera01ca122011-04-01 12:56:17 +0200510 signum=signum,
511 unregister=unregister,
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200512 chain=chain,
Victor Stinner024e37a2011-03-31 01:31:06 +0200513 )
Victor Stinner05585cb2011-03-31 13:29:56 +0200514 trace, exitcode = self.get_output(code, filename)
Victor Stinner024e37a2011-03-31 01:31:06 +0200515 trace = '\n'.join(trace)
Victor Stinnera01ca122011-04-01 12:56:17 +0200516 if not unregister:
517 if all_threads:
518 regex = 'Current thread XXX:\n'
519 else:
520 regex = 'Traceback \(most recent call first\):\n'
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200521 regex = expected_traceback(7, 28, regex)
Victor Stinnera01ca122011-04-01 12:56:17 +0200522 self.assertRegex(trace, regex)
Victor Stinner024e37a2011-03-31 01:31:06 +0200523 else:
Victor Stinnera01ca122011-04-01 12:56:17 +0200524 self.assertEqual(trace, '')
525 if unregister:
526 self.assertNotEqual(exitcode, 0)
527 else:
528 self.assertEqual(exitcode, 0)
Victor Stinner024e37a2011-03-31 01:31:06 +0200529
530 def test_register(self):
531 self.check_register()
532
Victor Stinnera01ca122011-04-01 12:56:17 +0200533 def test_unregister(self):
534 self.check_register(unregister=True)
535
Victor Stinner024e37a2011-03-31 01:31:06 +0200536 def test_register_file(self):
537 with temporary_filename() as filename:
538 self.check_register(filename=filename)
539
540 def test_register_threads(self):
541 self.check_register(all_threads=True)
542
Victor Stinnera9a9dab2011-07-13 23:39:53 +0200543 def test_register_chain(self):
544 self.check_register(chain=True)
545
Victor Stinner024e37a2011-03-31 01:31:06 +0200546
547def test_main():
548 support.run_unittest(FaultHandlerTests)
549
550if __name__ == "__main__":
551 test_main()