Xiangwei Zhou

112 papers A* 1B 17C 1Misc 3Journal 70Unranked 19
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Netw.
Yuwen Qian, Long Shi, Yiyang Ni, Xiangwei Zhou, Bin Cao, Jun Li
2026 J jnl
IEEE Commun. Mag.
Xiaobing Chen, Boyang Zhang, Xiangwei Zhou, Mingxuan Sun, Shuai Zhang, Songyang Zhang, Geoffrey Ye Li
2025 J jnl
IEEE Wirel. Commun. Lett.
Ruibin Lei, Xiaoxu Zhang, Fengwen Shi, Xiangwei Zhou, Zhengchun Zhou, Jiaqi Liu
2025 A* conf
AAAI
Xiaobing Chen, Xiangwei Zhou, Songyang Zhang, Mingxuan Sun
2025 J jnl
CoRR
Xiaobing Chen, Boyang Zhang, Xiangwei Zhou, Mingxuan Sun, Shuai Zhang, Songyang Zhang, Geoffrey Ye Li
2025 J jnl
CoRR
Boyang Zhang, Xiaobing Chen, Songyang Zhang, Shuai Zhang, Xiangwei Zhou, Mingxuan Sun
2025 J jnl
IEEE Internet Things J.
Xiaobing Chen, Xiangwei Zhou, Hongchao Zhang, Mingxuan Sun, Taibiao Zhao
2025 J jnl
CoRR
Taibiao Zhao, Mingxuan Sun, Hao Wang, Xiaobing Chen, Xiangwei Zhou
2025 conf
DSN-W
Cheng Chen, Yuhong Wang, Nafis S. Munir, Xiangwei Zhou, Xugui Zhou
2025 J jnl
CoRR
Cheng Chen, Yuhong Wang, Nafis S. Munir, Xiangwei Zhou, Xugui Zhou
2025 J jnl
CoRR
Jiaru Zhang, Zesong Wang, Hao Wang, Tao Song, Huai-an Su, Rui Chen, Yang Hua, Xiangwei Zhou, Ruhui Ma, Miao Pan, Haibing Guan
2025 J jnl
CoRR
Song Gao, Shusen Jing, Shuai Zhang, Yue Wang, Xiangwei Zhou, Songyang Zhang
2024 J jnl
IEEE Internet Things J.
Qingming Sun, Jinping Niu, Xiangwei Zhou, Ting Jin, Yanyan Li
2024 J jnl
IEEE Internet Things J.
Xiaobing Chen, Xiangwei Zhou, Hongchao Zhang, Mingxuan Sun, H. Vincent Poor
2024 conf
ICC
Xiaobing Chen, Xiangwei Zhou, Hongchao Zhang, Mingxuan Sun, Taibiao Zhao
2024 J jnl
CoRR
Xiaobing Chen, Xiangwei Zhou, Songyang Zhang, Mingxuan Sun
2024 J jnl
IEEE Trans. Wirel. Commun.
Liang Li, Chenpei Huang, Dian Shi, Hao Wang, Xiangwei Zhou, Minglei Shu, Miao Pan
2024 J jnl
IEEE Trans. Wirel. Commun.
Jinping Niu, Yiyao Wang, Xiangwei Zhou
2024 J jnl
IEEE Trans. Veh. Technol.
Yi Guo, Jinping Niu, Xiangwei Zhou, Tao Gu, Yanyan Li, Dingyi Fang
2024 J jnl
Secur. Saf.
Aiqun Hu, Liang Jin, Xiangyun Zhou, Feng Shu, Xiangwei Zhou
2024 J jnl
IEEE Trans. Veh. Technol.
Yiyao Wang, Jinping Niu, Gaojie Chen, Xiangwei Zhou, Yanyan Li, Shiwei Liu
2024 J jnl
IEEE Wirel. Commun.
Jinping Niu, Li Zhang, Yiyao Wang, Xiangwei Zhou, Jinsong Chen
2023 J jnl
IEEE Internet Things J.
Yuwen Qian, Wei Li, Yan Lin, Long Shi, Xiangwei Zhou, Jun Li, Feng Shu
2023 J jnl
IEEE J. Sel. Top. Signal Process.
Guo Yang, Yuwen Qian, Ke Ren, Zhen Mei, Feng Shu, Xiangwei Zhou, Wen Wu
2023 J jnl
IEEE Trans. Veh. Technol.
Yuwen Qian, Chenguang Yang, Zhen Mei, Xiangwei Zhou, Long Shi, Jun Li
2023 C conf
ICCC
Zhengrong Song, Chuan Ma, Ming Ding, Howard H. Yang, Yuwen Qian, Xiangwei Zhou
2023 J jnl
CoRR
Zhengrong Song, Chuan Ma, Ming Ding, Howard H. Yang, Yuwen Qian, Xiangwei Zhou
2023 conf
CyberC
Ping Chen, Hao Sun, Shuai Wang, Xiangwei Zhou
2022 conf
ICC
Wei Li, Jie Liao, Yuwen Qian, Xiangwei Zhou, Yan Lin
2022 J jnl
CoRR
Liang Li, Chenpei Huang, Dian Shi, Hao Wang, Xiangwei Zhou, Minglei Shu, Miao Pan
2021 J jnl
J. Commun. Inf. Networks
Fangfang Liu, Jiaxi Pan, Xiangwei Zhou, Geoffrey Ye Li
2021 J jnl
IEEE Trans. Wirel. Commun.
Mengmeng Liu, Xiangwei Zhou, Mingxuan Sun
2021 J jnl
Wirel. Commun. Mob. Comput.
Jiazhou Liu, Sa Xiao, Huayan Guo, Xiangwei Zhou, Shixin He
2021 J jnl
IEEE Commun. Mag.
Yuanwei Liu, Xiao Liu, Xinyu Gao, Xidong Mu, Xiangwei Zhou, Octavia A. Dobre, H. Vincent Poor
2021 J jnl
Sci. China Inf. Sci.
Linlin Sun, Jiahui Yan, Yuwen Qian, Feng Shu, Xiangwei Zhou
2020 J jnl
IEEE Trans. Cogn. Commun. Netw.
Zhijin Qin, Xiangwei Zhou, Lin Zhang, Yue Gao, Ying-Chang Liang, Geoffrey Ye Li
2020 B conf
GLOBECOM
Mengmeng Liu, Xiangwei Zhou, Mingxuan Sun
2020 J jnl
IEEE Netw.
Yuwen Qian, Long Shi, Jun Li, Xiangwei Zhou, Feng Shu, Jiangzhou Wang
2020 J jnl
IEEE Syst. J.
Shengjie Guo, Xiangwei Zhou, Xiangyun Zhou
2020 J jnl
CoRR
Yuanwei Liu, Xiao Liu, Xinyu Gao, Xidong Mu, Xiangwei Zhou, Octavia A. Dobre, H. Vincent Poor
2019 J jnl
CoRR
Zhijin Qin, Xiangwei Zhou, Lin Zhang, Yue Gao, Ying-Chang Liang, Geoffrey Ye Li
2019 J jnl
IEEE Syst. J.
Yuwen Qian, Xiangwei Zhou, Jun Li, Feng Shu, Dushantha Nalin K. Jayakody
2019 J jnl
IEEE Trans. Commun.
Feixiang Zhang, Xiangwei Zhou, Mingxuan Sun
2019 J jnl
IEEE Internet Things J.
Dian Shi, Jiahao Ding, Sai Mounika Errapotu, Hao Yue, Wenjun Xu, Xiangwei Zhou, Miao Pan
2019 J jnl
IEEE Internet Things J.
Yuwen Qian, Jiahui Yan, Haibing Guan, Jun Li, Xiangwei Zhou, Shengjie Guo, Dushantha Nalin K. Jayakody
2019 J jnl
IEEE Syst. J.
Shengjie Guo, Xiangwei Zhou, Sa Xiao, Mingxuan Sun
2019 J jnl
IEEE Access
Feng Shu, Shihao Yan, Dongming Wang, Xiangwei Zhou, Jiangzhou Wang
2019 J jnl
IEEE Trans. Wirel. Commun.
Nanmiao Wu, Xiangwei Zhou, Mingxuan Sun
2019 J jnl
IEEE Access
Jiaqi Liu, Gang Wu, Sa Xiao, Xiangwei Zhou, Geoffrey Ye Li, Shengjie Guo, Shaoqian Li
2019 conf
CCNC
Feixiang Zhang, Xiangwei Zhou, Mingxuan Sun
2019 J jnl
IEEE Syst. J.
Feixiang Zhang, Xiangwei Zhou, Mingxuan Sun
2019 J jnl
IEEE Trans. Commun.
Shengjie Guo, Xiangwei Zhou
2019 B conf
GLOBECOM
Guo Yang, Qi Liu, Xiangwei Zhou, Yuwen Qian, Wen Wu
2018 conf
ICC Workshops
Yuwen Qian, Hu Xie, Xiangwei Zhou, Feixiang Zhang
2018 J jnl
Ad Hoc Networks
Yu-Chen Kuo, Xiangwei Zhou
2018 B conf
GLOBECOM
Dian Shi, Jiahao Ding, Sai Mounika Errapotu, Hao Yue, Wenjun Xu, Xiangwei Zhou, Miao Pan
2018 J jnl
IEEE Access
Yuwen Qian, Xiangwei Zhou, Jun Li, Feixiang Zhang, Long Shi, Feng Shu
2018 B conf
GLOBECOM
Nanmiao Wu, Xiangwei Zhou, Mingxuan Sun
2018 conf
VTC Fall
Shengjie Guo, Xiangwei Zhou, Sa Xiao, Mingxuan Sun
2018 conf
ICC
Nanmiao Wu, Xiangwei Zhou, Mingxuan Sun
2018 conf
ICC
Jiaqi Liu, Sa Xiao, Xiangwei Zhou, Geoffrey Ye Li, Gang Wu, Shaoqian Li
2018 B conf
GLOBECOM
Jiaqi Liu, Shengjie Guo, Sa Xiao, Miao Pan, Xiangwei Zhou, Geoffrey Ye Li, Gang Wu, Shaoqian Li
2018 J jnl
CoRR
Jiaqi Liu, Shengjie Guo, Sa Xiao, Miao Pan, Xiangwei Zhou, Geoffrey Ye Li, Gang Wu, Shaoqian Li
2018 J jnl
IEEE Syst. J.
Feng Shu, Wei Zhu, Xiangwei Zhou, Jun Li, Jinhui Lu
2018 J jnl
IEEE Trans. Commun.
Nanmiao Wu, Xiangwei Zhou, Mingxuan Sun
2017 B conf
GLOBECOM
Feixiang Zhang, Xiangwei Zhou, Mingxuan Sun
2017 conf
ICC
Sa Xiao, Xiangwei Zhou, Yi Yuan-Wu, Geoffrey Ye Li, Wei Guo
2017 J jnl
IEEE Access
Jiancun Fan, Shengjie Guo, Xiangwei Zhou, Yajie Ren, Geoffrey Ye Li, Xi Chen
2017 J jnl
CoRR
Xiangwei Zhou, Mingxuan Sun, Geoffrey Ye Li, Biing-Hwang Juang
2017 J jnl
IEEE Trans. Wirel. Commun.
Sa Xiao, Xiangwei Zhou, Yi Yuan-Wu, Geoffrey Ye Li, Wei Guo
2017 J jnl
CoRR
Feng Shu, Wei Zhu, Xiangwei Zhou, Jun Li, Jinhui Lu
2017 B conf
PIMRC
Shengjie Guo, Xiangwei Zhou
2017 B conf
GLOBECOM
Nanmiao Wu, Xiangwei Zhou, Mingxuan Sun
2017 conf
VTC Fall
Yi Xie, Bo Li, Jiancun Fan, Xiangwei Zhou, Geoffrey Ye Li, Xun Li
2016 J jnl
IEEE Trans. Wirel. Commun.
Sa Xiao, Xiangwei Zhou, Daquan Feng, Yi Yuan-Wu, Geoffrey Ye Li, Wei Guo
2016 Misc conf
ICNC
Sa Xiao, Xiangwei Zhou, Daquan Feng, Yi Yuan-Wu, Geoffrey Ye Li, Wei Guo
2016 conf
ICC
Sa Xiao, Shengjie Guo, Xiangwei Zhou, Daquan Feng, Yi Yuan-Wu, Geoffrey Ye Li, Wei Guo
2016 J jnl
IEEE Trans. Commun.
Feixiang Zhang, Xiangwei Zhou, Xianghui Cao
2016 Misc conf
ICASSP
Bijia Huang, Guodong Zhao, Liying Li, Xiangwei Zhou, Zhi Chen
2016 J jnl
IEEE Wirel. Commun. Lett.
Guodong Zhao, Xin Tong, Liying Li, Xiangwei Zhou
2016 J jnl
IEEE Trans. Commun.
Guodong Zhao, Bijia Huang, Liying Li, Xiangwei Zhou
2016 B conf
GLOBECOM
Sa Xiao, Xiangwei Zhou, Geoffrey Ye Li, Wei Guo
2015 B conf
GLOBECOM
Shengjie Guo, Xiangwei Zhou
2015 J jnl
IEEE Trans. Wirel. Commun.
Xianghui Cao, Xiangwei Zhou, Lu Liu, Yu Cheng
2015 J jnl
IEEE Trans. Signal Process.
Liying Li, Guodong Zhao, Xiangwei Zhou
2014 conf
WCSP
Shengjie Guo, Xiangwei Zhou
2014 J jnl
CoRR
Xianghui Cao, Xiangwei Zhou, Yu Cheng
2014 conf
GlobalSIP
Xianghui Cao, Xiangwei Zhou, Yu Cheng
2014 B conf
GLOBECOM
Feixiang Zhang, Xiangwei Zhou
2014 conf
WCSP
Feixiang Zhang, Xiangwei Zhou
2013 conf
Allerton
Xiangwei Zhou, Hayder Al-Hraishawi, Yupeng Jia
2013 J jnl
IEEE J. Sel. Areas Commun.
Xiangwei Zhou, Geoffrey Ye Li, Guolin Sun
2012 conf
ICC
Fangfang Liu, Xiangwei Zhou, Nageen Himayat, Shu-Ping Yeh, Srikathyayani Srikanteswara, Shilpa Talwar, Chunyan Feng, Geoffrey Ye Li
2012 J jnl
IEEE Signal Process. Lett.
Xiangwei Zhou, Geoffrey Ye Li, Guolin Sun
2012 B conf
WCNC
Lu Lu, Xiangwei Zhou, Geoffrey Ye Li
2012 J jnl
EURASIP J. Wirel. Commun. Netw.
Lu Lu, Xiangwei Zhou, Uzoma Onunkwo, Geoffrey Ye Li
2011
Xiangwei Zhou
2011 J jnl
IEEE Trans. Broadcast.
Liying Li, Xiangwei Zhou, Hongbing Xu, Geoffrey Ye Li, Dandan Wang, Anthony C. K. Soong
2011 B conf
WCNC
Xiangwei Zhou, Geoffrey Ye Li, Guolin Sun
2011 B conf
GLOBECOM
Xiangwei Zhou, Geoffrey Ye Li, Guolin Sun
2011 J jnl
IEEE Trans. Wirel. Commun.
Liying Li, Xiangwei Zhou, Hongbing Xu, Geoffrey Ye Li, Dandan Wang, Anthony C. K. Soong
2010 Misc conf
ICASSP
Xiangwei Zhou, Geoffrey Ye Li, Dongdong Li, Dandan Wang, Anthony C. K. Soong
2010 conf
CCNC
Liying Li, Xiangwei Zhou, Hongbing Xu, Geoffrey Ye Li, Dandan Wang, Anthony C. K. Soong
2010 J jnl
IEEE Trans. Wirel. Commun.
Xiangwei Zhou, Geoffrey Ye Li, Dongdong Li, Dandan Wang, Anthony C. K. Soong
2010 J jnl
IEEE Trans. Commun.
Xiangwei Zhou, Jun Ma, Geoffrey Ye Li, Young Hoon Kwon, Anthony C. K. Soong
2010 J jnl
IEEE Trans. Commun.
Jun Ma, Xiangwei Zhou, Geoffrey Ye Li
2009 conf
ICC
Xiangwei Zhou, Jun Ma, Ye (Geoffrey) Li, Young Hoon Kwon, Anthony C. K. Soong
2009 B conf
GLOBECOM
Xiangwei Zhou, Ye (Geoffrey) Li, Dongdong Li, Dandan Wang, Anthony C. K. Soong
2009 J jnl
IEEE Trans. Wirel. Commun.
Xiangwei Zhou, Jun Ma, Geoffrey Ye Li, Young Hoon Kwon, Anthony C. K. Soong
2009 J jnl
Int. J. Commun. Syst.
Zhaoyang Zhang, Peng Cheng, Xiangwei Zhou, Peiliang Qiu
2008 B conf
GLOBECOM
Xiangwei Zhou, Geoffrey Ye Li, Young Hoon Kwon, Anthony C. K. Soong
2007 B conf
WCNC
Peng Cheng, Zhaoyang Zhang, Xiangwei Zhou, Jing Li, Peiliang Qiu
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