Skip to content

Commit 4bc8ddf

Browse files
test: cover tier-2 iterator monitoring errors
1 parent 2fc84dd commit 4bc8ddf

1 file changed

Lines changed: 33 additions & 7 deletions

File tree

‎Lib/test/test_monitoring.py‎

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2682,7 +2682,7 @@ def test_raise_callback_stop_iteration_in_for_tier2(self):
26822682
_testinternalcapi = import_helper.import_module("_testinternalcapi")
26832683
_opcode = import_helper.import_module("_opcode")
26842684
threshold = _testinternalcapi.SPECIALIZATION_THRESHOLD
2685-
callback_executor = None
2685+
monitoring_enabled = False
26862686

26872687
class Iterator:
26882688
def __init__(self):
@@ -2695,26 +2695,52 @@ def __next__(self):
26952695
if self.count < threshold:
26962696
self.count += 1
26972697
return self.count
2698-
sys.monitoring.set_events(TEST_TOOL, E.RAISE)
2698+
if monitoring_enabled:
2699+
sys.monitoring.set_events(TEST_TOOL, E.RAISE)
26992700
raise StopIteration
27002701

27012702
def run():
27022703
for _ in Iterator():
27032704
pass
27042705

2706+
# Warm up the loop before enabling monitoring, so the callback run
2707+
# executes the tier-2 executor rather than creating it.
2708+
run()
2709+
code = run.__code__
2710+
executor_offset = None
2711+
executor = None
2712+
for offset in range(0, len(code.co_code), 2):
2713+
try:
2714+
candidate = _opcode.get_executor(code, offset)
2715+
except ValueError:
2716+
continue
2717+
except RuntimeError as exc:
2718+
if "Executors are not available in this build" not in str(exc):
2719+
raise
2720+
self.skipTest("requires tier-2 executor support")
2721+
if candidate is not None:
2722+
uops = [op[0] for op in candidate]
2723+
if "_ITER_NEXT_INLINE" in uops:
2724+
executor_offset = offset
2725+
executor = candidate
2726+
break
2727+
if executor is None:
2728+
self.skipTest("requires _ITER_NEXT_INLINE executor")
2729+
2730+
callback_offset = None
2731+
27052732
def on_raise(code, offset, exc):
2706-
nonlocal callback_executor
2733+
nonlocal callback_offset
27072734
if code is run.__code__ and isinstance(exc, StopIteration):
2708-
callback_executor = _opcode.get_executor(code, offset)
2735+
callback_offset = offset
27092736
raise RuntimeError("monitor callback failed")
27102737

2738+
monitoring_enabled = True
27112739
try:
27122740
sys.monitoring.register_callback(TEST_TOOL, E.RAISE, on_raise)
27132741
with self.assertRaisesRegex(RuntimeError, "monitor callback failed"):
27142742
run()
2715-
self.assertIsNotNone(callback_executor)
2716-
uops = [op[0] for op in callback_executor]
2717-
self.assertIn("_ITER_NEXT_INLINE", uops)
2743+
self.assertEqual(callback_offset, executor_offset)
27182744
finally:
27192745
sys.monitoring.set_events(TEST_TOOL, 0)
27202746
sys.monitoring.register_callback(TEST_TOOL, E.RAISE, None)

0 commit comments

Comments
 (0)