aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_search.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_search.py')
-rw-r--r--tests/test_search.py109
1 files changed, 70 insertions, 39 deletions
diff --git a/tests/test_search.py b/tests/test_search.py
index 6fd1a25..7b80dda 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -16,8 +16,13 @@ import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from idatui.search import ( # noqa: E402
- BYTES, TEXT, classify, looks_like_bytes, normalise_pattern,
- pattern_problem, probably_meant_bytes,
+ BYTES,
+ TEXT,
+ classify,
+ looks_like_bytes,
+ normalise_pattern,
+ pattern_problem,
+ probably_meant_bytes,
)
PASS = FAIL = 0
@@ -35,63 +40,89 @@ def check(name, cond, detail=""):
def main() -> int:
# -- the asymmetry: hex-looking WORDS must stay text --------------------- #
- for word in ("add", "dead", "beef", "cafe", "ff", "0", "abcdef",
- "decode", "face"):
- check(f"{word!r} searches text, not bytes",
- classify(word)[0] == TEXT, classify(word))
+ for word in ("add", "dead", "beef", "cafe", "ff", "0", "abcdef", "decode", "face"):
+ check(
+ f"{word!r} searches text, not bytes",
+ classify(word)[0] == TEXT,
+ classify(word),
+ )
# -- unambiguous byte patterns ------------------------------------------ #
- for pat in ("48 8b ?? c3", "B8 ? ? ? ? 90", "48,8b,05", "de ad be ef",
- "48 8? ?? 24", "??"):
- check(f"{pat!r} searches bytes", classify(pat)[0] == BYTES,
- classify(pat))
+ for pat in (
+ "48 8b ?? c3",
+ "B8 ? ? ? ? 90",
+ "48,8b,05",
+ "de ad be ef",
+ "48 8? ?? 24",
+ "??",
+ ):
+ check(f"{pat!r} searches bytes", classify(pat)[0] == BYTES, classify(pat))
- check("a quoted literal is a byte pattern",
- classify('"Hello", 0')[0] == BYTES)
+ check("a quoted literal is a byte pattern", classify('"Hello", 0')[0] == BYTES)
# A TYPO in a byte pattern must stay a byte pattern, so it can be refused
# with a reason. Falling back to text answers "no match", which is
# indistinguishable from "those bytes are not in this binary".
- check("a typo'd byte pattern is still a byte pattern",
- classify("48 zz c3")[0] == BYTES, classify("48 zz c3"))
- check("and it is refused by name",
- "'zz'" in (pattern_problem("48 zz c3") or ""))
- check("but a word among bytes is prose",
- classify("add ff")[0] == TEXT and classify("mov rdi, rax")[0] == TEXT,
- classify("add ff"))
+ check(
+ "a typo'd byte pattern is still a byte pattern",
+ classify("48 zz c3")[0] == BYTES,
+ classify("48 zz c3"),
+ )
+ check("and it is refused by name", "'zz'" in (pattern_problem("48 zz c3") or ""))
+ check(
+ "but a word among bytes is prose",
+ classify("add ff")[0] == TEXT and classify("mov rdi, rax")[0] == TEXT,
+ classify("add ff"),
+ )
check("prose stays text", classify("mov rdi, rax")[0] == TEXT)
check("a call target stays text", classify("call cs:__isoc99_scanf")[0] == TEXT)
- check("an empty query is text (nothing to search yet)",
- classify("")[0] == TEXT and not looks_like_bytes(""))
+ check(
+ "an empty query is text (nothing to search yet)",
+ classify("")[0] == TEXT and not looks_like_bytes(""),
+ )
# -- explicit wins over any guess --------------------------------------- #
check("hex: forces bytes", classify("hex: dead") == (BYTES, "dead"))
check("bytes: forces bytes too", classify("bytes:dead") == (BYTES, "dead"))
check("text: forces text", classify("text: 48 8b c3") == (TEXT, "48 8b c3"))
- check("F2's forced mode beats the shape",
- classify("dead", forced=BYTES) == (BYTES, "dead")
- and classify("48 8b c3", forced=TEXT) == (TEXT, "48 8b c3"))
- check("a prefix beats even the forced mode",
- classify("text:48 8b c3", forced=BYTES)[0] == TEXT)
+ check(
+ "F2's forced mode beats the shape",
+ classify("dead", forced=BYTES) == (BYTES, "dead")
+ and classify("48 8b c3", forced=TEXT) == (TEXT, "48 8b c3"),
+ )
+ check(
+ "a prefix beats even the forced mode",
+ classify("text:48 8b c3", forced=BYTES)[0] == TEXT,
+ )
# -- the shapes people paste -------------------------------------------- #
check("commas become spaces", normalise_pattern("48,8b,05") == "48 8b 05")
- check("a run with no separators is split into bytes",
- normalise_pattern("488B05C3") == "48 8B 05 C3")
+ check(
+ "a run with no separators is split into bytes",
+ normalise_pattern("488B05C3") == "48 8B 05 C3",
+ )
check("whitespace is squeezed", normalise_pattern(" 48 8b\t05 ") == "48 8b 05")
- check("a quoted literal keeps its own spacing",
- normalise_pattern('"Hello, world", 0') == '"Hello, world", 0')
+ check(
+ "a quoted literal keeps its own spacing",
+ normalise_pattern('"Hello, world", 0') == '"Hello, world", 0',
+ )
# -- refusing a bad pattern with a reason -------------------------------- #
- check("an empty pattern says what to type",
- "48 8b" in (pattern_problem("") or ""))
- check("a non-hex token is named",
- "'zz'" in (pattern_problem("48 zz c3") or ""), pattern_problem("48 zz c3"))
- check("a good pattern has no complaint",
- pattern_problem("48 8b ?? c3") is None
- and pattern_problem('"Hi", 0') is None)
- check("an odd-length run is refused rather than silently split",
- pattern_problem("488B0") is not None, pattern_problem("488B0"))
+ check("an empty pattern says what to type", "48 8b" in (pattern_problem("") or ""))
+ check(
+ "a non-hex token is named",
+ "'zz'" in (pattern_problem("48 zz c3") or ""),
+ pattern_problem("48 zz c3"),
+ )
+ check(
+ "a good pattern has no complaint",
+ pattern_problem("48 8b ?? c3") is None and pattern_problem('"Hi", 0') is None,
+ )
+ check(
+ "an odd-length run is refused rather than silently split",
+ pattern_problem("488B0") is not None,
+ pattern_problem("488B0"),
+ )
print(f"\n{PASS} passed, {FAIL} failed")
return 1 if FAIL else 0