Weifeng Su

163 papers A* 3A 3B 39C 2Misc 5Journal 84Unranked 27
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Comput. Biol. Bioinform.
Wenchuan Zhang, Yujian Lee, Ricky Yuen-Tan Hou, Weifeng Su, Hong Yan, Wentao Fan
2026 A* conf
AAAI
Mingjie Zhao, Zhanpei Huang, Yang Lu, Mengke Li, Yiqun Zhang, Weifeng Su, Yiu-ming Cheung
2026 J jnl
IEEE Trans. Netw.
Payam Abdisarabshali, Kwang Taik Kim, Michael Langberg, Weifeng Su, Seyyedali Hosseinalipour
2026 J jnl
IEEE Trans. Mob. Comput.
Fengyi Huang, Wenhua Wang, Qin Liu, Wentao Fan, Weifeng Su, Weijia Jia, Tian Wang, Jiannong Cao
2026 J jnl
IEEE Internet Things Mag.
Payam Abdisarabshali, Nicholas Accurso, Filippo Malandra, Weifeng Su, Seyyedali Hosseinalipour
2026 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Wenchuan Zhang, Wentao Fan, Weifeng Su, Nizar Bouguila
2026 J jnl
IEEE Trans. Mob. Comput.
Haodong Zou, Jianxiong Guo, Yupeng Li, Wentao Fan, Weifeng Su, Changfu Xu, Yuzhu Liang, Tian Wang, Jiannong Cao
2026 J jnl
CoRR
Xinze Li, Pengxu Chen, Yiyuan Wang, Weifeng Su, Wentao Cheng
2025 conf
MICCAI (10)
Runlin Huang, Hongmin Cai, Weipeng Zhuo, Shangyan Cai, Haowei Lin, Wentao Fan, Weifeng Su
2025 conf
ICONIP (5)
Jiecheng Liao, Ruijie Hu, Junhao Lu, Weifeng Su, Shi He, Yixuan Ji, Liangfu Chen
2025 J jnl
CoRR
Yuqian Wu, Yuhong Peng, Jiapeng Yu, Xiangyu Liu, Zeting Yan, Kang Lin, Weifeng Su, Bingqing Qu, Raymond Lee, Dingqi Yang
2025 J jnl
CoRR
Mingjie Zhao, Zhanpei Huang, Yang Lu, Mengke Li, Yiqun Zhang, Weifeng Su, Yiu-ming Cheung
2025 A conf
ICME
Yuchen Guo, Ruoxiang Xu, Rongcheng Li, Weifeng Su
2025 J jnl
CoRR
Zhongyu Mai, Zewei Zhan, Hanyu Guo, Yulang Huang, Weifeng Su
2025 J jnl
Neural Networks
Zhixiang Li, Zhiwen Luo, Nizar Bouguila, Weifeng Su, Wentao Fan
2025 conf
BIBM
Chen Chen, Weipeng Zhuo, Zhewei Su, Wentao Fan, Hongmin Cai, Weifeng Su
2025 J jnl
CoRR
Ruilang Wang, Shuotong Xu, Bowen Liu, Runlin Huang, Donglong Chen, Weifeng Su
2025 J jnl
Neural Networks
Haowei Lin, Weifeng Su, Runlin Huang, Bo Zhao, Jing Zhao, Wentao Fan
2025 conf
MICCAI (7)
Runlin Huang, Haohui Liang, Hongmin Cai, Weipeng Zhuo, Wentao Fan, Weifeng Su
2025 Misc conf
ICASSP
Wenchuan Zhang, Jie Zhang, Ricky Yuen-Tan Hou, Weifeng Su, Wentao Fan
2025 J jnl
CoRR
Zhongyi Yu, Jianqiu Wu, Zhenghao Wu, Shuhan Zhong, Weifeng Su, Chul-Ho Lee, Weipeng Zhuo
2024 J jnl
CoRR
Yuchen Guo, Ruoxiang Xu, Rongcheng Li, Zhenghao Wu, Weifeng Su
2024 J jnl
CoRR
Payam Abdisarabshali, Kwang Taik Kim, Michael Langberg, Weifeng Su, Seyyedali Hosseinalipour
2024 J jnl
CoRR
Yuchen Guo, Weifeng Su
2024 conf
BIBM
Xinze Li, Runlin Huang, Zhenghao Wu, Bohan Yang, Wentao Fan, Chengzhang Zhu, Weifeng Su
2024 J jnl
CoRR
Xinze Li, Runlin Huang, Zhenghao Wu, Bohan Yang, Wentao Fan, Chengzhang Zhu, Weifeng Su
2024 J jnl
CoRR
Zhongyi Yu, Zhenghao Wu, Shuhan Zhong, Weifeng Su, S.-H. Gary Chan, Chul-Ho Lee, Weipeng Zhuo
2024 conf
MICCAI (3)
Shangyan Cai, Weitian Huang, Weiting Yi, Bin Zhang, Yi Liao, Qiu Wang, Hongmin Cai, Luonan Chen, Weifeng Su
2023 J jnl
BMC Medical Informatics Decis. Mak.
Chao Mao, Quanjing Zhu, Rong Chen, Weifeng Su
2023 J jnl
IEEE Trans. Wirel. Commun.
Jingfu Li, Zehui Xiong, Dusit Niyato, Weifeng Su, Wenjiang Feng, Weiheng Jiang
2023 J jnl
CoRR
Payam Abdisarabshali, Nicholas Accurso, Filippo Malandra, Weifeng Su, Seyyedali Hosseinalipour
2023 J jnl
IEEE Commun. Mag.
Su Wang, Seyyedali Hosseinalipour, Vaneet Aggarwal, Christopher G. Brinton, David J. Love, Weifeng Su, Mung Chiang
2023 J jnl
CoRR
Su Wang, Seyyedali Hosseinalipour, Vaneet Aggarwal, Christopher G. Brinton, David J. Love, Weifeng Su, Mung Chiang
2021 conf
ICANN (5)
Yue Yu, Mutong Wu, Weifeng Su, Yiu-ming Cheung
2021 conf
SmartWorld/SCALCOM/UIC/ATC/IOP/SCI
Zimu Xu, Jiahui Yu, Weifeng Su
2021 conf
ACL/IJCNLP (Findings)
Zhongyi Yu, Zhenghao Wu, Hao Zheng, Zhe Xuanyuan, Jefferson Fong, Weifeng Su
2021 J jnl
CoRR
Zhongyi Yu, Zhenghao Wu, Hao Zheng, Zhe Xuanyuan, Jefferson Fong, Weifeng Su
2019 conf
SemEval@NAACL-HLT
Zhenghao Wu, Hao Zheng, Jianming Wang, Weifeng Su, Jefferson Fong
2019 J jnl
IET Commun.
Azzam Al-Nahari, Hefdhallah Sakran, Weifeng Su, Sami Tarbosh
2019 C conf
IECON
Yan Li, Wei Wang, Bo Yuwen, Sanmin Wei, Weifeng Su, Zhigang Lu
2018 J jnl
IEEE Trans. Signal Process.
Yi Cao, Weifeng Su, Stella N. Batalama
2018 J jnl
Comput. Secur.
Tianqiang Huang, Xueli Zhang, Wei Huang, Lingpeng Lin, Weifeng Su
2017 J jnl
IEEE ACM Trans. Comput. Biol. Bioinform.
Yue Zhang, Yiu-ming Cheung, Bo Xu, Weifeng Su
2017 conf
MILCOM
Ngwe Thawdar, Ulysses Lee, Weifeng Su, Dimitris A. Pados
2017 B conf
WCNC
Kaiying Sun, Weifeng Su, John D. Matyjas, Michael J. Medley
2017 J jnl
IEEE Trans. Wirel. Commun.
Tengda Ying, Wenjiang Feng, Weifeng Su, Weiheng Jiang
2016 conf
MILCOM
Zijian Mo, Weifeng Su, John D. Matyjas
2016 B conf
GLOBECOM
George Sklivanitis, Yi Cao, Stella N. Batalama, Weifeng Su
2016 Misc conf
ICASSP
Yi Cao, Weifeng Su, Stella N. Batalama
2016 J jnl
ACM Trans. Web
Wensheng Wu, Weiyi Meng, Weifeng Su, Guangyou Zhou, Yao-Yi Chiang
2015 J jnl
BMC Bioinform.
Xiaoping Cheng, Hongmin Cai, Yue Zhang, Bo Xu, Weifeng Su
2015 B conf
GLOBECOM
Fuyu Chen, Weifeng Su, Dimitris A. Pados, John D. Matyjas, Michael J. Medley
2014 conf
ICC
Zijian Mo, Weifeng Su, Stella N. Batalama, John D. Matyjas
2014 J jnl
IEEE Trans. Wirel. Commun.
Zijian Mo, Weifeng Su, Stella N. Batalama, John D. Matyjas
2014 conf
ICC
Zijian Mo, Weifeng Su, Stella N. Batalama, John D. Matyjas
2014 conf
ICC
Zijian Mo, Weifeng Su, Stella N. Batalama, John D. Matyjas
2014 conf
WWW (Companion Volume)
Weifeng Su, Yafei Li, Frederick H. Lochovsky
2014 J jnl
Data Knowl. Eng.
Yafei Li, Dingming Wu, Jianliang Xu, Byron Choi, Weifeng Su
2013 J jnl
Enterp. Inf. Syst.
Yunqing Xia, Weifeng Su, Raymond Y. K. Lau, Yi Liu
2013 J jnl
IEEE Wirel. Commun. Lett.
Sandipan Kundu, Weifeng Su, Dimitrios A. Pados, Michael J. Medley
2013 J jnl
IEEE Trans. Wirel. Commun.
Weifeng Su, John D. Matyjas, Michael J. Gans, Stella N. Batalama
2013 J jnl
IEEE Trans. Commun.
Sandipan Kundu, Dimitrios A. Pados, Weifeng Su, Rohan Grover
2013 J jnl
ACM Trans. Web
Weifeng Su, Hejun Wu, Yafei Li, Jing Zhao, Frederick H. Lochovsky, Hongmin Cai, Tianqiang Huang
2012 J jnl
IEEE Trans. Signal Process.
Weifeng Su, John D. Matyjas, Stella N. Batalama
2012 J jnl
IEEE Trans. Knowl. Data Eng.
Weifeng Su, Jiying Wang, Frederick H. Lochovsky, Yi Liu
2012 B conf
GLOBECOM
Fuyu Chen, Weifeng Su, Stella N. Batalama, John D. Matyjas
2012 B conf
WCNC
Sandipan Kundu, Dimitrios A. Pados, Weifeng Su, Rohan Grover
2012 B conf
GLOBECOM
Weifeng Su, John D. Matyjas, Michael J. Gans, Stella N. Batalama
2012 J jnl
EURASIP J. Wirel. Commun. Netw.
Chen He, Xun Chen, Zhen Jane Wang, Weifeng Su
2012 conf
ICC
Sangkook Lee, Weifeng Su, Dimitrios A. Pados, John D. Matyjas
2012 A conf
CIKM
Yafei Li, Dingming Wu, Jianliang Xu, Byron Choi, Weifeng Su
2011 J jnl
Wirel. Pers. Commun.
Weifeng Su, Ahmed K. Sadek, K. J. Ray Liu
2011 J jnl
IEEE J. Sel. Top. Signal Process.
Qinqing Zhang, Sastri Kota, Vincent K. N. Lau, Weifeng Su, Andres Kwasinski
2011 J jnl
IEEE Trans. Signal Process.
Fuyu Chen, Weifeng Su, Stella N. Batalama, John D. Matyjas
2011 B conf
GLOBECOM
Fuyu Chen, Weifeng Su, Stella N. Batalama, John D. Matyjas
2011 J jnl
IEEE Trans. Commun.
Weifeng Su, Sangkook Lee, Dimitrios A. Pados, John D. Matyjas
2011 B conf
GLOBECOM
Sangkook Lee, Weifeng Su, Dimitrios A. Pados, John D. Matyjas
2010 Misc conf
ICASSP
Weifeng Su, John D. Matyjas, Stella N. Batalama
2010 J jnl
IEEE Trans. Wirel. Commun.
Sangkook Lee, Weifeng Su, Stella N. Batalama, John D. Matyjas
2010 J jnl
IEEE Trans. Wirel. Commun.
H. Vicky Zhao, Weifeng Su
2010 Misc conf
ICASSP
H. Vicky Zhao, Weifeng Su
2010 B conf
GLOBECOM
Sandipan Kundu, Weifeng Su, Dimitrios A. Pados, Michael J. Medley
2010 B conf
GLOBECOM
Fuyu Chen, Weifeng Su, Stella N. Batalama, John D. Matyjas
2010 conf
ICEBE
Yunqing Xia, Nianxing Ji, Weifeng Su, Yi Liu
2010 J jnl
IEEE Trans. Commun.
Weifeng Su, Xin Liu
2010 J jnl
IEEE Trans. Inf. Theory
Genyuan Wang, Weifeng Su, Xiang-Gen Xia
2010 Misc conf
ICASSP
Sangkook Lee, Weifeng Su, Stella N. Batalama, John D. Matyjas
2010 J jnl
IEEE Trans. Knowl. Data Eng.
Weifeng Su, Jiying Wang, Frederick H. Lochovsky
2010 B conf
GLOBECOM
Sangkook Lee, Weifeng Su, Dimitrios A. Pados, John D. Matyjas
2010 conf
ICC
Weifeng Su, Sangkook Lee, Dimitrios A. Pados, John D. Matyjas
2010 conf
ICC
Weifeng Su, Fuyu Chen, Dimitrios A. Pados, John D. Matyjas
2009 J jnl
EURASIP J. Adv. Signal Process.
Zhu Han, Guan-Ming Su, Haohong Wang, Song Ci, Weifeng Su
2009 J jnl
ACM Trans. Database Syst.
Weifeng Su, Jiying Wang, Frederick H. Lochovsky
2009 J jnl
IEEE Trans. Inf. Theory
Weifeng Su, Zoltan Safar, K. J. Ray Liu
2009 conf
ADHOCNETS
Sangkook Lee, Weifeng Su, Stella N. Batalama, John D. Matyjas
2008 J jnl
IEEE Trans. Wirel. Commun.
Rohan Grover, Weifeng Su, Dimitrios A. Pados
2008 J jnl
Wirel. Pers. Commun.
Weifeng Su, Ahmed K. Sadek, K. J. Ray Liu
2008 J jnl
IEEE Trans. Wirel. Commun.
Ahmed S. Ibrahim, Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2008 J jnl
IEEE Trans. Signal Process.
Thanongsak Himsoon, W. Pam Siriwongpairat, Weifeng Su, K. J. Ray Liu
2008 J jnl
IEEE Trans. Commun.
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2008 J jnl
IEEE Signal Process. Mag.
Weifeng Su
2007 conf
ICASSP (3)
Xin Liu, Weifeng Su
2007 J jnl
IEEE Trans. Signal Process.
Thanongsak Himsoon, W. Pam Siriwongpairat, Weifeng Su, K. J. Ray Liu
2007 J jnl
IEEE J. Sel. Areas Commun.
K. J. Ray Liu, Weifeng Su, Armin Wittneben
2007 J jnl
IEEE Trans. Signal Process.
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2007 J jnl
IEEE Signal Process. Lett.
Karim G. Seddik, Ahmed K. Sadek, Weifeng Su, Kuo J. Ray Liu
2007 conf
ICASSP (3)
Rohan Grover, Weifeng Su, Dimitrios A. Pados
2007 B conf
GLOBECOM
Weifeng Su
2006 J jnl
EURASIP J. Adv. Signal Process.
Zoltan Safar, Weifeng Su, K. J. Ray Liu
2006 B conf
WISE
Weifeng Su, Jiying Wang, Frederick H. Lochovsky
2006 B conf
WCNC
Thanongsak Himsoon, W. Pam Siriwongpairat, Weifeng Su, K. J. Ray Liu
2006 B conf
WCNC
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2006 J jnl
IEEE Trans. Commun.
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2006 B conf
WCNC
W. Pam Siriwongpairat, Weifeng Su, Zhu Han, K. J. Ray Liu
2006 A* conf
ICDE
Weifeng Su, Jiying Wang, Frederick H. Lochovsky
2006 B conf
EDBT
Weifeng Su, Jiying Wang, Frederick H. Lochovsky
2006 B conf
WCNC
W. Pam Siriwongpairat, Weifeng Su, K. J. Ray Liu
2006 J jnl
IEEE Trans. Signal Process.
W. Pam Siriwongpairat, Weifeng Su, Masoud Olfat, K. J. Ray Liu
2006 J jnl
IEEE Commun. Lett.
Weifeng Su, Stella N. Batalama, Dimitrios A. Pados
2006 J jnl
IEEE Trans. Veh. Technol.
Larry T. Younkins, Weifeng Su, K. J. Ray Liu
2006 B conf
GLOBECOM
Xin Liu, Weifeng Su
2006 B conf
WCNC
W. Pam Siriwongpairat, Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2006 B conf
WCNC
Karim G. Seddik, Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2006 J jnl
IEEE J. Sel. Areas Commun.
W. Pam Siriwongpairat, Weifeng Su, K. J. Ray Liu
2006 A conf
CIKM
Weifeng Su, Jiying Wang, Qiong Huang, Frederick H. Lochovsky
2006 B conf
GLOBECOM
Ahmed S. Ibrahim, Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2006 J jnl
IEEE Trans. Signal Process.
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2005 B conf
GLOBECOM
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2005 B conf
GLOBECOM
Ahmed S. Ibrahim, Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2005 J jnl
IEEE Signal Process. Lett.
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2005 J jnl
IEEE Trans. Commun.
Weifeng Su, K. J. Ray Liu
2005 J jnl
IEEE Signal Process. Lett.
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2005 J jnl
IEEE Trans. Inf. Theory
Weifeng Su, Zoltan Safar, K. J. Ray Liu
2005 B conf
ICTAI
Gang Wang, Weifeng Su, Xiangye Xiao, Frederick H. Lochovsky
2005 B conf
GLOBECOM
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2005 J jnl
Appl. Math. Comput.
Xiaofan Yang, Weifeng Su, Bill Chen, Graham M. Megson, David J. Evans
2005 conf
ICASSP (3)
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2005 B conf
WCNC
Weifeng Su, Ahmed K. Sadek, K. J. Ray Liu
2005 B conf
WCNC
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2005 B conf
WCNC
W. Pam Siriwongpairat, Weifeng Su, Masoud Olfat, K. J. Ray Liu
2004 A* conf
ACL
Dekai Wu, Weifeng Su, Marine Carpuat
2004 conf
ICC
Zoltan Safar, Weifeng Su, K. J. Ray Liu
2004 J jnl
IEEE Commun. Lett.
Weifeng Su, Xiang-Gen Xia, K. J. Ray Liu
2004 conf
SENSEVAL@ACL
Marine Carpuat, Weifeng Su, Dekai Wu
2004 B conf
GLOBECOM
Weifeng Su, K. J. Ray Liu
2004 J jnl
IEEE Trans. Inf. Theory
Weifeng Su, Zoltan Safar, K. J. Ray Liu
2004 B conf
WCNC
Thanongsak Himsoon, Weifeng Su, K. J. Ray Liu
2004 B conf
GLOBECOM
Ahmed K. Sadek, Weifeng Su, K. J. Ray Liu
2004 B conf
WCNC
Larry T. Younkins, Weifeng Su, K. J. Ray Liu
2004 B conf
COLING
Weifeng Su, Marine Carpuat, Dekai Wu
2004 J jnl
IEEE Trans. Inf. Theory
Weifeng Su, Xiang-Gen Xia
2004 B conf
WCNC
Weifeng Su, Xiang-Gen Xia, K. J. Ray Liu
2004 B conf
WCNC
Weifeng Su, Zoltan Safar, K. J. Ray Liu
2004 J jnl
IEEE Trans. Wirel. Commun.
Aijun Song, Genyuan Wang, Weifeng Su, Xiang-Gen Xia
2003 C conf
PACLIC
Shaozi Li, Weifeng Su, Tangqiu Li, Huowang Chen
2003 J jnl
IEEE Trans. Signal Process.
Weifeng Su, Zoltan Safar, Masoud Olfat, K. J. Ray Liu
2003 J jnl
Wirel. Pers. Commun.
Weifeng Su, Xiang-Gen Xia
2003 B conf
GLOBECOM
Genyuan Wang, Weifeng Su, Xiang-Gen Xia
2003 conf
ICC
Weifeng Su, Zoltan Safar, K. J. Ray Liu
2003 J jnl
IEEE Trans. Inf. Theory
Weifeng Su, Xiang-Gen Xia
2002 J jnl
Int. J. Comput. Linguistics Chin. Lang. Process.
Weifeng Su, Shaozi Li, Tanqiu Liu, Wenjian You
2002 B conf
GLOBECOM
Weifeng Su, Xiang-Gen Xia
2001 B conf
SMC
Shao-Zi Li, Weifeng Su, Tangqiu Li
tests/unit/test_decompile_analysis.py
← Index tests/unit/test_decompile_analysis.py python
"""Unit tests (mocked Binary Ninja) for analysis modules:
- bninja/analysis/cfg.py — CFGAnalysis
- bninja/analysis/disassembly.py — DisassemblyAnalysis
- bninja/analysis/low_level.py — LowLevelAnalysis
"""
import sys
import pytest
from unittest.mock import MagicMock

from tests.unit.conftest_binja_stubs import (
    install_binja_stubs,
    BranchType,
    InstructionTextTokenType,
    MockBasicBlock,
    MockEdge,
    MockFunction,
    MockToken,
    MockDisassemblyLine,
    MockBinaryView,
    MockSymbol,
    SymbolType,
    LowLevelILOperation,
)

install_binja_stubs()

from redb.extractors.decompiler.bninja.analysis.cfg import CFGAnalysis
from redb.extractors.decompiler.bninja.analysis.disassembly import DisassemblyAnalysis
from redb.extractors.decompiler.bninja.arch.x86 import Arch_x86


# ============================================================================
# 9a. CFGAnalysis
# ============================================================================


class TestCFGCyclomaticComplexity:
    def test_cyclomatic_complexity_linear(self):
        """Single block, no edges: E - N + 2 = 0 - 1 + 2 = 1."""
        block = MockBasicBlock(start=0x1000, end=0x1010, outgoing_edges=[])
        func = MockFunction(start=0x1000, basic_blocks=[block])
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        assert result["cyclomatic_complexity"] == 1

    def test_cyclomatic_complexity_branch(self):
        """Diamond: 4 blocks, 4 edges -> 4 - 4 + 2 = 2."""
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        true_b = MockBasicBlock(start=0x1010, end=0x1020)
        false_b = MockBasicBlock(start=0x1020, end=0x1030)
        merge = MockBasicBlock(start=0x1030, end=0x1040)

        entry.outgoing_edges = [MockEdge(target=true_b), MockEdge(target=false_b)]
        true_b.outgoing_edges = [MockEdge(target=merge)]
        false_b.outgoing_edges = [MockEdge(target=merge)]
        merge.outgoing_edges = []

        func = MockFunction(start=0x1000, basic_blocks=[entry, true_b, false_b, merge])
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        assert result["cyclomatic_complexity"] == 2

    def test_cyclomatic_complexity_loop(self):
        """Loop: 3 blocks, 3 edges -> 3 - 3 + 2 = 2."""
        header = MockBasicBlock(start=0x1000, end=0x1010)
        body = MockBasicBlock(start=0x1010, end=0x1020)
        exit_b = MockBasicBlock(start=0x1020, end=0x1030)

        header.outgoing_edges = [MockEdge(target=body), MockEdge(target=exit_b)]
        body.outgoing_edges = [MockEdge(target=header)]
        exit_b.outgoing_edges = []

        func = MockFunction(start=0x1000, basic_blocks=[header, body, exit_b])
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        assert result["cyclomatic_complexity"] == 2


class TestCFGExtractFunctionCFG:
    def _make_simple_cfg(self):
        """Create a simple two-block CFG for testing structure."""
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        exit_b = MockBasicBlock(start=0x1010, end=0x1020)

        entry.outgoing_edges = [MockEdge(source=entry, target=exit_b, edge_type=BranchType.UnconditionalBranch)]
        exit_b.incoming_edges = [MockEdge(source=entry, target=exit_b)]
        exit_b.outgoing_edges = []
        entry.incoming_edges = []

        func = MockFunction(start=0x1000, basic_blocks=[entry, exit_b])
        return func

    def test_extract_function_cfg_structure(self):
        func = self._make_simple_cfg()
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        assert "function_address" not in result
        # New schema: no "blocks" or "measures" nesting
        assert "blocks" not in result
        assert "measures" not in result

    def test_function_cfg_new_keys(self):
        """Assert all expected keys are present in the new output dict."""
        func = self._make_simple_cfg()
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        expected_keys = [
            "cfg_topology_hash",
            "block_count",
            "edge_count",
            "llil_total_operations",
            "call_count",
            "cyclomatic_complexity",
            "loop_count",
            "max_depth",
            "max_fan_out",
            "md_index_topdown",
            "md_index_bottomup",
            "prime_product_llil",
            "cfg_feature_tlsh",
            "wl_minhash",
            "bb_features",
            "cfg_adjacency",
        ]
        for key in expected_keys:
            assert key in result, f"Missing key: {key}"

    def test_returns_none_for_empty_blocks(self):
        func = MockFunction(start=0x1000, basic_blocks=[])
        cfg = CFGAnalysis(func)
        assert cfg.extract_function_cfg() is None


class TestCFGTopologyHash:
    def _make_two_block_cfg(self):
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        exit_b = MockBasicBlock(start=0x1010, end=0x1020)
        entry.outgoing_edges = [MockEdge(target=exit_b)]
        exit_b.outgoing_edges = []
        return MockFunction(start=0x1000, basic_blocks=[entry, exit_b])

    def test_topology_hash_is_16_bytes(self):
        func = self._make_two_block_cfg()
        cfg = CFGAnalysis(func)
        result = cfg.extract_function_cfg()
        assert isinstance(result["cfg_topology_hash"], bytes)
        assert len(result["cfg_topology_hash"]) == 16

    def test_topology_hash_deterministic(self):
        func = self._make_two_block_cfg()
        r1 = CFGAnalysis(func).extract_function_cfg()
        r2 = CFGAnalysis(func).extract_function_cfg()
        assert r1["cfg_topology_hash"] == r2["cfg_topology_hash"]


class TestCFGLoopCount:
    def test_no_loops(self):
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        exit_b = MockBasicBlock(start=0x1010, end=0x1020)
        entry.outgoing_edges = [MockEdge(target=exit_b)]
        exit_b.outgoing_edges = []
        func = MockFunction(start=0x1000, basic_blocks=[entry, exit_b])
        result = CFGAnalysis(func).extract_function_cfg()
        assert result["loop_count"] == 0

    def test_single_loop(self):
        header = MockBasicBlock(start=0x1000, end=0x1010)
        body = MockBasicBlock(start=0x1010, end=0x1020)
        exit_b = MockBasicBlock(start=0x1020, end=0x1030)
        header.outgoing_edges = [MockEdge(target=body), MockEdge(target=exit_b)]
        body.outgoing_edges = [MockEdge(target=header)]
        exit_b.outgoing_edges = []
        func = MockFunction(start=0x1000, basic_blocks=[header, body, exit_b])
        result = CFGAnalysis(func).extract_function_cfg()
        assert result["loop_count"] == 1


class TestCFGMaxDepth:
    def test_max_depth_linear(self):
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        b1 = MockBasicBlock(start=0x1010, end=0x1020)
        b2 = MockBasicBlock(start=0x1020, end=0x1030)
        entry.outgoing_edges = [MockEdge(target=b1)]
        b1.outgoing_edges = [MockEdge(target=b2)]
        b2.outgoing_edges = []
        func = MockFunction(start=0x1000, basic_blocks=[entry, b1, b2])
        result = CFGAnalysis(func).extract_function_cfg()
        assert result["max_depth"] == 2

    def test_max_depth_single_block(self):
        block = MockBasicBlock(start=0x1000, end=0x1010, outgoing_edges=[])
        func = MockFunction(start=0x1000, basic_blocks=[block])
        result = CFGAnalysis(func).extract_function_cfg()
        assert result["max_depth"] == 0


class TestCFGCollectBlockLlilOps:
    """Test that _collect_block_llil_ops correctly maps LLIL data to native blocks."""

    def test_llil_fields_nonzero_with_mock_llil(self):
        """When LLIL is available, llil_total_operations and call_count should be non-zero."""
        # Two native blocks
        entry = MockBasicBlock(start=0x1000, end=0x1010)
        exit_b = MockBasicBlock(start=0x1010, end=0x1020)
        entry.outgoing_edges = [MockEdge(target=exit_b)]
        exit_b.outgoing_edges = []

        # LLIL instructions: SET_REG, CALL in first block; STORE, RET in second
        llil_instrs_1 = [
            MockLLILInstruction(LowLevelILOperation.LLIL_SET_REG),
            MockLLILInstruction(LowLevelILOperation.LLIL_CALL),
        ]
        llil_instrs_2 = [
            MockLLILInstruction(LowLevelILOperation.LLIL_STORE),
            MockLLILInstruction(LowLevelILOperation.LLIL_RET),
        ]

        # LLIL basic blocks map back to native blocks via source_block
        llil_bb1 = MockLLILBasicBlock(llil_instrs_1, source_block=entry)
        llil_bb2 = MockLLILBasicBlock(llil_instrs_2, source_block=exit_b)
        llil_func = MockLLILFunction([llil_bb1, llil_bb2])

        func = MockFunction(start=0x1000, basic_blocks=[entry, exit_b], llil=llil_func)
        result = CFGAnalysis(func, llil_function=llil_func).extract_function_cfg()

        assert result["llil_total_operations"] == 4
        assert result["call_count"] == 1
        assert result["prime_product_llil"] != 0

    def test_llil_none_gives_zero_fields(self):
        """Without LLIL, LLIL-dependent fields should be zero."""
        block = MockBasicBlock(start=0x1000, end=0x1010, outgoing_edges=[])
        func = MockFunction(start=0x1000, basic_blocks=[block])
        result = CFGAnalysis(func).extract_function_cfg()

        assert result["llil_total_operations"] == 0
        assert result["call_count"] == 0
        assert result["prime_product_llil"] == 0

    def test_bb_features_with_llil(self):
        """bb_features should reflect LLIL instruction categories when LLIL is available."""
        block = MockBasicBlock(start=0x1000, end=0x1010, outgoing_edges=[])

        llil_instrs = [
            MockLLILInstruction(LowLevelILOperation.LLIL_ADD),
            MockLLILInstruction(LowLevelILOperation.LLIL_LOAD),
            MockLLILInstruction(LowLevelILOperation.LLIL_CALL),
        ]
        llil_bb = MockLLILBasicBlock(llil_instrs, source_block=block)
        llil_func = MockLLILFunction([llil_bb])

        func = MockFunction(start=0x1000, basic_blocks=[block])
        result = CFGAnalysis(func, llil_function=llil_func).extract_function_cfg()

        feats = result["bb_features"]
        assert len(feats) == 1
        assert feats[0][0] == 3  # instruction count = 3
        # At least one non-zero category count (not all OTHER)
        category_counts = feats[0][1:7]
        assert sum(category_counts) > 0


# ============================================================================
# 9b. DisassemblyAnalysis
# ============================================================================


class TestDisassemblyAnalysisGetJson:
    def _make_analysis(self, instructions=None, basic_blocks=None):
        arch = Arch_x86()
        if instructions is None:
            instructions = [
                (
                    [
                        MockToken("push", InstructionTextTokenType.InstructionToken),
                        MockToken(" ", InstructionTextTokenType.TextToken),
                        MockToken("rbp", InstructionTextTokenType.RegisterToken),
                    ],
                    0x1000,
                ),
                (
                    [
                        MockToken("mov", InstructionTextTokenType.InstructionToken),
                        MockToken(" ", InstructionTextTokenType.TextToken),
                        MockToken("rsp", InstructionTextTokenType.RegisterToken),
                    ],
                    0x1003,
                ),
            ]
        if basic_blocks is None:
            basic_blocks = [MockBasicBlock(
                start=0x1000, end=0x1010,
                disassembly_text=[MockDisassemblyLine([MockToken("push rbp")])]
            )]

        func = MockFunction(
            name="test_func",
            start=0x1000,
            basic_blocks=basic_blocks,
            instructions=instructions,
            symbol=MockSymbol(symbol_type=SymbolType.FunctionSymbol, name="test_func"),
            stack_adjustment=MagicMock(value=-8),
            mlil=None,
        )
        bv = MockBinaryView()
        logger = MagicMock()
        return DisassemblyAnalysis(arch, func, bv, logger)

    def test_get_json_basic_structure(self):
        da = self._make_analysis()
        result, errors = da.get_json()
        expected_keys = [
            "disassembled_function_hash",
            "disassembled_function",
            "disassembled_function_no_addresses",
            "disassembled_function_name",
            "disassembled_function_address",
            "instructions_count",
            "function_type",
            "instructions_types",
            "control_flow_count",
            "memory_access_pattern",
            "register_usage",
            "data_references_count",
        ]
        for key in expected_keys:
            assert key in result, f"Missing key: {key}"

    def test_get_json_hash_deterministic(self):
        da = self._make_analysis()
        r1, _ = da.get_json()
        da2 = self._make_analysis()
        r2, _ = da2.get_json()
        assert r1["disassembled_function_hash"] == r2["disassembled_function_hash"]


class TestDisassemblyCollectInstructionTypes:
    def test_collect_instruction_types(self):
        arch = Arch_x86()
        instructions = [
            ([MockToken("MOV", InstructionTextTokenType.InstructionToken)], 0x1000),
            ([MockToken("ADD", InstructionTextTokenType.InstructionToken)], 0x1001),
            ([MockToken("MOV", InstructionTextTokenType.InstructionToken)], 0x1002),
        ]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        types = da.collect_instruction_types()
        assert "DATA_MOVEMENT" in types
        assert "ARITHMETIC" in types

    def test_collect_instruction_types_empty(self):
        arch = Arch_x86()
        func = MockFunction(start=0x1000, instructions=[], symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        types = da.collect_instruction_types()
        assert types == {}


class TestDisassemblyMemoryPatterns:
    def _make_memory_instruction(self, tokens):
        return ([t for t in tokens], 0x1000)

    def test_collect_memory_patterns_stack(self):
        arch = Arch_x86()
        tokens = [
            MockToken("[", InstructionTextTokenType.BeginMemoryOperandToken),
            MockToken("RSP", InstructionTextTokenType.RegisterToken),
            MockToken("+0x8", InstructionTextTokenType.TextToken),
            MockToken("]", InstructionTextTokenType.EndMemoryOperandToken),
        ]
        instructions = [self._make_memory_instruction(tokens)]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        patterns = da.collect_memory_patterns()
        assert "MEM_STACK" in patterns

    def test_collect_memory_patterns_direct(self):
        arch = Arch_x86()
        tokens = [
            MockToken("[", InstructionTextTokenType.BeginMemoryOperandToken),
            MockToken("0x402000", InstructionTextTokenType.TextToken),
            MockToken("]", InstructionTextTokenType.EndMemoryOperandToken),
        ]
        instructions = [self._make_memory_instruction(tokens)]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        patterns = da.collect_memory_patterns()
        assert "MEM_DIRECT" in patterns

    def test_collect_memory_patterns_scaled(self):
        arch = Arch_x86()
        tokens = [
            MockToken("[", InstructionTextTokenType.BeginMemoryOperandToken),
            MockToken("RAX+RCX*4", InstructionTextTokenType.TextToken),
            MockToken("]", InstructionTextTokenType.EndMemoryOperandToken),
        ]
        instructions = [self._make_memory_instruction(tokens)]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        patterns = da.collect_memory_patterns()
        assert "MEM_SCALED_INDEX" in patterns

    def test_collect_memory_patterns_base_offset(self):
        arch = Arch_x86()
        tokens = [
            MockToken("[", InstructionTextTokenType.BeginMemoryOperandToken),
            MockToken("RAX+0x10", InstructionTextTokenType.TextToken),
            MockToken("]", InstructionTextTokenType.EndMemoryOperandToken),
        ]
        instructions = [self._make_memory_instruction(tokens)]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        patterns = da.collect_memory_patterns()
        assert "MEM_BASE_OFFSET" in patterns


class TestDisassemblyRegisterUsage:
    def test_collect_register_usage_gpr(self):
        arch = Arch_x86()
        instructions = [
            ([MockToken("RAX", InstructionTextTokenType.RegisterToken)], 0x1000),
        ]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        regs = da.collect_register_usage()
        assert "GPR" in regs

    def test_collect_register_usage_simd(self):
        arch = Arch_x86()
        instructions = [
            ([MockToken("XMM0", InstructionTextTokenType.RegisterToken)], 0x1000),
        ]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        regs = da.collect_register_usage()
        assert "SIMD" in regs

    def test_collect_register_usage_fpu(self):
        arch = Arch_x86()
        instructions = [
            ([MockToken("ST0", InstructionTextTokenType.RegisterToken)], 0x1000),
        ]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        regs = da.collect_register_usage()
        assert "FPU" in regs


class TestDisassemblyMisc:
    def test_count_data_references(self):
        arch = Arch_x86()
        func = MockFunction(start=0x1000, instructions=[], symbol=MockSymbol(), mlil=None)
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.count_data_references() == 0

    def test_compute_max_block_size(self):
        arch = Arch_x86()
        blocks = [
            MockBasicBlock(disassembly_text=[MockDisassemblyLine([]) for _ in range(3)]),
            MockBasicBlock(disassembly_text=[MockDisassemblyLine([]) for _ in range(5)]),
        ]
        func = MockFunction(start=0x1000, basic_blocks=blocks, instructions=[], symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.compute_max_block_size() == 5

    def test_compute_num_calls(self):
        arch = Arch_x86()
        instructions = [
            ([MockToken("CALL", InstructionTextTokenType.InstructionToken)], 0x1000),
            ([MockToken("MOV", InstructionTextTokenType.InstructionToken)], 0x1005),
            ([MockToken("CALL", InstructionTextTokenType.InstructionToken)], 0x1010),
        ]
        func = MockFunction(start=0x1000, instructions=instructions, symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.compute_num_calls() == 2

    def test_estimate_stack_size_value(self):
        arch = Arch_x86()
        stack = MagicMock()
        stack.value = -16
        func = MockFunction(start=0x1000, instructions=[], symbol=MockSymbol(), stack_adjustment=stack)
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.estimate_stack_size() == -16

    def test_estimate_stack_size_int(self):
        arch = Arch_x86()
        func = MockFunction(start=0x1000, instructions=[], symbol=MockSymbol(), stack_adjustment=-8)
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.estimate_stack_size() == -8

    def test_normalize_opcode(self):
        arch = Arch_x86()
        func = MockFunction(start=0x1000, instructions=[], symbol=MockSymbol())
        da = DisassemblyAnalysis(arch, func, MockBinaryView(), MagicMock())
        assert da.normalize_opcode("mov") == "MOV"
        assert da.normalize_opcode("PUSH") == "PUSH"


# ============================================================================
# 9c. LowLevelAnalysis (basic tests with mocked LLIL)
# ============================================================================


class MockLLILInstruction:
    """Mock LLIL instruction for low_level.py tests."""
    def __init__(self, operation, operands=None, address=0):
        self.operation = operation
        self.operands = operands or []
        self.address = address

    def __str__(self):
        return f"LLIL_{self.operation}"


class MockLLILBasicBlock:
    def __init__(self, instructions, source_block=None):
        self._instructions = instructions
        self.source_block = source_block

    def __iter__(self):
        return iter(self._instructions)


class MockLLILFunction:
    def __init__(self, basic_blocks):
        self.basic_blocks = basic_blocks
        self._instructions = []
        for bb in basic_blocks:
            self._instructions.extend(bb._instructions)

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

    @property
    def source_function(self):
        mock = MagicMock()
        mock.start = 0x1000
        return mock


class TestLowLevelAnalysisCountControlFlow:
    def test_count_control_flow_instructions(self):
        from redb.extractors.decompiler.bninja.analysis.low_level import LowLevelAnalysis
        instrs = [
            MockLLILInstruction(LowLevelILOperation.LLIL_IF),
            MockLLILInstruction(LowLevelILOperation.LLIL_SET_REG),
            MockLLILInstruction(LowLevelILOperation.LLIL_CALL),
            MockLLILInstruction(LowLevelILOperation.LLIL_GOTO),
        ]
        bb = MockLLILBasicBlock(instrs)
        llil_func = MockLLILFunction([bb])

        func = MockFunction(start=0x1000, llil=llil_func, symbol=MockSymbol())
        func.low_level_il = None
        bv = MockBinaryView()
        bv.arch = MagicMock()
        bv.arch.stack_pointer = "sp"
        la = LowLevelAnalysis(func, bv, MagicMock())
        assert la.count_control_flow_instructions() == 3  # IF, CALL, GOTO


class TestLowLevelAnalysisNumCalls:
    def test_compute_num_calls_llil(self):
        from redb.extractors.decompiler.bninja.analysis.low_level import LowLevelAnalysis
        instrs = [
            MockLLILInstruction(LowLevelILOperation.LLIL_CALL),
            MockLLILInstruction(LowLevelILOperation.LLIL_TAILCALL),
            MockLLILInstruction(LowLevelILOperation.LLIL_SET_REG),
        ]
        bb = MockLLILBasicBlock(instrs)
        llil_func = MockLLILFunction([bb])

        func = MockFunction(start=0x1000, llil=llil_func, symbol=MockSymbol())
        func.low_level_il = None
        bv = MockBinaryView()
        la = LowLevelAnalysis(func, bv, MagicMock())
        assert la.compute_num_calls() == 2


class TestLowLevelAnalysisCollectNormalization:
    def test_collect_low_level(self):
        from redb.extractors.decompiler.bninja.analysis.low_level import LowLevelAnalysis
        instrs = [
            MockLLILInstruction(LowLevelILOperation.LLIL_SET_REG, address=0x1000),
            MockLLILInstruction(LowLevelILOperation.LLIL_STORE, address=0x1004),
        ]
        bb = MockLLILBasicBlock(instrs)
        llil_func = MockLLILFunction([bb])

        func = MockFunction(start=0x1000, llil=llil_func, symbol=MockSymbol())
        func.low_level_il = None
        bv = MockBinaryView()
        la = LowLevelAnalysis(func, bv, MagicMock())
        result, _ = la._collect_low_level_and_with_addr()
        assert len(result) == 2
        # Each item is a list of operation ints
        assert isinstance(result[0], list)

    def test_collect_low_level_with_addr_offset_clamping(self):
        from redb.extractors.decompiler.bninja.analysis.low_level import LowLevelAnalysis
        instrs = [
            MockLLILInstruction(LowLevelILOperation.LLIL_SET_REG, address=0x0FFF),  # Before function start
        ]
        bb = MockLLILBasicBlock(instrs)
        llil_func = MockLLILFunction([bb])

        func = MockFunction(start=0x1000, llil=llil_func, symbol=MockSymbol())
        func.low_level_il = None
        bv = MockBinaryView()
        la = LowLevelAnalysis(func, bv, MagicMock())
        _, result = la._collect_low_level_and_with_addr()
        assert len(result) == 1
        offset, _ = result[0]
        assert offset == 0  # Clamped to 0