C. Victor Jongeneel

18 papers A 1C 1Journal 15Unranked 1
YearRankTypeTitle / Venue / Authors
2021 J jnl
PLoS Comput. Biol.
Shaun Aron, C. Victor Jongeneel, Paballo Abel Chauke, Melek Chaouch, Judit Kumuthini, Lyndon Zass, Fouzia Radouani, Samar Kamal Kassim, Faisal M. Fadlelmola, Nicola J. Mulder
2018 J jnl
BMC Bioinform.
Shakuntala Baichoo, Yassine Souilmi, Sumir Panji, Gerrit Botha, Ayton Meintjes, Scott Hazelhurst, Hocine Bendou, Eugene de Beste, Phelelani T. Mpangase, Oussema Souiai, Mustafa Alghali, Long Yi, Brian D. O'Connor, Michael R. Crusoe, Don Armstrong, Shaun Aron, Fourie Joubert, Azza E. Ahmed, Mamana Mbiyavanga, Peter van Heusden, Lerato E. Magosi, Jennie Zermeno, Liudmila S. Mainzer, Faisal M. Fadlelmola, C. Victor Jongeneel, Nicola J. Mulder
2017 J jnl
PLoS Comput. Biol.
C. Victor Jongeneel, Ovokeraye Achinike-Oduaran, Ezekiel F. Adebiyi, Marion O. Adebiyi, Seun Adeyemi, Bola Akanle, Shaun Aron, Efejiro Ashano, Hocine Bendou, Gerrit Botha, Emile R. Chimusa, Ananyo Choudhury, Ravikiran Donthu, Jenny Drnevich, Oluwadamilare Falola, Christopher J. Fields, Scott Hazelhurst, Liesl Hendry, Itunuoluwa Isewon, Radhika S. Khetani, Judit Kumuthini, Magambo Phillip Kimuda, Lerato E. Magosi, Liudmila S. Mainzer, Suresh Maslamoney, Mamana Mbiyavanga, Ayton Meintjes, Danny Mugutso, Phelelani T. Mpangase, Richard Munthali, Victoria Nembaware, Andrew Ndhlovu, Trust Odia, Adaobi Okafor, Olaleye Oladipo, Sumir Panji, Venesa Pillay, Gloria Rendon, Dhriti Sengupta, Nicola J. Mulder
2016 conf
DIDC@HPDC
Subho S. Banerjee, Arjun P. Athreya, Liudmila S. Mainzer, C. Victor Jongeneel, Wen-mei W. Hwu, Zbigniew T. Kalbarczyk, Ravishankar K. Iyer
2015 J jnl
J. Am. Medical Informatics Assoc.
Saurabh Sinha, Jun Song, Richard M. Weinshilboum, C. Victor Jongeneel, Jiawei Han
2010 J jnl
Database J. Biol. Databases Curation
Robin Liechti, Gábor Csárdi, Sven Bergmann, Frédéric Schütz, Thierry Sengstag, Sylvia F. Boj, Joan-Marc Servitja, Jorge Ferrer, Leentje Van Lommel, Frans Schuit, Sonia Klinger, Bernard Thorens, Najib Naamane, Decio L. Eizirik, Lorella Marselli, Marco Bugliani, Piero Marchetti, Stephanie Lucas, Cecilia Holm, C. Victor Jongeneel, Ioannis Xenarios
2007 J jnl
Nucleic Acids Res.
Marco Pagni, Vassilios Ioannidis, Lorenzo Cerutti, Monique Zahn-Zabal, C. Victor Jongeneel, Jörg Hau, Olivier Martin, Dmitri Kuznetsov, Laurent Falquet
2007 J jnl
Nucleic Acids Res.
Sébastien Moretti, Fabrice Armougom, Iain M. Wallace, Desmond G. Higgins, C. Victor Jongeneel, Cédric Notredame
2005 J jnl
Bioinform.
Florence Armand, Philipp Bucher, C. Victor Jongeneel, Edward E. Farmer
2004 J jnl
Nucleic Acids Res.
Marco Pagni, Vassilios Ioannidis, Lorenzo Cerutti, Monique Zahn-Zabal, C. Victor Jongeneel, Laurent Falquet
2004 J jnl
Nucleic Acids Res.
Peter Sperisen, Christian Iseli, Marco Pagni, Brian J. Stevenson, Philipp Bucher, C. Victor Jongeneel
2003 C conf
ECCB
Claudio Lottaz, Christian Iseli, C. Victor Jongeneel, Philipp Bucher
2003 J jnl
Nucleic Acids Res.
Laurent Falquet, Lorenza Bordoli, Vassilios Ioannidis, Marco Pagni, C. Victor Jongeneel
2001 J jnl
Briefings Bioinform.
Marco Pagni, C. Victor Jongeneel
2001 J jnl
Nucleic Acids Res.
Marco Pagni, Christian Iseli, Thomas Junier, Laurent Falquet, C. Victor Jongeneel, Philipp Bucher
2000 J jnl
Briefings Bioinform.
C. Victor Jongeneel
2000 J jnl
Bioinform.
C. Victor Jongeneel
1999 A conf
ISMB
Christian Iseli, C. Victor Jongeneel, Philipp Bucher
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