aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-23 20:03:39 +0200
committerblasty <blasty@local>2026-07-23 20:03:39 +0200
commit4dbb9de9117a85b48f16efbf97477fc58b8283fe (patch)
tree255fc47da48ff8c33d15cc98d7ea7da09c582081 /tests
parentunify: the continuous listing is the one code view; deprecate DisasmView (diff)
downloadida-tui-4dbb9de9117a85b48f16efbf97477fc58b8283fe.tar.gz
ida-tui-4dbb9de9117a85b48f16efbf97477fc58b8283fe.tar.xz
ida-tui-4dbb9de9117a85b48f16efbf97477fc58b8283fe.zip
listing: IDA-style function boundary banners in the unified view
Each function gets clear boundary annotations in the continuous listing: a blank + '; ==== S U B R O U T I N E ====' separator and a 'name proc near' header before the entry, and a 'name endp' + rule after the last item. The function name moves to the proc header (stripped from the inline entry instruction). Server: heads gains an annotate flag (default off, so DisasmModel/test_domain stay 1:1 with instructions); when on, _rows_for emits kind=sep/funchdr rows at function starts/ends. ListingModel requests annotate=true and does NOT index banner rows by ea, so goto/xref/follow land on real code. ListingView renders sep (dim) and funchdr (bold gold); new _S_SEP/_S_FUNCHDR styles. Verified: func_banners 5/0; region_define/listing_view/listing_name_addr/ listing_struct_expand/continuous_view/follow_xrefs/disasm_nav/scroll_restore/ paging green. Needs a supervisor restart (heads tool changed).
Diffstat (limited to 'tests')
-rw-r--r--tests/test_scenarios.py25
1 files changed, 25 insertions, 0 deletions
diff --git a/tests/test_scenarios.py b/tests/test_scenarios.py
index 8a5df2e..73fc50b 100644
--- a/tests/test_scenarios.py
+++ b/tests/test_scenarios.py
@@ -1619,6 +1619,31 @@ async def s_continuous_view(c: Ctx):
app._active == "listing", f"active={app._active}")
+@scenario("func_banners")
+async def s_func_banners(c: Ctx):
+ """The unified listing shows IDA-style function boundary banners: a
+ SUBROUTINE separator + 'name proc near' header and a 'name endp' footer,
+ and those banner rows are display-only (navigation lands on real code)."""
+ app = c.app
+ fn = await c.open_biggest("listing")
+ c.lst.model.load_all()
+ heads = [c.lst.model.get(i) for i in range(len(c.lst.model))]
+ ci = c.lst.model.index_of_ea(fn.addr)
+ c.check("navigation to a function lands on its code head, not a banner",
+ ci >= 0 and c.lst.model.get(ci).kind == "code",
+ f"kind={c.lst.model.get(ci).kind if ci >= 0 else None}")
+ c.check("a SUBROUTINE separator banner is present",
+ any(h.kind == "sep" and "S U B R O U T I N E" in h.text for h in heads))
+ c.check("a 'name proc near' header is present",
+ any(h.kind == "funchdr" and h.text.endswith("proc near") for h in heads))
+ c.check("a 'name endp' footer is present",
+ any(h.kind == "funchdr" and h.text.endswith("endp") for h in heads))
+ # the proc header for the origin function carries its name
+ hdr = next((h for h in heads if h.kind == "funchdr"
+ and h.text == f"{fn.name} proc near"), None)
+ c.check("the proc header names the function", hdr is not None, f"fn={fn.name}")
+
+
# --------------------------------------------------------------------------- #
# Runner
# --------------------------------------------------------------------------- #