Irfan Younas

34 papers B 1Journal 22Unranked 10
YearRankTypeTitle / Venue / Authors
2025 J jnl
Big Data Res.
Sobia Tariq Javed, Kashif Zafar, Irfan Younas
2024 J jnl
Cogn. Syst. Res.
Sobia Tariq Javed, Kashif Zafar, Irfan Younas
2024 J jnl
Neural Comput. Appl.
Sobia Tariq Javed, Kashif Zafar, Irfan Younas
2023 conf
ADMA (1)
Adeem Ali Anwar, Irfan Younas, Guanfeng Liu, Xuyun Zhang
2023 J jnl
Int. J. Artif. Intell. Tools
Kiran Ilyas, Irfan Younas
2022 conf
ADMA (2)
Adeem Ali Anwar, Irfan Younas, Guanfeng Liu, Amin Beheshti, Xuyun Zhang
2022 J jnl
J. Intell. Fuzzy Syst.
Ammara Idrees, S. A. M. Gilani, Irfan Younas
2022 J jnl
Comput. Biol. Medicine
Mamoona Riaz, Maryam Bashir, Irfan Younas
2022 J jnl
Comput. Electr. Eng.
Irfan Younas, Ameera Naeem
2021 J jnl
Multim. Tools Appl.
Syeda Iram Batool, Irfan Younas, Majid Khan, Naveed Yaqoob
2021 J jnl
Soft Comput.
Qamar Askari, Irfan Younas, Mehreen Saeed
2021 J jnl
Comput. Electr. Eng.
Saba Kanwal, Irfan Younas, Maryam Bashir
2021 J jnl
Expert Syst. Appl.
Qamar Askari, Irfan Younas
2021 J jnl
Neural Process. Lett.
Qamar Askari, Irfan Younas
2021 conf
AALTD@ECML/PKDD
Abdul Hameed Azeemi, Muhammad Hamza Sohail, Talha Zubair, Muaz Maqbool, Irfan Younas, Omair Shafiq
2021 J jnl
CoRR
Abdul Hameed Azeemi, Muhammad Hamza Sohail, Talha Zubair, Muaz Maqbool, Irfan Younas, Omair Shafiq
2021 J jnl
Multim. Tools Appl.
Maria Tamoor, Irfan Younas, Hassan Mohy-ud-Din
2020 J jnl
IEEE Access
Shah Bano, Maryam Bashir, Irfan Younas
2020 conf
GECCO Companion
Qamar Askari, Irfan Younas, Mehreen Saeed
2020 J jnl
Expert Syst. Appl.
Qamar Askari, Mehreen Saeed, Irfan Younas
2020 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Hafiz Asadul Rehman, Muhammad Iqbal, Irfan Younas, Maryam Bashir
2020 J jnl
Int. J. Artif. Intell. Tools
Adeem Ali Anwar, Irfan Younas
2020 J jnl
Knowl. Based Syst.
Qamar Askari, Irfan Younas, Mehreen Saeed
2018 J jnl
Entropy
Irfan Younas, Majid Khan
2018 J jnl
Neurocomputing
Irfan Younas, Farzad Kamrani, Maryam Bashir, Johan Schubert
2014
Irfan Younas
2013 conf
GECCO (Companion)
Irfan Younas, Farzad Kamrani, Rassul Ayani
2013 conf
AsiaSim
Irfan Younas, Farzad Kamrani, Farshad Moradi, Rassul Ayani, Johan Schubert, Anne Håkansson
2013 B conf
SMC
Irfan Younas, Rassul Ayani, Johan Schubert, Hirad Asadi
2012 J jnl
Int. J. Comput. Aided Eng. Technol.
Muhammad Zahoor, Irfan Younas, Abad Ali Shah
2011 conf
CISched
Irfan Younas, Farzad Kamrani, Christian Schulte, Rassul Ayani
2005 conf
EEE
Zakaria Maamar, Irfan Younas, Djamal Benslimane, Chirine Ghedira, Hamdi Yahyaoui
2005 conf
CSREA HCI
Irfan Younas, Asim Makki
2004 conf
International Conference on Computational Intelligence
Irfan Younas, Ibrahim I. Esat
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