Ilan Shimshoni

149 papers A* 20A 4B 10C 1Misc 1Journal 73Unranked 40
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Devon Levy, Bar Assayag, Laura Gáspár, Ilan Shimshoni, Bella Specktor-Fadida
2025 J jnl
Comput. Vis. Image Underst.
Alaa Kryeem, Noy Boutboul, Itai Bear, Shmuel Raz, Dana Eluz, Dorit Itah, Hagit Hel-Or, Ilan Shimshoni
2025 conf
VR Workshops
Muhammad Haj Ali, Rafael Damouni, Amjad Nassar, Ilan Shimshoni, Sarit Felicia Anais Szpiro
2025 J jnl
Ecol. Informatics
Inbal Schekler, Eyal Halabi, Nir Sapir, Ilan Shimshoni, Ohad Hatzofe, Yoav Perlman, Yosef Kiat
2024 A conf
WACV
Offry Hayon, Stefan Münger, Ilan Shimshoni, Ayellet Tal
2024 J jnl
Int. J. Comput. Vis.
George Martvel, Ilan Shimshoni, Anna Zamansky
2024 J jnl
Sensors
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2024 J jnl
CoRR
George Martvel, Greta Abele, Annika Bremhorst, Chiara Canori, Nareed Farhat, Giulia Pedretti, Ilan Shimshoni, Anna Zamansky
2024 conf
AVICH@AVI
Bashar Egbariya, Tsvi Kuflik, Ilan Shimshoni
2023 J jnl
Sensors
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2023 J jnl
CoRR
George Martvel, Ilan Shimshoni, Anna Zamansky
2023 J jnl
CoRR
George Martvel, Nareed Farhat, Ilan Shimshoni, Anna Zamansky
2023 J jnl
J. Imaging
Guillaume Caron, Olga Regina Pereira Bellon, Ilan Shimshoni
2023 J jnl
ISPRS Int. J. Geo Inf.
Liat David, Motti Zohar, Ilan Shimshoni
2023 conf
ICCV (Workshops)
Alaa Kryeem, Shmuel Raz, Dana Eluz, Dorit Itah, Hagit Hel-Or, Ilan Shimshoni
2022 conf
UMAP (Adjunct Publication)
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2022 J jnl
CoRR
Offry Hayon, Stefan Münger, Ilan Shimshoni, Ayellet Tal
2022 J jnl
Sensors
Nadav Eichler, Shmuel Raz, Adi Toledano-Shubi, Daphna Livne, Ilan Shimshoni, Hagit Hel-Or
2022 conf
ECCV Workshops (3)
Liran Katzir, Danny Veikherman, Valentin Dashinsky, Roman Goldenberg, Ilan Shimshoni, Nadav Rabani, Regev Cohen, Ori Kelner, Ehud Rivlin, Daniel Freedman
2022 J jnl
ACM Trans. Interact. Intell. Syst.
Rotem Kronenberg, Tsvi Kuflik, Ilan Shimshoni
2022 conf
ECCV Workshops (3)
David Sabban, Ilan Shimshoni
2022 J jnl
Sensors
Nadav Eichler, Hagit Hel-Or, Ilan Shimshoni
2022 J jnl
Mach. Vis. Appl.
Jenny Lerner, Ilan Shimshoni
2021 J jnl
Int. J. Geogr. Inf. Sci.
Motti Zohar, Ilan Shimshoni
2021 J jnl
ACM Journal on Computing and Cultural Heritage
Roy Abitbol, Ilan Shimshoni, Jonathan Ben-Dov
2021 J jnl
Pattern Recognit.
Niv Derech, Ayellet Tal, Ilan Shimshoni
2020 J jnl
CoRR
Daniel Freedman, Yochai Blau, Liran Katzir, Amit Aides, Ilan Shimshoni, Danny Veikherman, Tomer Golany, Ariel Gordon, Greg Corrado, Yossi Matias, Ehud Rivlin
2020 J jnl
IEEE Trans. Medical Imaging
Daniel Freedman, Yochai Blau, Liran Katzir, Amit Aides, Ilan Shimshoni, Danny Veikherman, Tomer Golany, Ariel Gordon, Greg Corrado, Yossi Matias, Ehud Rivlin
2020 conf
ETRA Short Papers
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2020 conf
GISTAM
Motti Zohar, Ilan Shimshoni, Fadi Khateb
2020 conf
CVPR Workshops
Alaa Masalha, Nadav Eichler, Shmuel Raz, Adi Toledano-Shubi, Daphna Niv, Ilan Shimshoni, Hagit Hel-Or
2019 conf
ICCV Workshops
Tal Hakim, Ilan Shimshoni
2019 J jnl
CoRR
Tal Hakim, Ilan Shimshoni
2019 A conf
CAiSE
Iris Reinhartz-Berger, Ilan Shimshoni, Aviva Abdal
2019 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Lior Talker, Yael Moses, Ilan Shimshoni
2019 J jnl
Neurocomputing
Murad Badarna, Ilan Shimshoni
2018 J jnl
IET Comput. Vis.
Nadav Eichler, Hagit Hel-Or, Ilan Shimshoni, Dorit Itah, Bella Gross, Shmuel Raz
2018 conf
ECCV (10)
Lior Talker, Yael Moses, Ilan Shimshoni
2018 J jnl
Future Gener. Comput. Syst.
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2018 B conf
IJCNN
Nadav Eichler, Hagit Hel-Or, Ilan Shimshoni, Dorit Itah, Bella Gross, Shmuel Raz
2018 J jnl
AI Mag.
Bruno Bouchard, Kevin Bouchard, Noam Brown, Niyati Chhaya, Eitan Farchi, Sébastien Gaboury, Christopher W. Geib, Amelie Gyrard, Kokil Jaidka, Sarah Keren, Roni Khardon, Parisa Kordjamshidi, David R. Martinez, Nicholas Mattei, Martin Michalowski, Reuth Mirsky, Joseph C. Osborn, Cem Sahin, Onn Shehory, Arash Shaban-Nejad, Amit P. Sheth, Ilan Shimshoni, Howard E. Shrobe, Arunesh Sinha, Atanu R. Sinha, Biplav Srivastava, William W. Streilein, Georgios Theocharous, K. Brent Venable, Neal Wagner, Anna Zamansky
2018 J jnl
CoRR
Niv Derech, Ayellet Tal, Ilan Shimshoni
2018 J jnl
Cogn. Comput.
Murad Badarna, Ilan Shimshoni, Gil Luria, Sara Rosenblum
2017 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Igor Kviatkovsky, Moshe Gabel, Ehud Rivlin, Ilan Shimshoni
2017 conf
3DV
Ido Haim Ferencz, Ilan Shimshoni
2017 J jnl
Image Vis. Comput.
Yehonatan Goldman, Ehud Rivlin, Ilan Shimshoni
2016 conf
MobileHCI Adjunct
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2016 J jnl
Int. J. Pattern Recognit. Artif. Intell.
Nir Sharet, Ilan Shimshoni
2016 conf
GCH
Danit Gilad-Glickman, Ilan Shimshoni
2016 conf
GCH
Stephen C. Phillips, Paul W. Walland, Stefano Modafferi, Leo Dorst, Michela Spagnuolo, Chiara Eva Catalano, Dominic Oldman, Ayellet Tal, Ilan Shimshoni, Sorin Hermon
2016 conf
MLDM
Loai AbdAllah, Ilan Shimshoni
2016 B conf
Intelligent Vehicles Symposium
Victoria Kogan, Ilan Shimshoni, Dan Levi
2016 conf
AI*CH@AI*IA
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2016 J jnl
Int. J. Appl. Math. Comput. Sci.
Loai AbedAllah, Ilan Shimshoni
2016 B conf
AVI
Moayad Mokatren, Tsvi Kuflik, Ilan Shimshoni
2016 A* conf
CVPR
Lior Talker, Yael Moses, Ilan Shimshoni
2015 J jnl
CoRR
Maria Kushnir, Ilan Shimshoni
2015 J jnl
IEEE Geosci. Remote. Sens. Lett.
Benny Kupfer, Nathan S. Netanyahu, Ilan Shimshoni
2015 J jnl
CoRR
Lior Talker, Yael Moses, Ilan Shimshoni
2015 J jnl
Comput. Medical Imaging Graph.
Assaf Cohen, Ehud Rivlin, Ilan Shimshoni, Edmond Sabo
2015 conf
CVPR Workshops
Igor Kviatkovsky, Ilan Shimshoni, Ehud Rivlin
2014 conf
MLMI
Assaf Cohen, Ehud Rivlin, Ilan Shimshoni, Edmond Sabo
2014 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Maria Kushnir, Ilan Shimshoni
2014 B conf
DaWaK
Loai AbedAllah, Ilan Shimshoni
2014 J jnl
Comput. Vis. Image Underst.
Igor Kviatkovsky, Ehud Rivlin, Ilan Shimshoni
2013 C conf
IGARSS
Benny Kupfer, Nathan S. Netanyahu, Ilan Shimshoni
2013 J jnl
Int. J. Bus. Intell. Data Min.
Loai AbdAllah, Ilan Shimshoni
2013 A* conf
CVPR
Michael Kolomenkin, Ilan Shimshoni, Ayellet Tal
2013 J jnl
ACM Journal on Computing and Cultural Heritage
Michael Kolomenkin, George Leifman, Ilan Shimshoni, Ayellet Tal
2012 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Meir Cohen, Ilan Shimshoni, Ehud Rivlin, Amit Adam
2012 conf
ACCV (4)
Maria Kushnir, Ilan Shimshoni
2012 B conf
DaWaK
Loai AbedAllah, Ilan Shimshoni
2011 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Stas Rozenfeld, Ilan Shimshoni, Michael Lindenbaum
2011 J jnl
Int. J. Comput. Vis.
Michael Kolomenkin, Ilan Shimshoni, Ayellet Tal
2011 A* conf
CVPR
Michael Kolomenkin, George Leifman, Ilan Shimshoni, Ayellet Tal
2010 J jnl
Robotics Auton. Syst.
I. Loevsky, Ilan Shimshoni
2010 A* conf
ACM Multimedia
Olga Regina Pereira Bellon, Ilan Shimshoni, Matteo Dellepiane
2009 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Yael Moses, Ilan Shimshoni
2009 A* conf
CVPR
Michael Kolomenkin, Ilan Shimshoni, Ayellet Tal
2009 conf
BMMDS/EMMSAD
Dolev Mezebovsky, Pnina Soffer, Ilan Shimshoni
2009 conf
ICCV Workshops
Michael Kolomenkin, Ilan Shimshoni, Ayellet Tal
2009 conf
VISAPP (2)
Ran Dror, Ilan Shimshoni
2008 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Liran Goshen, Ilan Shimshoni
2008 J jnl
ACM Trans. Graph.
Michael Kolomenkin, Ilan Shimshoni, Ayellet Tal
2008 J jnl
Int. J. Comput. Vis.
Liran Goshen, Ilan Shimshoni
2008 B conf
VRST
Doron Tal, Ilan Shimshoni, Ayellet Tal
2008 J jnl
J. Vis. Lang. Comput.
Igal Koifman, Ilan Shimshoni, Ayellet Tal
2008 J jnl
IEEE Trans. Syst. Man Cybern. Part B
Irina Lavva, Eyal Hameiri, Ilan Shimshoni
2008 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Amit Adam, Ehud Rivlin, Ilan Shimshoni, David Reinitz
2007 A* conf
CVPR
Stas Rozenfeld, Ilan Shimshoni, Michael Lindenbaum
2007 J jnl
Comput. Vis. Image Underst.
Guy Froimovich, Ehud Rivlin, Ilan Shimshoni, Octavian Soldea
2007 J jnl
IEEE Trans. Robotics
Ronen Lerner, Ehud Rivlin, Ilan Shimshoni
2007 conf
ICDSC
Zehavit Mandel, Ilan Shimshoni, Daniel Keren
2006 conf
ACCV (1)
Yael Moses, Ilan Shimshoni
2006 J jnl
Comput. Animat. Virtual Worlds
Oren Tropp, Ayellet Tal, Ilan Shimshoni
2006 B conf
ICIP
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2006 conf
ECCV (2)
Liran Goshen, Ilan Shimshoni
2006 conf
ICPR (2)
Ilan Shimshoni, Ehud Rivlin, Octavian Soldea
2006 conf
CVPR (2)
Michael Kolomenkin, Ilan Shimshoni
2006 A conf
IROS
Ronen Lerner, Ehud Rivlin, Ilan Shimshoni
2006 J jnl
Image Vis. Comput.
Ilan Shimshoni, Aviva Sasporta
2006 conf
CVPR (1)
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2006 J jnl
Int. J. Shape Model.
Oren Tropp, Ayellet Tal, Ilan Shimshoni, David P. Dobkin
2005 conf
CVPR (1)
Liran Goshen, Ilan Shimshoni
2005 J jnl
Int. J. Comput. Vis.
Liran Goshen, Ilan Shimshoni, P. Anandan, Daniel Keren
2005 conf
CVPR (1)
Stas Rozenfeld, Ilan Shimshoni
2004 conf
ICPR (3)
Haifeng Chen, Ilan Shimshoni, Peter Meer
2004 J jnl
Presence Teleoperators Virtual Environ.
Sara Keren, Ilan Shimshoni, Ayellet Tal
2004 conf
ICPR (2)
Alexander Kaplan, Ehud Rivlin, Ilan Shimshoni
2003 J jnl
IEEE Trans. Syst. Man Cybern. Part B
Eyal Hameiri, Ilan Shimshoni
2003 A conf
IROS
Ehud Rivlin, Ilan Shimshoni, Evgency Smolyar
2003 A* conf
ICCV
Bogdan Georgescu, Ilan Shimshoni, Peter Meer
2003 A* conf
ICCV
Liran Goshen, Ilan Shimshoni, P. Anandan, Daniel Keren
2002 conf
Theoretical Foundations of Computer Vision
Daniel Keren, Ilan Shimshoni, Liran Goshen, Michael Werman
2002 conf
3DPVT
Eyal Hameiri, Ilan Shimshoni
2002 J jnl
Vis. Comput.
Gideon Moiza, Ayellet Tal, Ilan Shimshoni, David Barnett, Yael Moses
2002 conf
HCC
Igal Koifman, Ilan Shimshoni, Ayellet Tal
2002 conf
3DPVT
Guy Froimovich, Ehud Rivlin, Ilan Shimshoni
2002 J jnl
IEEE Trans. Robotics Autom.
Ilan Shimshoni
2002 B conf
VRST
Sara Keren, Ilan Shimshoni, Ayellet Tal
2002 conf
3DPVT
Eyal Hameiri, Ilan Shimshoni
2001 J jnl
IEEE Trans. Robotics Autom.
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2001 A* conf
ICRA
Ilan Shimshoni
2001 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2001 A* conf
ICRA
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2001 A* conf
ICRA
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2000 A* conf
ICRA
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2000 J jnl
Int. J. Comput. Vis.
Ilan Shimshoni, Jean Ponce
2000 A* conf
CVPR
Amit Adam, Ehud Rivlin, Ilan Shimshoni
2000 J jnl
J. Math. Imaging Vis.
Daniel Keren, Ehud Rivlin, Ilan Shimshoni, Isaac Weiss
2000 J jnl
Int. J. Comput. Vis.
Ilan Shimshoni, Yael Moses, Michael Lindenbaum
2000 B conf
ICPR
Amit Adam, Ehud Rivlin, Ilan Shimshoni
1999 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Ilan Shimshoni, Ronen Basri, Ehud Rivlin
1999 A* conf
ICRA
Ronen Basri, Ehud Rivlin, Ilan Shimshoni
1999 J jnl
Comput. Vis. Image Underst.
Ilan Shimshoni
1999 Misc conf
ICIAP
Ilan Shimshoni, Michael Lindenbaum, Yael Moses
1999 J jnl
Int. J. Comput. Vis.
Ronen Basri, Ehud Rivlin, Ilan Shimshoni
1998 A* conf
ICRA
Daniel Keren, Ehud Rivlin, Ilan Shimshoni, Isaac Weiss
1998 conf
ICIP (3)
Daniel Keren, Ehud Rivlin, Ilan Shimshoni, Isaac Weiss
1998 A* conf
ICCV
Ronen Basri, Ehud Rivlin, Ilan Shimshoni
1997 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Ilan Shimshoni, Jean Ponce
1997 J jnl
Comput. Vis. Image Underst.
Ilan Shimshoni, Jean Ponce
1997 conf
Block Island Workshop on Vision and Control
Ronen Basri, Ehud Rivlin, Ilan Shimshoni
1996 B conf
ICPR
Ilan Shimshoni
1996 J jnl
Comput. Vis. Image Underst.
Ilan Shimshoni, Ron Kimmel, Alfred M. Bruckstein
1995 A* conf
ICCV
Ilan Shimshoni, Jean Ponce
1994 A* conf
CVPR
Ilan Shimshoni, Jean Ponce
1992 A* conf
ICRA
Jean Ponce, Ilan Shimshoni
1989 A* conf
FOCS
Amos Fiat, Shahar Moses, Adi Shamir, Ilan Shimshoni, Gábor Tardos
tests/unit/test_apk_decompile_extractor.py
← Index tests/unit/test_apk_decompile_extractor.py python
"""
Unit tests for DecompileAPK extractor, export data, and ClickHouse schemas.

Tests the main DecompileAPK extractor class following the DecompileBinja test pattern.
All analysis is mocked — no JADX/apktool/Java installation required.
"""
import hashlib
import os
import tempfile
import zipfile

import pytest
from unittest.mock import MagicMock, patch, PropertyMock
from dataclasses import asdict

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


def _create_fake_apk_file():
    """Create a minimal APK file for testing and return its path."""
    tmpdir = tempfile.mkdtemp()
    apk_path = os.path.join(tmpdir, "test.apk")
    with zipfile.ZipFile(apk_path, "w") as zf:
        zf.writestr("AndroidManifest.xml", b"<manifest/>")
        zf.writestr("classes.dex", b"dex\n035\x00" + b"\x00" * 100)
    return apk_path


# ============================================================================
# DecompileAPK Extractor Tests
# ============================================================================

class TestDecompileAPK:
    """Tests for the DecompileAPK extractor class."""

    def test_tag(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            assert ext.tag() == "apk_decompiled"
        finally:
            os.unlink(apk_path)

    def test_get_clickhouse_table(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            assert ext.get_clickhouse_table() is None
        finally:
            os.unlink(apk_path)

    def test_timeout_default(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            assert ext.APK_DECOMPILE_TIMEOUT == 600
        finally:
            os.unlink(apk_path)

    def test_timeout_from_env(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            with patch.dict(os.environ, {"APK_DECOMPILE_TIMEOUT": "900"}):
                ext = DecompileAPK(apk_path, MagicMock())
                assert ext.APK_DECOMPILE_TIMEOUT == 900
        finally:
            os.unlink(apk_path)

    def test_timeout_invalid_env(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            with patch.dict(os.environ, {"APK_DECOMPILE_TIMEOUT": "not_a_number"}):
                ext = DecompileAPK(apk_path, MagicMock())
                assert ext.APK_DECOMPILE_TIMEOUT == 600
        finally:
            os.unlink(apk_path)

    def test_calculate_md5(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            result = ext.calculate_md5("test_string")
            assert len(result) == 32
            assert result == hashlib.md5(b"test_string").hexdigest()
        finally:
            os.unlink(apk_path)

    def test_context_manager(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            with DecompileAPK(apk_path, MagicMock()) as ext:
                assert ext is not None
        finally:
            os.unlink(apk_path)

    def test_cleanup_run(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            ext.analyzer = MagicMock()
            ext.cleanup_run()
            assert ext.analyzer is None
        finally:
            os.unlink(apk_path)


# ============================================================================
# Export Data Tests
# ============================================================================

class TestPrepareExportData:
    """Tests for DecompileAPK.prepare_export_data() ClickHouse schemas."""

    def _make_extractor_with_results(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        ext = DecompileAPK(apk_path, MagicMock())
        ext.analysis_results = {
            "sha256": "a" * 64,
            "sha1": "b" * 40,
            "md5": "c" * 32,
            "decompiled_content": [
                {
                    "decompiled_method_hash": "d" * 64,
                    "decompiled_method": "public void foo() {}",
                    "decompiled_method_type": "USER",
                    "decompiled_has_string_encryption": False,
                    "decompiled_has_reflection_calls": False,
                    "decompiled_excessive_goto_count": False,
                }
            ],
            "decompiled_refs": [
                {
                    "decompiled_method_hash": "d" * 64,
                    "smali_method_hash": "e" * 64,
                    "decompiled_class_name": "com.example.Foo",
                    "decompiled_method_name": "foo",
                    "decompiled_method_signature": "()V",
                    "decompiled_method_prototype": "void foo()",
                    "functions_caller": ["bar"],
                    "functions_call": ["baz"],
                }
            ],
            "smali_content": [
                {
                    "smali_method_hash": "e" * 64,
                    "smali_method": "invoke-virtual {p0}, Lfoo;->bar()V\nreturn-void",
                    "smali_method_type": "USER",
                    "smali_instructions_count": 10,
                    "smali_register_count": 3,
                    "smali_has_string_encryption": False,
                    "smali_has_reflection_calls": False,
                    "smali_excessive_goto_count": False,
                    "smali_flattened_score": 0.0,
                    "smali_mba_score": 0.0,
                }
            ],
            "smali_refs": [
                {
                    "smali_method_hash": "e" * 64,
                    "decompiled_method_hash": "d" * 64,
                    "smali_class_name": "com.example.Foo",
                    "smali_method_name": "foo",
                    "smali_method_signature": "()V",
                    "ssdeep_smali": None,
                    "tlsh_smali": None,
                }
            ],
            "similarity_metrics": [
                {
                    "smali_method_hash": "e" * 64,
                    "cyclomatic_complexity": 2,
                    "ssdeep_smali": None,
                    "tlsh_smali": None,
                    "ssdeep_smali_normalized": None,
                    "tlsh_smali_normalized": None,
                    "minhash": [],
                }
            ],
            "cfg": [
                {
                    "smali_method_hash": "e" * 64,
                    "cfg_topology_hash": b'\x01' * 16,
                    "block_count": 3,
                    "edge_count": 3,
                    "cfg_instructions_count": 10,
                    "call_count": 1,
                    "cyclomatic_complexity": 2,
                    "loop_count": 0,
                    "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": [[5, 1, 0, 1, 1, 0, 0, 2]] * 3,
                    "cfg_adjacency": [0x00000001, 0x00000002],
                }
            ],
            "strings": [
                {
                    "string": "https://evil.example.com/payload",
                    "string_encoding": "UTF8",
                    "string_offset": 0,
                    "string_length": 31,
                    "string_entropy": 3.95,
                }
            ],
            "analysis_errors": [
                {
                    "class_name": "com.example.Foo",
                    "method_name": "bar",
                    "error_location": "jadx",
                    "error_message": "timeout",
                    "error_type": "TimeoutError",
                }
            ],
        }
        return ext, apk_path

    def test_returns_none_when_no_results(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            assert ext.prepare_export_data("ClickHouseExporter") is None
        finally:
            os.unlink(apk_path)

    def test_multi_table_flag(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            assert export["multi_table"] is True
        finally:
            os.unlink(apk_path)

    def test_all_table_keys_present(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            assert "decompiled_content" in export
            assert "decompiled_refs" in export
            assert "smali_content" in export
            assert "smali_refs" in export
            assert "method_similarity_metrics" in export
            assert "strings_raw" in export
            assert "analysis_errors" in export
        finally:
            os.unlink(apk_path)

    def test_decompiled_content_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            dc = export["decompiled_content"]
            assert dc["table"] == "code_apk_decompiled_methods_content"
            assert len(dc["column_names"]) == 7
            assert len(dc["column_type_names"]) == 7
            assert "decompiled_method_hash" in dc["column_names"]
            assert "decompiled_method" in dc["column_names"]
            assert "analysis_date" in dc["column_names"]
            assert len(dc["data"]) == 1
            assert len(dc["data"][0]) == 7
        finally:
            os.unlink(apk_path)

    def test_decompiled_refs_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            dr = export["decompiled_refs"]
            assert dr["table"] == "code_apk_decompiled_methods_references"
            assert len(dr["column_names"]) == 10
            assert len(dr["column_type_names"]) == 10
            assert "sha256" in dr["column_names"]
            assert "sha1" not in dr["column_names"]
            assert "md5" not in dr["column_names"]
            assert "functions_caller" in dr["column_names"]
            assert "functions_call" in dr["column_names"]
        finally:
            os.unlink(apk_path)

    def test_smali_content_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            sc = export["smali_content"]
            assert sc["table"] == "code_apk_smali_methods_content"
            assert len(sc["column_names"]) == 11
            assert len(sc["column_type_names"]) == 11
            assert "smali_instructions_count" in sc["column_names"]
            assert "smali_register_count" in sc["column_names"]
            assert "smali_flattened_score" in sc["column_names"]
            assert "smali_mba_score" in sc["column_names"]
        finally:
            os.unlink(apk_path)

    def test_smali_refs_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            sr = export["smali_refs"]
            assert sr["table"] == "code_apk_smali_methods_references"
            assert len(sr["column_names"]) == 7
            assert len(sr["column_type_names"]) == 7
            assert "sha1" not in sr["column_names"]
            assert "md5" not in sr["column_names"]
            assert "ssdeep_smali" not in sr["column_names"]
            assert "tlsh_smali" not in sr["column_names"]
        finally:
            os.unlink(apk_path)

    def test_similarity_metrics_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            sm = export["method_similarity_metrics"]
            assert sm["table"] == "code_apk_method_similarity_metrics"
            assert len(sm["column_names"]) == 7
            assert "minhash" in sm["column_names"]
            assert "ssdeep_smali_normalized" in sm["column_names"]
            assert "tlsh_smali_normalized" in sm["column_names"]
            # cyclomatic_complexity moved to cfg table
            assert "cyclomatic_complexity" not in sm["column_names"]
            assert "block_count" not in sm["column_names"]
            assert "loop_count" not in sm["column_names"]
        finally:
            os.unlink(apk_path)

    def test_analysis_errors_schema(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            ae = export["analysis_errors"]
            assert ae["table"] == "code_apk_analysis_errors"
            assert len(ae["column_names"]) == 9
            assert "error_hash" in ae["column_names"]
            assert "status" in ae["column_names"]
        finally:
            os.unlink(apk_path)

    def test_sha256_propagated_to_refs(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            # Check that sha256 from analysis_results appears in ref rows
            dr_row = export["decompiled_refs"]["data"][0]
            assert dr_row[0] == "a" * 64  # sha256
            # sha1 and md5 no longer included in refs
            assert "sha1" not in export["decompiled_refs"]["column_names"]
            assert "md5" not in export["decompiled_refs"]["column_names"]
        finally:
            os.unlink(apk_path)

    def test_empty_tables_not_included(self):
        from redb.extractors.decompiler.DecompileAPK import DecompileAPK
        apk_path = _create_fake_apk_file()
        try:
            ext = DecompileAPK(apk_path, MagicMock())
            ext.analysis_results = {
                "sha256": "a" * 64,
                "sha1": "b" * 40,
                "md5": "c" * 32,
                "decompiled_content": [],
                "decompiled_refs": [],
                "smali_content": [],
                "smali_refs": [],
                "similarity_metrics": [],
                "cfg": [],
                "strings": [],
                "analysis_errors": [],
            }
            export = ext.prepare_export_data("ClickHouseExporter")
            assert export == {"multi_table": True}
        finally:
            os.unlink(apk_path)

    def test_non_clickhouse_exporter_returns_none(self):
        ext, apk_path = self._make_extractor_with_results()
        try:
            result = ext.prepare_export_data("ElasticsearchExporter")
            assert result is None
        finally:
            os.unlink(apk_path)


# ============================================================================
# Dataclass Tests
# ============================================================================

class TestAPKCodeAnalysisDataclasses:
    """Tests for the new APK code analysis dataclasses."""

    def test_decompiled_method_content(self):
        from redb.models.dataclasses import APKDecompiledMethodContent
        dc = APKDecompiledMethodContent(
            decompiled_method_hash="a" * 64,
            decompiled_method="public void foo() {}",
            decompiled_method_type="USER",
        )
        assert dc.decompiled_has_string_encryption is False
        assert dc.decompiled_has_reflection_calls is False
        assert dc.decompiled_excessive_goto_count is False

    def test_decompiled_method_content_populated(self):
        from redb.models.dataclasses import APKDecompiledMethodContent
        dc = APKDecompiledMethodContent(
            decompiled_method_hash="a" * 64,
            decompiled_method="public void foo() {}",
            decompiled_method_type="USER",
            decompiled_has_string_encryption=True,
            decompiled_has_reflection_calls=True,
            decompiled_excessive_goto_count=True,
        )
        assert dc.decompiled_has_string_encryption is True
        d = asdict(dc)
        assert d["decompiled_method_hash"] == "a" * 64

    def test_decompiled_method_reference(self):
        from redb.models.dataclasses import APKDecompiledMethodReference
        dr = APKDecompiledMethodReference(
            sha256="a" * 64,
            sha1="b" * 40,
            md5="c" * 32,
            decompiled_method_hash="d" * 64,
        )
        assert dr.functions_caller == []
        assert dr.functions_call == []
        assert dr.smali_method_hash is None

    def test_smali_method_content(self):
        from redb.models.dataclasses import APKSmaliMethodContent
        sc = APKSmaliMethodContent(
            smali_method_hash="e" * 64,
            smali_method="invoke-virtual {p0}, Lfoo;->bar()V",
            smali_method_type="USER",
            smali_instructions_count=5,
            smali_register_count=3,
        )
        assert sc.smali_instructions_count == 5
        assert sc.smali_register_count == 3

    def test_smali_method_reference(self):
        from redb.models.dataclasses import APKSmaliMethodReference
        sr = APKSmaliMethodReference(
            sha256="a" * 64,
            sha1="b" * 40,
            md5="c" * 32,
            smali_method_hash="e" * 64,
        )
        assert sr.decompiled_method_hash is None
        assert sr.ssdeep_smali is None
        assert sr.tlsh_smali is None

    def test_method_similarity_metrics(self):
        from redb.models.dataclasses import APKMethodSimilarityMetrics
        ms = APKMethodSimilarityMetrics(smali_method_hash="e" * 64)
        assert ms.cyclomatic_complexity is None
        assert ms.ssdeep_smali_normalized is None
        assert ms.tlsh_smali_normalized is None
        assert ms.minhash == []

    def test_code_analysis_error(self):
        from redb.models.dataclasses import APKCodeAnalysisError
        err = APKCodeAnalysisError(
            sha256="a" * 64,
            error_location="jadx",
            error_message="timeout",
        )
        assert err.class_name is None
        assert err.method_name is None
        assert err.error_type is None


# ============================================================================
# Tag Enum Tests
# ============================================================================

class TestAPKDecompiledTag:
    """Tests for the APK_DECOMPILED tag enum."""

    def test_tag_exists(self):
        from redb.extractors.enum import Tag
        assert hasattr(Tag, "APK_DECOMPILED")

    def test_tag_value(self):
        from redb.extractors.enum import Tag
        assert Tag.APK_DECOMPILED.value == "apk_decompiled"


# ============================================================================
# Worker Integration Tests
# ============================================================================

class TestAPKWorkerDecompileIntegration:
    """Tests that DecompileAPK is registered in workers.py."""

    def test_module_registered(self):
        """Verify DecompileAPK is discoverable via the extractor registry."""
        from redb.extractor_registry import get_extractor_class
        cls = get_extractor_class("DecompileAPK")
        assert cls is not None, "DecompileAPK not found in extractor registry"
        assert cls.__name__ == "DecompileAPK"

    def test_worker_apk_dispatch_includes_decompile(self):
        import inspect
        import redb.workers as workers
        source = inspect.getsource(workers.process_binary_file)
        assert "DecompileAPK" in source