Cathy Wu

106 papers A* 12A 4Misc 2Journal 68Unranked 19
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Peixin Huang, Yaoxin Wu, Yining Ma, Cathy Wu, Wen Song, Wei Zhang
2026 J jnl
IEEE Trans. Control. Netw. Syst.
Muhammad Umar B. Niazi, Jung-Hoon Cho, Munther A. Dahleh, Roy Dong, Cathy Wu
2026 J jnl
CoRR
Han Zheng, Yining Ma, Brandon Araki, Jingkai Chen, Cathy Wu
2026 J jnl
J. Artif. Intell. Res.
Han Zheng, Yining Ma, Brandon Araki, Jingkai Chen, Cathy Wu
2026 J jnl
CoRR
Junyi Ji, Ruth Lu, Linda Belkessa, Liming Wang, Silvia Varotto, Yongqi Dong, Nicolas Saunier, Mostafa Ameli, Gregory S. Macfarlane, Bahman Madadi, Cathy Wu
2026 J jnl
CoRR
Cameron Hickert, Sirui Li, Zhengbing He, Cathy Wu
2026 J jnl
IEEE Trans. Intell. Transp. Syst.
Cameron Hickert, Sirui Li, Zhengbing He, Cathy Wu
2026 A* conf
AAAI
Tianyue Zhou, Jung-Hoon Cho, Cathy Wu
2026 J jnl
CoRR
Tianyue Zhou, Jung-Hoon Cho, Cathy Wu
2026 J jnl
IEEE Trans. Robotics
Jung-Hoon Cho, Sirui Li, Jeongyun Kim, Cathy Wu
2026 J jnl
CoRR
Jieyi Bi, Zhiguang Cao, Jianan Zhou, Wen Song, Yaoxin Wu, Jie Zhang, Yining Ma, Cathy Wu
2025 J jnl
CoRR
Zhengbing He, Jorge Laval, Yu Han, Ryosuke Nishi, Cathy Wu
2025 J jnl
CoRR
Alan Papalia, Charles Dawson, Laurentiu L. Anton, Norhan Bayomi, Bianca Champenois, Jung-Hoon Cho, Levi Cai, Joseph DelPreto, Kristen Edwards, Bilha-Catherine Githinji, Cameron Hickert, Vindula Jayawardana, Matthew Kramer, Shreyaa Raghavan, David Russell, Shide Salimi, Jingnan Shi, Soumya Sudhakar, Yanwei Wang, Shouyi Wang, Luca Carlone, Vijay Kumar, Daniela Rus, John E. Fernandez, Cathy Wu, George Kantor, Derek Young, Hanumant Singh
2025 J jnl
CoRR
Minwei Kong, Ao Qu, Xiaotong Guo, Wenbin Ouyang, Chonghe Jiang, Han Zheng, Yining Ma, Dingyi Zhuang, Yuhan Tang, Junyi Li, Hai Wang, Cathy Wu, Jinhua Zhao
2025 A* conf
ICLR
Vindula Jayawardana, Baptiste Freydt, Ao Qu, Cameron Hickert, Zhongxia Yan, Cathy Wu
2025 J jnl
CoRR
Wenbin Ouyang, Sirui Li, Yining Ma, Cathy Wu
2025 A* conf
ICLR
Sirui Li, Wenbin Ouyang, Yining Ma, Cathy Wu
2025 J jnl
CoRR
Sirui Li, Wenbin Ouyang, Yining Ma, Cathy Wu
2025 J jnl
IEEE Intell. Transp. Syst. Mag.
Aamir Hasan, Neeloy Chakraborty, Haonan Chen, Cathy Wu, Katherine Driggs-Campbell
2025 J jnl
CoRR
Chengyuan Zhang, Cathy Wu, Lijun Sun
2025 J jnl
CoRR
Vindula Jayawardana, Sirui Li, Yashar Zeiynali Farid, Cathy Wu
2025 J jnl
CoRR
Edgar Ramirez Sanchez, Catherine Tang, Yaosheng Xu, Nrithya Renganathan, Vindula Jayawardana, Zhengbing He, Cathy Wu
2025 J jnl
CoRR
Vindula Jayawardana, Catherine Tang, Junyi Ji, Jonah Philion, Xue Bin Peng, Cathy Wu
2025 J jnl
CoRR
Enrico Marchesini, Benjamin Donnot, Constance Crozier, Ian Dytham, Christian Merz, Lars Schewe, Nico Westerbeck, Cathy Wu, Antoine Marot, Priya L. Donti
2025 conf
KDD (2)
Federico Berto, Chuanbo Hua, Junyoung Park, Laurin Luttmann, Yining Ma, Fanchen Bu, Jiarui Wang, Haoran Ye, Minsu Kim, Sanghyeok Choi, Nayeli Gast Zepeda, André Hottung, Jianan Zhou, Jieyi Bi, Yu Hu, Fei Liu, Hyeonah Kim, Jiwoo Son, Haeyeon Kim, Davide Angioni, Wouter Kool, Zhiguang Cao, Qingfu Zhang, Joungho Kim, Jie Zhang, Kijung Shin, Cathy Wu, Sungsoo Ahn, Guojie Song, Changhyun Kwon, Kevin Tierney, Lin Xie, Jinkyoo Park
2025 J jnl
CoRR
Yutong Xia, Ao Qu, Yunhan Zheng, Yihong Tang, Dingyi Zhuang, Yuxuan Liang, Cathy Wu, Roger Zimmermann, Jinhua Zhao
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Jeongyun Kim, Jung-Hoon Cho, Cathy Wu
2025 J jnl
CoRR
Heeseung Bang, Jung-Hoon Cho, Cathy Wu, Andreas A. Malikopoulos
2025 J jnl
IEEE Trans. Control. Netw. Syst.
Tianyue Zhou, Jung-Hoon Cho, Cathy Wu
2025 A* conf
ICLR
Sirui Li, Janardhan Kulkarni, Ishai Menache, Cathy Wu, Beibin Li
2025 J jnl
CoRR
Chengyuan Zhang, Zhengbing He, Cathy Wu, Lijun Sun
2024 A conf
IROS
Cameron Hickert, Zhongxia Yan, Cathy Wu
2024 J jnl
CoRR
Cameron Hickert, Zhongxia Yan, Cathy Wu
2024 J jnl
CoRR
Aamir Hasan, Neeloy Chakraborty, Haonan Chen, Jung-Hoon Cho, Cathy Wu, Katherine Rose Driggs-Campbell
2024 J jnl
CoRR
Muhammad Umar B. Niazi, Jung-Hoon Cho, Munther A. Dahleh, Roy Dong, Cathy Wu
2024 conf
L4DC
Tianyue Zhou, Jung-Hoon Cho, Babak Rahimi Ardabili, Hamed Tabkhi, Cathy Wu
2024 J jnl
CoRR
Tianyue Zhou, Jung-Hoon Cho, Babak Rahimi Ardabili, Hamed Tabkhi, Cathy Wu
2024 A* conf
ICRA
Vindula Jayawardana, Sirui Li, Cathy Wu, Yashar Zeiynali Farid, Kentaro Oguchi
2024 J jnl
CoRR
Vindula Jayawardana, Sirui Li, Cathy Wu, Yashar Zeiynali Farid, Kentaro Oguchi
2024 J jnl
IEEE Trans. Robotics
Sirui Li, Roy Dong, Cathy Wu
2024 conf
ECC
Muhammad Umar B. Niazi, Jung-Hoon Cho, Munther A. Dahleh, Roy Dong, Cathy Wu
2024 J jnl
IEEE Trans. Control. Netw. Syst.
Sirui Li, Roy Dong, Cathy Wu
2024 J jnl
CoRR
Vindula Jayawardana, Baptiste Freydt, Ao Qu, Cameron Hickert, Zhongxia Yan, Cathy Wu
2024 J jnl
CoRR
Aamir Hasan, Neeloy Chakraborty, Haonan Chen, Cathy Wu, Katherine Driggs-Campbell
2024 J jnl
CoRR
Vindula Jayawardana, Baptiste Freydt, Ao Qu, Cameron Hickert, Edgar Sanchez, Catherine Tang, Mark Taylor, Blaine Leonard, Cathy Wu
2024 A* conf
NeurIPS
Jung-Hoon Cho, Vindula Jayawardana, Sirui Li, Cathy Wu
2024 J jnl
CoRR
Jung-Hoon Cho, Vindula Jayawardana, Sirui Li, Cathy Wu
2024 J jnl
IEEE Trans. Intell. Transp. Syst.
Dajiang Suo, Vindula Jayawardana, Cathy Wu
2024 A* conf
ICRA
Zhongxia Yan, Han Zheng, Cathy Wu
2024 J jnl
CoRR
Zhongxia Yan, Han Zheng, Cathy Wu
2024 A conf
IROS
Han Zheng, Zhongxia Yan, Cathy Wu
2024 J jnl
CoRR
Han Zheng, Zhongxia Yan, Cathy Wu
2024 A* conf
ICLR
Zhongxia Yan, Cathy Wu
2024 A conf
IROS
Zhongxia Yan, Cathy Wu
2024 J jnl
CoRR
Tianyue Zhou, Jung-Hoon Cho, Cathy Wu
2024 J jnl
CoRR
Sirui Li, Janardhan Kulkarni, Ishai Menache, Cathy Wu, Beibin Li
2024 J jnl
CoRR
Ao Qu, Anirudh Valiveru, Catherine Tang, Vindula Jayawardana, Baptiste Freydt, Cathy Wu
2024 J jnl
CoRR
Yuxuan Zhu, Shiyi Wang, Wenqing Zhong, Nianchen Shen, Yunqi Li, Siqi Wang, Zhiheng Li, Cathy Wu, Zhengbing He, Li Li
2023 J jnl
IEEE Trans. Robotics
Cameron Hickert, Sirui Li, Cathy Wu
2023 J jnl
CoRR
Edgar Ramirez Sanchez, Shreyaa Raghavan, Cathy Wu
2023 J jnl
CoRR
Sirui Li, Roy Dong, Cathy Wu
2023 J jnl
CoRR
Muhammad Umar B. Niazi, Jung-Hoon Cho, Munther A. Dahleh, Roy Dong, Cathy Wu
2023 J jnl
CoRR
Sirui Li, Roy Dong, Cathy Wu
2023 A* conf
NeurIPS
Sirui Li, Wenbin Ouyang, Max B. Paulus, Cathy Wu
2023 J jnl
CoRR
Sirui Li, Wenbin Ouyang, Max B. Paulus, Cathy Wu
2023 J jnl
CoRR
Dajiang Suo, Vindula Jayawardana, Cathy Wu
2023 conf
ITSC
Sanjula Jayawardana, Vindula Jayawardana, Kaneeka Vidanage, Cathy Wu
2023 conf
ITSC
Aamir Hasan, Neeloy Chakraborty, Haonan Chen, Jung-Hoon Cho, Cathy Wu, Katherine Driggs-Campbell
2023 J jnl
CoRR
Aamir Hasan, Neeloy Chakraborty, Haonan Chen, Jung-Hoon Cho, Cathy Wu, Katherine Rose Driggs-Campbell
2023 conf
ECC
Sirui Li, Roy Dong, Cathy Wu
2023 J jnl
CoRR
Jung-Hoon Cho, Sirui Li, Jeongyun Kim, Cathy Wu
2023 J jnl
CoRR
Aamir Hasan, Neeloy Chakraborty, Cathy Wu, Katherine Rose Driggs-Campbell
2023 J jnl
IEEE Trans Autom. Sci. Eng.
Zhongxia Yan, Abdul Rahman Kreidieh, Eugene Vinitsky, Alexandre M. Bayen, Cathy Wu
2022 J jnl
IEEE Trans. Robotics
Cathy Wu, Abdul Rahman Kreidieh, Kanaad Parvate, Eugene Vinitsky, Alexandre M. Bayen
2022 conf
ECC
Vindula Jayawardana, Cathy Wu
2022 J jnl
CoRR
Vindula Jayawardana, Cathy Wu
2022 J jnl
CoRR
Thomas Krendl Gilbert, Aaron J. Snoswell, Michael Dennis, Rowan McAllister, Cathy Wu
2022 J jnl
CoRR
Dingyi Zhuang, Yuzhu Huang, Vindula Jayawardana, Jinhua Zhao, Dajiang Suo, Cathy Wu
2022 conf
ITSC
Dingyi Zhuang, Yuzhu Huang, Vindula Jayawardana, Jinhua Zhao, Dajiang Suo, Cathy Wu
2022 A* conf
NeurIPS
Vindula Jayawardana, Catherine Tang, Sirui Li, Dajiang Suo, Cathy Wu
2022 J jnl
CoRR
Vindula Jayawardana, Catherine Tang, Sirui Li, Dajiang Suo, Cathy Wu
2022 A conf
CIKM
Hua Wei, Guni Sharon, Cathy Wu, Sanjay Chawla, Zhenhui Li
2022 J jnl
CoRR
Zhongxia Yan, Abdul Rahman Kreidieh, Eugene Vinitsky, Alexandre M. Bayen, Cathy Wu
2021 J jnl
CoRR
Cameron Hickert, Sirui Li, Cathy Wu
2021 J jnl
CoRR
Brent J. Hecht, Lauren Wilcox, Jeffrey P. Bigham, Johannes Schöning, Ehsan Hoque, Jason Ernst, Yonatan Bisk, Luigi De Russis, Lana Yarosh, Bushra Anjum, Danish Contractor, Cathy Wu
2021 J jnl
CoRR
Sirui Li, Zhongxia Yan, Cathy Wu
2021 A* conf
NeurIPS
Sirui Li, Zhongxia Yan, Cathy Wu
2021 conf
ITSC
Vindula Jayawardana, Anna Landler, Cathy Wu
2021 conf
ITSC
Mayuri Sridhar, Cathy Wu
2021 conf
ITSC
Zhongxia Yan, Cathy Wu
2021 J jnl
CoRR
Zhongxia Yan, Cathy Wu
2020 J jnl
IEEE Trans. Intell. Transp. Syst.
Cathy Wu, Alexey Pozdnukhov, Alexandre M. Bayen
2018 Misc conf
CoRL
Eugene Vinitsky, Aboudy Kreidieh, Luc Le Flem, Nishant Kheterpal, Kathy Jang, Cathy Wu, Fangyu Wu, Richard Liaw, Eric Liang, Alexandre M. Bayen
2018 conf
ITSC
Abdul Rahman Kreidieh, Cathy Wu, Alexandre M. Bayen
2018 conf
ITSC
Eugene Vinitsky, Kanaad Parvate, Aboudy Kreidieh, Cathy Wu, Alexandre M. Bayen
2018
Cathy Wu
2018 A* conf
ICRA
Cathy Wu, Alexandre M. Bayen, Ankur Mehta
2018 conf
ICLR
Cathy Wu, Aravind Rajeswaran, Yan Duan, Vikash Kumar, Alexandre M. Bayen, Sham M. Kakade, Igor Mordatch, Pieter Abbeel
2018 J jnl
CoRR
Cathy Wu, Aravind Rajeswaran, Yan Duan, Vikash Kumar, Alexandre M. Bayen, Sham M. Kakade, Igor Mordatch, Pieter Abbeel
2017 Misc conf
CoRL
Cathy Wu, Aboudy Kreidieh, Eugene Vinitsky, Alexandre M. Bayen
2017 J jnl
CoRR
Cathy Wu, Aboudy Kreidieh, Kanaad Parvate, Eugene Vinitsky, Alexandre M. Bayen
2017 conf
ITSC
Cathy Wu, Kanaad Parvate, Nishant Kheterpal, Leah Dickstein, Ankur Mehta, Eugene Vinitsky, Alexandre M. Bayen
2017 conf
ITSC
Cathy Wu, Eugene Vinitsky, Aboudy Kreidieh, Alexandre M. Bayen
2016 conf
ITSC
Cathy Wu, Ece Kamar, Eric Horvitz
2016 conf
ITSC
Cathy Wu, Kalyanaraman Shankari, Ece Kamar, Randy H. Katz, David E. Culler, Christos H. Papadimitriou, Eric Horvitz, Alexandre M. Bayen
2015 conf
CDC
Jerome Thai, Cathy Wu, Alexey Pozdnukhov, Alexandre M. Bayen
tests/unit/test_decompile_medium_level.py
← Index tests/unit/test_decompile_medium_level.py python
# tests/unit/test_decompile_medium_level.py
"""Unit tests (mocked BN) for bninja/analysis/medium_level.py
   and bninja/analysis/medium_level_normalization.py."""
# tests/unit/test_decompile_medium_level.py
import sys
from unittest.mock import MagicMock, patch

# Installa gli stubs BN
from tests.unit.conftest_binja_stubs import install_binja_stubs
install_binja_stubs()

# ── Definisci MockMLILInstruction PRIMA di importare il modulo ──
class MockMLILInstruction:
    def __init__(self, operation, address=0, operands=None):
        self.operation = operation
        self.address = address
        self.operands = operands or []

# ── Patcha il modulo BN in modo che isinstance() funzioni ──
sys.modules["binaryninja"].MediumLevelILInstruction = MockMLILInstruction
sys.modules["binaryninja"].SSAVariable = type("SSAVariable", (), {})
sys.modules["binaryninja"].Variable = type("Variable", (), {})
sys.modules["binaryninja"].ILIntrinsic = type("ILIntrinsic", (), {})

# Ora importa il modulo — vede già i tipi corretti
from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
    MediumLevelNormalization,
)	

class MockMLILFunction:
    def __init__(self, instructions):
        self._instructions = instructions

    @property
    def instructions(self):
        return iter(self._instructions)

    @property
    def basic_blocks(self):
        # one block containing all instructions, good enough for MinHasher
        block = MagicMock()
        block.__iter__ = lambda self_: iter([])  # not used by MediumLevelAnalysis
        return [block]


class MockFunction:
    def __init__(self, name="func", start=0x1000, mlil=None):
        self.name = name
        self.start = start
        self.mlil = mlil



class TestMediumLevelNormalization:
    def setup_method(self):
        from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
            MediumLevelNormalization,
        )
        self.norm = MediumLevelNormalization()

    def test_normalize_skeleton_single_instruction(self):
        il = MockMLILInstruction(operation=42, operands=[])
        result = self.norm.normalize_instruction_all_levels(il)
        assert result == [42]

    def test_normalize_skeleton_nested(self):
        inner = MockMLILInstruction(operation=7, operands=[])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [1, 7]

    def test_normalize_skeleton_with_list_operand(self):
        inner_a = MockMLILInstruction(operation=10, operands=[])
        inner_b = MockMLILInstruction(operation=11, operands=[])
        outer = MockMLILInstruction(operation=2, operands=[[inner_a, inner_b]])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [2, 10, 11]

    def test_normalize_skeleton_none(self):
        result = self.norm.normalize_instruction_all_levels(None)
        # collect on None should leave ops empty
        assert result == []

    def test_normalize_typed_appends_leaf_types(self):
        # operand is a plain int -> "CONST"
        il = MockMLILInstruction(operation=3, operands=[42])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [3, "CONST"]

    def test_normalize_typed_bool_before_int(self):
        # bool must be detected before int (since bool is an int subclass)
        il = MockMLILInstruction(operation=4, operands=[True])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [4, "BOOL"]

    def test_normalize_typed_float(self):
        il = MockMLILInstruction(operation=5, operands=[1.5])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [5, "FLOAT_CONST"]

    def test_normalize_typed_str(self):
        il = MockMLILInstruction(operation=6, operands=["hello"])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [6, "STR"]

    def test_normalize_typed_unknown_falls_back_to_typename(self):
        class Weird:
            pass
        il = MockMLILInstruction(operation=8, operands=[Weird()])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [8, "WEIRD"]

    def test_normalize_typed_nested_mlil(self):
        inner = MockMLILInstruction(operation=99, operands=[7])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instr_with_operands(outer)
        assert result == [1, 99, "CONST"]

    def test_normalize_typed_list_mixed(self):
        inner = MockMLILInstruction(operation=50, operands=[])
        il = MockMLILInstruction(operation=2, operands=[[inner, 99]])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [2, 50, "CONST"]


class TestMediumLevelAnalysis:
    def _make_analysis(self, instructions=None, mlil=True, start=0x1000):
        from redb.extractors.decompiler.bninja.analysis.medium_level import (
            MediumLevelAnalysis,
        )
        mlil_func = MockMLILFunction(instructions or []) if mlil else None
        func = MockFunction(name="testfunc", start=start, mlil=mlil_func)
        bv = MagicMock()
        return MediumLevelAnalysis(func, bv, MagicMock())

    def test_collect_returns_empty_when_no_mlil(self):
        a = self._make_analysis(mlil=False)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk == [] and sk_addr == [] and ty == [] and ty_addr == []

    def test_collect_skeleton_and_typed_basic(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()

        assert sk == [[1], [2]]
        assert ty == [[1], [2, "CONST"]]
        assert sk_addr == [(0, [1]), (4, [2])]
        assert ty_addr == [(0, [1]), (4, [2, "CONST"])]

    def test_collect_negative_offset_clamped_to_zero(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x900, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        _, sk_addr, _, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk_addr[0][0] == 0
        assert ty_addr[0][0] == 0

    def test_log_error_records_entry(self):
        a = self._make_analysis()
        a.log_error("boom", "fname", 0x1234, ValueError("x"), "loc")
        assert len(a.errors) == 1
        err = a.errors[0]
        assert err["function_name"] == "fname"
        assert err["function_address"] == "4660"  # hex 0x1234
        assert err["error_location"] == "loc"
        assert err["error_message"] == "boom"
        assert err["error_type"] == "ValueError"
        assert "timestamp" in err

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_returns_expected_keys(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = [1, 2, 3]

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        result, errors = a.analyze()

        expected_keys = {
            "function_address",
            "body_mlil_skeleton_vector",
            "sha256_mlil_skeleton",
            "tlsh_mlil_skeleton",
            "minhash_mlil_skeleton",
            "body_mlil_typed_vector",
            "sha256_mlil_typed",
            "tlsh_mlil_typed",
            "minhash_mlil_typed",
        }
        assert set(result.keys()) == expected_keys
        assert result["function_address"] == 0x1000
        assert result["minhash_mlil_skeleton"] == [1, 2, 3]
        assert result["minhash_mlil_typed"] == [1, 2, 3]
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_empty_mlil(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []
        a = self._make_analysis(mlil=False)
        result, errors = a.analyze()
        assert result["body_mlil_skeleton_vector"] == []
        assert result["body_mlil_typed_vector"] == []
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_sha256_differs_skeleton_vs_typed(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[42]),
            MockMLILInstruction(operation=2, address=0x1004, operands=["foo"]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[True]),
        ]
        a = self._make_analysis(instructions=instrs)
        result, _ = a.analyze()
        # skeleton ignores operand leaves, typed includes them -> different hashes
        assert result["sha256_mlil_skeleton"] != result["sha256_mlil_typed"]


class TestMinHasherMLILKinds:
    def _make_func(self, instrs):
        # MinHasher iterates basic_blocks then over each block
        block = MagicMock()
        block.__iter__ = lambda self_: iter(instrs)
        f = MagicMock()
        f.basic_blocks = [block]
        return f

    def test_mlil_skeleton_uses_medium_normalizer(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=i, operands=[]) for i in range(5)
        ]
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        result = hasher.calculateMinHash()
        # 5 instructions -> 3 trigrams -> non-empty signature
        assert result != []

    def test_typed_mlil_differs_from_skeleton(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=1, operands=[42]),
            MockMLILInstruction(operation=2, operands=["s"]),
            MockMLILInstruction(operation=3, operands=[True]),
            MockMLILInstruction(operation=4, operands=[1.5]),
        ]
        func = self._make_func(instrs)
        skel = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL).calculateMinHash()
        typed = MinHasher(seed=42, il_function=func, kind=TokenKind.TYPED_MLIL).calculateMinHash()
        # Same seed, same instructions, but typed has extra leaf tokens
        # -> hashes should generally differ
        assert skel != typed

    def test_mlil_too_few_instructions(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [MockMLILInstruction(operation=1, operands=[])] * 2
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        assert hasher.calculateMinHash() == []

    def test_unsupported_kind_raises(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import MinHasher
        func = self._make_func([])
        hasher = MinHasher(seed=42, il_function=func, kind="bogus")
        with pytest.raises(ValueError):
            hasher.calculateMinHash()