diff options
| author | blasty <blasty@local> | 2026-07-09 13:54:40 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-09 13:54:40 +0200 |
| commit | 8d9644e8c6158af45ce95467c4a0611e8e10fa22 (patch) | |
| tree | c22c94a1f130308fcc2514a83b01c6f93f6e8f73 /tests | |
| parent | function-name filter: incremental + highlight + clear (diff) | |
| download | ida-tui-8d9644e8c6158af45ce95467c4a0611e8e10fa22.tar.gz ida-tui-8d9644e8c6158af45ce95467c4a0611e8e10fa22.tar.xz ida-tui-8d9644e8c6158af45ce95467c4a0611e8e10fa22.zip | |
xrefs + follow-under-cursor (disasm & pseudocode)
- Enter follows the reference under the cursor: disasm uses xref_query(from) to
find the code target; pseudocode matches a decompiler ref name on the line.
Navigates to the containing function at the exact line (address-history push).
- x opens an xrefs popup (XrefsScreen modal): xrefs_to the subject under cursor
(call target if any, else the current item); Enter jumps to a referencing
site, Esc closes.
- domain: Program.function_of (mid-addr -> containing func via lookup_funcs),
xrefs_from/xrefs_to (xref_query), Xref model, DisasmModel ea->index map for
landing on an exact address.
- fix: goto to a mid-function address now lands on the right line (was opening
it as a bogus function start).
- pilot suite 32/32; domain 17/17.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_tui.py | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/tests/test_tui.py b/tests/test_tui.py index 2aaf8ff..999d341 100644 --- a/tests/test_tui.py +++ b/tests/test_tui.py @@ -12,8 +12,10 @@ import os import sys sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -from idatui.app import DecompView, DisasmView, FunctionsPanel, IdaTui # noqa: E402 -from textual.widgets import DataTable, Input, Static # noqa: E402 +from idatui.app import ( # noqa: E402 + DecompView, DisasmView, FunctionsPanel, IdaTui, XrefsScreen, +) +from textual.widgets import DataTable, Input, OptionList, Static # noqa: E402 from rich.text import Text # noqa: E402 PASS = FAIL = 0 @@ -227,6 +229,42 @@ async def run(db): check("Esc on the list clears the filter", table.row_count == full, f"{table.row_count}/{full}") + # Follow (Enter) + back (Esc) + xrefs (x), using a real call site. + dis = app.query_one(DisasmView) + dis.focus() + await pilot.pause(0.1) + lines = dis.model.lines(0, 400, prefetch=False) + call_idx = next((i for i, ln in enumerate(lines) + if ln.text.startswith("call ")), None) + if call_idx is None: + check("found a call line to exercise follow/xrefs", False, "no call in first 400") + else: + dis.cursor = call_idx + dis.refresh() + orig = app._cur.ea + depth = len(app._nav) + await pilot.press("enter") + await wait_until(pilot, lambda: len(app._nav) > depth, timeout=25) + check("Enter follows the call into another function", + app._cur.ea != orig and len(app._nav) > depth, f"cur={app._cur.ea:#x}") + await pilot.press("escape") + await pilot.pause(0.2) + check("Esc returns from the follow", app._cur.ea == orig, f"cur={app._cur.ea:#x}") + dis.cursor = call_idx + dis.refresh() + await pilot.press("x") + opened = await wait_until( + pilot, lambda: isinstance(app.screen, XrefsScreen), timeout=25) + check("'x' opens the xrefs popup", opened, + f"screen={type(app.screen).__name__}") + if opened: + check("xrefs popup has entries", + app.screen.query_one(OptionList).option_count >= 1) + await pilot.press("escape") + await pilot.pause(0.2) + check("Esc closes the xrefs popup", + not isinstance(app.screen, XrefsScreen)) + def main(argv): db = None |
