Iraj Mahdavi

82 papers Journal 76Unranked 6
YearRankTypeTitle / Venue / Authors
2025 J jnl
Comput. Ind. Eng.
Habib Heydari, Mohammad Mahdi Paydar, Iraj Mahdavi
2024 J jnl
IEEE Trans. Engineering Management
Erfan Babaee Tirkolaee, Nadi Serhan Aydin, Iraj Mahdavi
2024 J jnl
Neural Comput. Appl.
Habib Heydari, Mohammad Mahdi Paydar, Iraj Mahdavi, Alireza Khatayi
2023 J jnl
Expert Syst. Appl.
Erfan Babaee Tirkolaee, Nadi Serhan Aydin, Iraj Mahdavi
2022 J jnl
Int. J. Manuf. Res.
Hamed Sharifi, Mohammad Nagahisarchoghaei, Morteza Nagahi, Ra'ed M. Jaradat, Iraj Mahdavi, Javad Rezaeian, Mohammad Mahdi Paydar
2022 J jnl
Comput. Oper. Res.
Yaser Zarouk, Iraj Mahdavi, Javad Rezaeian, Francisco J. Santos-Arteaga
2022 J jnl
Comput. Ind. Eng.
Arash Amirteimoori, Iraj Mahdavi, Maghsud Solimanpur, Sadia Samar Ali, Erfan Babaee Tirkolaee
2021 J jnl
RAIRO Oper. Res.
Saeed Khanchehzarrin, Maral Shahmizad, Iraj Mahdavi, Nezam Mahdavi-Amiri, Peiman Ghasemi
2021 J jnl
RAIRO Oper. Res.
Yaser Zarook, Javad Rezaeian, Iraj Mahdavi, Masoud Yaghini
2021 J jnl
Comput. Ind. Eng.
Navid Gholamian, Iraj Mahdavi, Nezam Mahdavi-Amiri, Reza Tavakkoli-Moghaddam
2021 J jnl
RAIRO Oper. Res.
Bardia Behnia, Babak Shirazi, Iraj Mahdavi, Mohammad Mahdi Paydar
2021 J jnl
Comput. Ind. Eng.
Hadi Mirzagoltabar, Babak Shirazi, Iraj Mahdavi, Alireza Arshadi Khamseh
2020 J jnl
Comput. Intell.
Milad Hematian, Mir Mehdi Seyyed Esfahani, Iraj Mahdavi, Nezam Mahdavi-Amiri, Javad Rezaeian
2020 J jnl
Comput. Intell.
Erfan Babaee Tirkolaee, Shaghayegh Hadian, Gerhard-Wilhelm Weber, Iraj Mahdavi
2020 J jnl
Comput. Ind. Eng.
Behzad Maleki Vishkaei, Iraj Mahdavi, Nezam Mahdavi-Amiri, Esmaile Khorram
2020 J jnl
Appl. Soft Comput.
Milad Pakseresht, Iraj Mahdavi, Babak Shirazi, Nezam Mahdavi-Amiri
2020 J jnl
Int. J. Intell. Eng. Informatics
Babak Shirazi, Elnaz Ebrahimi, Hadi Mirzagoltabar, Iraj Mahdavi
2020 J jnl
Oper. Res.
Sahar Porkar, Iraj Mahdavi, Behzad Maleki Vishkaei, Milad Hematian
2020 J jnl
Appl. Soft Comput.
Reza Alizadeh Foroutan, Javad Rezaeian, Iraj Mahdavi
2019 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Mehrnaz Mazini, Babak Shirazi, Iraj Mahdavi
2018 J jnl
Int. J. Math. Oper. Res.
Reza Hassanzadeh, Iraj Mahdavi, Nezam Mahdavi-Amiri, Ali Tajdin
2018 J jnl
Oper. Res.
Seyyed Mostafa Mousavi, Iraj Mahdavi, Javad Rezaeian, Mostafa Zandieh
2017 J jnl
Int. J. Math. Oper. Res.
Morteza Kiani, Hany Seidgar, Iraj Mahdavi
2016 J jnl
Comput. Ind. Eng.
Zahra Alizadeh Afrouzy, Seyed Hadi Nasseri, Iraj Mahdavi
2016 J jnl
Int. J. Comput. Integr. Manuf.
Navid Gholamian, Iraj Mahdavi, Reza Tavakkoli-Moghaddam
2016 J jnl
Int. J. Math. Oper. Res.
Armaghan Heidarzade, Iraj Mahdavi, Nezam Mahdavi-Amiri
2016 J jnl
Comput. Ind. Eng.
Behrang Bootaki, Iraj Mahdavi, Mohammad Mahdi Paydar
2016 J jnl
Int. J. Comput. Integr. Manuf.
Saber Shiripour, Nezam Mahdavi-Amiri, Iraj Mahdavi
2016 J jnl
Appl. Soft Comput.
Armaghan Heidarzade, Iraj Mahdavi, Nezam Mahdavi-Amiri
2015 J jnl
Appl. Soft Comput.
Morteza Alizadeh, Iraj Mahdavi, Nezam Mahdavi-Amiri, Saber Shiripour
2015 J jnl
Int. J. Adv. Oper. Manag.
Reza Hassanzadeh, Iraj Mahdavi, Nezam Mahdavi-Amiri
2015 J jnl
Appl. Soft Comput.
Navid Gholamian, Iraj Mahdavi, Reza Tavakkoli-Moghaddam, Nezam Mahdavi-Amiri
2015 J jnl
Int. J. Comput. Integr. Manuf.
Behrang Bootaki, Iraj Mahdavi, Mohammad Mahdi Paydar
2015 J jnl
J. Math. Model. Algorithms Oper. Res.
Saber Shiripour, Nezam Mahdavi-Amiri, Iraj Mahdavi
2015 J jnl
Appl. Soft Comput.
Fatemeh Nikzad, Javad Rezaeian, Iraj Mahdavi, Iman Rastgar
2014 J jnl
Int. J. Comput. Intell. Appl.
Armaghan Heidarzade, Nezam Mahdavi-Amiri, Iraj Mahdavi
2014 J jnl
Int. J. Knowl. Based Organ.
Iraj Mahdavi, Hamed Fazlollahtabar, Nezam Mahdavi-Amiri, Mohsen Arabmaghsudi, Mohammad Hassan Yahyanejad
2014 J jnl
Comput. Ind. Eng.
Behrang Bootaki, Iraj Mahdavi, Mohammad Mahdi Paydar
2014 J jnl
Appl. Soft Comput.
Mojtaba Farhanchi, Reza Hassanzadeh, Iraj Mahdavi, Nezam Mahdavi-Amiri
2014 J jnl
J. Intell. Fuzzy Syst.
Mohammadreza Torkjazi, Hamed Fazlollahtabar, Iraj Mahdavi
2013 J jnl
Knowl. Based Syst.
Ali Hadighi, Navid Sahebjamnia, Iraj Mahdavi, Mohsen Akbarpour Shirazi
2013 J jnl
Appl. Soft Comput.
Amin Aalaei, Hamed Fazlollahtabar, Iraj Mahdavi, Nezam Mahdavi-Amiri, Mohammad Hassan Yahyanejad
2013 J jnl
Math. Comput. Model.
Reza Hassanzadeh, Iraj Mahdavi, Nezam Mahdavi-Amiri, Ali Tajdin
2013 J jnl
Int. J. Strateg. Decis. Sci.
Fatemeh Akbari, Hamed Fazlollahtabar, Iraj Mahdavi
2013 J jnl
Appl. Soft Comput.
Hamed Fazlollahtabar, Iraj Mahdavi, Amir Mohajeri
2013 J jnl
Comput. Ind.
Iraj Mahdavi, Babak Shirazi, Narges Ghorbani, Navid Sahebjamnia
2013 J jnl
Comput. Ind. Eng.
Vahid Kayvanfar, Iraj Mahdavi, G. M. Komaki
2013 J jnl
Math. Comput. Model.
Ashkan Mozdgir, Iraj Mahdavi, Iman Seyedi Badeleh, Maghsud Solimanpur
2012 J jnl
Appl. Soft Comput.
Samane Noori-Darvish, Iraj Mahdavi, Nezam Mahdavi-Amiri
2011 J jnl
Intell. Inf. Manag.
Ali Hadighi, Iraj Mahdavi
2011 J jnl
Appl. Soft Comput.
Reza Hassanzadeh, Esmaile Khorram, Iraj Mahdavi, Nezam Mahdavi-Amiri
2011 J jnl
Int. J. Comput. Intell. Syst.
Kaveh Taghizadeh, Morteza Bagherpour, Iraj Mahdavi
2011 J jnl
Expert Syst. Appl.
Iraj Mahdavi, Mahyar Movahed Nejad, Fereydoun Adbesh
2011 J jnl
Simul. Model. Pract. Theory
Babak Shirazi, Iraj Mahdavi, Nezam Mahdavi-Amiri
2010 J jnl
Wirel. Sens. Netw.
Ali Tajdin, Iraj Mahdavi, Nezam Mahdavi-Amiri, Bahram Sadeghpour Gildeh, Reza Hassanzadeh
2010 J jnl
Adv. Eng. Softw.
Babak Shirazi, Hamed Fazlollahtabar, Iraj Mahdavi
2010 J jnl
Future Gener. Comput. Syst.
Ali Bagheri, Mostafa Zandieh, Iraj Mahdavi, Mehdi Yazdani
2010 J jnl
Int. J. Appl. Decis. Sci.
Mohammad Mahdi Paydar, Iraj Mahdavi, Kathryn A. Szabat
2010 J jnl
Comput. Ind. Eng.
Mohammad Mahdi Paydar, Iraj Mahdavi, Iman Sharafuddin, Maghsud Solimanpur
2010 J jnl
Comput. Math. Appl.
Ali Tajdin, Iraj Mahdavi, Nezam Mahdavi-Amiri, Bahram Sadeghpour Gildeh
2010 J jnl
Comput. Math. Appl.
Iraj Mahdavi, Amin Aalaei, Mohammad Mahdi Paydar, Maghsud Solimanpur
2010 J jnl
J. Intell. Manuf.
Navid Sahebjamnia, Iraj Mahdavi, Namjae Cho
2010 J jnl
J. Softw. Eng. Appl.
Babak Shirazi, Iraj Mahdavi, Maghsud Solimanpur
2010 J jnl
Simul. Model. Pract. Theory
Iraj Mahdavi, Babak Shirazi, Maghsud Solimanpur
2010 J jnl
J. Softw. Eng. Appl.
Shahram Saeedi, Maghsud Solimanpur, Iraj Mahdavi, Nikbakhsh Javadian
2009 J jnl
Appl. Soft Comput.
Iraj Mahdavi, Rahele Nourifar, Armaghan Heidarzade, Nezam Mahdavi-Amiri
2009 J jnl
J. Intell. Manuf.
Iraj Mahdavi, Shima Mohebbi, Mahdi Zandakbari, Namjae Cho, Nezam Mahdavi-Amiri
2009 conf
NCM
Iraj Mahdavi, Shima Mohebbi, Namjae Cho, Rasoul Shafaei, Mahdi Zandakbari
2009 J jnl
Expert Syst. Appl.
Iraj Mahdavi, Mohammad Mahdi Paydar, Maghsud Solimanpur, Armaghan Heidarzade
2008 J jnl
Int. J. Inf. Decis. Sci.
Iraj Mahdavi, Hamed Fazlollahtabar, Ellieh Mozaffari, Morvarid Heidari, Nezam Mahdavi-Amiri
2008 J jnl
Int. J. Inf. Syst. Supply Chain Manag.
Iraj Mahdavi, Shima Mohebbi, Namjae Cho, Mohammad Mahdi Paydar
2008 J jnl
Appl. Math. Comput.
Iraj Mahdavi, Nezam Mahdavi-Amiri, Armaghan Heidarzade, Rahele Nourifar
2008 J jnl
Data Knowl. Eng.
Iraj Mahdavi, Namjae Cho, Babak Shirazi, Navid Sahebjamnia
2008 conf
ICEIS (2)
Iraj Mahdavi, Babak Shirazi, Mohammad Mahdi Paydar
2008 J jnl
Comput. Ind.
Iraj Mahdavi, Babak Shirazi, Namjae Cho, Navid Sahebjamnia, Shahram Ghobadi
2008 J jnl
J. Frankl. Inst.
Babak Javadi, Mohammad Saidi-Mehrabad, Alireza Haji, Iraj Mahdavi, Fariborz Jolai, Nezam Mahdavi-Amiri
2008 conf
ICEIS (2)
Iraj Mahdavi, Mohammad Mahdi Paydar, Babak Shirazi, Maghsud Solimanpur
2007 J jnl
Appl. Math. Comput.
Iraj Mahdavi, Babak Javadi, Kaveh Fallah-Alipour, Jannes Slomp
2007 conf
ICEIS (3)
Iraj Mahdavi, Babak Shirazi, Maghsud Solimanpur, Shahram Ghobadi
2007 conf
ICEIS (2)
Iraj Mahdavi, Babak Shirazi, Namjae Cho, Navid Sahebjamnia, Meysam Aminzadeh
2007 J jnl
Appl. Math. Comput.
Iraj Mahdavi, Namjae Cho
2007 conf
ICEIS (2)
Iraj Mahdavi, Babak Javadi, S. S. Sabet
tests/unit/test_smali_normalization.py
← Index tests/unit/test_smali_normalization.py python
"""Unit tests for smali semantic normalization.

Tests the three normalization levels (category, opcode, opcode_api),
opcode categorization, ACFG feature index mapping, and integration
with MinHash computation.
"""
import pytest

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


class TestCategorizeOpcode:
    """Tests for opcode -> semantic category mapping."""

    def test_arithmetic(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("add-int") == "ALU"
        assert categorize_opcode("mul-long/2addr") == "ALU"
        assert categorize_opcode("neg-int") == "ALU"

    def test_data_movement(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("move-result") == "MOV"
        assert categorize_opcode("const/4") == "CONST"
        assert categorize_opcode("const-string") == "CONST"

    def test_memory_access(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("iget-object") == "LOAD"
        assert categorize_opcode("sput-wide") == "STORE"
        assert categorize_opcode("aget-byte") == "LOAD"

    def test_invocation(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("invoke-virtual") == "CALL"
        assert categorize_opcode("invoke-static") == "CALL"
        assert categorize_opcode("invoke-direct") == "CALL"

    def test_control_flow(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("if-eqz") == "BRANCH"
        assert categorize_opcode("goto") == "JMP"
        assert categorize_opcode("goto/16") == "JMP"
        assert categorize_opcode("return-void") == "RET"

    def test_comparison(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("cmp-long") == "CMP"
        assert categorize_opcode("cmpl-float") == "CMP"
        assert categorize_opcode("cmpg-double") == "CMP"

    def test_conversion(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("int-to-long") == "CONV"
        assert categorize_opcode("float-to-int") == "CONV"

    def test_object_type(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("new-instance") == "ALLOC"
        assert categorize_opcode("check-cast") == "TYPE"
        assert categorize_opcode("instance-of") == "TYPE"

    def test_exception_sync(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("throw") == "EXC"
        assert categorize_opcode("monitor-enter") == "SYNC"

    def test_unknown(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("nop") == "OTHER"


class TestNormalizeInstruction:
    """Tests for single instruction normalization at various levels."""

    def test_category_level(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("add-int v0, v1, v2", "category") == "ALU"
        assert normalize_instruction("invoke-virtual {p0}, Lcom/Foo;->bar()V", "category") == "CALL"
        assert normalize_instruction("return-void", "category") == "RET"

    def test_opcode_level_strips_width(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Width variants collapse to same base
        assert normalize_instruction("add-int v0, v1, v2", "opcode") == "add"
        assert normalize_instruction("add-long v0, v2, v4", "opcode") == "add"
        assert normalize_instruction("add-float v0, v1, v2", "opcode") == "add"
        # Addressing modes collapse too
        assert normalize_instruction("add-int/2addr v0, v1", "opcode") == "add"

    def test_opcode_api_invoke(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "invoke-virtual {p0, v0}, Lcom/example/Foo;->bar(I)V"
        )
        assert result == "CALL Lcom/example/Foo;->bar(I)V"

    def test_opcode_api_invoke_no_ref(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # If somehow no method ref is found, fallback to CALL
        assert normalize_instruction("invoke-virtual {v0}") == "CALL"

    def test_opcode_api_field_load(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "LOAD Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_field_store(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iput-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "STORE Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_androguard_field_format(self):
        """androguard uses space instead of colon in field references."""
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField Ljava/lang/String;"
        )
        assert result.startswith("LOAD")
        assert "Lcom/Foo;->mField" in result

    def test_opcode_api_new_instance(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "new-instance v0, Lcom/example/MyClass;"
        )
        assert result == "ALLOC Lcom/example/MyClass;"

    def test_opcode_api_const_string(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string v0, "hello world"'
        )
        assert result == 'CONST_STR "hello world"'

    def test_opcode_api_const_string_jumbo(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string/jumbo v0, "large string"'
        )
        assert result == 'CONST_STR "large string"'

    def test_opcode_api_fallback_to_category(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Non-special instructions fall back to category
        assert normalize_instruction("add-int v0, v1, v2") == "ALU"
        assert normalize_instruction("return-void") == "RET"
        assert normalize_instruction("nop") == "OTHER"

    def test_empty_input(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("") == ""
        assert normalize_instruction("   ") == ""


class TestNormalizeMethodBody:
    """Tests for full method body normalization."""

    def test_filters_directives_labels_comments(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
.locals 2
# comment
:label_0
add-int v0, v1, v2
.line 42
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        result = normalize_method_body(body, "category")
        assert result == ["ALU", "CALL", "RET"]

    def test_opcode_api_preserves_api_refs(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->setX(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
return-void
"""
        result = normalize_method_body(body, "opcode_api")
        assert result[0] == "CONST"
        assert result[1] == "CALL Lcom/Foo;->setX(I)V"
        assert result[2] == "LOAD Lcom/Foo;->name:Ljava/lang/String;"
        assert result[3] == "RET"

    def test_empty_body(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        assert normalize_method_body("") == []
        assert normalize_method_body("\n\n") == []


class TestNormalizationWithMinHash:
    """Integration tests: normalization + MinHash computation."""

    def test_minhash_returns_signature(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        sig = compute_minhash(body)
        assert sig is not None
        assert len(sig) == 64
        assert all(0 <= v < 256 for v in sig)

    def test_minhash_register_invariance(self):
        """Same operations with different registers should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        body_b = """\
const/4 v3, 0x0
invoke-virtual {p1, v3}, Lcom/Foo;->bar(I)V
iget-object v4, p1, Lcom/Foo;->name:Ljava/lang/String;
add-int v5, v3, v4
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a == sig_b

    def test_minhash_width_invariance(self):
        """Width variants of same operations should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_int = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        body_long = """\
add-long v0, v2, v4
sub-long v6, v0, v2
mul-long v8, v0, v6
return-wide v8
"""
        sig_int = compute_minhash(body_int)
        sig_long = compute_minhash(body_long)
        # Both normalize to ALU, ALU, ALU, RET -> identical
        assert sig_int == sig_long

    def test_minhash_different_apis_differ(self):
        """Methods calling different APIs should produce different signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/crypto/AES;->encrypt([B)[B
invoke-virtual {v0}, Ljava/io/OutputStream;->write([B)V
return-void
"""
        body_b = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Ljava/lang/String;->length()I
invoke-virtual {v0}, Ljava/io/PrintStream;->println(I)V
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a != sig_b

    def test_minhash_too_few_instructions(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        assert compute_minhash("return-void\nnop") is None


class TestACFGBlockFeatures:
    """Tests for per-block ACFG feature extraction via smali_cfg."""

    def test_simple_linear_method(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 1
        assert len(metrics.block_features) == metrics.block_count
        # Each feature vector has 8 elements
        for feat in metrics.block_features:
            assert len(feat) == 8

    def test_branching_method_has_multiple_blocks(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
const/4 v0, 0x0
if-eqz v0, :cond_0
invoke-virtual {p0}, Lcom/Foo;->a()V
goto :goto_0
:cond_0
invoke-virtual {p0}, Lcom/Foo;->b()V
:goto_0
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 3
        assert len(metrics.block_features) == metrics.block_count

    def test_feature_vector_arithmetic_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        metrics = compute_cfg_metrics(body)
        assert len(metrics.block_features) == 1
        feat = metrics.block_features[0]
        # feat[0] = instr_count (4), feat[1] = arithmetic (3)
        assert feat[0] == 4
        assert feat[1] >= 3  # 3 ALU ops

    def test_feature_vector_call_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
invoke-virtual {p0}, Lcom/A;->a()V
invoke-static {v0}, Lcom/B;->b()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        feat = metrics.block_features[0]
        # feat[4] = call count
        assert feat[4] == 2