Haiping Ma

126 papers A* 25A 7B 3C 2Journal 77Unranked 12
YearRankTypeTitle / Venue / Authors
2026 J jnl
Pattern Recognit.
Haiping Ma, Jiyuan Huang, Chenxu Shen, Jin Liu, Qingming Liu
2026 J jnl
Swarm Evol. Comput.
Haiping Ma, Jin Liu, Jiajun Li, Junhan Jia
2026 conf
KDD (1)
Ziwen Wang, Shangshang Yang, Xiaoshan Yu, Haiping Ma, Xingyi Zhang
2026 J jnl
CoRR
Ziwen Wang, Shangshang Yang, Xiaoshan Yu, Haiping Ma, Xingyi Zhang
2026 J jnl
Inf. Process. Manag.
Huiting Liu, Yao Quan, Zirui Wang, Haiping Ma, Xindong Wu
2026 A* conf
AAAI
Shangshang Yang, Xuewen Duan, Xiaoshan Yu, Ziwen Wang, Haiping Ma, Xingyi Zhang
2026 J jnl
Trans. Inst. Meas. Control
Haiping Ma, Ting Liu, Yajing Zhang, Minrui Fei, Huiyu Zhou
2026 A* conf
AAAI
Xiaoshan Yu, Ziwei Huang, Shangshang Yang, Ziwen Wang, Haiping Ma, Xingyi Zhang
2026 J jnl
ACM Trans. Intell. Syst. Technol.
Ziwen Wang, Jingyuan Wang, Haiping Ma, Hengshu Zhu, Shangshang Yang, Xiaoshan Yu, Shuhuan Liu, Haifeng Zhang, Xingyi Zhang
2026 J jnl
Expert Syst. Appl.
Haiping Ma, Junhan Jia, Jiajun Li, Baogen Jin, Zheheng Jiang
2026 J jnl
CoRR
Xiaoshan Yu, Shangshang Yang, Ziwen Wang, Haiping Ma, Xingyi Zhang
2025 J jnl
Complex Intell. Syst.
Qijun Wang, Chunxin Sang, Haiping Ma, Chao Wang
2025 A* conf
AAAI
Haiping Ma, Yue Yao, Changqian Wang, Siyu Song, Yong Yang
2025 J jnl
IEEE Trans. Evol. Comput.
Shangshang Yang, Haiping Ma, Ying Bi, Ye Tian, Limiao Zhang, Yaochu Jin, Xingyi Zhang
2025 J jnl
IEEE Trans. Artif. Intell.
Ye Tian, Luke Ji, Yiwei Hu, Haiping Ma, Le Wu, Xingyi Zhang
2025 conf
KDD (1)
Haiping Ma, Aoqing Xia, Changqian Wang, Hai Wang, Xingyi Zhang
2025 A* conf
IJCAI
Shangshang Yang, Linrui Qin, Xiaoshan Yu, Ziwen Wang, Xueming Yan, Haiping Ma, Ye Tian
2025 A* conf
AAAI
Changqian Wang, Shangshang Yang, Siyu Song, Ziwen Wang, Haiping Ma, Xingyi Zhang, Bo Jin
2025 conf
BESC (3)
Tianle Li, Hai Wang, Haiping Ma
2025 J jnl
CoRR
Shangshang Yang, Jialin Han, Xiaoshan Yu, Ziwen Wang, Hao Jiang, Haiping Ma, Xingyi Zhang, Geyong Min
2025 J jnl
ACM Trans. Manag. Inf. Syst.
Haiping Ma, Manwei Li, Chuan Qin, Dazhong Shen, Hengshu Zhu, Xingyi Zhang, Hui Xiong
2025 A* conf
SIGIR
Xiaoshan Yu, Shangshang Yang, Ziwen Wang, Siyu Song, Haiping Ma, Zhiguang Cao, Xingyi Zhang
2025 conf
KDD (2)
Haiping Ma, Yi Yin, Ziwen Wang, Changqian Wang, Xiaoshan Yu, Shangshang Yang, Xingyi Zhang
2025 J jnl
CoRR
Xiaoshan Yu, Ziwei Huang, Shangshang Yang, Ziwen Wang, Haiping Ma, Xingyi Zhang
2025 A* conf
SIGIR
Haiping Ma, Weiyuan Zhou, Xiaoshan Yu, Changqian Wang, Shangshang Yang, Limiao Zhang, Xingyi Zhang
2025 conf
KDD (2)
Xiaoshan Yu, Shangshang Yang, Jian Li, Ziwen Wang, Chuan Qin, Haiping Ma, Xingyi Zhang
2025 J jnl
Pattern Recognit.
Haiping Ma, Jiyuan Huang, Chenxu Shen, Zheheng Jiang
2025 A* conf
WWW
Limiao Zhang, Xinyang Qi, Haiping Ma, Jie Gao, Xingyi Zhang, Yanqing Hu, Yaochu Jin
2024 A* conf
IJCAI
Haiping Ma, Siyu Song, Chuan Qin, Xiaoshan Yu, Limiao Zhang, Xingyi Zhang, Hengshu Zhu
2024 A* conf
ICDM
Xiaoshan Yu, Chuan Qin, Qi Zhang, Chen Zhu, Haiping Ma, Xingyi Zhang, Hengshu Zhu
2024 J jnl
CoRR
Xiaoshan Yu, Chuan Qin, Qi Zhang, Chen Zhu, Haiping Ma, Xingyi Zhang, Hengshu Zhu
2024 J jnl
CoRR
Haiping Ma, Aoqing Xia, Changqian Wang, Hai Wang, Xingyi Zhang
2024 A* conf
NeurIPS
Shangshang Yang, Mingyang Chen, Ziwen Wang, Xiaoshan Yu, Panpan Zhang, Haiping Ma, Xingyi Zhang
2024 J jnl
CoRR
Shangshang Yang, Mingyang Chen, Ziwen Wang, Xiaoshan Yu, Panpan Zhang, Haiping Ma, Xingyi Zhang
2024 A* conf
AAAI
Haiping Ma, Changqian Wang, Hengshu Zhu, Shangshang Yang, Xiaoming Zhang, Xingyi Zhang
2024 A* conf
WWW
Haiping Ma, Yong Yang, Chuan Qin, Xiaoshan Yu, Shangshang Yang, Xingyi Zhang, Hengshu Zhu
2024 J jnl
Evol. Intell.
Haiping Ma, Shengyi Sun, Dawei Du, Dan Simon
2024 J jnl
ACM Trans. Intell. Syst. Technol.
Haoyang Bi, Qi Liu, Han Wu, Weidong He, Zhenya Huang, Yu Yin, Haiping Ma, Yu Su, Shijin Wang, Enhong Chen
2024 J jnl
IEEE Trans. Emerg. Top. Comput. Intell.
Dayu Tan, Zhiyuan Yao, Xin Peng, Haiping Ma, Yike Dai, Yansen Su, Weimin Zhong
2024 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Yajie Zhang, Hao Jiang, Ye Tian, Haiping Ma, Xingyi Zhang
2024 J jnl
IEEE Trans. Knowl. Data Eng.
Xiaoshan Yu, Chuan Qin, Dazhong Shen, Haiping Ma, Le Zhang, Xingyi Zhang, Hengshu Zhu, Hui Xiong
2024 A* conf
KDD
Xiaoshan Yu, Chuan Qin, Dazhong Shen, Shangshang Yang, Haiping Ma, Hengshu Zhu, Xingyi Zhang
2024 J jnl
CoRR
Xiaoshan Yu, Chuan Qin, Dazhong Shen, Shangshang Yang, Haiping Ma, Hengshu Zhu, Xingyi Zhang
2024 J jnl
CoRR
Yunfei Zhang, Chuan Qin, Dazhong Shen, Haiping Ma, Le Zhang, Xingyi Zhang, Hengshu Zhu
2024 J jnl
CoRR
Qi Liu, Yan Zhuang, Haoyang Bi, Zhenya Huang, Weizhe Huang, Jiatong Li, Junhao Yu, Zirui Liu, Zirui Hu, Yuting Hong, Zachary A. Pardos, Haiping Ma, Mengxiao Zhu, Shijin Wang, Enhong Chen
2024 J jnl
IEEE Signal Process. Lett.
Haiping Ma, Jiuyi Yao, Jiyuan Huang, Weijia Zhang, Zheheng Jiang
2024 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Yajing Zhang, Shengyi Sun, Weijia Zhang, Minrui Fei, Huiyu Zhou
2023 J jnl
J. Comput. Sci. Technol.
Jia-Yu Liu, Fei Wang, Haiping Ma, Zhenya Huang, Qi Liu, En-Hong Chen, Yu Su
2023 J jnl
IEEE Trans. Comput. Soc. Syst.
Lei Zhang, Kaicong Ma, Haipeng Yang, Cheng Zhang, Haiping Ma, Qi Liu
2023 J jnl
Artif. Intell. Rev.
Haiping Ma, Yajing Zhang, Shengyi Sun, Ting Liu, Yu Shan
2023 J jnl
Complex Intell. Syst.
Haiping Ma, Yi Zeng, Shangshang Yang, Chuan Qin, Xingyi Zhang, Limiao Zhang
2023 J jnl
Swarm Evol. Comput.
Ye Tian, Jiaxing Hu, Cheng He, Haiping Ma, Limiao Zhang, Xingyi Zhang
2023 conf
ICSI (1)
Xiaoshu Xiang, Ling Wu, Haiping Ma, Xingyi Zhang
2023 J jnl
IEEE Trans. Emerg. Top. Comput. Intell.
Shangshang Yang, Haoyu Wei, Haiping Ma, Ye Tian, Xingyi Zhang, Yunbo Cao, Yaochu Jin
2023 J jnl
IEEE Trans. Emerg. Top. Comput. Intell.
Ye Tian, Xiaopeng Li, Haiping Ma, Xingyi Zhang, Kay Chen Tan, Yaochu Jin
2023 J jnl
CoRR
Shangshang Yang, Haiping Ma, Cheng Zhen, Ye Tian, Limiao Zhang, Yaochu Jin, Xingyi Zhang
2023 J jnl
CoRR
Haiping Ma, Changqian Wang, Hengshu Zhu, Shangshang Yang, Xiaoming Zhang, Xingyi Zhang
2023 A* conf
NeurIPS
Shangshang Yang, Xiaoshan Yu, Ye Tian, Xueming Yan, Haiping Ma, Xingyi Zhang
2023 J jnl
CoRR
Shangshang Yang, Xiaoshan Yu, Ye Tian, Xueming Yan, Haiping Ma, Xingyi Zhang
2023 A conf
CIKM
Shuhuan Liu, Xiaoshan Yu, Haiping Ma, Ziwen Wang, Chuan Qin, Xingyi Zhang
2023 J jnl
IEEE Signal Process. Lett.
Haiping Ma, Shengyi Sun, Senggang Ye, Zheheng Jiang
2023 conf
RICAI
Yulin Li, Weijia Zhang, Haiping Ma, Feiyu Chen, Dongqin Sun, Xue Cheng, Yuan Zheng, Zhaowei Wang, Shaomin Cai
2023 A* conf
ICDM
Yunfei Zhang, Chuan Qin, Dazhong Shen, Haiping Ma, Le Zhang, Xingyi Zhang, Hengshu Zhu
2023 J jnl
CoRR
Feiyu Chen, Haiping Ma, Weijia Zhang
2022 A conf
CIKM
Haiping Ma, Jinwei Zhu, Shangshang Yang, Qi Liu, Haifeng Zhang, Xingyi Zhang, Yunbo Cao, Xuemin Zhao
2022 J jnl
IEEE Trans. Evol. Comput.
Hongke Zhao, Xinpeng Wu, Chuang Zhao, Lei Zhang, Haiping Ma, Fan Cheng
2022 A* conf
AAAI
Yan Zhuang, Qi Liu, Zhenya Huang, Zhi Li, Shuanghong Shen, Haiping Ma
2022 J jnl
IEEE CAA J. Autom. Sinica
Ye Tian, Haowen Chen, Haiping Ma, Xingyi Zhang, Kay Chen Tan, Yaochu Jin
2022 A conf
CIKM
Haiping Ma, Manwei Li, Le Wu, Haifeng Zhang, Yunbo Cao, Xingyi Zhang, Xuemin Zhao
2022 J jnl
Soft Comput.
Haiping Ma, Yu Shan, Jinglin Wang, Xiaolei Chen, Zhile Yang, Dan Simon
2022 A* conf
IJCAI
Haiping Ma, Jingyuan Wang, Hengshu Zhu, Xin Xia, Haifeng Zhang, Xingyi Zhang, Lei Zhang
2022 J jnl
Pattern Recognit.
Long Chen, Feixiang Zhou, Shengke Wang, Junyu Dong, Ning Li, Haiping Ma, Xin Wang, Huiyu Zhou
2021 J jnl
IEEE Trans. Evol. Comput.
Ye Tian, Ruchen Liu, Xingyi Zhang, Haiping Ma, Kay Chen Tan, Yaochu Jin
2021 J jnl
Complex.
Yanhui Zhang, Shili Lin, Haiping Ma, Yuanjun Guo, Wei Feng
2021 J jnl
Neural Comput. Appl.
Haiping Ma, Haipeng Yang, Kefei Zhou, Lei Zhang, Xingyi Zhang
2021 J jnl
Inf. Sci.
Haiping Ma, Haoyu Wei, Ye Tian, Ran Cheng, Xingyi Zhang
2021 J jnl
Knowl. Based Syst.
Haiping Ma, Zhenjie Liu, Xingyi Zhang, Lei Zhang, Hao Jiang
2021 A conf
WSDM
Jinze Wu, Zhenya Huang, Qi Liu, Defu Lian, Hao Wang, Enhong Chen, Haiping Ma, Shijin Wang
2021 A* conf
SIGIR
Shuai Wang, Kun Zhang, Le Wu, Haiping Ma, Richang Hong, Meng Wang
2021 J jnl
CoRR
Shuai Wang, Kun Zhang, Le Wu, Haiping Ma, Richang Hong, Meng Wang
2021 J jnl
CoRR
Haoyang Bi, Haiping Ma, Zhenya Huang, Yu Yin, Qi Liu, Enhong Chen, Yu Su, Shijin Wang
2020 J jnl
IEEE Trans. Cybern.
Haiping Ma, Minrui Fei, Zheheng Jiang, Ling Li, Huiyu Zhou, Danny Crookes
2020 B conf
CEC
Lei Zhang, Fengiiao Sun, Fan Cheng, Haiping Ma, Xiaoyan Sun
2020 A* conf
SIGIR
Shuanghong Shen, Qi Liu, Enhong Chen, Han Wu, Zhenya Huang, Weihao Zhao, Yu Su, Haiping Ma, Shijin Wang
2020 conf
NCAA
Tianyu Hu, Lidong Zhang, Zhile Yang, Yuanjun Guo, Haiping Ma
2020 J jnl
ACM Trans. Inf. Syst.
Zhenya Huang, Qi Liu, Yuying Chen, Le Wu, Keli Xiao, Enhong Chen, Haiping Ma, Guoping Hu
2020 J jnl
Frontiers Comput. Sci.
Ming He, Hao Guo, Guangyi Lv, Le Wu, Yong Ge, Enhong Chen, Haiping Ma
2020 J jnl
Complex.
Haiping Ma, Chao Sun, Jinglin Wang, Zhile Yang, Huiyu Zhou
2020 A* conf
ICDM
Haoyang Bi, Haiping Ma, Zhenya Huang, Yu Yin, Qi Liu, Enhong Chen, Yu Su, Shijin Wang
2020 J jnl
CoRR
Long Chen, Feixiang Zhou, Shengke Wang, Junyu Dong, Ning Li, Haiping Ma, Xin Wang, Huiyu Zhou
2020 A* conf
ICDM
Shiwei Tong, Qi Liu, Wei Huang, Zhenya Huang, Enhong Chen, Chuanren Liu, Haiping Ma, Shijin Wang
2019 J jnl
IEEE Trans. Image Process.
Zheheng Jiang, Danny Crookes, Brian Desmond Green, Yunfeng Zhao, Haiping Ma, Ling Li, Shengping Zhang, Dacheng Tao, Huiyu Zhou
2019 A conf
CIKM
Song Cheng, Qi Liu, Enhong Chen, Zai Huang, Zhenya Huang, Yiying Chen, Haiping Ma, Guoping Hu
2019 A* conf
KDD
Qi Liu, Shiwei Tong, Chuanren Liu, Hongke Zhao, Enhong Chen, Haiping Ma, Shijin Wang
2019 J jnl
CoRR
Qi Liu, Shiwei Tong, Chuanren Liu, Hongke Zhao, Enhong Chen, Haiping Ma, Shijin Wang
2019 J jnl
Swarm Evol. Comput.
Haiping Ma, Shigen Shen, Mei Yu, Zhile Yang, Minrui Fei, Huiyu Zhou
2018 conf
ICSI (1)
Zhile Yang, Qun Niu, Yuanjun Guo, Haiping Ma, Boyang Qu
2018 B conf
CEC
Zhile Yang, Yuanjun Guo, Qun Niu, Haiping Ma, Yimin Zhou, Li Zhang
2018 J jnl
Knowl. Based Syst.
Zhile Yang, Kang Li, Yuanjun Guo, Haiping Ma, Min Zheng
2018 J jnl
Complex.
Yadong Yu, Haiping Ma, Mei Yu, Sengang Ye, Xiaolei Chen
2017 J jnl
J. Netw. Comput. Appl.
Shigen Shen, Haiping Ma, En Fan, Keli Hu, Shui Yu, Jianhua Liu, Qiying Cao
2017 A conf
CIKM
Zai Huang, Zhen Pan, Qi Liu, Bai Long, Haiping Ma, Enhong Chen
2017 J jnl
IEEE Trans. Emerg. Top. Comput. Intell.
Haiping Ma, Dan Simon, Patrick Siarry, Zhile Yang, Minrui Fei
2017 J jnl
Soft Comput.
Haiping Ma, Sengang Ye, Dan Simon, Minrui Fei
2017 J jnl
IEEE Trans. Syst. Man Cybern. Syst.
Haiping Ma, Dan Simon, Minrui Fei, Hongwei Mo
2017 conf
LSMS/ICSEE (3)
Haiping Ma, Pengcheng You, Kailong Liu, Zhile Yang, Minrui Fei
2016 J jnl
Neurocomputing
Haiping Ma, Minrui Fei, Zhile Yang
2016 A* conf
ICDM
Zhen Pan, Enhong Chen, Qi Liu, Tong Xu, Haiping Ma, Hongjie Lin
2016 J jnl
Evol. Comput.
Haiping Ma, Dan Simon, Minrui Fei
2015 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Shufei Su, Dan Simon, Minrui Fei
2015 C conf
KSEM
Yifan Sun, Xin Li, Lin Li, Qi Liu, Enhong Chen, Haiping Ma
2014 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Dan Simon, Minrui Fei, Xinzhan Shu, Zixiang Chen
2013 J jnl
Int. J. Inf. Technol. Decis. Mak.
Qi Liu, Haiping Ma, Enhong Chen, Hui Xiong
2013 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Dan Simon, Minrui Fei, Zixiang Chen
2013 C conf
CIS
Ting Jin, Tong Xu, Enhong Chen, Qi Liu, Haiping Ma, Jingsong Lv, Guoping Hu
2013 J jnl
Inf. Sci.
Haiping Ma, Dan Simon, Minrui Fei, Zhikun Xie
2012 A* conf
WWW
Haiping Ma, Huanhuan Cao, Qiang Yang, Enhong Chen, Jilei Tian
2012 B conf
IEEE Congress on Evolutionary Computation
Haiping Ma, Minrui Fei, Zhiguo Ding, Jing Jin
2012 J jnl
Neurocomputing
Haiping Ma, Enhong Chen, Linli Xu, Hui Xiong
2011 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Dan Simon
2011 J jnl
Eng. Appl. Artif. Intell.
Haiping Ma, Dan Simon
2011 J jnl
Inf. Process. Manag.
Enhong Chen, Yanggang Lin, Hui Xiong, Qiming Luo, Haiping Ma
2010 J jnl
Inf. Sci.
Haiping Ma
2010 A conf
GECCO
Haiping Ma, Dan Simon
2009 conf
CDC
Man Sun, Suhong Ni, Haiping Ma
2009 conf
CDC
Haiping Ma, Suhong Ni, Man Sun
tests/unit/test_cfg_features.py
← Index tests/unit/test_cfg_features.py python
"""
Unit tests for cfg_features.py — all new CFG feature computations.

These tests use plain Python data structures (index-based adjacency lists)
and require no Binary Ninja dependency.
"""
import pytest

from redb.extractors.decompiler.bninja.analysis.cfg_features import (
    bfs_order,
    bfs_max_depth,
    count_back_edges,
    compute_topology_hash,
    compute_md_index_topdown,
    compute_md_index_bottomup,
    compute_prime_product,
    build_block_features,
    compute_cfg_feature_tlsh,
    compute_wl_minhash,
    pack_adjacency,
    LLIL_OP_CATEGORIES,
    CAT_ARITHMETIC,
    CAT_LOGIC,
    CAT_CALL,
    CAT_MEMORY,
    NUM_WL_MINHASH_PERMS,
)


# ===================================================================
# Helper: common graph topologies
# ===================================================================

def _linear_chain(n):
    """0 -> 1 -> 2 -> ... -> (n-1)"""
    return [[i + 1] if i < n - 1 else [] for i in range(n)]


def _diamond():
    """
    0 -> 1, 0 -> 2, 1 -> 3, 2 -> 3
    (classic if/else diamond)
    """
    return [[1, 2], [3], [3], []]


def _predecessors_from_successors(successors, n):
    preds = [[] for _ in range(n)]
    for src, targets in enumerate(successors):
        for tgt in targets:
            preds[tgt].append(src)
    return preds


# ===================================================================
# TestBfsOrder
# ===================================================================

class TestBfsOrder:
    def test_empty_graph(self):
        assert bfs_order([], 0) == []

    def test_single_node(self):
        assert bfs_order([[]], 1) == [0]

    def test_linear_chain(self):
        succs = _linear_chain(4)
        assert bfs_order(succs, 4) == [0, 1, 2, 3]

    def test_diamond(self):
        succs = _diamond()
        order = bfs_order(succs, 4)
        assert order[0] == 0
        assert order[-1] == 3
        assert set(order) == {0, 1, 2, 3}

    def test_unreachable_nodes(self):
        # 0 -> 1, node 2 is unreachable
        succs = [[1], [], []]
        order = bfs_order(succs, 3)
        assert order[:2] == [0, 1]
        assert 2 in order  # unreachable appended

    def test_all_nodes_visited(self):
        succs = _diamond()
        order = bfs_order(succs, 4)
        assert len(order) == 4


# ===================================================================
# TestBfsMaxDepth
# ===================================================================

class TestBfsMaxDepth:
    def test_empty_graph(self):
        assert bfs_max_depth([], 0) == 0

    def test_single_block(self):
        assert bfs_max_depth([[]], 1) == 0

    def test_linear_chain(self):
        succs = _linear_chain(5)
        assert bfs_max_depth(succs, 5) == 4

    def test_diamond(self):
        succs = _diamond()
        assert bfs_max_depth(succs, 4) == 2

    def test_wide_graph(self):
        # 0 -> 1, 0 -> 2, 0 -> 3 (all at depth 1)
        succs = [[1, 2, 3], [], [], []]
        assert bfs_max_depth(succs, 4) == 1


# ===================================================================
# TestCountBackEdges
# ===================================================================

class TestCountBackEdges:
    def test_empty_graph(self):
        assert count_back_edges([], 0) == 0

    def test_no_loops(self):
        succs = _linear_chain(3)
        assert count_back_edges(succs, 3) == 0

    def test_single_loop(self):
        # 0 -> 1 -> 2 -> 0 (one back edge: 2->0)
        succs = [[1], [2], [0]]
        assert count_back_edges(succs, 3) == 1

    def test_nested_loops(self):
        # 0 -> 1 -> 2 -> 1 (inner), 2 -> 3 -> 0 (outer)
        succs = [[1], [2], [1, 3], [0]]
        assert count_back_edges(succs, 4) == 2

    def test_self_loop(self):
        # 0 -> 0 (self-loop)
        succs = [[0]]
        assert count_back_edges(succs, 1) == 1

    def test_diamond_no_loops(self):
        succs = _diamond()
        assert count_back_edges(succs, 4) == 0

    def test_single_node_no_loop(self):
        succs = [[]]
        assert count_back_edges(succs, 1) == 0


# ===================================================================
# TestTopologyHash
# ===================================================================

class TestTopologyHash:
    def test_same_graph_same_hash(self):
        succs = _diamond()
        bfs = bfs_order(succs, 4)
        h1 = compute_topology_hash(succs, bfs, 4)
        h2 = compute_topology_hash(succs, bfs, 4)
        assert h1 == h2

    def test_different_graphs_different_hash(self):
        succs1 = _linear_chain(3)
        bfs1 = bfs_order(succs1, 3)
        h1 = compute_topology_hash(succs1, bfs1, 3)

        succs2 = _diamond()
        bfs2 = bfs_order(succs2, 4)
        h2 = compute_topology_hash(succs2, bfs2, 4)

        assert h1 != h2

    def test_returns_16_bytes(self):
        succs = _diamond()
        bfs = bfs_order(succs, 4)
        h = compute_topology_hash(succs, bfs, 4)
        assert isinstance(h, bytes)
        assert len(h) == 16

    def test_isomorphic_graphs_same_hash(self):
        # Graph A: 0->1, 0->2, 1->3, 2->3 (diamond with successors [1,2])
        succs_a = [[1, 2], [3], [3], []]
        # Graph B: same structure but successors listed as [2,1]
        # BFS from 0 will visit them in different order, but after remapping
        # the canonical form should be identical for isomorphic graphs
        succs_b = [[2, 1], [3], [3], []]

        bfs_a = bfs_order(succs_a, 4)
        bfs_b = bfs_order(succs_b, 4)

        h_a = compute_topology_hash(succs_a, bfs_a, 4)
        h_b = compute_topology_hash(succs_b, bfs_b, 4)
        assert h_a == h_b

    def test_empty_graph(self):
        h = compute_topology_hash([], [], 0)
        assert h == b'\x00' * 16

    def test_single_node(self):
        succs = [[]]
        bfs = bfs_order(succs, 1)
        h = compute_topology_hash(succs, bfs, 1)
        assert isinstance(h, bytes)
        assert len(h) == 16


# ===================================================================
# TestMdIndex
# ===================================================================

class TestMdIndex:
    def test_single_block_topdown(self):
        succs = [[]]
        preds = [[]]
        bfs = [0]
        result = compute_md_index_topdown(succs, preds, bfs)
        assert isinstance(result, int)
        assert result > 0

    def test_single_block_bottomup(self):
        succs = [[]]
        preds = [[]]
        result = compute_md_index_bottomup(succs, preds, 1)
        assert isinstance(result, int)
        assert result > 0

    def test_linear_chain_topdown_vs_bottomup(self):
        succs = _linear_chain(4)
        preds = _predecessors_from_successors(succs, 4)
        bfs = bfs_order(succs, 4)
        td = compute_md_index_topdown(succs, preds, bfs)
        bu = compute_md_index_bottomup(succs, preds, 4)
        # Top-down and bottom-up should be different for a linear chain
        # (entry has in_deg=0, exit has out_deg=0, so the sequences differ)
        assert td != bu

    def test_deterministic(self):
        succs = _diamond()
        preds = _predecessors_from_successors(succs, 4)
        bfs = bfs_order(succs, 4)
        td1 = compute_md_index_topdown(succs, preds, bfs)
        td2 = compute_md_index_topdown(succs, preds, bfs)
        assert td1 == td2

    def test_different_graphs_different_index(self):
        succs1 = _linear_chain(3)
        preds1 = _predecessors_from_successors(succs1, 3)
        bfs1 = bfs_order(succs1, 3)
        td1 = compute_md_index_topdown(succs1, preds1, bfs1)

        succs2 = _diamond()
        preds2 = _predecessors_from_successors(succs2, 4)
        bfs2 = bfs_order(succs2, 4)
        td2 = compute_md_index_topdown(succs2, preds2, bfs2)

        assert td1 != td2

    def test_topdown_empty(self):
        assert compute_md_index_topdown([], [], []) == 0

    def test_bottomup_empty(self):
        assert compute_md_index_bottomup([], [], 0) == 0


# ===================================================================
# TestPrimeProduct
# ===================================================================

class TestPrimeProduct:
    def test_empty(self):
        assert compute_prime_product([]) == 0

    def test_known_sequence(self):
        # Use actual LLIL enum values from conftest_binja_stubs:
        # LLIL_NOP=0 -> prime 1, LLIL_LOAD=4 -> prime 5
        from redb.extractors.decompiler.bninja.analysis.cfg_features import LLIL_OP_PRIMES
        nop_val = 0   # LLIL_NOP
        load_val = 4  # LLIL_LOAD
        expected = LLIL_OP_PRIMES.get(nop_val, 1) * LLIL_OP_PRIMES.get(load_val, 1)
        result = compute_prime_product([nop_val, load_val])
        assert result == expected

    def test_order_independence(self):
        # LLIL_LOAD=4, LLIL_STORE=5, LLIL_ADD=13
        ops_a = [4, 5, 13]
        ops_b = [13, 4, 5]
        assert compute_prime_product(ops_a) == compute_prime_product(ops_b)

    def test_unknown_ops_map_to_1(self):
        # Unknown ops get prime 1, so they don't change the product
        result_known = compute_prime_product([4])  # LLIL_LOAD -> 5
        result_with_unknown = compute_prime_product([4, 9999])  # LOAD * unknown(1)
        assert result_known == result_with_unknown

    def test_mod_2_64(self):
        # Product should be mod 2^64
        result = compute_prime_product([4] * 1000)  # LLIL_LOAD
        assert 0 <= result < 2**64

    def test_single_op(self):
        # LLIL_STORE=5 -> prime 7
        assert compute_prime_product([5]) == 7


# ===================================================================
# TestBuildBlockFeatures
# ===================================================================

class TestBuildBlockFeatures:
    def test_empty_llil(self):
        succs = [[1], []]
        features = build_block_features([[], []], succs, 2)
        assert len(features) == 2
        # All zeros except successor_count
        assert features[0] == [0, 0, 0, 0, 0, 0, 0, 1]  # 1 successor
        assert features[1] == [0, 0, 0, 0, 0, 0, 0, 0]  # 0 successors

    def test_correct_categorization(self):
        # Set up categories for testing
        import redb.extractors.decompiler.bninja.analysis.cfg_features as cf
        old_cats = cf.LLIL_OP_CATEGORIES.copy()
        cf.LLIL_OP_CATEGORIES.update({
            100: CAT_ARITHMETIC,
            101: CAT_ARITHMETIC,
            200: CAT_LOGIC,
            300: CAT_CALL,
            400: CAT_MEMORY,
        })
        try:
            block_ops = [[100, 101, 200, 300, 400]]
            succs = [[]]
            features = build_block_features(block_ops, succs, 1)
            assert features[0][0] == 5   # instr_count
            assert features[0][1] == 2   # arithmetic
            assert features[0][2] == 1   # logic
            assert features[0][4] == 1   # call
            assert features[0][6] == 1   # memory
        finally:
            cf.LLIL_OP_CATEGORIES.clear()
            cf.LLIL_OP_CATEGORIES.update(old_cats)

    def test_cap_at_65535(self):
        # More than 65535 ops in one block
        huge_ops = [0] * 70000  # NOP x 70000
        succs = [[]]
        features = build_block_features([huge_ops], succs, 1)
        assert features[0][0] == 65535  # capped

    def test_missing_block_ops(self):
        # block_llil_ops shorter than n
        succs = [[1], [2], []]
        features = build_block_features([[1, 2]], succs, 3)
        assert len(features) == 3
        # Block 1 and 2 get empty ops since block_llil_ops only has 1 entry
        assert features[1] == [0, 0, 0, 0, 0, 0, 0, 1]
        assert features[2] == [0, 0, 0, 0, 0, 0, 0, 0]


# ===================================================================
# TestCfgFeatureTlsh
# ===================================================================

class TestCfgFeatureTlsh:
    def test_too_few_blocks_returns_none(self):
        # 5 blocks = 5 * 9 bytes = 45 < 50
        bb_features = [[10, 1, 0, 2, 0, 1, 1, 2]] * 5
        bfs = list(range(5))
        result = compute_cfg_feature_tlsh(bb_features, bfs)
        assert result is None

    def test_uniform_data_returns_none(self):
        # 7 identical blocks — TLSH returns TNULL for low-entropy input
        bb_features = [[10, 1, 0, 2, 0, 1, 1, 2]] * 7
        bfs = list(range(7))
        result = compute_cfg_feature_tlsh(bb_features, bfs)
        assert result is None

    def test_varied_data_returns_string(self):
        # 20 blocks with varied features — enough entropy for TLSH
        bb_features = [
            [i * 7 + 3, (i * 13) % 50, (i * 17) % 30, (i * 23) % 40,
             (i * 11) % 20, (i * 7) % 25, (i * 19) % 35, (i * 3) % 10]
            for i in range(20)
        ]
        bfs = list(range(20))
        result = compute_cfg_feature_tlsh(bb_features, bfs)
        assert isinstance(result, str)
        assert len(result) > 0
        assert result.startswith("T1")


# ===================================================================
# TestWlMinhash
# ===================================================================

class TestWlMinhash:
    def test_empty_function(self):
        result = compute_wl_minhash([], [], [], 0)
        assert result == [255] * NUM_WL_MINHASH_PERMS

    def test_returns_128_elements(self):
        succs = _diamond()
        preds = _predecessors_from_successors(succs, 4)
        bb_feats = [[5, 1, 0, 2, 0, 1, 1, 2]] * 4
        result = compute_wl_minhash(succs, preds, bb_feats, 4)
        assert len(result) == 128

    def test_all_uint8(self):
        succs = _linear_chain(3)
        preds = _predecessors_from_successors(succs, 3)
        bb_feats = [[3, 1, 0, 1, 0, 0, 1, 1]] * 3
        result = compute_wl_minhash(succs, preds, bb_feats, 3)
        assert all(0 <= v <= 255 for v in result)

    def test_identical_graphs_same_signature(self):
        succs = _diamond()
        preds = _predecessors_from_successors(succs, 4)
        bb_feats = [[5, 1, 0, 2, 0, 1, 1, 2]] * 4
        sig1 = compute_wl_minhash(succs, preds, bb_feats, 4)
        sig2 = compute_wl_minhash(succs, preds, bb_feats, 4)
        assert sig1 == sig2

    def test_different_graphs_different_signatures(self):
        # Graph 1: linear chain
        succs1 = _linear_chain(4)
        preds1 = _predecessors_from_successors(succs1, 4)
        bb_feats1 = [[5, 1, 0, 2, 0, 1, 1, i] for i in range(4)]
        sig1 = compute_wl_minhash(succs1, preds1, bb_feats1, 4)

        # Graph 2: diamond
        succs2 = _diamond()
        preds2 = _predecessors_from_successors(succs2, 4)
        bb_feats2 = [[10, 3, 2, 1, 0, 0, 0, i] for i in range(4)]
        sig2 = compute_wl_minhash(succs2, preds2, bb_feats2, 4)

        assert sig1 != sig2

    def test_single_node(self):
        succs = [[]]
        preds = [[]]
        bb_feats = [[1, 0, 0, 0, 0, 0, 0, 0]]
        result = compute_wl_minhash(succs, preds, bb_feats, 1)
        assert len(result) == 128


# ===================================================================
# TestPackAdjacency
# ===================================================================

class TestPackAdjacency:
    def test_empty(self):
        assert pack_adjacency([]) == []

    def test_single_edge(self):
        succs = [[1], []]
        edges = pack_adjacency(succs)
        assert len(edges) == 1
        assert edges[0] == (0 << 16) | 1

    def test_correct_packing(self):
        succs = _diamond()
        edges = pack_adjacency(succs)
        assert len(edges) == 4
        # 0->1, 0->2, 1->3, 2->3
        expected = {
            (0 << 16) | 1,
            (0 << 16) | 2,
            (1 << 16) | 3,
            (2 << 16) | 3,
        }
        assert set(edges) == expected

    def test_roundtrip(self):
        """Unpack edges and verify source/target pairs."""
        succs = [[1, 2], [3], [3], []]
        edges = pack_adjacency(succs)
        unpacked = [(e >> 16, e & 0xFFFF) for e in edges]
        expected = [(0, 1), (0, 2), (1, 3), (2, 3)]
        assert sorted(unpacked) == sorted(expected)

    def test_large_index_filtered(self):
        # Create a successor list where index >= 65536
        succs = [[] for _ in range(65537)]
        succs[0] = [65536]  # target is exactly 65536 — should be filtered
        edges = pack_adjacency(succs)
        assert len(edges) == 0

    def test_max_valid_index(self):
        # Index 65535 is the maximum valid
        succs = [[] for _ in range(65536)]
        succs[0] = [65535]
        edges = pack_adjacency(succs)
        assert len(edges) == 1
        assert edges[0] == (0 << 16) | 65535