Mantas Simkus

140 papers A* 36A 4B 8C 1Misc 1Journal 31Unranked 55
YearRankTypeTitle / Venue / Authors
2026 J jnl
Artif. Intell.
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2025 J jnl
TGDK
Shqiponja Ahmetaj, Robert David, Axel Polleres, Mantas Simkus
2025 A* conf
WWW
Shqiponja Ahmetaj, Iovka Boneva, Jan Hidders, Katja Hose, Maxime Jakubowski, José Emilio Labra Gayo, Wim Martens, Fabio Mogavero, Filip Murlak, Cem Okulmus, Axel Polleres, Ognjen Savkovic, Mantas Simkus, Dominik Tomaszuk
2025 J jnl
CoRR
Shqiponja Ahmetaj, Iovka Boneva, Jan Hidders, Katja Hose, Maxime Jakubowski, José Emilio Labra Gayo, Wim Martens, Fabio Mogavero, Filip Murlak, Cem Okulmus, Axel Polleres, Ognjen Savkovic, Mantas Simkus, Dominik Tomaszuk
2025 A* conf
KR
Federica Di Stefano, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Reijo Jaakkola, Tomi Janhunen, Antti Kuusisto, Magdalena Ortiz, Matias Selin, Mantas Simkus
2025 A* conf
KR
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 conf
DL
Federica Di Stefano, Quentin Manière, Magdalena Ortiz, Mantas Simkus
2025 conf
ISWC (1)
Shqiponja Ahmetaj, George Konstantinidis, Magdalena Ortiz, Paolo Pareti, Mantas Simkus
2025 J jnl
CoRR
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2025 J jnl
CoRR
Shqiponja Ahmetaj, George Konstantinidis, Magdalena Ortiz, Paolo Pareti, Mantas Simkus
2025 conf
DL
Jonas Philipp Haldimann, Magdalena Ortiz, Mantas Simkus
2025 conf
JELIA (1)
Jonas Haldimann, Magdalena Ortiz, Mantas Simkus
2025 conf
DL
Federica Di Stefano, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2024 J jnl
Artif. Intell.
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2024 A* conf
KR
Federica Di Stefano, Mantas Simkus
2024 conf
Description Logics
Anouk Oudshoorn, Magdalena Ortiz, Mantas Simkus
2024 B ed.
RuleML+RR
Sabrina Kirrane, Mantas Simkus, Ahmet Soylu, Dumitru Roman
2024 A* conf
KR
Cem Okulmus, Mantas Simkus
2024 conf
Description Logics
Federica Di Stefano, Mantas Simkus
2024 A* conf
AAAI
Federica Di Stefano, Mantas Simkus
2024 conf
AMW
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2024 conf
Description Logics
Federica Di Stefano, Mantas Simkus
2023 conf
Description Logics
Piero A. Bonatti, Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2023 A* conf
IJCAI
Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2023 conf
Description Logics
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2023 conf
AMW
Diego Calvanese, Cem Okulmus, Magdalena Ortiz, Mantas Simkus
2023 conf
Description Logics
Shqiponja Ahmetaj, Magdalena Ortiz, Anouk Michelle Oudshoorn, Mantas Simkus
2023 A conf
ECAI
Shqiponja Ahmetaj, Magdalena Ortiz, Anouk Oudshoorn, Mantas Simkus
2023 conf
ISWC (Posters/Demos/Industry)
Anouk Oudshoorn, Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2023 conf
RuleML+RR (Companion)
Arka Ghosh, Mantas Simkus, Diego Calvanese
2023 J jnl
Comput. Ind.
Iris Beerepoot, Claudio Di Ciccio, Hajo A. Reijers, Stefanie Rinderle-Ma, Wasana Bandara, Andrea Burattin, Diego Calvanese, Tianwa Chen, Izack Cohen, Benoît Depaire, Gemma Di Federico, Marlon Dumas, Christopher G. J. van Dun, Tobias Fehrer, Dominik Andreas Fischer, Avigdor Gal, Marta Indulska, Vatche Isahagian, Christopher Klinkmüller, Wolfgang Kratsch, Henrik Leopold, Amy Van Looy, Hugo A. López, Sanja Lukumbuzya, Jan Mendling, Lara Meyers, Linda Moder, Marco Montali, Vinod Muthusamy, Manfred Reichert, Yara Rizk, Michael Rosemann, Maximilian Röglinger, Shazia Sadiq, Ronny Seiger, Tijs Slaats, Mantas Simkus, Ida Asadi Someh, Barbara Weber, Ingo Weber, Mathias Weske, Francesca Zerbato
2023 conf
RuleML+RR (Companion)
Romuald Esdras Wandji, Mantas Simkus, Diego Calvanese
2022 J jnl
Proc. VLDB Endow.
Shqiponja Ahmetaj, Bianca Löhnert, Magdalena Ortiz, Mantas Simkus
2022 conf
Description Logics
Federica Di Stefano, Magdalena Ortiz, Mantas Simkus
2022 ed.
RW
Mantas Simkus, Ivan Varzinczak
2022 Misc conf
ISWC
Shqiponja Ahmetaj, Robert David, Axel Polleres, Mantas Simkus
2022 conf
Datalog
Adrian Chmurovic, Mantas Simkus
2021 A* conf
IJCAI
Sanja Lukumbuzya, Mantas Simkus
2021 conf
ISWC (Posters/Demos/Industry)
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2021 conf
ISWC (Posters/Demos/Industry)
Shqiponja Ahmetaj, Bianca Loehnert, Magdalena Ortiz, Mantas Simkus
2021 conf
Problems@BPM
Diego Calvanese, Sanja Lukumbuzya, Marco Montali, Mantas Simkus
2021 conf
Description Logics
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2021 A* conf
KR
Shqiponja Ahmetaj, Robert David, Magdalena Ortiz, Axel Polleres, Bojken Shehu, Mantas Simkus
2020 J jnl
CoRR
Nadia Labai, Magdalena Ortiz, Mantas Simkus
2020 A* conf
KR
Nadia Labai, Magdalena Ortiz, Mantas Simkus
2020 A* conf
KR
Tomasz Gogacz, Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2020 J jnl
Künstliche Intell.
Diego Calvanese, Mantas Simkus
2020 J jnl
Künstliche Intell.
Thomas Schneider, Mantas Simkus
2020 A conf
ECAI
Tomasz Gogacz, Víctor Gutiérrez-Basulto, Yazmín Ibáñez-García, Filip Murlak, Magdalena Ortiz, Mantas Simkus
2020 J jnl
Artif. Intell.
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2020 A* conf
AAAI
Medina Andresel, Magdalena Ortiz, Mantas Simkus
2020 A* conf
AAAI
Sanja Lukumbuzya, Magdalena Ortiz, Mantas Simkus
2020 J jnl
Künstliche Intell.
Thomas Schneider, Mantas Simkus
2020 J jnl
Künstliche Intell.
Thomas Schneider, Mantas Simkus
2020 A* conf
WWW
Medina Andresel, Julien Corman, Magdalena Ortiz, Juan L. Reutter, Ognjen Savkovic, Mantas Simkus
2019 conf
Description Logics
Magdalena Ortiz, Sanja Pavlovic, Mantas Simkus
2019 J jnl
CoRR
Tomasz Gogacz, Víctor Gutiérrez-Basulto, Yazmín Angélica Ibáñez-García, Filip Murlak, Magdalena Ortiz, Mantas Simkus
2019 J jnl
CoRR
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2019 ed.
RuleML+RR (Supplement)
Ahmet Soylu, Sotiris Moschoyiannis, Guido Governatori, Mantas Simkus, Petros S. Stefaneas, Alexander Steen, Adrian Giurca
2019 ed.
Description Logics
Mantas Simkus, Grant E. Weddell
2019 A* conf
AAAI
Medina Andresel, Yazmín Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 A* conf
AAAI
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2018 A* conf
IJCAI
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2018 A* conf
KR
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 J jnl
CoRR
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 A conf
ICDT
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2018 conf
Description Logics
Sebastian Rudolph, Mantas Simkus
2018 conf
Description Logics
Medina Andresel, Yazmín Angélica Ibáñez-García, Magdalena Ortiz, Mantas Simkus
2018 J jnl
Fundam. Informaticae
Georg Gottlob, Andreas Pieris, Mantas Simkus
2018 B conf
LPAR
Sebastian Rudolph, Mantas Simkus
2017 conf
Description Logics
Labinot Bajraktari, Magdalena Ortiz, Mantas Simkus
2017 J jnl
ACM Trans. Comput. Log.
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2016 conf
Description Logics
Medina Andresel, Magdalena Ortiz, Mantas Simkus
2016 conf
AMW
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2016 A* conf
KR
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2016 A* conf
IJCAI
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 conf
AMW
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 conf
Description Logics
Shqiponja Ahmetaj, Magdalena Ortiz, Mantas Simkus
2016 conf
FoIKS
Shqiponja Ahmetaj, Wolfgang Fischl, Markus Kröll, Reinhard Pichler, Mantas Simkus, Sebastian Skritek
2016 conf
RR
Georg Gottlob, Andreas Pieris, Mantas Simkus
2016 A conf
ICDT
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2015 conf
RR
Thomas Eiter, Jeff Z. Pan, Patrik Schneider, Mantas Simkus, Guohui Xiao
2015 conf
RuleML
Mantas Simkus
2015 conf
Description Logics
Shqiponja Ahmetaj, Wolfgang Fischl, Reinhard Pichler, Mantas Simkus, Sebastian Skritek
2015 A* conf
LICS
Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2015 B conf
LPNMR
Thomas Eiter, Mantas Simkus
2015 conf
AMW
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2015 J jnl
J. Artif. Intell. Res.
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2015 conf
Description Logics
Nhung Ngo, Magdalena Ortiz, Mantas Simkus
2015 conf
AMW
Shqiponja Ahmetaj, Wolfgang Fischl, Reinhard Pichler, Mantas Simkus, Sebastian Skritek
2015 A* conf
WWW
Shqiponja Ahmetaj, Wolfgang Fischl, Reinhard Pichler, Mantas Simkus, Sebastian Skritek
2014 A* conf
AAAI
Diego Calvanese, Wolfgang Fischl, Reinhard Pichler, Emanuel Sallinger, Mantas Simkus
2014 conf
Description Logics
Diego Calvanese, Wolfgang Fischl, Reinhard Pichler, Emanuel Sallinger, Mantas Simkus
2014 A* conf
PODS
Georg Gottlob, Sebastian Rudolph, Mantas Simkus
2014 J jnl
CoRR
Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2014 ed.
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Riccardo Rosati, Mantas Simkus
2014 A* conf
AAAI
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
AMW
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 A* conf
KR
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Meghyn Bienvenu, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
Description Logics
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 conf
AMW
Shqiponja Ahmetaj, Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2014 J jnl
CoRR
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2014 conf
RR
Magdalena Ortiz, Mantas Simkus
2014 B conf
IFM
Diego Calvanese, Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2014 conf
Description Logics
Diego Calvanese, Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2014 conf
Description Logics
Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2014 conf
ORE
Thomas Eiter, Patrik Schneider, Mantas Simkus, Guohui Xiao
2013 A* conf
IJCAI
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2013 conf
Description Logics
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2013 J jnl
J. Artif. Intell. Res.
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2013 J jnl
CoRR
Diego Calvanese, Tomer Kotek, Mantas Simkus, Helmut Veith, Florian Zuleger
2013 conf
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus, Guohui Xiao
2013 A* conf
IJCAI
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus, Guohui Xiao
2012 conf
Description Logics
Meghyn Bienvenu, Magdalena Ortiz, Mantas Simkus
2012 J jnl
J. Comput. Syst. Sci.
Thomas Eiter, Magdalena Ortiz, Mantas Simkus
2012 conf
Reasoning Web
Georg Gottlob, Giorgio Orsi, Andreas Pieris, Mantas Simkus
2012 A* conf
AAAI
Thomas Eiter, Magdalena Ortiz, Mantas Simkus, Trung-Kien Tran, Guohui Xiao
2012 conf
Reasoning Web
Magdalena Ortiz, Mantas Simkus
2012 A* conf
KR
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2012 conf
Description Logics
Thomas Eiter, Magdalena Ortiz, Mantas Simkus, Trung-Kien Tran, Guohui Xiao
2011 A* conf
IJCAI
Diego Calvanese, Magdalena Ortiz, Mantas Simkus
2011 A* conf
IJCAI
Magdalena Ortiz, Sebastian Rudolph, Mantas Simkus
2011 conf
Description Logics
Diego Calvanese, Magdalena Ortiz, Mantas Simkus, Giorgio Stefanoni
2010 J jnl
ACM Trans. Comput. Log.
Thomas Eiter, Mantas Simkus
2010 conf
Description Logics
Meghyn Bienvenu, Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2010 A* conf
KR
Magdalena Ortiz, Sebastian Rudolph, Mantas Simkus
2009 A* conf
IJCAI
Thomas Eiter, Mantas Simkus
2009 B conf
ICLP
Mantas Simkus
2009 A* conf
IJCAI
Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2009 C conf
WoLLIC
Thomas Eiter, Carsten Lutz, Magdalena Ortiz, Mantas Simkus
2008 conf
Description Logics
Magdalena Ortiz, Mantas Simkus, Thomas Eiter
2008 B conf
JELIA
Thomas Eiter, Georg Gottlob, Magdalena Ortiz, Mantas Simkus
2008 B conf
LPAR
Thomas Eiter, Magdalena Ortiz, Mantas Simkus
2008 A* conf
AAAI
Magdalena Ortiz, Mantas Simkus, Thomas Eiter
2007 B conf
LPAR
Mantas Simkus, Thomas Eiter
2006 J jnl
CoRR
Mantas Simkus, Evaldas Taroza, Lina Lubyte, Daniel Trivellato, Zivile Norkunaite
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