Rana Asif Rehman

37 papers Misc 6Journal 22Unranked 9
YearRankTypeTitle / Venue / Authors
2026 J jnl
PeerJ Comput. Sci.
Rimsha Asif, Rana Asif Rehman, Ahmad Arsalan, Byung-Seo Kim
2026 J jnl
ICT Express
Ahmad Arsalan, Tariq Umer, Rana Asif Rehman, Byung-Seo Kim, Mohsin Murtaza, Chi-Tsun Cheng
2025 J jnl
IEEE Access
Ahmad Arsalan, Tariq Umer, Rana Asif Rehman, Byung-Seo Kim
2024 J jnl
Comput. Mater. Continua
Ahmed Khalid, Rana Asif Rehman, Byung-Seo Kim
2024 J jnl
IEEE Access
Muhammad Umar Sattar, Rana Asif Rehman, Ahmad Arsalan, Byung-Seo Kim
2024 conf
CCECE
Ahmed Khalid, Rana Asif Rehman, Byung-Seo Kim
2023 J jnl
IEEE Access
Muhammad Burhan, Hina Alam, Ahmad Arsalan, Rana Asif Rehman, Muhammad Anwar, Muhammad Faheem, Muhammad Waqar Ashraf
2023 J jnl
Ad Hoc Networks
Ammarah Khalid, Rana Asif Rehman, Muhammad Burhan
2023 Misc conf
FIT
Sana Bari, Rana Asif Rehman
2023 J jnl
IEEE Access
Ahmad Arsalan, Muhammad Burhan, Rana Asif Rehman, Tariq Umer, Byung-Seo Kim
2023 J jnl
Ad Hoc Networks
Farwa Ansari, Rana Asif Rehman, Ahmad Arsalan
2022 Misc conf
FIT
Ahmad Arsalan, Muhammad Burhan, Rana Asif Rehman
2022 J jnl
Comput. Networks
Ahmad Arsalan, Rana Asif Rehman
2021 J jnl
IEICE Trans. Inf. Syst.
Muhammad Mudasir Qazi, Rana Asif Rehman, Asadullah Tariq, Byung-Seo Kim
2020 conf
ICACS
Muhammad Burhan, Rana Asif Rehman
2020 J jnl
J. Netw. Comput. Appl.
Khizra Asaf, Rana Asif Rehman, Byung-Seo Kim
2020 conf
ICACS
Asadullah Tariq, Rana Asif Rehman
2020 J jnl
IEEE Commun. Surv. Tutorials
Asadullah Tariq, Rana Asif Rehman, Byung-Seo Kim
2020 conf
WCNC Workshops
Muhammad Mudasir Qazi, Rana Asif Rehman, Byung-Seo Kim
2020 conf
WCNC Workshops
Muhammad Burhan, Rana Asif Rehman, Byung-Seo Kim
2019 conf
GLOBECOM Workshops
Farwa Ansari, Rana Asif Rehman, Byung-Seo Kim
2019 conf
CCNC
Ahmad Arsalan, Rana Asif Rehman
2019 Misc conf
FIT
Muhammad Umar Sattar, Rana Asif Rehman
2018 Misc conf
FIT
Muhammad Usman Tahir, Rana Asif Rehman
2018 J jnl
Sensors
Muhammad Burhan, Rana Asif Rehman, Bilal Khan, Byung-Seo Kim
2018 Misc conf
FIT
Ahmed Arsalan, Rana Asif Rehman
2018 J jnl
Wirel. Commun. Mob. Comput.
Hammad Shafiq, Rana Asif Rehman, Byung-Seo Kim
2017 J jnl
IEEE Trans. Veh. Technol.
Rana Asif Rehman, Byung-Seo Kim
2017 J jnl
IEEE Access
Rana Asif Rehman, Syed Hassan Ahmed, Byung-Seo Kim
2017 J jnl
IEEE Access
Chan-Min Park, Rana Asif Rehman, Byung-Seo Kim
2016 J jnl
IEICE Trans. Inf. Syst.
Rana Asif Rehman, Byung-Seo Kim
2016 conf
SENSORNETS
Hong Min Bae, Chan-Min Park, Shinil Suh, Rana Asif Rehman, Byung-Seo Kim
2016 conf
WMNC
Rana Asif Rehman, Tran Dinh Hieu, Hong Min Bae, Sung-Hoon Mah, Byung-Seo Kim
2015 Misc conf
FIT
Rana Asif Rehman, Byung-Seo Kim
2015 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Rana Asif Rehman, Byung-Seo Kim
2015 J jnl
Mob. Inf. Syst.
Rana Asif Rehman, Jong Kim, Byung-Seo Kim
2014 J jnl
Int. J. Distributed Sens. Networks
Rana Asif Rehman, Byung-Seo Kim
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