Skip to content

Commit bb28257

Browse files
committed
simpler
1 parent 443f5c1 commit bb28257

1 file changed

Lines changed: 75 additions & 110 deletions

File tree

‎Lib/test/test_external_inspection.py‎

Lines changed: 75 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -3955,109 +3955,52 @@ def test_get_stats_disabled_raises(self):
39553955
class TestMetadataDegradation(RemoteInspectionTestBase):
39563956
"""Tests for graceful degradation of oversized code-object metadata."""
39573957

3958-
@contextmanager
3959-
def _running_target(self, script_body):
3960-
"""Run a target script (socket handshake prepended), yield (process, socket)."""
3961-
port = find_unused_port()
3962-
script = (
3963-
textwrap.dedent(
3964-
f"""\
3965-
import time, socket
3966-
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3967-
sock.connect(('localhost', {port}))
3968-
"""
3969-
)
3970-
+ textwrap.dedent(script_body)
3971-
)
3972-
3973-
with os_helper.temp_dir() as work_dir:
3974-
script_dir = os.path.join(work_dir, "script_pkg")
3975-
os.mkdir(script_dir)
3976-
3977-
server_socket = _create_server_socket(port)
3978-
script_name = _make_test_script(script_dir, "script", script)
3979-
client_socket = None
3980-
3981-
try:
3982-
with _managed_subprocess([sys.executable, script_name]) as p:
3983-
client_socket, _ = server_socket.accept()
3984-
server_socket.close()
3985-
server_socket = None
3986-
yield p, client_socket
3987-
finally:
3988-
_cleanup_sockets(client_socket, server_socket)
3989-
3990-
def _sample_until_frame(self, pid, predicate):
3991-
"""Sample until a frame matching predicate appears; return that frame."""
3992-
unwinder = RemoteUnwinder(pid, all_threads=True)
3993-
traces = _get_stack_trace_with_retry(
3994-
unwinder,
3995-
condition=lambda t: self._find_frame_in_trace(t, predicate)
3996-
is not None,
3997-
)
3998-
return self._find_frame_in_trace(traces, predicate)
3999-
40003958
def test_long_qualname_truncated_not_dropped(self):
40013959
"""A qualname longer than 1024 chars is truncated instead of
40023960
failing the whole sample."""
4003-
script_body = """\
4004-
src = ("def " + "f" * 1100 + "():\\n"
4005-
" sock.sendall(b'ready')\\n"
4006-
" time.sleep(10_000)\\n")
4007-
ns = {"sock": sock, "time": time}
4008-
exec(src, ns)
4009-
ns["f" * 1100]()
4010-
"""
4011-
with self._running_target(script_body) as (p, client_socket):
4012-
_wait_for_signal(client_socket, b"ready")
4013-
frame = self._sample_until_frame(
4014-
p.pid, lambda f: f.funcname.startswith("fff")
4015-
)
4016-
self.assertEqual(frame.funcname, "f" * 1024)
3961+
name = "f" * 1100
3962+
src = f"def {name}(sample):\n return sample()\n"
3963+
ns = {}
3964+
exec(src, ns)
3965+
3966+
trace = ns[name](RemoteUnwinder(os.getpid()).get_stack_trace)
3967+
frame = self._find_frame_in_trace(
3968+
trace, lambda f: f.funcname.startswith("fff")
3969+
)
3970+
self.assertIsNotNone(frame)
3971+
self.assertEqual(frame.funcname, "f" * 1024)
40173972

40183973
def test_long_filename_truncated(self):
40193974
"""A filename longer than 1024 chars is truncated instead of
40203975
failing the whole sample."""
4021-
script_body = """\
4022-
src = ("def g():\\n"
4023-
" sock.sendall(b'ready')\\n"
4024-
" time.sleep(10_000)\\n")
4025-
ns = {"sock": sock, "time": time}
4026-
exec(compile(src, "x" * 1500 + ".py", "exec"), ns)
4027-
ns["g"]()
4028-
"""
4029-
with self._running_target(script_body) as (p, client_socket):
4030-
_wait_for_signal(client_socket, b"ready")
4031-
frame = self._sample_until_frame(
4032-
p.pid, lambda f: f.funcname == "g"
4033-
)
4034-
self.assertEqual(frame.filename, "x" * 1024)
3976+
src = "def g(sample):\n return sample()\n"
3977+
ns = {}
3978+
exec(compile(src, "x" * 1500 + ".py", "exec"), ns)
3979+
3980+
trace = ns["g"](RemoteUnwinder(os.getpid()).get_stack_trace)
3981+
frame = self._find_frame_in_trace(trace, lambda f: f.funcname == "g")
3982+
self.assertIsNotNone(frame)
3983+
self.assertEqual(frame.filename, "x" * 1024)
40353984

40363985
def test_oversized_linetable_degrades_to_no_location(self):
40373986
"""A linetable over MAX_LINETABLE_SIZE degrades to a frame without
40383987
location instead of failing the whole sample."""
4039-
script_body = """\
4040-
body = " x = 1\\n" * 16_000
4041-
src = ("def big():\\n" + body + "\\n"
4042-
" sock.sendall(b'ready')\\n"
4043-
" time.sleep(10_000)\\n")
4044-
ns = {"sock": sock, "time": time}
4045-
exec(compile(src, "big_linetable.py", "exec"), ns)
4046-
sock.sendall(b"lt:%d\\n" % len(ns["big"].__code__.co_linetable))
4047-
ns["big"]()
4048-
"""
4049-
with self._running_target(script_body) as (p, client_socket):
4050-
buffer = _wait_for_signal(client_socket, [b"lt:", b"ready"])
4051-
linetable_size = int(
4052-
buffer.partition(b"lt:")[2].partition(b"\n")[0]
4053-
)
4054-
self.assertGreater(linetable_size, 64 * 1024)
4055-
4056-
frame = self._sample_until_frame(
4057-
p.pid, lambda f: f.funcname == "big"
4058-
)
4059-
self.assertIsNone(frame.location)
4060-
self.assertEqual(frame.filename, "big_linetable.py")
3988+
src = (
3989+
"def big(sample):\n"
3990+
+ " x = 1\n" * 16_000
3991+
+ " return sample()\n"
3992+
)
3993+
ns = {}
3994+
exec(compile(src, "big_linetable.py", "exec"), ns)
3995+
big = ns["big"]
3996+
self.assertGreater(len(big.__code__.co_linetable), 64 * 1024)
3997+
3998+
trace = big(RemoteUnwinder(os.getpid()).get_stack_trace)
3999+
frame = self._find_frame_in_trace(
4000+
trace, lambda f: f.funcname == "big"
4001+
)
4002+
self.assertIsNone(frame.location)
4003+
self.assertEqual(frame.filename, "big_linetable.py")
40614004

40624005
@unittest.skipIf(
40634006
sys.platform == "win32",
@@ -4066,29 +4009,51 @@ def test_oversized_linetable_degrades_to_no_location(self):
40664009
def test_dead_process_raises_not_degrades(self):
40674010
"""Death of the target raises ProcessLookupError instead of
40684011
degrading to synthetic frames."""
4069-
script_body = """\
4012+
port = find_unused_port()
4013+
script = textwrap.dedent(
4014+
f"""\
4015+
import time, socket
4016+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4017+
sock.connect(('localhost', {port}))
40704018
sock.sendall(b"ready")
40714019
time.sleep(10_000)
40724020
"""
4073-
with self._running_target(script_body) as (p, client_socket):
4074-
_wait_for_signal(client_socket, b"ready")
4075-
unwinder = RemoteUnwinder(p.pid, all_threads=True)
4076-
_get_stack_trace_with_retry(unwinder)
4021+
)
40774022

4078-
p.kill()
4079-
p.wait()
4023+
with os_helper.temp_dir() as work_dir:
4024+
script_dir = os.path.join(work_dir, "script_pkg")
4025+
os.mkdir(script_dir)
40804026

4081-
for _ in busy_retry(SHORT_TIMEOUT, error=False):
4082-
try:
4083-
unwinder.get_stack_trace()
4084-
except ProcessLookupError:
4085-
break
4086-
except RuntimeError:
4087-
continue
4088-
else:
4089-
self.fail(
4090-
"ProcessLookupError never raised for dead process"
4091-
)
4027+
server_socket = _create_server_socket(port)
4028+
script_name = _make_test_script(script_dir, "script", script)
4029+
client_socket = None
4030+
4031+
try:
4032+
with _managed_subprocess([sys.executable, script_name]) as p:
4033+
client_socket, _ = server_socket.accept()
4034+
server_socket.close()
4035+
server_socket = None
4036+
_wait_for_signal(client_socket, b"ready")
4037+
4038+
unwinder = RemoteUnwinder(p.pid, all_threads=True)
4039+
_get_stack_trace_with_retry(unwinder)
4040+
4041+
p.kill()
4042+
p.wait()
4043+
4044+
for _ in busy_retry(SHORT_TIMEOUT, error=False):
4045+
try:
4046+
unwinder.get_stack_trace()
4047+
except ProcessLookupError:
4048+
break
4049+
except RuntimeError:
4050+
continue
4051+
else:
4052+
self.fail(
4053+
"ProcessLookupError never raised for dead process"
4054+
)
4055+
finally:
4056+
_cleanup_sockets(client_socket, server_socket)
40924057

40934058

40944059
if __name__ == "__main__":

0 commit comments

Comments
 (0)