aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_project_ui.py
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-07 04:00:03 +0200
committeruser <user@clank>2026-08-07 04:00:03 +0200
commit8218b9112393420286210458daabe187af57cd8c (patch)
tree744c7ca91896b9487595e6bde5e1584d4e1ba2c4 /tests/test_project_ui.py
parentautoresearch: record the bench history, the budget and the graph non-determin... (diff)
downloadida-tui-8218b9112393420286210458daabe187af57cd8c.tar.gz
ida-tui-8218b9112393420286210458daabe187af57cd8c.tar.xz
ida-tui-8218b9112393420286210458daabe187af57cd8c.zip
CORRECTNESS REPAIR, kept on its merits. The full suite (which the gate was NOT running) revealed that the worker-connect poll change made test_project_ui flaky: 5ms polling on a background thread through a cold auto-analysis starved the UI thread enough that the loading overlay was still up when the test pressed Ctrl+O. Poll now backs off to a 25ms cap (keeps the boot win, no busy-wait), the racy boot wait is fixed, and checks.sh runs tests/run.py in full (830 checks) instead of just the scenario suite.
Result: {"status":"keep","total_ms":18608,"lg_boot_ms":708.5,"lg_decomp_ms":2454.9,"lg_graph_ms":1034.5,"lg_hex_ms":431.9,"lg_index_ms":95.1,"lg_listing_cold_ms":530.2,"lg_listing_warm_ms":413.4,"lg_nav_ms":7057.9,"lg_palette_ms":5,"lg_render_ms":214.2,"lg_search_ms":1408.9,"pure_graph_ms":213.3,"sm_boot_ms":433.6,"sm_decomp_ms":1292,"sm_graph_ms":754,"sm_hex_ms":433.4,"sm_index_ms":2.6,"sm_listing_cold_ms":260.4,"sm_listing_warm_ms":280.5,"sm_nav_ms":286.1,"sm_palette_ms":0.3,"sm_render_ms":251,"sm_search_ms":46.5,"fails":0}
Diffstat (limited to 'tests/test_project_ui.py')
-rw-r--r--tests/test_project_ui.py29
1 files changed, 24 insertions, 5 deletions
diff --git a/tests/test_project_ui.py b/tests/test_project_ui.py
index 753717a..7e93c81 100644
--- a/tests/test_project_ui.py
+++ b/tests/test_project_ui.py
@@ -56,10 +56,27 @@ async def run(bins):
async def settle(pred, t=180.0):
return await wait_for(pred, pilot.pause, t, 0.05)
+ async def usable(t=180.0):
+ """Loaded AND drivable.
+
+ An index that has finished streaming does not mean the app is
+ taking keys yet: the loading overlay is a ModalScreen and it is
+ dismissed a moment later, by auto-land. Between those two the
+ app looks ready and swallows every keypress -- so a test that
+ waits only for the index presses Ctrl+O into the overlay and
+ sees no switcher. Which side of that gap the poll lands on is
+ decided by how fast the backend happens to be, so it has to be
+ waited for explicitly, not hoped for.
+ """
+ return await settle(
+ lambda: app.program is not None
+ and app._func_index is not None
+ and app._func_index.complete
+ and app._loading_screen is None
+ and len(app.screen_stack) == 1, t)
+
# -- boots on the project's first binary ----------------------- #
- ok = await settle(lambda: app.program is not None
- and app._func_index is not None
- and app._func_index.complete)
+ ok = await usable()
check("project mode boots on the first binary", ok,
f"binary={app._binary}")
check("the active binary is the first one", app._binary == first,
@@ -100,7 +117,8 @@ async def run(bins):
await pilot.press("enter")
switched = await settle(
lambda: app._binary == second and app.program is not None
- and app._func_index is not None and app._func_index.complete)
+ and app._func_index is not None and app._func_index.complete
+ and len(app.screen_stack) == 1)
check("switching opens the other binary", switched,
f"binary={app._binary}")
check("the second binary has its own function index",
@@ -127,7 +145,8 @@ async def run(bins):
await pilot.press("enter")
back = await settle(lambda: app._binary == first
and app._func_index is not None
- and app._func_index.complete, 120)
+ and app._func_index.complete
+ and len(app.screen_stack) == 1, 120)
check("switching back returns to the first binary", back,
f"binary={app._binary}")
check("its function index came back intact",