Xia Yao

92 papers C 13Journal 76Unranked 3
YearRankTypeTitle / Venue / Authors
2026 J jnl
Comput. Electron. Agric.
Miao Su, Shaoyang Luo, Yaze Yun, Bing Ding, Hailong Wang, Xiangming Zhou, Yan Zhu, Xia Yao, Weixing Cao, Dong Zhou
2026 J jnl
Comput. Electron. Agric.
Minglei Yu, Jiaoyang He, Wanyu Li, Xue Wang, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2025 J jnl
Comput. Electron. Agric.
Bowen Xue, Long Tian, Pablo J. Zarco-Tejada, Yuanyuan Kong, Tomas Poblete, Xue Wang, Hengbiao Zheng, Chongya Jiang, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yapeng Wu, Weiguo Yu, Yangyang Gu, Qi Zhang, Yuan Xiong, Hengbiao Zheng, Chongya Jiang, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Tai Guo, Wei Li, Mathias Disney, Yongqing Wang, Hengbiao Zheng, Dong Zhou, Chongya Jiang, Yongchao Tian, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2025 J jnl
Comput. Electron. Agric.
Dong Li, Jing M. Chen, Weiguo Yu, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2025 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yan Yan, Dong Li, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2025 J jnl
Comput. Electron. Agric.
Tai Guo, Yongqing Wang, Yangyang Gu, Yuan Fang, Hengbiao Zheng, Xiaohu Zhang, Dong Zhou, Chongya Jiang, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2025 J jnl
Comput. Electron. Agric.
Haoran Sun, Zhijian Wei, Weiguo Yu, Gaoxiang Yang, Junnan She, Hengbiao Zheng, Chongya Jiang, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng, Iftikhar Ali
2024 J jnl
Comput. Electron. Agric.
Dong Li, Jing M. Chen, Weiguo Yu, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Xiaoxu Han, Meng Zhou, Caili Guo, Hongxu Ai, Tongjie Li, Wei Li, Xiaohu Zhang, Qi Chen, Chongya Jiang, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2024 J jnl
Comput. Electron. Agric.
Yuanyuan Pan, Wenxuan Wu, Jiaoyang He, Jie Zhu, Xi Su, Wanyu Li, Dong Li, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Dong Li, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2024 J jnl
Comput. Electron. Agric.
Yangyang Gu, Yongqing Wang, Tai Guo, Caili Guo, Xue Wang, Chongya Jiang, Tao Cheng, Yan Zhu, Weixing Cao, Qi Chen, Xia Yao
2024 J jnl
Comput. Electron. Agric.
Ghulam Mustafa, Hengbiao Zheng, Imran Haider Khan, Jie Zhu, Tao Yang, Aiguo Wang, Bowen Xue, Can He, Haiyan Jia, Guoqiang Li, Tao Cheng, Weixing Cao, Yan Zhu, Xia Yao
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Dong Li, Yapeng Wu, Katja Berger, Qianliang Kuang, Wei Feng, Jing M. Chen, Wenhui Wang, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2024 J jnl
Remote. Sens.
Minglei Yu, Jiaoyang He, Wanyu Li, Hengbiao Zheng, Xue Wang, Xia Yao, Tao Cheng, Xiaohu Zhang, Yan Zhu, Weixing Cao, Yongchao Tian
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xi Su, Jiaoyang He, Wanyu Li, Yuanyuan Pan, Dong Li, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Wanyu Li, Jiaoyang He, Minglei Yu, Xi Su, Xue Wang, Hengbiao Zheng, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yongqing Wang, Yangyang Gu, Jinxin Tang, Binbin Guo, Timothy A. Warner, Caili Guo, Hengbiao Zheng, Fumiki Hosoi, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2024 J jnl
Comput. Electron. Agric.
Jie Yuan, Xu Li, Meng Zhou, Hengbiao Zheng, Zhitao Liu, Yang Liu, Ming Wen, Tao Cheng, Weixing Cao, Yan Zhu, Xia Yao
2024 J jnl
Remote. Sens.
Yanxi Zhao, Jiaoyang He, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2024 J jnl
Comput. Electron. Agric.
Gaoxiang Yang, Xingrong Li, Yuan Xiong, Meng He, Xue Wang, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yuanchao Li, Hongwei Zeng, Miao Zhang, Bingfang Wu, Yan Zhao, Xia Yao, Tao Cheng, Xingli Qin, Fangming Wu
2023 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Zhiyuan Ma, Wei Li, Timothy A. Warner, Can He, Xue Wang, Yu Zhang, Caili Guo, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2023 J jnl
Comput. Electron. Agric.
Yanxi Zhao, Haiyu Tao, Ping He, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2023 J jnl
Comput. Electron. Agric.
Yuanyuan Pan, Wenxuan Wu, Jiawen Zhang, Yuejiao Zhao, Jiayi Zhang, Yangyang Gu, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2023 J jnl
IEEE Trans. Geosci. Remote. Sens.
Yan Yan, Dong Li, Qianliang Kuang, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2023 J jnl
Comput. Electron. Agric.
Dong Li, Weiguo Yu, Hengbiao Zheng, Caili Guo, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2022 J jnl
Comput. Electron. Agric.
Jianqing Zhao, Jiawei Yan, Tianjie Xue, Suwan Wang, Xiaolei Qiu, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Xiaohu Zhang
2022 J jnl
Remote. Sens.
Jiale Jiang, Haiyan Liu, Chen Zhao, Can He, Jifeng Ma, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2022 J jnl
ISPRS Int. J. Geo Inf.
Yiyi Huang, Tao Lin, Guoqin Zhang, Wei Zhu, Nicholas A. S. Hamm, Yuqin Liu, Junmao Zhang, Xia Yao
2022 J jnl
Remote. Sens.
Ghulam Mustafa, Hengbiao Zheng, Imran Haider Khan, Long Tian, Haiyan Jia, Guoqiang Li, Tao Cheng, Yongchao Tian, Weixing Cao, Yan Zhu, Xia Yao
2022 J jnl
Remote. Sens.
Junmao Zhang, Tao Lin, Caige Sun, Meixia Lin, Yulin Zhan, Yuan Chen, Hong Ye, Xia Yao, Yiyi Huang, Guoqin Zhang, Yuqin Liu
2022 J jnl
IEEE Trans. Geosci. Remote. Sens.
Jiale Jiang, Qiaofeng Zhang, Wenhui Wang, Yapeng Wu, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2022 J jnl
Int. J. Crowd Sci.
Li Li, Hongbo Sun, Xia Yao
2021 J jnl
Remote. Sens.
Jianqing Zhao, Xiaohu Zhang, Jiawei Yan, Xiaolei Qiu, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2021 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Wenhui Wang, Yapeng Wu, Qiaofeng Zhang, Hengbiao Zheng, Xia Yao, Yan Zhu, Weixing Cao, Tao Cheng
2021 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Gaoxiang Yang, Weiguo Yu, Xia Yao, Hengbiao Zheng, Qiang Cao, Yan Zhu, Weixing Cao, Tao Cheng
2021 J jnl
Remote. Sens.
Jingshan Lu, Jan U. H. Eitel, Jyoti S. Jennewein, Jie Zhu, Hengbiao Zheng, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2021 J jnl
Remote. Sens.
Imran Haider Khan, Haiyan Liu, Wei Li, Aizhong Cao, Xue Wang, Hongyan Liu, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Xia Yao
2021 J jnl
Remote. Sens.
Jiale Jiang, Jie Zhu, Xue Wang, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Xia Yao
2021 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Yeshanbele Alebele, Wenhui Wang, Weiguo Yu, Xue Zhang, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2021 J jnl
Sensors
Baohua Yang, Jifeng Ma, Xia Yao, Weixing Cao, Yan Zhu
2021 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Jingshan Lu, Jan U. H. Eitel, Mary Engels, Jie Zhu, Yong Ma, Feng Liao, Hengbiao Zheng, Xue Wang, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2021 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Tiancheng Yang, Jingshan Lu, Feng Liao, Hao Qi, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2020 J jnl
Int. J. Crowd Sci.
Xia Yao, Hongbo Sun, Baode Fan
2020 J jnl
Comput. Electron. Agric.
Tao Cheng, Xusheng Ji, Gaoxiang Yang, Hengbiao Zheng, Jifeng Ma, Xia Yao, Yan Zhu, Weixing Cao
2020 J jnl
Comput. Electron. Agric.
Meng Zhou, Xue Ma, Kangkang Wang, Tao Cheng, Yongchao Tian, Jing Wang, Yan Zhu, Yongqiang Hu, Qingsong Niu, Lijuan Gui, Chunyu Yue, Xia Yao
2020 J jnl
Comput. Electron. Agric.
Hengbiao Zheng, Xiang Zhou, Jiaoyang He, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2020 J jnl
Remote. Sens.
Hengbiao Zheng, Jifeng Ma, Meng Zhou, Dong Li, Xia Yao, Weixing Cao, Yan Zhu, Tao Cheng
2020 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Penglei Li, Xiao Zhang, Wenhui Wang, Hengbiao Zheng, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Qi Chen, Tao Cheng
2020 J jnl
Remote. Sens.
Yeshanbele Alebele, Xue Zhang, Wenhui Wang, Gaoxiang Yang, Xia Yao, Hengbiao Zheng, Yan Zhu, Weixing Cao, Tao Cheng
2020 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Jiale Jiang, Qiaofeng Zhang, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2019 J jnl
Comput. Electron. Agric.
Min Jia, Wei Li, Kangkang Wang, Chen Zhou, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Xia Yao
2019 J jnl
Sensors
Jiale Jiang, Hengbiao Zheng, Xusheng Ji, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Reza Ehsani, Xia Yao
2019 J jnl
Comput. Electron. Agric.
Tai Guo, Yuan Fang, Tao Cheng, Yongchao Tian, Yan Zhu, Qi Chen, Xiaolei Qiu, Xia Yao
2019 J jnl
Remote. Sens.
Jiaoyang He, Ni Zhang, Xi Su, Jingshan Lu, Xia Yao, Tao Cheng, Yan Zhu, Weixing Cao, Yongchao Tian
2019 J jnl
Sensors
Baohua Yang, Mengxuan Wang, Zhengxia Sha, Bing Wang, Jianlin Chen, Xia Yao, Tao Cheng, Weixing Cao, Yan Zhu
2019 J jnl
Remote. Sens.
Wei Li, Jiale Jiang, Tai Guo, Meng Zhou, Yining Tang, Ying Wang, Yu Zhang, Tao Cheng, Yan Zhu, Weixing Cao, Xia Yao
2019 J jnl
Remote. Sens.
Min Jia, Dong Li, Roberto Colombo, Ying Wang, Xue Wang, Tao Cheng, Yan Zhu, Xia Yao, Changjun Xu, Geli Ouer, Hongying Li, Chaokun Zhang
2019 J jnl
Remote. Sens.
Jiale Jiang, Weidi Cai, Hengbiao Zheng, Tao Cheng, Yongchao Tian, Yan Zhu, Reza Ehsani, Yongqiang Hu, Qingsong Niu, Lijuan Gui, Xia Yao
2018 J jnl
Remote. Sens.
Hengbiao Zheng, Wei Li, Jiale Jiang, Yong Liu, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Yu Zhang, Xia Yao
2018 C conf
IGARSS
Dong Li, Hengbiao Zheng, Xiaoqing Xu, Ning Lu, Xia Yao, Jiale Jiang, Xue Wang, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2018 C conf
IGARSS
Long Tian, Zefu Wan, Dong Li, Jiale Jiang, Xia Yao, Qiang Cao, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2018 J jnl
Remote. Sens.
Min Jia, Jie Zhu, Chunchen Ma, Luis Alonso, Dong Li, Tao Cheng, Yongchao Tian, Yan Zhu, Xia Yao, Weixing Cao
2018 J jnl
Remote. Sens.
Xinjie Xu, Xusheng Ji, Jiale Jiang, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Qiang Cao, Hongjian Yang, Zhongkui Shi, Tao Cheng
2018 J jnl
Remote. Sens.
Hengbiao Zheng, Tao Cheng, Dong Li, Xiang Zhou, Xia Yao, Yongchao Tian, Weixing Cao, Yan Zhu
2018 J jnl
Remote. Sens.
Jiale Jiang, Xusheng Ji, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2018 conf
Agro-Geoinformatics
Dong Li, Min Jia, Jie Zhu, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao, Tao Cheng
2018 C conf
IGARSS
Jiale Jiang, Tao Cheng, Jianxi Huang, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2018 C conf
IGARSS
Min Jia, Jie Zhu, Chunchen Ma, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Xia Yao
2017 J jnl
Sensors
Kai Zhou, Xinqiang Deng, Xia Yao, Yongchao Tian, Weixing Cao, Yan Zhu, Susan L. Ustin, Tao Cheng
2017 J jnl
Remote. Sens.
Xia Yao, Ni Wang, Yong Liu, Tao Cheng, Yongchao Tian, Qi Chen, Yan Zhu
2017 J jnl
Remote. Sens.
Tao Cheng, Renzhong Song, Dong Li, Kai Zhou, Hengbiao Zheng, Xia Yao, Yongchao Tian, Weixing Cao, Yan Zhu
2016 conf
WHISPERS
Kai Zhou, Tao Cheng, Xinqiang Deng, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2016 C conf
IGARSS
Yong Liu, Tao Cheng, Yan Zhu, Yongchao Tian, Weixing Cao, Xia Yao, Ni Wang
2016 C conf
IGARSS
Chen Zhou, Min Jia, Xue Ma, Tao Cheng, Yan Zhu, Yongchao Tian, Weixing Cao, Xia Yao
2016 C conf
IGARSS
Renzhong Song, Tao Cheng, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2016 C conf
IGARSS
Hengbiao Zheng, Xiang Zhou, Tao Cheng, Xia Yao, Yongchao Tian, Weixing Cao, Yan Zhu
2016 C conf
IGARSS
Min Jia, Chen Zhou, Tao Cheng, Yongchao Tian, Yan Zhu, Weixing Cao, Xia Yao
2016 C conf
IGARSS
Jiaoyang He, Yehui Qin, Caili Guo, Liyun Zhao, Xiang Zhou, Xia Yao, Tao Cheng, Yongchao Tian
2016 conf
WHISPERS
Dong Li, Tao Cheng, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2016 C conf
IGARSS
Tao Cheng, Dong Li, Hengbiao Zheng, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2016 C conf
IGARSS
Dong Li, Tao Cheng, Xia Yao, Zhaoying Zhang, Yongchao Tian, Yan Zhu, Weixing Cao
2015 C conf
IGARSS
Tao Cheng, Dong Li, Xia Yao, Yongchao Tian, Yan Zhu, Weixing Cao
2015 J jnl
Int. J. Distributed Sens. Networks
Jun Ni, Hanping Mao, Fangrong Pang, Yan Zhu, Xia Yao, Yongchao Tian
2015 J jnl
Remote. Sens.
Xia Yao, Yu Huang, Guiyan Shang, Chen Zhou, Tao Cheng, Yongchao Tian, Weixing Cao, Yan Zhu
2014 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Xia Yao, Haijian Ren, Zhongsheng Cao, Yongchao Tian, Weixing Cao, Yan Zhu, Tao Cheng
2013 J jnl
Sensors
Xinfeng Yao, Xia Yao, Wenqing Jia, Yongchao Tian, Jun Ni, Weixing Cao, Yan Zhu
2010 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Xia Yao, Yan Zhu, Yongchao Tian, Wei Feng, Weixing Cao
2008 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yan Zhu, Xia Yao, Yongchao Tian, Xiaojun Liu, Weixing Cao
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