M. Anwar Hossain

95 papers A* 2A 5B 1C 4Misc 2Journal 58Unranked 21
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
Rahatara Ferdousi, M. Anwar Hossain
2025 C conf
ICCE
Rahatara Ferdousi, M. Anwar Hossain, Abdulmotaleb El Saddik
2024 J jnl
CoRR
Rahatara Ferdousi, M. Anwar Hossain, Chunsheng Yang, Abdulmotaleb El Saddik
2024 J jnl
CoRR
Rahatara Ferdousi, Chunsheng Yang, M. Anwar Hossain, Fedwa Laamarti, M. Shamim Hossain, Abdulmotaleb El Saddik
2024 J jnl
Cogn. Comput.
Rahatara Ferdousi, Chunsheng Yang, M. Anwar Hossain, Fedwa Laamarti, M. Shamim Hossain, Abdulmotaleb El Saddik
2024 J jnl
CoRR
Rahatara Ferdousi, M. Anwar Hossain, Abdulmotaleb El Saddik
2022 conf
FTC (2)
Sk Alamgir Hossain, Md. Anisur Rahman, M. Anwar Hossain
2021 J jnl
IEEE Access
Rahatara Ferdousi, M. Anwar Hossain, Abdulmotaleb El Saddik
2021 conf
GLOBECOM (Workshops)
Rahatara Ferdousi, M. Anwar Hossain, Abdulmotaleb El Saddik
2021 conf
GLOBECOM (Workshops)
Anika Tabassum Bristy, Rahatara Ferdousi, Arman Hossain, M. M. Faniqul Islam, M. Anwar Hossain, Abdulmotaleb El Saddik
2020 J jnl
IEEE Access
M. Anwar Hossain, Rahatara Ferdousi, Sk Alamgir Hossain, Mohammed F. Alhamid, Abdulmotaleb El Saddik
2020 J jnl
Sensors
Tamanna Tabassum, S. K. Alamgir Hossain, Md. Anisur Rahman, Mohammed F. Alhamid, M. Anwar Hossain
2020 J jnl
J. Parallel Distributed Comput.
M. Anwar Hossain, Rahatara Ferdousi, Mohammed F. Alhamid
2020 J jnl
CCF Trans. Pervasive Comput. Interact.
Mahmoud S. Fayed, Muhammad Al-Qurishi, Atif Alamri, M. Anwar Hossain, Ahmad A. Al-Daraiseh
2019 J jnl
Future Gener. Comput. Syst.
Andrej Somrak, Iztok Humar, M. Shamim Hossain, Mohammed F. Alhamid, M. Anwar Hossain, Joze Guna
2018 J jnl
Mob. Networks Appl.
Jun Yang, Mengchen Liu, Jiayi Lu, Yiming Miao, M. Anwar Hossain, Mohammed F. Alhamid
2018 J jnl
IEEE Access
Mohd Usama, Belal Ahmad, Jiafu Wan, M. Shamim Hossain, Mohammed F. Alhamid, M. Anwar Hossain
2018 J jnl
J. Parallel Distributed Comput.
S. K. Alamgir Hossain, Md. Anisur Rahman, M. Anwar Hossain
2018 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Jordi Sanchez-Riera, Kathiravan Srinivasan, Kai-Lung Hua, Wen-Huang Cheng, M. Anwar Hossain, Mohammed F. Alhamid
2017 J jnl
Future Gener. Comput. Syst.
Aitor Urbieta, Alejandra N. González-Beltrán, Sonia Ben Mokhtar, M. Anwar Hossain, Licia Capra
2017 J jnl
Clust. Comput.
Mohammed G. H. al Zamil, Samer M. J. Samarah, Majdi Rawashdeh, M. Anwar Hossain
2017 C conf
ISM
Amjad A. Alghanim, Sk. Md. Mizanur Rahman, M. Anwar Hossain
2017 J jnl
IEEE Access
Mashail N. Alkhomsan, M. Anwar Hossain, Sk. Md. Mizanur Rahman, Mehedi Masud
2016 J jnl
Concurr. Comput. Pract. Exp.
Yuxin Mao, Ping Zhu, Guiyi Wei, Mohammad Mehedi Hassan, M. Anwar Hossain
2016 J jnl
EURASIP J. Image Video Process.
Fatma S. Abousaleh, Tekoing Lim, Wen-Huang Cheng, Neng-Hao Yu, M. Anwar Hossain, Mohammed F. Alhamid
2016 Misc conf
UCC
Aljawharah Al-muaythir, M. Anwar Hossain
2016 J jnl
Mob. Networks Appl.
M. Anwar Hossain, Biao Song
2016 J jnl
IEEE Trans. Hum. Mach. Syst.
Mohammed F. Alhamid, Majdi Rawashdeh, Haiwei Dong, M. Anwar Hossain, Abdulmotaleb El Saddik
2016 J jnl
IEEE Wirel. Commun.
M. Anwar Hossain, Jorge Parra, Sk. Md. Mizanur Rahman, Atif Alamri, Sana Ullah, Hussein T. Mouftah
2016 J jnl
IEEE Internet Comput.
Wei Tan, Yushun Fan, Ahmed Ghoneim, M. Anwar Hossain, Schahram Dustdar
2016 conf
ICME Workshops
Mona A. Alhumud, M. Anwar Hossain, Mehedi Masud
2016 J jnl
Neurocomputing
Tsung-Hung Tsai, Wei-Cih Jhou, Wen-Huang Cheng, Min-Chun Hu, I-Chao Shen, Tekoing Lim, Kai-Lung Hua, Ahmed Ghoneim, M. Anwar Hossain, Shintami Chusnul Hidayati
2016 J jnl
Peer-to-Peer Netw. Appl.
Sk. Md. Mizanur Rahman, Md. Mehedi Masud, M. Anwar Hossain, Abdulhameed Alelaiwi, Mohammad Mehedi Hassan, Atif Alamri
2016 J jnl
Multim. Syst.
Mohammed F. Alhamid, Majdi Rawashdeh, Haiwei Dong, M. Anwar Hossain, Abdulhameed Alelaiwi, Abdulmotaleb El Saddik
2016 Misc conf
IRI
Awny Alnusair, Majdi Rawashdeh, Mohammed F. Alhamid, M. Anwar Hossain, Ghulam Muhammad
2016 J jnl
Future Gener. Comput. Syst.
Sk. Md. Mizanur Rahman, M. Anwar Hossain, Mohammad Mehedi Hassan, Atif Alamri, Abdullah S. Alghamdi, Mukaddim Pathan
2016 J jnl
Int. J. Distributed Sens. Networks
M. Anwar Hossain, Jemal H. Abawajy, Raúl García-Castro, Wen-Huang Cheng, Dewan Tanvir Ahmed
2016 J jnl
J. Intell. Inf. Syst.
Mohammed F. Alhamid, Majdi Rawashdeh, M. Anwar Hossain, Abdulhameed Alelaiwi, Abdulmotaleb El Saddik
2015 J jnl
Int. J. Distributed Sens. Networks
Mir Mehedi Ahsan Pritom, Sujan Sarker, Md. Abdur Razzaque, Mohammad Mehedi Hassan, M. Anwar Hossain, Abdulhameed Alelaiwi
2015 J jnl
Clust. Comput.
Mohammad Mehedi Hassan, M. Anwar Hossain, Mohammad Abdullah-Al-Wadud, Tsaheel Al-Mudaihesh, Sultan Alyahya, Abdullah Sharaf Alghamdi
2015 conf
ICME Workshops
Majdi Rawashdeh, Mohammed F. Alhamid, M. Anwar Hossain, Abdulmotaleb El Saddik
2015 conf
CCECE
S. M. Kamruzzaman, M. Anwar Hossain, Abdullah Sharaf Alghamdi
2015 J jnl
Clust. Comput.
Aitor Urbieta, Alejandra N. González-Beltrán, Sonia Ben Mokhtar, Jorge Parra, Licia Capra, M. Anwar Hossain, Abdulhameed Alelaiwi, Juan Ignacio Vázquez
2015 conf
ICME Workshops
M. Anwar Hossain, Jorge Parra, Atif Alamri
2014 J jnl
Sensors
M. Anwar Hossain, Atif Alamri, Ahmad S. Almogren, S. K. Alamgir Hossain, Jorge Parra
2014 conf
IDCS
Noura Alhakbani, Mohammad Mehedi Hassan, M. Anwar Hossain, Mohammed Abdullah Alnuem
2014 conf
ICME Workshops
M. Anwar Hossain, Atif Alamri, Mohammed F. Alhamid, Majdi Rawashdeh, Awny Alnusair
2014 J jnl
Multim. Tools Appl.
Pradeep K. Atrey, Saeed Alharthi, M. Anwar Hossain, Abdullah Sharaf Alghamdi, Abdulmotaleb El Saddik
2014 A* conf
ACM Multimedia
M. Anwar Hossain, Abdulmotaleb El Saddik
2014 J jnl
KSII Trans. Internet Inf. Syst.
Mohammad Mehedi Hassan, Biao Song, M. Shamim Hossain, Atif Alamri, Mohammed Abdullah Alnuem, Muhammad Mostafa Monowar, M. Anwar Hossain
2014 J jnl
Comput. Hum. Behav.
Atif Alamri, Mohammad Mehedi Hassan, M. Anwar Hossain, Muhammad Al-Qurishi, Yousuf Aldukhayyil, M. Shamim Hossain
2014 J jnl
Int. J. Distributed Sens. Networks
M. Anwar Hossain
2014 J jnl
Multim. Tools Appl.
Pradeep K. Atrey, M. Anwar Hossain, Mohan S. Kankanhalli
2014 J jnl
Comput. Hum. Behav.
M. Anwar Hossain
2014 ed.
EMASC@MM
M. Anwar Hossain, Abdulmotaleb El Saddik
2014 J jnl
Sensors
Jorge Parra, M. Anwar Hossain, Aitor Uribarren, Eduardo Jacob
2014 J jnl
Multim. Tools Appl.
Dewan Tanvir Ahmed, M. Anwar Hossain, Shervin Shirmohammadi, Abdullah S. Alghamdi, Pradeep K. Atrey, Abdulmotaleb El Saddik
2013 J jnl
Int. J. Distributed Sens. Networks
Atif Alamri, Wasai Shadab Ansari, Mohammad Mehedi Hassan, M. Shamim Hossain, Abdulhameed Alelaiwi, M. Anwar Hossain
2013 J jnl
Comput. Sci. Inf. Syst.
Atif Alamri, M. Anwar Hossain, Mohammad Mehedi Hassan, M. Shamim Hossain, Mohammed Abdullah Alnuem, Dewan Tanvir Ahmed, Abdulmotaleb El Saddik
2013 J jnl
Multim. Tools Appl.
M. Anwar Hossain, Ali Asghar Nazari Shirehjini, Abdullah S. Alghamdi, Abdulmotaleb El Saddik
2013 conf
HPCC/EUC
M. Anwar Hossain
2013 J jnl
Multim. Tools Appl.
M. Shamim Hossain, S. K. Alamgir Hossain, Atif Alamri, M. Anwar Hossain
2013 conf
ICME Workshops
M. Anwar Hossain, Atif Alamri, Jorge Parra
2013 conf
ICME Workshops
Mohammad Mehedi Hassan, M. Anwar Hossain, Yousuf Aldukhayyil, Atif Alamri, Muhammad Al-Qurishi, M. Shamim Hossain, Dewan Tanvir Ahmed, Abdulmotaleb El Saddik
2013 conf
ISBAST
M. Anwar Hossain, Sk. Md. Mizanur Rahman
2012 conf
ICME Workshops
M. Anwar Hossain, Dewan Tanvir Ahmed
2012 J jnl
Multim. Syst.
Sk. Md. Mizanur Rahman, M. Anwar Hossain, Hussein T. Mouftah, Abdulmotaleb El Saddik, Eiji Okamoto
2012 J jnl
Multim. Tools Appl.
Pradeep K. Atrey, Hicham Ibrahim, M. Anwar Hossain, Sheela Ramanna, Abdulmotaleb El Saddik
2012 J jnl
Multim. Tools Appl.
Ali Karime, M. Anwar Hossain, Abu Saleh Md. Mahfujur Rahman, Wail Gueaieb, Jihad M. Alja'am, Abdulmotaleb El Saddik
2012 J jnl
IEEE Trans. Inf. Technol. Biomed.
M. Anwar Hossain, Dewan Tanvir Ahmed
2011 A conf
ICME
M. Anwar Hossain
2011 A conf
ICME
Mohsin Iftikhar, M. Anwar Hossain
2011 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2010 A conf
ICME
Sk. Md. Mizanur Rahman, M. Anwar Hossain, Hussein T. Mouftah, Abdulmotaleb El Saddik, Eiji Okamoto
2010 conf
ISSPA
Bassem Barake, Pradeep K. Atrey, M. Anwar Hossain, Abdulmotaleb El Saddik
2010 J jnl
Multim. Syst.
Pradeep K. Atrey, M. Anwar Hossain, Abdulmotaleb El Saddik, Mohan S. Kankanhalli
2010 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Abu Saleh Md. Mahfujur Rahman, M. Anwar Hossain, Abdulmotaleb El Saddik
2009 J jnl
Multim. Tools Appl.
M. Anwar Hossain, Jorge Parra, Pradeep K. Atrey, Abdulmotaleb El Saddik
2009 J jnl
IEEE Trans. Instrum. Meas.
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2009 A conf
ICME
Ali Karime, M. Anwar Hossain, Wail Gueaieb, Abdulmotaleb El Saddik
2009 A* conf
ACM Multimedia
Abu Saleh Md. Mahfujur Rahman, M. Anwar Hossain, Jorge Parra, Abdulmotaleb El Saddik
2008 conf
SRMC
Ali Karime, M. Anwar Hossain, Abdulmotaleb El Saddik, Wail Gueaieb
2008 J jnl
Int. J. Web Grid Serv.
Pradeep K. Atrey, M. Anwar Hossain, Abdulmotaleb El Saddik
2008 A conf
ICME
Pradeep K. Atrey, M. Anwar Hossain, Abdulmotaleb El Saddik
2008 B conf
MASS
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2008 conf
SAME
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2008 J jnl
Mob. Networks Appl.
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2008 conf
ISPAN
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2008 ch.
Encyclopedia of Wireless and Mobile Communications
Abdulmotaleb El Saddik, M. Anwar Hossain
2008 conf
HCC
M. Anwar Hossain, Abdulmotaleb El Saddik
2008 J jnl
IEEE Trans. Instrum. Meas.
Abdulmotaleb El Saddik, Abu Saleh Md. Mahfujur Rahman, M. Anwar Hossain
2007 conf
ICDE Workshops
M. Anwar Hossain, Pradeep K. Atrey, Abdulmotaleb El Saddik
2007 conf
ICDE Workshops
M. Shamim Hossain, M. Anwar Hossain, Abdulmotaleb El Saddik
2006 C conf
ISM
M. Anwar Hossain, Md. Anisur Rahman, Iluju Kiringa, Abdulmotaleb El Saddik
2004 C conf
DS-RT
Md. Abdur Rahman, M. Anwar Hossain, Abdulmotaleb El Saddik
tests/unit/test_apk_cfg_features.py
← Index tests/unit/test_apk_cfg_features.py python
"""
Unit tests for APK CFG feature parity with the Binary Ninja pipeline.

Tests advanced CFG features computed from smali (topology hash, MD-index,
WL-MinHash, prime product, packed adjacency, block features export) and
the slimmed similarity table.

All tests use mocked smali input — no JADX/apktool/Java required.
"""
import pytest

from redb.extractors.decompiler.apk.smali_cfg import (
    SmaliCFGMetrics,
    compute_cfg_metrics,
)
from redb.extractors.decompiler.apk.method_extractor import (
    SMALI_OP_PRIMES,
    compute_prime_product_smali,
    count_call_instructions,
)

pytestmark = [pytest.mark.unit, pytest.mark.apk, pytest.mark.decompile]


# ===================================================================
# Sample smali bodies for testing
# ===================================================================

# Simple linear method: 3 instructions, 1 block
SMALI_LINEAR = """\
    const/4 v0, 0x0
    invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
    return-void
"""

# Diamond CFG: if-else with two paths merging
SMALI_DIAMOND = """\
    const/4 v0, 0x1
    if-eqz v0, :cond_0
    invoke-virtual {p0}, Lcom/Foo;->pathA()V
    goto :goto_0
    :cond_0
    invoke-virtual {p0}, Lcom/Foo;->pathB()V
    :goto_0
    return-void
"""

# Loop: a back edge from goto to a label before it
SMALI_LOOP = """\
    const/4 v0, 0x0
    :loop_start
    add-int/lit8 v0, v0, 0x1
    if-lt v0, v1, :loop_start
    return-void
"""

# Multi-block with several invoke calls
SMALI_MULTI_CALL = """\
    invoke-virtual {p0}, Lcom/Foo;->a()V
    invoke-static {v0}, Lcom/Bar;->b(I)V
    invoke-direct {p0, v1}, Lcom/Baz;-><init>(I)V
    const/4 v0, 0x0
    return-void
"""


# ===================================================================
# TestSmaliCFGMetricsAdvanced — new fields in SmaliCFGMetrics
# ===================================================================

class TestSmaliCFGMetricsAdvanced:
    """Test that advanced CFG fields are populated by compute_cfg_metrics."""

    def test_topology_hash_is_bytes(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert isinstance(m.cfg_topology_hash, bytes)
        assert len(m.cfg_topology_hash) == 16

    def test_topology_hash_nonzero_for_multiblock(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert m.cfg_topology_hash != b'\x00' * 16

    def test_topology_hash_zero_for_empty(self):
        m = compute_cfg_metrics("")
        assert m.cfg_topology_hash == b'\x00' * 16

    def test_identical_cfg_same_topology_hash(self):
        """Two smali methods with the same CFG structure produce the same hash."""
        smali_a = """\
    const/4 v0, 0x1
    if-eqz v0, :cond_0
    const/4 v1, 0x2
    goto :goto_0
    :cond_0
    const/4 v1, 0x3
    :goto_0
    return-void
"""
        smali_b = """\
    const/4 v5, 0x9
    if-nez v5, :cond_0
    add-int v6, v5, v5
    goto :goto_0
    :cond_0
    sub-int v6, v5, v5
    :goto_0
    return-void
"""
        m_a = compute_cfg_metrics(smali_a)
        m_b = compute_cfg_metrics(smali_b)
        assert m_a.cfg_topology_hash == m_b.cfg_topology_hash

    def test_different_cfg_different_topology_hash(self):
        m_linear = compute_cfg_metrics(SMALI_LINEAR)
        m_diamond = compute_cfg_metrics(SMALI_DIAMOND)
        assert m_linear.cfg_topology_hash != m_diamond.cfg_topology_hash

    def test_md_index_topdown_nonzero(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert m.md_index_topdown != 0

    def test_md_index_bottomup_nonzero(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert m.md_index_bottomup != 0

    def test_md_index_zero_for_empty(self):
        m = compute_cfg_metrics("")
        assert m.md_index_topdown == 0
        assert m.md_index_bottomup == 0

    def test_wl_minhash_length(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert len(m.wl_minhash) == 128

    def test_wl_minhash_sentinel_for_empty(self):
        m = compute_cfg_metrics("")
        assert m.wl_minhash == [255] * 128

    def test_wl_minhash_values_are_uint8(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        for val in m.wl_minhash:
            assert 0 <= val <= 255

    def test_cfg_adjacency_nonempty_for_multiblock(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert len(m.cfg_adjacency) > 0

    def test_cfg_adjacency_empty_for_empty(self):
        m = compute_cfg_metrics("")
        assert m.cfg_adjacency == []

    def test_cfg_adjacency_packed_format(self):
        """Each entry should be (src << 16) | tgt."""
        m = compute_cfg_metrics(SMALI_DIAMOND)
        for edge in m.cfg_adjacency:
            assert isinstance(edge, int)
            src = edge >> 16
            tgt = edge & 0xFFFF
            assert src < m.block_count
            assert tgt < m.block_count

    def test_block_features_exported(self):
        m = compute_cfg_metrics(SMALI_DIAMOND)
        assert len(m.block_features) == m.block_count
        for bf in m.block_features:
            assert len(bf) == 8  # 7 categories + successor_count

    def test_cfg_feature_tlsh_none_for_small(self):
        """Small methods produce None (< 50 bytes of feature data)."""
        m = compute_cfg_metrics(SMALI_LINEAR)
        # Single-block linear method — too small for TLSH
        assert m.cfg_feature_tlsh is None

    def test_loop_count_with_back_edge(self):
        m = compute_cfg_metrics(SMALI_LOOP)
        assert m.loop_count >= 1


# ===================================================================
# TestPrimeProductSmali
# ===================================================================

class TestPrimeProductSmali:

    def test_empty_returns_zero(self):
        assert compute_prime_product_smali("") == 0

    def test_none_returns_zero(self):
        assert compute_prime_product_smali(None) == 0

    def test_known_computation(self):
        """Single invoke instruction → CALL category → prime 17."""
        smali = "    invoke-virtual {p0}, Lcom/Foo;->bar()V"
        assert compute_prime_product_smali(smali) == 17

    def test_two_instructions(self):
        """const (CONST→2) * invoke (CALL→17) = 34."""
        smali = """\
    const/4 v0, 0x0
    invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
"""
        assert compute_prime_product_smali(smali) == 2 * 17

    def test_skips_directives_and_labels(self):
        """Directives, labels, and comments should be skipped."""
        smali = """\
.registers 2
.line 10
    :label
    # comment
    const/4 v0, 0x0
"""
        # Only const/4 → CONST → prime 2
        assert compute_prime_product_smali(smali) == 2

    def test_position_independent(self):
        """Reordering instructions produces the same product (multiplication is commutative)."""
        smali_a = """\
    add-int v0, v1, v2
    invoke-virtual {p0}, Lcom/Foo;->bar()V
"""
        smali_b = """\
    invoke-virtual {p0}, Lcom/Foo;->bar()V
    add-int v0, v1, v2
"""
        assert compute_prime_product_smali(smali_a) == compute_prime_product_smali(smali_b)

    def test_all_categories_have_primes(self):
        """Every category in SMALI_OP_PRIMES is a positive integer."""
        for cat, prime in SMALI_OP_PRIMES.items():
            assert isinstance(prime, int)
            assert prime >= 1

    def test_mod_2_64(self):
        """Result should be mod 2^64 (doesn't overflow)."""
        # A very long method — product stays within uint64
        smali = "\n".join(["    mul-int v0, v1, v2"] * 1000)
        result = compute_prime_product_smali(smali)
        assert 0 <= result < 2**64


# ===================================================================
# TestCallCount
# ===================================================================

class TestCallCount:

    def test_empty(self):
        assert count_call_instructions("") == 0

    def test_none(self):
        assert count_call_instructions(None) == 0

    def test_single_invoke(self):
        smali = "    invoke-virtual {p0}, Lcom/Foo;->bar()V"
        assert count_call_instructions(smali) == 1

    def test_multiple_invoke_types(self):
        assert count_call_instructions(SMALI_MULTI_CALL) == 3

    def test_non_invoke_not_counted(self):
        smali = """\
    const/4 v0, 0x0
    add-int v1, v0, v0
    return-void
"""
        assert count_call_instructions(smali) == 0


# ===================================================================
# TestSimilarityTableSlimmed
# ===================================================================

class TestSimilarityTableSlimmed:
    """Verify the similarity table no longer contains moved fields."""

    def test_export_similarity_no_block_count(self):
        """block_count should not be in similarity export columns."""
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        from unittest.mock import MagicMock

        extractor = DecompileAPK.__new__(DecompileAPK)
        extractor.log = MagicMock()
        extractor.sha256 = "a" * 64
        extractor.sha1 = "b" * 40
        extractor.md5 = "c" * 32
        extractor.analysis_results = {
            "sha256": "a" * 64,
            "sha1": "b" * 40,
            "md5": "c" * 32,
            "similarity_metrics": [{
                "smali_method_hash": "d" * 64,
                "cyclomatic_complexity": 3,
                "ssdeep_smali": None,
                "tlsh_smali": None,
                "minhash": [1, 2, 3],
            }],
        }

        export = extractor.prepare_export_data("ClickHouseExporter")
        sim_cols = export["method_similarity_metrics"]["column_names"]
        assert "block_count" not in sim_cols
        assert "edge_count" not in sim_cols
        assert "loop_count" not in sim_cols
        assert "max_depth" not in sim_cols
        assert "max_fan_out" not in sim_cols
        # These should still be there
        assert "smali_method_hash" in sim_cols
        assert "ssdeep_smali" in sim_cols
        assert "minhash" in sim_cols
        # cyclomatic_complexity moved to cfg table
        assert "cyclomatic_complexity" not in sim_cols


# ===================================================================
# TestCFGTableExport
# ===================================================================

class TestCFGTableExport:
    """Verify the new CFG table is exported correctly."""

    def test_export_cfg_table_present(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        from unittest.mock import MagicMock

        extractor = DecompileAPK.__new__(DecompileAPK)
        extractor.log = MagicMock()
        extractor.analysis_results = {
            "sha256": "a" * 64,
            "sha1": "b" * 40,
            "md5": "c" * 32,
            "cfg": [{
                "smali_method_hash": "d" * 64,
                "cfg_topology_hash": b'\x01' * 16,
                "block_count": 4,
                "edge_count": 5,
                "instructions_count": 20,
                "call_count": 3,
                "cyclomatic_complexity": 3,
                "loop_count": 1,
                "max_depth": 2,
                "max_fan_out": 2,
                "md_index_topdown": 12345,
                "md_index_bottomup": 67890,
                "prime_product_smali": 999,
                "cfg_feature_tlsh": None,
                "wl_minhash": [0] * 128,
                "bb_features": [[10, 1, 0, 2, 1, 0, 0, 2]] * 4,
                "cfg_adjacency": [0x00010000, 0x00010002],
            }],
        }

        export = extractor.prepare_export_data("ClickHouseExporter")
        assert "cfg_methods" in export
        cfg_export = export["cfg_methods"]
        assert cfg_export["table"] == "code_apk_cfg_methods"
        assert len(cfg_export["data"]) == 1
        assert "cfg_topology_hash" in cfg_export["column_names"]
        assert "prime_product_smali" in cfg_export["column_names"]
        assert "wl_minhash" in cfg_export["column_names"]
        assert "bb_features" in cfg_export["column_names"]
        assert "cfg_adjacency" in cfg_export["column_names"]
        # Verify column count matches data width
        assert len(cfg_export["column_names"]) == len(cfg_export["data"][0])
        assert len(cfg_export["column_type_names"]) == len(cfg_export["data"][0])