Man Zhou

28 papers A* 3A 2Journal 21Unranked 2
YearRankTypeTitle / Venue / Authors
2026 J jnl
IET Image Process.
Zhe Chen, Man Zhou, Yantao Zhu, Mingwei Shen
2026 J jnl
Knowl. Based Syst.
Ming He, Changle Li, Man Zhou, Yongjie Zheng, Xiaojing Wang
2026 J jnl
CoRR
Zijian Ling, Pingyi Hu, Xiuyong Gao, Xiaojing Ma, Man Zhou, Jun Feng, Songfeng Lu, Dongmei Zhang, Bin Benjamin Zhu
2025 J jnl
Neurocomputing
Ming He, Man Zhou, Changle Li, Yongjie Zheng, Xiaojing Wang
2025 J jnl
Veh. Commun.
Man Zhou, Jie Tian, Dongyang Li, Tiantian Li, Ji Bian
2025 A conf
ICME
Zijian Ling, Wenyu Zhou, Yi Ouyang, Yuting Zhou, Man Zhou
2025 A conf
CIKM
Ming He, Yongjie Zheng, Changle Li, Man Zhou
2024 A* conf
IJCAI
Hongxin Xiang, Shuting Jin, Jun Xia, Man Zhou, Jianmin Wang, Li Zeng, Xiangxiang Zeng
2024 A* conf
NeurIPS
Man Zhou
2024 J jnl
Mob. Networks Appl.
Man Zhou, Lansheng Han
2023 J jnl
J. Inf. Secur. Appl.
Jiarui Yu, Jingsong Cui, Hang Tu, Chunwu Yu, Man Zhou
2023 J jnl
CoRR
Hu Yu, Li Shen, Jie Huang, Man Zhou, Hongsheng Li, Feng Zhao
2023 A* conf
NeurIPS
Hu Yu, Jie Huang, Lingzhi Li, Man Zhou, Feng Zhao
2023 conf
ICCT
Fanqiang Cheng, Jie Tian, Yu Dai, Man Zhou, Tiantian Li, Ji Bian
2022 J jnl
IEEE Trans. Serv. Comput.
Jiewu Leng, Man Zhou, J. Leon Zhao, Yongfeng Huang, Yiyang Bian
2021 conf
DTPI
Hu Zhang, Jiewu Leng, Hao Zhang, Guolei Ruan, Man Zhou, Yang Zhang
2021 J jnl
Trans. Emerg. Telecommun. Technol.
Jingjing Wang, Lansheng Han, Man Zhou, Wenkui Qian, Dezhi An
2021 J jnl
IEEE Trans. Syst. Man Cybern. Syst.
Jiewu Leng, Shide Ye, Man Zhou, J. Leon Zhao, Qiang Liu, Wei Guo, Wei Cao, Leijie Fu
2021 J jnl
Mob. Networks Appl.
Man Zhou, Lansheng Han, Hongwei Lu, Cai Fu
2021 J jnl
BioData Min.
Congmin Xu, Man Zhou, Zhongjie Xie, Mo Li, Xi Zhu, Huaiqiu Zhu
2021 J jnl
Nat. Mach. Intell.
Cheng Yang, Man Zhou, Haoling Xie, Huaiqiu Zhu
2020 J jnl
Comput. Networks
Man Zhou, Lansheng Han, Hongwei Lu, Cai Fu
2019 J jnl
IEEE Trans. Instrum. Meas.
Jiliang Yi, Man Zhou, Zhongqi Li, Junjun Li
2019 J jnl
Inf. Sci.
Lansheng Han, Man Zhou, Wenjing Jia, Zakaria Dalil, Xingbo Xu
2019 J jnl
Concurr. Comput. Pract. Exp.
Lansheng Han, Man Zhou, Shuxia Han, Wenjing Jia, Changhua Sun, Cai Fu
2019 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Kai Wang, Man Zhou, Lin Zhou, Jiaying Tu
2018 J jnl
Sensors
Man Zhou, Dapeng Mao, Mingyue Zhang, Lihong Guo, Mingde Gong
2018 J jnl
Bioinform.
Cheng Yang, Longshu Yang, Man Zhou, Haoling Xie, Chengjiu Zhang, May D. Wang, Huaiqiu Zhu
tests/unit/test_decompile_similarity.py
← Index tests/unit/test_decompile_similarity.py python
"""Unit tests for similarity modules:
- bninja/similarity/minhashcustom.py
- bninja/similarity/minhasher.py
"""
import numpy as np
import pytest

from redb.extractors.decompiler.bninja.similarity.minhashcustom import MinHashCustom
from redb.extractors.decompiler.bninja.analysis.low_level_normalization import LowLevelNormalization


# ============================================================================
# 2a. MinHashCustom
# ============================================================================

class TestMinHashCustomInit:
    def test_init_empty(self):
        mh = MinHashCustom()
        assert not mh.hasMinHash()
        assert mh.minhash == b""
        assert mh.minhash_int == []

    def test_init_from_signature(self):
        sig = [10, 20, 30, 40]
        mh = MinHashCustom(minhash_signature=sig)
        assert mh.hasMinHash()
        assert mh.minhash_int == sig

    def test_init_from_bytes_uint32(self):
        """Verify round-trip: ints -> bytes -> MinHashCustom -> ints."""
        sig = [100, 200, 300]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        # np.frombuffer returns numpy scalars; setMinHash does % 2**32 which
        # overflows numpy uint32, so verify the raw bytes round-trip instead.
        raw_arr = np.frombuffer(packed, dtype=np.uint32)
        assert list(raw_arr) == sig

    def test_init_from_bytes_uint8(self):
        """Verify round-trip: ints -> bytes -> back."""
        sig = [10, 20, 30]
        packed = np.array(sig, dtype=np.uint8).tobytes()
        raw_arr = np.frombuffer(packed, dtype=np.uint8)
        assert list(raw_arr) == sig

    def test_init_both_raises(self):
        sig = [1, 2, 3]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        with pytest.raises(ValueError, match="only one"):
            MinHashCustom(minhash_bytes=packed, minhash_signature=sig)


class TestMinHashCustomSetGet:
    def test_set_and_get_minhash(self):
        mh = MinHashCustom()
        sig = [5, 10, 15]
        mh.setMinHash(sig)
        raw = mh.getMinHash()
        assert raw == np.array(sig, dtype=np.uint32).tobytes()
        assert mh.getMinHashInt() == sig

    def test_minhash_int_truncation(self):
        mh = MinHashCustom(minhash_bits=8)
        # Values > 256 should be truncated mod 2^8
        mh.setMinHash([300, 500, 256])
        for val in mh.minhash_int:
            assert 0 <= val < 256


class TestMinHashCustomHashData:
    def test_hash_data_string(self):
        result = MinHashCustom.hashData("hello", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_bytes(self):
        result = MinHashCustom.hashData(b"bytes", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_list(self):
        result = MinHashCustom.hashData([1, 2, 3], 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_unsupported_type(self):
        with pytest.raises(NotImplementedError, match="Type not supported"):
            MinHashCustom.hashData(123, 42)

    def test_hash_data_deterministic(self):
        assert MinHashCustom.hashData("test", 7) == MinHashCustom.hashData("test", 7)


class TestMinHashCustomScore:
    def test_score_identical(self):
        sig = [1, 2, 3, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig)
        mh2 = MinHashCustom(minhash_signature=sig)
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score == 100.0

    def test_score_different(self):
        mh1 = MinHashCustom(minhash_signature=[1, 2, 3, 4, 5])
        mh2 = MinHashCustom(minhash_signature=[6, 7, 8, 9, 10])
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score < 100.0

    def test_score_against(self):
        sig1 = [1, 2, 3, 4, 5]
        sig2 = [1, 2, 99, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig1)
        mh2 = MinHashCustom(minhash_signature=sig2)
        instance_score = mh1.scoreAgainst(mh2)
        static_score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert instance_score == static_score


class TestMinHashCustomBitModes:
    def test_8bit_mode(self):
        mh = MinHashCustom(minhash_bits=8)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint8)
        assert list(arr) == [10, 20, 30]

    def test_32bit_mode(self):
        mh = MinHashCustom(minhash_bits=32)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint32)
        assert list(arr) == [10, 20, 30]


# ============================================================================
# 2b. MinHasher
# ============================================================================


class MockILNode:
    """Mock IL node with operation and operands for normalization."""
    def __init__(self, operation, operands=None):
        self.operation = operation
        self.operands = operands or []


class MockLLILBasicBlock:
    """Mock LLIL basic block that yields IL instructions."""
    def __init__(self, instructions):
        self._instructions = instructions

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


class MockLLILFunction:
    """Mock LLIL function with basic blocks."""
    def __init__(self, basic_blocks):
        self.basic_blocks = basic_blocks


# Import MinHasher after we know the module can handle the import
from redb.extractors.decompiler.bninja.similarity.minhasher import (
    MinHasher,
    MINHASH_SIGNATURE_LENGTH,
    MINHASH_SIGNATURE_BITS,
)


class TestMinHasherMakeNgrams:
    def setup_method(self):
        # Create a minimal minhasher with a mock LLIL function
        empty_func = MockLLILFunction([])
        self.hasher = MinHasher(seed=42, il_function=empty_func)

    def test_make_ngrams_basic(self):
        result = self.hasher.make_ngrams(["a", "b", "c", "d"], n=3)
        assert result == [("a", "b", "c"), ("b", "c", "d")]

    def test_make_ngrams_short_input(self):
        result = self.hasher.make_ngrams(["a", "b"], n=3)
        assert result == []

    def test_make_ngrams_exact_n(self):
        result = self.hasher.make_ngrams(["a", "b", "c"], n=3)
        assert result == [("a", "b", "c")]


class TestMinHasherCalculate:
    def _make_llil_function(self, num_instructions=10):
        """Create a mock LLIL function with enough instructions."""
        instructions = [
            MockILNode(operation=i % 20) for i in range(num_instructions)
        ]
        bb = MockLLILBasicBlock(instructions)
        return MockLLILFunction([bb])

    def test_calculate_minhash_empty_function(self):
        # Function with < 3 LLIL instructions -> empty list
        func = self._make_llil_function(num_instructions=2)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert result == []

    def test_calculate_minhash_deterministic(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=42, il_function=func)
        h2 = MinHasher(seed=42, il_function=func)
        assert h1.calculateMinHash() == h2.calculateMinHash()

    def test_calculate_minhash_length(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert len(result) == MINHASH_SIGNATURE_LENGTH

    def test_calculate_minhash_value_range(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        for val in result:
            assert 0 <= val < 2 ** MINHASH_SIGNATURE_BITS

    def test_shingle_hash_deterministic(self):
        func = self._make_llil_function(num_instructions=5)
        hasher = MinHasher(seed=42, il_function=func)
        shingle = ([1, 2], [3, 4], [5, 6])
        assert hasher.shingle_hash(shingle, 99) == hasher.shingle_hash(shingle, 99)

    def test_seed_reproducibility(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=1, il_function=func)
        h2 = MinHasher(seed=2, il_function=func)
        r1 = h1.calculateMinHash()
        r2 = h2.calculateMinHash()
        # Different seeds should (very likely) produce different results
        assert r1 != r2