summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-08-06 23:48:04 +0200
committerblasty <blasty@local>2026-08-06 23:48:04 +0200
commit8c9490c0cc1712f61dfdd2efaaee93d33e1825f9 (patch)
treedd8595d8ff6d6694ca4509ed5f19c107fa4ceac4 /tests
parenttests: deterministic fixtures, and a correction (diff)
downloadida-tui-8c9490c0cc1712f61dfdd2efaaee93d33e1825f9.tar.gz
ida-tui-8c9490c0cc1712f61dfdd2efaaee93d33e1825f9.tar.xz
ida-tui-8c9490c0cc1712f61dfdd2efaaee93d33e1825f9.zip
tests: a guard that actually regresses on the resync storm
The split resync loop (f898350) had no test. Two attempts at one were worthless and are not in this commit: a scroll-based guard passed with the bug reintroduced, and a constructed anchor -- inside the loaded function, outside its mapped span -- skipped, because on this target the map covers the whole function. The real trigger is the race window while the decomp map lags the decompiler re-pointing, which is tedious to force but wide open in split_view's own flow. So split_view counts lookup_funcs across its body and bounds it. Verified both ways, which is the only reason it's worth having: 29,227 calls with the bug put back, under 500 with the fix. The bound is loose because the bug was three orders of magnitude out, not a near miss. 733 checks, 139s.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_scenarios.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py
index a1ffaad..6c22c7c 100644
--- a/tests/test_scenarios.py
+++ b/tests/test_scenarios.py
@@ -635,6 +635,33 @@ async def s_strings(c: Ctx):
@scenario("split_view")
async def s_split_view(c: Ctx):
app, lst, dec = c.app, c.lst, c.dec
+ # Count worker lookups across this whole scenario. _sync_split used to bounce
+ # off _apply_resync and back for as long as the decomp map lagged the
+ # decompiler -- one thread worker and one lookup_funcs round trip per
+ # iteration, 23,665 of them in this scenario alone (four distinct
+ # addresses; 21,156 for one of them), and an idle split view pegging the
+ # worker in the live app. The race window is real work to reproduce
+ # deliberately, but it is wide open in the flow below, so the cheap guard is
+ # to count. The bound is loose because the bug was three orders of magnitude
+ # out, not a near miss.
+ _lookups = {"n": 0}
+ _orig_call = c.prog.client.call
+
+ def _counting(name, *a, **kw):
+ if name == "lookup_funcs":
+ _lookups["n"] += 1
+ return _orig_call(name, *a, **kw)
+
+ c.prog.client.call = _counting
+ try:
+ await _split_view_body(c, app, lst, dec)
+ finally:
+ c.prog.client.call = _orig_call
+ c.check("split view doesn't storm the worker with function lookups",
+ _lookups["n"] < 500, f"{_lookups['n']} lookup_funcs calls")
+
+
+async def _split_view_body(c: Ctx, app, lst, dec):
await c.open_biggest("listing")
await c.press("s")
shown = await c.wait(lambda: app._split and lst.display and dec.display, 20)