Skip to content

Commit 533b1db

Browse files
committed
Add tests for dump_c_stack()
1 parent 50b4964 commit 533b1db

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

Lib/test/test_faulthandler.py

+40-5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ def temporary_filename():
4545
finally:
4646
os_helper.unlink(filename)
4747

48+
49+
ADDRESS_EXPR = "0x[0-9a-f]+"
50+
C_STACK_REGEX = [
51+
r"Current thread's C stack trace \(most recent call first\):",
52+
fr" ((\/.+)+\(.*\+{ADDRESS_EXPR}\) \[{ADDRESS_EXPR}\])|(<.+>)"
53+
]
54+
4855
class FaultHandlerTests(unittest.TestCase):
4956

5057
def get_output(self, code, filename=None, fd=None):
@@ -101,16 +108,15 @@ def check_error(self, code, lineno, fatal_error, *,
101108
102109
Raise an error if the output doesn't match the expected format.
103110
"""
104-
address_expr = "0x[0-9a-f]+"
105111
all_threads_disabled = (
106112
all_threads
107113
and (not sys._is_gil_enabled())
108114
)
109115
if all_threads and not all_threads_disabled:
110116
if know_current_thread:
111-
header = f'Current thread {address_expr}'
117+
header = f'Current thread {ADDRESS_EXPR}'
112118
else:
113-
header = f'Thread {address_expr}'
119+
header = f'Thread {ADDRESS_EXPR}'
114120
else:
115121
header = 'Stack'
116122
regex = [f'^{fatal_error}']
@@ -129,8 +135,7 @@ def check_error(self, code, lineno, fatal_error, *,
129135
regex.append(' Garbage-collecting')
130136
regex.append(fr' File "<string>", line {lineno} in {function}')
131137
if c_stack:
132-
regex.append("Current thread's C stack (most recent call first):")
133-
regex.append(fr" (\/.+\(\+.+\) \[{address_expr}\])|(<.+>)")
138+
regex.extend(C_STACK_REGEX)
134139
regex = '\n'.join(regex)
135140

136141
if other_regex:
@@ -941,5 +946,35 @@ def run(self):
941946
_, exitcode = self.get_output(code)
942947
self.assertEqual(exitcode, 0)
943948

949+
def check_c_stack(self, output):
950+
starting_line = output.pop(0)
951+
self.assertRegex(starting_line, C_STACK_REGEX[0])
952+
self.assertGreater(len(output), 0)
953+
954+
for line in output:
955+
with self.subTest(line=line):
956+
if line != '': # Ignore trailing or leading newlines
957+
self.assertRegex(line, C_STACK_REGEX[1])
958+
959+
960+
def test_dump_c_stack(self):
961+
code = dedent("""
962+
import faulthandler
963+
faulthandler.dump_c_stack()
964+
""")
965+
output, exitcode = self.get_output(code)
966+
self.assertEqual(exitcode, 0)
967+
self.check_c_stack(output)
968+
969+
970+
def test_dump_c_stack_file(self):
971+
import tempfile
972+
973+
with tempfile.TemporaryFile("w+") as tmp:
974+
faulthandler.dump_c_stack(file=tmp)
975+
tmp.flush() # Just in case
976+
tmp.seek(0)
977+
self.check_c_stack(tmp.read().split("\n"))
978+
944979
if __name__ == "__main__":
945980
unittest.main()

0 commit comments

Comments
 (0)