Han Huang

136 papers A* 17A 1B 5C 4Misc 3Journal 73Unranked 33
YearRankTypeTitle / Venue / Authors
2026 J jnl
Expert Syst. Appl.
Lin Luo, Ning Wu, Yu Liu, Yiming Liu, Han Huang
2026 J jnl
J. Comput. Civ. Eng.
Chao Deng, Han Huang, Ziyi Ke, Yulun Wu, Ge Gao, Ming Gu
2026 J jnl
Inf. Softw. Technol.
Shaojian Qiu, Weibiao Chen, Haiyang Liu, Shaosheng Wang, Han Huang
2025 conf
CICC
Haoyu Bai, Ling Hao, Dong Wang, Keer Gao, Han Huang, Jiazheng Zhou, Jiaqi He, Junhua Liu, Huailin Liao
2025 J jnl
Entropy
Ningning Tao, Xiaosong Chen, Fei Xie, Yongwen Zhang, Yan Xia, Xuan Ma, Han Huang, Hongyu Wang
2025 J jnl
CoRR
Han Huang, Tianyu Wang, Chaoda Peng, Tongli He, Zhifeng Hao
2025 J jnl
Eng. Appl. Artif. Intell.
Kang Liu, Tongtong Yu, Han Huang, Yueli Song, Yuling Li
2025 J jnl
CoRR
Han Huang, Chengzhi Ma, Yuxin Zhao, Qingyao Wang, Xinglong Xiao, Xiulin Shu, Zhifeng Hao
2025 J jnl
IEEE Trans. Parallel Distributed Syst.
Han Huang, Tengyang Zheng, Tianxing Yang, Yang Ye, Siran Liu, Zhe Tang, Shengyou Lu, Guangnan Feng, Zhiguang Chen, Dan Huang
2025 J jnl
CoRR
Dongxin Lyu, Han Huang, Cheng Tan, Zimu Li
2025 J jnl
CoRR
Ningning Tao, Fei Xie, Baoxiang Pan, Hongyu Wang, Han Huang, Zhongpu Qiu, Ke Gui, Jiali Luo, Xiaosong Chen
2025 B conf
TEI
Han Huang, Tingyu Cheng, Jinzhi Ye, Yuhui Zhao, Yiyang Wang, Haiqing Xu, Abigale Stangl, HyunJoo Oh
2025 J jnl
J. Intell. Manuf.
Sangkyoung Lee, Zhuoxiao Chen, Yadan Luo, Xuliang Li, Mingyuan Lu, Zi Helen Huang, Han Huang
2025 J jnl
CoRR
Chao Song, Zhiyuan Liu, Han Huang, Liang Wang, Qiong Wang, Jianyu Shi, Hui Yu, Yihang Zhou, Yang Zhang
2025 A* conf
ICLR
Yifan Du, Yuqi Huo, Kun Zhou, Zijia Zhao, Haoyu Lu, Han Huang, Xin Zhao, Bingning Wang, Weipeng Chen, Ji-Rong Wen
2025 A* conf
AAAI
Han Huang, Yulun Wu, Chao Deng, Ge Gao, Ming Gu, Yu-Shen Liu
2025 J jnl
CoRR
Han Huang, Yulun Wu, Chao Deng, Ge Gao, Ming Gu, Yu-Shen Liu
2025 A conf
SC
Han Huang, Jiabin Xie, Guangnan Feng, Xianwei Zhang, Dan Huang, Zhiguang Chen, Yutong Lu
2025 J jnl
J. Imaging
Bohan Chen, Bowen Qu, Yu Zhou, Han Huang, Jianing Guo, Yanning Xian, Longxiang Ma, Jinxuan Yu, Jingyu Chen
2025 A* conf
CVPR
Wenyuan Zhang, Yixiao Yang, Han Huang, Liang Han, Kanle Shi, Yu-Shen Liu, Zhizhong Han
2025 J jnl
CoRR
Wenyuan Zhang, Yixiao Yang, Han Huang, Liang Han, Kanle Shi, Yu-Shen Liu, Zhizhong Han
2025 J jnl
CoRR
Min Huang, Pengxiang Chen, Han Huang, Tonli He, Yushan Zhang, Zhifeng Hao
2025 A* conf
ICLR
Zhiyuan Liu, Yanchen Luo, Han Huang, Enzhi Zhang, Sihang Li, Junfeng Fang, Yaorui Shi, Xiang Wang, Kenji Kawaguchi, Tat-Seng Chua
2025 J jnl
CoRR
Zhiyuan Liu, Yanchen Luo, Han Huang, Enzhi Zhang, Sihang Li, Junfeng Fang, Yaorui Shi, Xiang Wang, Kenji Kawaguchi, Tat-Seng Chua
2025 A* conf
COLT
Han Huang, Elchanan Mossel
2025 J jnl
CoRR
Ziwen Li, Xin Wang, Hanlue Zhang, Runnan Chen, Runqi Lin, Xiao He, Han Huang, Yandong Guo, Fakhri Karray, Tongliang Liu, Mingming Gong
2025 J jnl
CoRR
Han Huang, Pakawut Jiradilok, Elchanan Mossel
2025 J jnl
CoRR
Min Huang, Pengxiang Chen, Han Huang, Tongli He, Yushan Zhang, Zhifeng Hao
2025 J jnl
Int. J. Comput. Sci. Math.
Hui Hu, Wai Chong Chia, Yunli Lee, Kok-Lim Alvin Yau, Han Huang
2025 J jnl
CoRR
Han Huang, Han Sun, Ningzhong Liu, Huiyu Zhou, Jiaquan Shen
2025 conf
PRCV (10)
Han Huang, Han Sun, Ningzhong Liu, Huiyu Zhou, Jiaquan Shen
2025 A* conf
AAAI
Yulun Wu, Han Huang, Wenyuan Zhang, Chao Deng, Ge Gao, Ming Gu, Yu-Shen Liu
2025 J jnl
CoRR
Yulun Wu, Han Huang, Wenyuan Zhang, Chao Deng, Ge Gao, Ming Gu, Yu-Shen Liu
2025 J jnl
CCF Trans. High Perform. Comput.
Hengzhong Liang, Han Huang, Xianwei Zhang
2025 J jnl
Medical Image Anal.
Ruobing Huang, Yinyu Ye, Ao Chang, Han Huang, Zijie Zheng, Long Tan, Guoxue Tang, Man Luo, Xiuwen Yi, Pan Liu, Jiayi Wu, Baoming Luo, Dong Ni
2025 J jnl
J. Comput. Phys.
Han Huang, Rongjie Lai
2024 C conf
ISCAS
Haoyu Bai, Dong Wang, Sihao Zhang, Han Huang, Junhua Liu, Huailin Liao
2024 J jnl
CoRR
Han Huang, Yuqi Huo, Zijia Zhao, Haoyu Lu, Shu Wu, Bingning Wang, Qiang Liu, Weipeng Chen, Liang Wang
2024 J jnl
IEEE Trans. Engineering Management
Han Huang, Jie Xiong, Lu Xu, Zhe Yuan, Chun Liu
2024 J jnl
Pattern Recognit.
Yan Huang, Zhang Zhang, Yan Huang, Qiang Wu, Han Huang, Yi Zhong, Liang Wang
2024 J jnl
CoRR
Yifan Du, Yuqi Huo, Kun Zhou, Zijia Zhao, Haoyu Lu, Han Huang, Wayne Xin Zhao, Bingning Wang, Weipeng Chen, Ji-Rong Wen
2024 B conf
PPoPP
Jiabin Xie, Guangnan Feng, Han Huang, Junxuan Feng, Zhiguang Chen, Yutong Lu
2024 J jnl
CoRR
Han Huang, Haitian Zhong, Qiang Liu, Shu Wu, Liang Wang, Tieniu Tan
2024 A* conf
CHI
Fernanda De La Torre, Cathy Mengying Fang, Han Huang, Andrzej Banburski-Fahey, Judith Amores Fernandez, Jaron Lanier
2024 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Han Huang, Leilei Sun, Bowen Du, Weifeng Lv
2024 A* conf
NeurIPS
Han Huang, Elchanan Mossel
2024 A* conf
AAAI
Han Huang, Yulun Wu, Junsheng Zhou, Ge Gao, Ming Gu, Yu-Shen Liu
2024 A* conf
COLT
Han Huang, Pakawut Jiradilok, Elchanan Mossel
2024 J jnl
CoRR
Han Huang, Pakawut Jiradilok, Elchanan Mossel
2024 J jnl
CoRR
Tingyu Cheng, Zhihan Zhang, Han Huang, Yingting Gao, Wei Sun, Gregory D. Abowd, HyunJoo Oh, Josiah D. Hester
2024 J jnl
Bioinform.
Han Huang, Ziqian Lin, Dongchen He, Liang Hong, Yu Li
2024 J jnl
CoRR
Han Huang, Rongjie Lai
2024 A* conf
NeurIPS
Han Huang, Haitian Zhong, Tao Yu, Qiang Liu, Shu Wu, Liang Wang, Tieniu Tan
2023 J jnl
IEEE Trans. Intell. Transp. Syst.
Bin Ji, Han Huang, Samson S. Yu
2023 J jnl
IEEE Trans. Robotics
Liu Yang, Tieshan Zhang, Han Huang, Hao Ren, Wanfeng Shang, Yajing Shen
2023 J jnl
J. Comput. Phys.
Han Huang, Jiajia Yu, Jie Chen, Rongjie Lai
2023 A* conf
AAAI
Han Huang, Leilei Sun, Bowen Du, Weifeng Lv
2023 J jnl
CoRR
Han Huang, Leilei Sun, Bowen Du, Weifeng Lv
2023 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Han Huang, Li Shen, Chaoyang He, Weisheng Dong, Wei Liu
2023 J jnl
IEEE Access
Qian Zhou, Shiling Zhang, Yanjun Li, Zhe Li, Qin Fang, Han Huang
2023 J jnl
CoRR
Fernanda De La Torre, Cathy Mengying Fang, Han Huang, Andrzej Banburski-Fahey, Judith Amores Fernandez, Jaron Lanier
2023 J jnl
CoRR
Han Huang, Leilei Sun, Bowen Du, Weifeng Lv
2023 conf
MICCAI (5)
Junyu Li, Han Huang, Dong Ni, Wufeng Xue, Dongmei Zhu, Jun Cheng
2023 J jnl
CoRR
Junyu Li, Han Huang, Dong Ni, Wufeng Xue, Dongmei Zhu, Jun Cheng
2023 J jnl
CoRR
Han Huang, Yulun Wu, Junsheng Zhou, Ge Gao, Ming Gu, Yu-Shen Liu
2023 A* conf
ICDE
Mingzhe Liu, Han Huang, Hao Feng, Leilei Sun, Bowen Du, Yanjie Fu
2023 J jnl
CoRR
Mingzhe Liu, Han Huang, Hao Feng, Leilei Sun, Bowen Du, Yanjie Fu
2023 J jnl
CoRR
Han Huang, Fernanda De La Torre, Cathy Mengying Fang, Andrzej Banburski-Fahey, Judith Amores, Jaron Lanier
2023 J jnl
Technol. Anal. Strateg. Manag.
Jie Xiong, Ke Wang, Jie Yan, Lu Xu, Han Huang
2023 J jnl
CoRR
Han Huang, Yan Huang, Liang Wang
2022 conf
ECCV Workshops (7)
Hairong Luo, Ge Gao, Han Huang, Ziyi Ke, Cheng Peng, Ming Gu
2022 J jnl
CoRR
Hairong Luo, Ge Gao, Han Huang, Ziyi Ke, Cheng Peng, Ming Gu
2022 J jnl
CoRR
Han Huang, Konstantin E. Tikhomirov
2022 J jnl
CoRR
Han Huang, Jiajia Yu, Jie Chen, Rongjie Lai
2022 J jnl
Remote. Sens.
Han Huang, Yongsheng Wang, Yamei Li, Yang Zhou, Zhaoqi Zeng
2022 A* conf
ICDM
Han Huang, Leilei Sun, Bowen Du, Yanjie Fu, Weifeng Lv
2022 J jnl
CoRR
Han Huang, Leilei Sun, Bowen Du, Yanjie Fu, Weifeng Lv
2022 B conf
LREC
Han Huang, Tomoyuki Kajiwara, Yuki Arase
2022 conf
CVPR Workshops
Yawei Li, Kai Zhang, Radu Timofte, Luc Van Gool, Fangyuan Kong, Mingxi Li, Songwei Liu, Zongcai Du, Ding Liu, Chenhui Zhou, Jingyi Chen, Qingrui Han, Zheyuan Li, Yingqi Liu, Xiangyu Chen, Haoming Cai, Yu Qiao, Chao Dong, Long Sun, Jinshan Pan, Yi Zhu, Zhikai Zong, Xiaoxiao Liu, Zheng Hui, Tao Yang, Peiran Ren, Xuansong Xie, Xian-Sheng Hua, Yanbo Wang, Xiaozhong Ji, Chuming Lin, Donghao Luo, Ying Tai, Chengjie Wang, Zhizhong Zhang, Yuan Xie, Shen Cheng, Ziwei Luo, Lei Yu, Zhihong Wen, Qi Wu, Youwei Li, Haoqiang Fan, Jian Sun, Shuaicheng Liu, Yuanfei Huang, Meiguang Jin, Hua Huang, Jing Liu, Xinjian Zhang, Yan Wang, Lingshun Long, Gen Li, Yuanfan Zhang, Zuowei Cao, Lei Sun, Panaetov Alexander, Yucong Wang, Minjie Cai, Li Wang, Lu Tian, Zheyuan Wang, Hongbing Ma, Jie Liu, Chao Chen, Yidong Cai, Jie Tang, Gangshan Wu, Weiran Wang, Shirui Huang, Honglei Lu, Huan Liu, Keyan Wang, Jun Chen, Shi Chen, Yuchun Miao, Zimo Huang, Lefei Zhang, Mustafa Ayazoglu, Wei Xiong, Chengyi Xiong, Fei Wang, Hao Li, Ruimian Wen, Zhijing Yang, Wenbin Zou, Weixin Zheng, Tian Ye, Yuncheng Zhang, Xiangzhen Kong, Aditya Arora, Syed Waqas Zamir, Salman H. Khan, Munawar Hayat, Fahad Shahbaz Khan, Dandan Gao, Dengwen Zhou, Qian Ning, Jingzhu Tang, Han Huang, Yufei Wang, Zhangheng Peng, Haobo Li, Wenxue Guan, Shenghua Gong, Xin Li, Jun Liu, Wanjun Wang, Kun Zeng, Hanjiang Lin, Xinyu Chen, Jinsheng Fang
2022 conf
MICCAI (3)
Han Huang, Yijie Dong, Xiaohong Jia, Jianqiao Zhou, Dong Ni, Jun Cheng, Ruobing Huang
2022 J jnl
CoRR
Han Huang, Yijie Dong, Xiaohong Jia, Jianqiao Zhou, Dong Ni, Jun Cheng, Ruobing Huang
2022 conf
ICDLT
Zengquan Yang, Han Huang, Fuming Xia, Zhen Shi
2022 conf
ICITE
Zhengxiao Sang, Fuming Xia, Han Huang, Zhen Shi
2022 J jnl
Appl. Intell.
Yanjing Sun, Han Huang, Xiao Yun, Bin Yang, Kaiwen Dong
2021 conf
EMNLP (1)
Han Huang, Tomoyuki Kajiwara, Yuki Arase
2021 conf
EEET
Bin Zhang, Yanjun Li, Han Huang, Xuemeng Wang, Zijian Dong, Zhanlong Zhang
2021 J jnl
Scientometrics
Xiaoguang Wang, Hongyu Wang, Han Huang
2021 J jnl
Int. J. Unconv. Comput.
Songhai Fan, Yiyu Gong, Gexiang Zhang, Yun Xiao, Haina Rong, Prithwineel Paul, Xiaomin Ma, Han Huang, Marian Gheorghe
2021 J jnl
CoRR
Han Huang, Li Shen, Chaoyang He, Weisheng Dong, Haozhi Huang, Guangming Shi
2021 conf
CSAI
Yuncheng Sang, Han Huang, Shuangqing Ma, Shouwen Cai, Zhen Shi
2021 A* conf
KDD
Han Huang, Leilei Sun, Bowen Du, Chuanren Liu, Weifeng Lv, Hui Xiong
2021 conf
ISPA/BDCloud/SocialCom/SustainCom
Han Huang, Hua Luan
2020 A* conf
IJCAI
Xiaotong Lu, Han Huang, Weisheng Dong, Xin Li, Guangming Shi
2020 B conf
ISIT
Jing Hao, Han Huang, Galyna V. Livshyts, Konstantin E. Tikhomirov
2020 conf
ICIC (1)
Han Huang, Yong-Li Ma
2020 J jnl
Sci. Program.
Xiaoping Chen, Jiamin Lin, Han Huang, Yunpeng Huang
2020 conf
ICA3PP (1)
Han Huang, Hua Luan
2020 J jnl
Random Struct. Algorithms
Han Huang, Mark Rudelson
2019 conf
MMAsia
Zhengjun Xu, Haitao Zhang, Han Huang
2019 C conf
IECON
Han Huang, Grazia Todeschini, Surya Santoso
2019 J jnl
CoRR
Jing Hao, Han Huang, Galyna V. Livshyts, Konstantin E. Tikhomirov
2019 J jnl
Comput. Biol. Chem.
Han Huang, Chen-Liang Chu, Lin Chen, Dong Shui
2019 conf
NEMS
Sören Zimmermann, Han Huang
2019 conf
ISPA/BDCloud/SocialCom/SustainCom
Tongyu Guo, Haitao Zhang, Han Huang, Jianli Guo, Chenze He
2019 J jnl
J. Comput. Neurosci.
Victor J. Barranca, Han Huang, Genji Kawakita
2019 B conf
ICPADS
Han Huang, Haitao Zhang, Tongyu Guo, Jianli Guo, Chenze He
2019 J jnl
J. Lond. Math. Soc.
Han Huang, Boaz A. Slomka, Elisabeth M. Werner
2018 conf
ICIC (1)
Han Huang, Zhi-Kai Huang, Yong-Li Ma, Ling-Ying Hou
2018 C conf
IECON
Han Huang, L. Zhang, B. V. P. Chong
2018 conf
ICIC (2)
Fangyuan Ding, Min Huang, Yongsheng Deng, Han Huang
2017 J jnl
IEEE Syst. J.
Yang Liu, Shiyan Hu, Han Huang, Rajiv Ranjan, Albert Y. Zomaya, Lizhe Wang
2017 conf
ICIC (1)
Han Huang, Ling-Ying Hou
2016 J jnl
Neurocomputing
Zhi-Kai Huang, Zhihong Li, Han Huang, Zhibiao Li, Ling-Ying Hou
2016 conf
BIC-TA (2)
Yueting Xu, Ziheng Wu, Han Huang, Tianxiong Yang, Pan Yu, Erang Lu
2015 conf
ICIC (1)
Zhi-Kai Huang, Fang Wang, Jun-Mei Xi, Han Huang
2015 J jnl
J. Circuits Syst. Comput.
Lin Liu, Xin Yang, Han Huang, Shiyan Hu
2014 J jnl
Int. J. Mob. Commun.
Hong Zhang, Yaobin Lu, Sumeet Gupta, Ling Zhao, Aihui Chen, Han Huang
2013 Misc conf
ICMLC
Weidi Xu, Han Huang, Ji Luo, Hao-Xun Zhan
2013 conf
BIC-TA
Florentin Ipate, Raluca Lefticaru, Laurentiu Mierla, Luis Valencia-Cabrera, Han Huang, Gexiang Zhang, Ciprian Dragomir, Mario J. Pérez-Jiménez, Marian Gheorghe
2013 J jnl
Int. J. Autom. Technol.
Jun Shimizu, Libo Zhou, Takeyuki Yamamoto, Hirotaka Ojima, Teppei Onuki, Han Huang
2012 conf
CDC
Jun-Qing Chen, Linpeng Huang, Han Huang, Chengyuan Yu, Chen Li
2012 conf
ICAISC (SIDE-EC)
Hao Liu, Han Huang, Shusen Liu
2012 conf
ICSI (1)
Hao Liu, Han Huang, Yingjun Wu, Zhenhua Huang
2012 conf
WISM
Xiaoyong Zhao, Yang Yang, Li-Li Sun, Han Huang
2011 J jnl
J. Softw.
Weibin Wu, Tiansheng Hong, Su Li, Jinxing Guo, Han Huang, Zhilin Mai, Dongdong Li
2010 Misc conf
ICNC
Zhongming Yang, Han Huang
2010 conf
CCTA (3)
Zhigang Wu, Yichuan Bai, Han Huang, Wenxin Li, Zhimei Li, Zhihong Li
2008 conf
CCTA (1)
Han Huang, Edwin G. Rajotte, Zhihong Li, Ke Chen, Shengfang Zhang
2008 conf
ICNC (7)
Guangchao Wu, Han Huang
2007 conf
IITA
Shi-xu Shi, Qi Lun Zheng, Han Huang
2005 conf
ISCAS (2)
Shiyan Hu, Han Huang, Dariusz Czarkowski
2004 C conf
CIT
Shiyan Hu, Han Huang
2004 conf
VTC Fall (2)
Han Huang, Huarui Yin, Guo Wei, Jinkang Zhu
2000 A* conf
ICRA
Zhiming Gong, Xiaoqi Chen, Han Huang
1999 Misc conf
ICIAP
Daw-Tung Lin, Han Huang
1969 J jnl
IEEE Trans. Inf. Theory
Azriel Rosenfeld, Han Huang, Victor H. Schneider
tests/unit/test_apk_strings_ioc.py
← Index tests/unit/test_apk_strings_ioc.py python
"""Tests for APK string extraction and IOC extraction integration.

Covers:
- APKCodeAnalyzer._extract_strings() — string extraction from DEX objects
- APKCodeAnalyzer._string_entropy() — Shannon entropy computation
- DecompileAPK strings export table schema
- IOCExtractorFromResults with APK-format analysis_results
- Worker IOC wiring for APK
"""
import os
import tempfile
from dataclasses import asdict
from unittest.mock import MagicMock, patch

import pytest

from redb.extractors.ioc_extractor.ioc_extractor import IOCExtractorFromResults
from redb.extractors.ioc_extractor.standalone_ioc_extractor import (
    IOCType,
    SourceType,
)

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


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _make_analyzer(min_instructions=1):
    """Create an APKCodeAnalyzer with mocked dependencies."""
    with patch(
        "redb.extractors.decompiler.apk.analyzer.JADXDecompiler"
    ), patch(
        "redb.extractors.decompiler.apk.analyzer.ApktoolDisassembler"
    ):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
        analyzer = APKCodeAnalyzer("/fake/path.apk")
        analyzer.min_instructions = min_instructions
        return analyzer


def _make_mock_dex(strings):
    """Create a mock DEX object that returns the given strings."""
    dex = MagicMock()
    dex.get_strings.return_value = strings
    return dex


def _create_fake_apk_file():
    """Create a temporary file to act as a fake APK."""
    fd, path = tempfile.mkstemp(suffix=".apk")
    os.write(fd, b"PK\x03\x04fake apk content for hashing")
    os.close(fd)
    return path


# ---------------------------------------------------------------------------
# Tests: _string_entropy
# ---------------------------------------------------------------------------

class TestStringEntropy:
    """Tests for Shannon entropy computation."""

    def test_empty_string(self):
        analyzer = _make_analyzer()
        assert analyzer._string_entropy("") == 0.0

    def test_single_char(self):
        analyzer = _make_analyzer()
        assert analyzer._string_entropy("a") == 0.0

    def test_repeated_char(self):
        analyzer = _make_analyzer()
        assert analyzer._string_entropy("aaaa") == 0.0

    def test_two_equal_chars(self):
        analyzer = _make_analyzer()
        # "ab" -> entropy = 1.0
        assert abs(analyzer._string_entropy("ab") - 1.0) < 0.01

    def test_higher_entropy(self):
        analyzer = _make_analyzer()
        # More variety = higher entropy
        low = analyzer._string_entropy("aabb")
        high = analyzer._string_entropy("abcd")
        assert high > low

    def test_url_string_entropy(self):
        analyzer = _make_analyzer()
        entropy = analyzer._string_entropy("https://evil.com/payload")
        assert entropy > 2.0  # URLs have moderate entropy


# ---------------------------------------------------------------------------
# Tests: _extract_strings
# ---------------------------------------------------------------------------

class TestExtractStrings:
    """Tests for DEX string extraction."""

    def test_basic_extraction(self):
        analyzer = _make_analyzer()
        dex = _make_mock_dex(["hello", "world"])
        result = analyzer._extract_strings([dex])

        assert len(result) == 2
        assert result[0]["string"] == "hello"
        assert result[1]["string"] == "world"

    def test_string_fields_present(self):
        analyzer = _make_analyzer()
        dex = _make_mock_dex(["test_string"])
        result = analyzer._extract_strings([dex])

        entry = result[0]
        assert "string" in entry
        assert "string_encoding" in entry
        assert "string_offset" in entry
        assert "string_length" in entry
        assert "string_entropy" in entry
        assert entry["string_encoding"] == "UTF8"
        assert entry["string_length"] == len("test_string")

    def test_deduplication_across_dex(self):
        """Same string in multiple DEX files is only extracted once."""
        analyzer = _make_analyzer()
        dex1 = _make_mock_dex(["shared", "unique1"])
        dex2 = _make_mock_dex(["shared", "unique2"])
        result = analyzer._extract_strings([dex1, dex2])

        string_values = [s["string"] for s in result]
        assert string_values.count("shared") == 1
        assert "unique1" in string_values
        assert "unique2" in string_values
        assert len(result) == 3

    def test_empty_strings_filtered(self):
        analyzer = _make_analyzer()
        dex = _make_mock_dex(["", "valid", None, "also_valid"])
        result = analyzer._extract_strings([dex])

        string_values = [s["string"] for s in result]
        assert "" not in string_values
        assert None not in string_values
        assert "valid" in string_values
        assert "also_valid" in string_values

    def test_no_dex_files(self):
        analyzer = _make_analyzer()
        result = analyzer._extract_strings([])
        assert result == []

    def test_dex_get_strings_returns_none(self):
        analyzer = _make_analyzer()
        dex = MagicMock()
        dex.get_strings.return_value = None
        result = analyzer._extract_strings([dex])
        assert result == []

    def test_dex_get_strings_exception(self):
        analyzer = _make_analyzer()
        dex = MagicMock()
        dex.get_strings.side_effect = RuntimeError("corrupt DEX")
        result = analyzer._extract_strings([dex])
        assert result == []

    def test_entropy_computed(self):
        analyzer = _make_analyzer()
        dex = _make_mock_dex(["abcdefgh"])
        result = analyzer._extract_strings([dex])
        assert result[0]["string_entropy"] > 0.0

    def test_incremental_offsets(self):
        """String offsets are incremented sequentially."""
        analyzer = _make_analyzer()
        dex = _make_mock_dex(["a", "b", "c"])
        result = analyzer._extract_strings([dex])

        offsets = [s["string_offset"] for s in result]
        assert offsets == [0, 1, 2]

    def test_url_strings_preserved(self):
        """URL strings are extracted without modification."""
        analyzer = _make_analyzer()
        dex = _make_mock_dex([
            "https://evil.com/payload",
            "http://c2.malware.org/gate",
        ])
        result = analyzer._extract_strings([dex])
        strings = [s["string"] for s in result]
        assert "https://evil.com/payload" in strings
        assert "http://c2.malware.org/gate" in strings


# ---------------------------------------------------------------------------
# Tests: strings in extract() integration
# ---------------------------------------------------------------------------

class TestExtractStringsIntegration:
    """Tests that strings are included in extract() results."""

    @patch("redb.extractors.decompiler.apk.analyzer.APKCodeAnalyzer._run_androguard")
    @patch("redb.extractors.decompiler.apk.analyzer.ApktoolDisassembler")
    @patch("redb.extractors.decompiler.apk.analyzer.JADXDecompiler")
    def test_extract_includes_strings(self, mock_jadx, mock_apktool, mock_androguard):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer

        mock_dex = _make_mock_dex(["hello", "world"])
        mock_analysis = MagicMock()
        mock_analysis.get_methods.return_value = []
        mock_androguard.return_value = (MagicMock(), [mock_dex], mock_analysis)

        analyzer = APKCodeAnalyzer("/fake/path.apk", log=MagicMock())
        results = analyzer.extract()

        assert "strings" in results
        assert len(results["strings"]) == 2
        assert results["strings"][0]["string"] == "hello"
        analyzer.cleanup()

    @patch("redb.extractors.decompiler.apk.analyzer.APKCodeAnalyzer._run_androguard")
    @patch("redb.extractors.decompiler.apk.analyzer.ApktoolDisassembler")
    @patch("redb.extractors.decompiler.apk.analyzer.JADXDecompiler")
    def test_extract_strings_error_is_non_fatal(self, mock_jadx, mock_apktool, mock_androguard):
        from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer

        # Return a bad dex list that will cause _extract_strings to fail
        mock_analysis = MagicMock()
        mock_analysis.get_methods.return_value = []
        # dexs is not iterable — triggers the except block
        mock_androguard.return_value = (MagicMock(), 42, mock_analysis)

        analyzer = APKCodeAnalyzer("/fake/path.apk", log=MagicMock())
        results = analyzer.extract()

        # Should not crash, strings should be empty, error recorded
        assert results["strings"] == []
        assert any(
            e.get("error_location") == "strings"
            for e in results["analysis_errors"]
        )
        analyzer.cleanup()


# ---------------------------------------------------------------------------
# Tests: DecompileAPK strings export table
# ---------------------------------------------------------------------------

class TestDecompileAPKStringsExport:
    """Tests for strings table in DecompileAPK.prepare_export_data()."""

    def _make_extractor_with_strings(self, strings_data):
        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_refs": [],
            "smali_content": [],
            "smali_refs": [],
            "similarity_metrics": [],
            "strings": strings_data,
            "analysis_errors": [],
        }
        return ext, apk_path

    def test_strings_table_present(self):
        ext, path = self._make_extractor_with_strings([
            {"string": "hello", "string_encoding": "UTF8",
             "string_offset": 0, "string_length": 5, "string_entropy": 2.32}
        ])
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            assert "strings_raw" in export
        finally:
            os.unlink(path)

    def test_strings_table_schema(self):
        ext, path = self._make_extractor_with_strings([
            {"string": "hello", "string_encoding": "UTF8",
             "string_offset": 0, "string_length": 5, "string_entropy": 2.32}
        ])
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            sr = export["strings_raw"]
            assert sr["table"] == "code_binja_strings_raw"
            assert len(sr["column_names"]) == 8
            assert len(sr["column_type_names"]) == 8
            assert "sha256" in sr["column_names"]
            assert "string" in sr["column_names"]
            assert "string_raw" in sr["column_names"]
            assert "string_encoding" in sr["column_names"]
            assert "string_offset" in sr["column_names"]
            assert "string_length" in sr["column_names"]
            assert "string_raw_length" in sr["column_names"]
            assert "string_entropy" in sr["column_names"]
            assert len(sr["data"]) == 1
            assert len(sr["data"][0]) == 8
        finally:
            os.unlink(path)

    def test_strings_sha256_propagated(self):
        ext, path = self._make_extractor_with_strings([
            {"string": "test", "string_encoding": "UTF8",
             "string_offset": 0, "string_length": 4, "string_entropy": 2.0}
        ])
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            row = export["strings_raw"]["data"][0]
            assert row[0] == "a" * 64  # sha256 is first column
        finally:
            os.unlink(path)

    def test_empty_strings_not_exported(self):
        ext, path = self._make_extractor_with_strings([])
        try:
            export = ext.prepare_export_data("ClickHouseExporter")
            assert "strings_raw" not in export
        finally:
            os.unlink(path)


# ---------------------------------------------------------------------------
# Tests: IOCExtractorFromResults with APK format
# ---------------------------------------------------------------------------

class TestIOCExtractorAPKFormat:
    """Tests that IOCExtractorFromResults handles APK analysis_results."""

    def setup_method(self):
        self.log = MagicMock()

    def test_extract_iocs_from_apk_strings(self):
        """IOCs extracted from APK strings (same format as Binja)."""
        results = {
            "strings": [
                {"string": "https://evil.com/payload", "string_offset": 0},
                {"string": "Contact [email protected]", "string_offset": 1},
            ],
            "decompiled": [],
            "decompiled_content": [],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()

        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        assert len(url_iocs) >= 1
        assert any("evil.com" in i.ioc_value for i in url_iocs)

    def test_extract_iocs_from_apk_decompiled_content(self):
        """IOCs extracted from APK's decompiled_content key."""
        results = {
            "strings": [],
            "decompiled": [],  # Binja format — empty
            "decompiled_content": [  # APK format
                {
                    "decompiled_method": "connect('https://c2.malware.org/gate');",
                    "decompiled_method_hash": "hash123",
                    "method_type": "USER",
                }
            ],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()

        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        assert len(url_iocs) >= 1

    def test_apk_library_methods_skipped(self):
        """LIBRARY methods in decompiled_content are skipped."""
        results = {
            "strings": [],
            "decompiled": [],
            "decompiled_content": [
                {
                    "decompiled_method": "https://should-skip.com",
                    "decompiled_method_hash": "lib_hash",
                    "method_type": "LIBRARY",
                }
            ],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()
        assert len(iocs) == 0

    def test_combined_binja_and_apk_sources(self):
        """Both Binja and APK format decompiled entries are processed."""
        results = {
            "strings": [],
            "decompiled": [
                {
                    "decompiled_function": "call('https://binja.example.com');",
                    "decompiled_function_hash": "binja_hash",
                    "function_type": "USER",
                }
            ],
            "decompiled_content": [
                {
                    "decompiled_method": "send('https://apk.example.com');",
                    "decompiled_method_hash": "apk_hash",
                    "method_type": "USER",
                }
            ],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()

        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        urls = [i.ioc_value for i in url_iocs]
        assert any("binja.example.com" in u for u in urls)
        assert any("apk.example.com" in u for u in urls)

    def test_apk_results_only(self):
        """Works when only APK keys are present (no 'decompiled' key)."""
        results = {
            "strings": [
                {"string": "https://evil.com", "string_offset": 0},
            ],
            "decompiled_content": [
                {
                    "decompiled_method": "x = 1",
                    "decompiled_method_hash": "h",
                    "method_type": "USER",
                }
            ],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()
        # Should not crash, and should find URL from strings
        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        assert len(url_iocs) >= 1

    def test_source_type_is_string_for_strings(self):
        results = {
            "strings": [
                {"string": "https://evil.com/test", "string_offset": 42},
            ],
            "decompiled_content": [],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()
        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        assert url_iocs[0].source_type == SourceType.STRING
        assert url_iocs[0].source_identifier == "42"

    def test_source_type_is_decompiled_for_methods(self):
        results = {
            "strings": [],
            "decompiled_content": [
                {
                    "decompiled_method": "https://evil.com/method",
                    "decompiled_method_hash": "myhash",
                    "method_type": "USER",
                }
            ],
        }
        extractor = IOCExtractorFromResults(results, sha256="a" * 64, log=self.log)
        iocs = extractor.extract()
        url_iocs = [i for i in iocs if i.ioc_type == IOCType.URL]
        assert url_iocs[0].source_type == SourceType.DECOMPILED_FUNCTION
        assert url_iocs[0].source_identifier == "myhash"


# ---------------------------------------------------------------------------
# Tests: Worker IOC wiring for APK
# ---------------------------------------------------------------------------

class TestWorkerAPKIOCWiring:
    """Tests that workers.py wires IOC extraction for APK."""

    def test_worker_source_contains_ioc_for_apk(self):
        """Verify workers.py source has IOC extraction in APK branch."""
        import inspect
        from redb import workers
        source = inspect.getsource(workers)
        # APK branch should import IOCExtractorFromResults
        assert "IOCExtractorFromResults" in source
        # Should be in the APK section (near DecompileAPK)
        apk_section = source[source.index("DecompileAPK("):]
        ioc_pos = apk_section.find("IOCExtractorFromResults")
        assert ioc_pos != -1, "IOCExtractorFromResults not found after DecompileAPK"