Kai Chen

105 papers A* 6A 6B 11C 5Misc 4Journal 42Unranked 31
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Zhihai Bi, Yushan Zhang, Kai Chen, Guoyang Zhao, Yulin Li, Jun Ma
2026 J jnl
CoRR
Yulin Li, Zhiyuan Song, Yiming Li, Zhicheng Song, Kai Chen, Chunxin Zheng, Zhihai Bi, Jiahang Cao, Sylvain Calinon, Fan Shi, Jun Ma
2026 J jnl
CoRR
Guoyang Zhao, Weiqing Qi, Kai Zhang, Chenguang Zhang, Zeying Gong, Zhihai Bi, Kai Chen, Benshan Ma, Ming Liu, Jun Ma
2025 J jnl
CoRR
Chunxin Zheng, Kai Chen, Zhihai Bi, Yulin Li, Liang Pan, Jinni Zhou, Haoang Li, Jun Ma
2025 J jnl
IEEE Robotics Autom. Lett.
Yulin Li, Zhicheng Song, Chunxin Zheng, Zhihai Bi, Kai Chen, Michael Yu Wang, Jun Ma
2025 J jnl
IEEE Robotics Autom. Lett.
Kai Chen, Jiahang Cao, Yulin Li, Haoang Li, Jun Ma
2025 A conf
IROS
Zhihai Bi, Kai Chen, Chunxin Zheng, Yulin Li, Haoang Li, Jun Ma
2025 J jnl
CoRR
Zhihai Bi, Kai Chen, Chunxin Zheng, Yulin Li, Haoang Li, Jun Ma
2025 conf
CASE
Yongjian Li, Minzhe Zheng, Kai Chen, Hongji Liu, Jinni Zhou, Lujia Wang, Jun Ma
2025 A* conf
ICRA
Kai Chen, Haichao Liu, Yulin Li, Jianghua Duan, Lei Zhu, Jun Ma
2025 J jnl
CoRR
Kai Chen, Zhihai Bi, Guoyang Zhao, Chunxin Zheng, Yulin Li, Hang Zhao, Jun Ma
2025 J jnl
CoRR
Guoyang Zhao, Yudong Li, Weiqing Qi, Kai Zhang, Bonan Liu, Kai Chen, Haoang Li, Jun Ma
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Haichao Liu, Kai Chen, Yulin Li, Zhenmin Huang, Ming Liu, Jun Ma
2025 J jnl
CoRR
Haichao Liu, Kai Chen, Yulin Li, Zhenmin Huang, Ming Liu, Jun Ma
2024 J jnl
IEEE Robotics Autom. Lett.
Yulin Li, Chunxin Zheng, Kai Chen, Yusen Xie, Xindong Tang, Michael Yu Wang, Jun Ma
2024 J jnl
CoRR
Yulin Li, Chunxin Zheng, Kai Chen, Yusen Xie, Xindong Tang, Michael Yu Wang, Jun Ma
2024 J jnl
CoRR
Yulin Li, Zhicheng Song, Chunxin Zheng, Zhihai Bi, Kai Chen, Michael Yu Wang, Jun Ma
2024 J jnl
IEEE Robotics Autom. Lett.
Yulin Li, Xindong Tang, Kai Chen, Chunxin Zheng, Haichao Liu, Jun Ma
2024 C conf
IV
Haichao Liu, Kai Chen, Jun Ma
2024 J jnl
CoRR
Yusen Xie, Zhenmin Huang, Kai Chen, Lei Zhu, Jun Ma
2024 A conf
IROS
Yusen Xie, Zhenmin Huang, Kai Chen, Lei Zhu, Jun Ma
2024 J jnl
CoRR
Tiancheng Lin, Jinglei Zhang, Yi Xu, Kai Chen, Rui Zhang, Chang-Wen Chen
2024 J jnl
CoRR
Kai Chen, Haichao Liu, Yulin Li, Jianghua Duan, Lei Zhu, Jun Ma
2023 J jnl
IEEE Trans Autom. Sci. Eng.
Sheng Xu, Kai Chen, Yongsheng Ou, Zhiyang Wang, Chenguang Yang
2023 A* conf
AAAI
Xiaoyang Huang, Yi Zhang, Bingbing Ni, Teng Li, Kai Chen, Wenjun Zhang
2023 conf
ICANN (6)
Xinrui Deng, Zheng Huang, Kefan Ma, Kai Chen, Jie Guo, Weidong Qiu
2023 J jnl
CoRR
Yulin Li, Xindong Tang, Kai Chen, Chunxin Zheng, Haichao Liu, Jun Ma
2023 conf
ROBIO
Qingnan Zhong, Kai Chen, Jianghua Duan, Jun Ma
2023 conf
ROBIO
Haichao Liu, Kai Chen, Yulin Li, Zhenmin Huang, Jianghua Duan, Jun Ma
2023 J jnl
CoRR
Haichao Liu, Kai Chen, Yulin Li, Zhenmin Huang, Jianghua Duan, Jun Ma
2023 A* conf
ICCV
Xiaoyang Huang, Yi Zhang, Kai Chen, Teng Li, Wenjun Zhang, Bingbing Ni
2023 conf
ROBIO
Zilong Cheng, Yulin Li, Kai Chen, Jianghua Duan, Jun Ma, Tong Heng Lee
2023 conf
ICANN (6)
Xinrui Deng, Zheng Huang, Kefan Ma, Kai Chen, Jie Guo, Weidong Qiu
2023 A* conf
ACM Multimedia
Jinglei Zhang, Tiancheng Lin, Yi Xu, Kai Chen, Rui Zhang
2023 J jnl
CoRR
Jinglei Zhang, Tiancheng Lin, Yi Xu, Kai Chen, Rui Zhang
2023 conf
ICDAR (6)
Kefan Ma, Yuchen Luo, Zheng Huang, Kai Chen, Jie Guo, Weidong Qiu
2022 J jnl
CoRR
Xiaoyang Huang, Yi Zhang, Bingbing Ni, Teng Li, Kai Chen, Wenjun Zhang
2021 Misc conf
DICTA
Yi-Li Huang, Shi-Lin Wang, Chengyu Gu, Zheng Huang, Kai Chen
2021 J jnl
IEEE Trans. Pattern Anal. Mach. Intell.
Yongchao Xu, Mingtao Fu, Qimeng Wang, Yukang Wang, Kai Chen, Gui-Song Xia, Xiang Bai
2021 J jnl
CoRR
Zheng Huang, Kai Chen, Jianhua He, Xiang Bai, Dimosthenis Karatzas, Shijian Lu, C. V. Jawahar
2021 A conf
BMVC
Yi-Li Huang, Chengyu Gu, Shilin Wang, Zheng Huang, Kai Chen
2021 A* conf
ICRA
YangYang Qu, Kai Chen, Chao Liu, Yongsheng Ou
2020 conf
ML4CS (3)
Shiyin He, Zheng Huang, Kai Chen, Jie Guo, Weidong Qiu
2020 J jnl
IEEE Trans. Intell. Transp. Syst.
Jian Wei, Jianhua He, Yi Zhou, Kai Chen, Zuoyin Tang, Zhiliang Xiong
2020 B conf
ICPR
Dafeng Wei, Hongtao Lu, Yi Zhou, Kai Chen
2020 B conf
ICPR
Xuan Peng, Zheng Huang, Kai Chen, Jie Guo, Weidong Qiu
2020 A* conf
AAAI
Minghui Liao, Zhaoyi Wan, Cong Yao, Kai Chen, Xiang Bai
2020 J jnl
CoRR
YangYang Qu, Kai Chen, Chao Liu, Yongsheng Ou
2020 B conf
ICPR
Chengyu Gu, Shilin Wang, Yiwei Zhu, Zheng Huang, Kai Chen
2019 A conf
ICDAR
Jian Wei, Kai Chen, Jianhua He, Zheng Huang, Yunrui Lian, Yi Zhou
2019 conf
DSC
Yiwei Zhu, Shilin Wang, Zheng Huang, Kai Chen, Xiang Lin, Quanhai Zhang
2019 C conf
VCIP
Yuting Gao, Zheng Huang, Yuchen Dai, Cheng Xu, Kai Chen, Jie Guo
2019 J jnl
CoRR
Yongchao Xu, Mingtao Fu, Qimeng Wang, Yukang Wang, Kai Chen, Gui-Song Xia, Xiang Bai
2019 A conf
ICDAR
Zheng Huang, Kai Chen, Jianhua He, Xiang Bai, Dimosthenis Karatzas, Shijian Lu, C. V. Jawahar
2019 J jnl
CoRR
Minghui Liao, Zhaoyi Wan, Cong Yao, Kai Chen, Xiang Bai
2019 B conf
ICIP
Yiwei Zhu, Shilin Wang, Zheng Huang, Kai Chen
2019 B conf
ICIP
Yuting Gao, Zheng Huang, Yuchen Dai, Kai Chen, Jie Guo, Weidong Qiu
2018 B conf
ICPR
Yuchen Dai, Zheng Huang, Yuting Gao, Youxuan Xu, Kai Chen, Jie Guo, Weidong Qiu
2018 J jnl
IEEE Internet Things J.
Jianhua He, Jian Wei, Kai Chen, Zuoyin Tang, Yi Zhou, Yan Zhang
2017 J jnl
IEEE Trans. Multim.
Xiaohang Ren, Yi Zhou, Jianhua He, Kai Chen, Xiaokang Yang, Jun Sun
2017 J jnl
IEEE Access
Xiaohang Ren, Yi Zhou, Zheng Huang, Jun Sun, Xiaokang Yang, Kai Chen
2017 J jnl
Expert Syst. Appl.
Jian Wei, Jianhua He, Kai Chen, Yi Zhou, Zuoyin Tang
2017 J jnl
ACM Trans. Inf. Syst.
Zhongchen Miao, Kai Chen, Yi Fang, Jianhua He, Yi Zhou, Wenjun Zhang, Hongyuan Zha
2017 J jnl
CoRR
Yuchen Dai, Zheng Huang, Yuting Gao, Kai Chen
2017 J jnl
Telematics Informatics
Tieying Liu, Yang Zhong, Kai Chen
2016 J jnl
CoRR
Xiaohang Ren, Kai Chen, Jun Sun
2016 J jnl
CoRR
Xiaohang Ren, Kai Chen, Jun Sun
2016 C conf
VCIP
Xiaohang Ren, Kai Chen, Xiaokang Yang, Yi Zhou, Jianhua He, Jun Sun
2016 B conf
ICPR
Xiaohang Ren, Kai Chen, Xiaokang Yang, Yi Zhou, Jianhua He, Jun Sun
2016 conf
BigDataService
Jian Wei, Kai Chen, Yi Zhou, Qu Zhou, Jianhua He
2016 conf
DASC/PiCom/DataCom/CyberSciTech
Jian Wei, Jianhua He, Kai Chen, Yi Zhou, Zuoyin Tang
2016 J jnl
IEEE Access
Zhongchen Miao, Junchi Yan, Kai Chen, Xiaokang Yang, Hongyuan Zha, Wenjun Zhang
2015 conf
IEEE BigData
Kai Chen, Yi Zhou, Fangyan Dai
2015 conf
ChinaSIP
Xiaohang Ren, Kai Chen, Xiaokang Yang, Yi Zhou, Jianhua He, Jun Sun
2015 conf
ICC
Zhongchen Miao, Kai Chen, Yi Zhou, Hongyuan Zha, Jianhua He, Xiaokang Yang, Wenjun Zhang
2014 conf
IEEE BigData
Yifang Jiang, Diao Zhang, Kai Chen, Qu Zhou, Yi Zhou, Jianhua He
2014 conf
ICDM Workshops
Mengmeng Yang, Kai Chen, Zhongchen Miao, Xiaokang Yang
2014 conf
SocInfo Workshops
Tieying Liu, Kai Chen, Yang Zhong
2013 B conf
ASONAM
Pei Shen, Yi Zhou, Kai Chen
2013 conf
SNAKDD
Chengfeng Lin, Jianhua He, Yi Zhou, Xiaokang Yang, Kai Chen, Li Song
2013 conf
WWW (Companion Volume)
Kai Chen, Yi Zhou, Hongyuan Zha, Jianhua He, Pei Shen, Xiaokang Yang
2013 conf
IEEE BigData
Mengmeng Yang, Yi Zhou, Qu Zhou, Kai Chen, Jianhua He, Xiaokang Yang
2012 B conf
ASONAM
Yi Zhou, Kai Chen, Li Song, Xiaokang Yang, Jianhua He
2012 B conf
ICPR
Qing Yan, Yi Xu, Xiaokang Yang, Kai Chen
2012 conf
GLOBECOM Workshops
Yin Zhang, Yi Zhou, Kai Chen
2011 J jnl
J. Softw.
Haibing Guan, Erzhou Zhu, Kai Chen, Ruhui Ma, Yunchao He, Haipeng Deng, Hongbo Yang
2011 conf
FGIT-UNESST
Zhongzhi Che, Jianhua He, Zuoyin Tang, Yi Zhou, Kai Chen
2011 B conf
ASONAM
Kai Chen, Yi Zhou, Li Song, Xiaokang Yang
2011 conf
VTC Spring
Yi Zhou, Kai Chen, Jianhua He, Haibing Guan
2011 Misc conf
MVA
Kai Chen, Yi Zhou, Qi Zheng, Xiaokang Yang, Li Song
2011 Misc conf
SAC
Jun Nakajima, Qian Lin, Sheng Yang, Min Zhu, Shang Gao, Mingyuan Xia, Peijie Yu, Yaozu Dong, Zhengwei Qi, Kai Chen, Haibing Guan
2011 Misc conf
SAC
Qian Lin, Mingyuan Xia, Miao Yu, Peijie Yu, Min Zhu, Shang Gao, Zhengwei Qi, Kai Chen, Haibing Guan
2011 J jnl
IEEE Commun. Lett.
Jianhua He, Wenyang Guan, Lin Bai, Kai Chen
2010 conf
PAAP
Yunchao He, Kai Chen, Jinghui Gu, Haipeng Deng, Alei Liang, Haibing Guan
2010 conf
WCRE
Gengbiao Chen, Zhuo Wang, Ruoyu Zhang, Kan Zhou, Shiqiu Huang, Kangqi Ni, Zhengwei Qi, Kai Chen, Haibing Guan
2010 A conf
HPDC
Haibing Guan, Yindong Yang, Kai Chen, Yi Ge, Liang Liu, Ying Chen
2010 conf
GCC
Haipeng Deng, Kai Chen, Bo Liu, Yunchao He, Kan Zhou, Yindong Yang, Alei Liang, Haibing Guan
2010 C conf
EUC
Peijie Yu, Mingyuan Xia, Qian Lin, Min Zhu, Shang Gao, Zhengwei Qi, Kai Chen, Haibing Guan
2010 conf
ACCV (3)
Qi Zheng, Kai Chen, Yi Zhou, Congcong Gu, Haibing Guan
2009 C conf
HPCC
Yi Zhou, Kai Chen, Jianhua He, Jianbo Chen, Alei Liang
2009 conf
ScalCom-EmbeddedCom
Lei Shang, Kai Chen, Haibing Guan, Alei Liang
2009 conf
ACCV (2)
Zhiyuan Zhang, Kaiyue Qi, Kai Chen, Chenxuan Li, Jianbo Chen, Haibing Guan
2009 conf
ICUMT
Shijun Huang, Kai Chen, Chao Liu, Alei Liang, Haibing Guan
2009 J jnl
EURASIP J. Wirel. Commun. Netw.
Yi Zhou, Kai Chen, Jianhua He, Haibing Guan, Yan Zhang, Alei Liang
2006 conf
GCC Workshops
Kai Chen, Qianni Deng
tests/unit/test_apk_dataclasses.py
← Index tests/unit/test_apk_dataclasses.py python
"""
Unit tests for APK dataclasses in redb/models/dataclasses.py.
"""
import pytest
from dataclasses import asdict, fields

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


# ============================================================================
# APKFeatures
# ============================================================================

class TestAPKFeaturesDataclass:
    """Tests for APKFeatures dataclass."""

    def test_named_fields(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.example.app",
            app_name="Example App",
            version_code=1,
            version_name="1.0.0",
        )
        assert f.package_name == "com.example.app"
        assert f.app_name == "Example App"
        assert f.version_code == 1
        assert f.version_name == "1.0.0"

    def test_all_fields_default_none_or_safe(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures()
        # Nullable fields default to None
        assert f.package_name is None
        assert f.app_name is None
        assert f.version_code is None
        assert f.version_name is None
        assert f.min_sdk_version is None
        assert f.target_sdk_version is None
        assert f.compile_sdk_version is None
        assert f.main_activity is None
        # Non-nullable fields have safe defaults
        assert f.is_debuggable is False
        assert f.allow_backup is True
        assert f.uses_cleartext_traffic is False
        assert f.supported_abis == []
        assert f.dex_count == 0
        assert f.total_dex_size == 0
        assert f.total_file_count == 0
        assert f.has_native_code is False
        assert f.has_assets is False
        assert f.uses_libraries == []
        assert f.earliest_content_modification is None
        assert f.latest_content_modification is None
        assert f.contains_embedded_apk is False

    def test_all_fields_populated(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.malware.test",
            app_name="Malware",
            version_code=42,
            version_name="6.6.6",
            min_sdk_version=21,
            target_sdk_version=33,
            compile_sdk_version=33,
            main_activity="com.malware.test.MainActivity",
            is_debuggable=True,
            allow_backup=False,
            uses_cleartext_traffic=True,
            supported_abis=["armeabi-v7a", "arm64-v8a", "x86"],
            dex_count=3,
            total_dex_size=5000000,
            total_file_count=200,
            has_native_code=True,
            has_assets=True,
            uses_libraries=["com.google.android.maps"],
            earliest_content_modification="2024-01-01T00:00:00Z",
            latest_content_modification="2024-06-15T12:00:00Z",
            contains_embedded_apk=True,
        )
        assert f.is_debuggable is True
        assert f.dex_count == 3
        assert len(f.supported_abis) == 3
        assert f.contains_embedded_apk is True

    def test_asdict_roundtrip(self):
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.test",
            app_name="Test",
            version_code=1,
            version_name="1.0",
        )
        d = asdict(f)
        assert d["package_name"] == "com.test"
        assert d["is_debuggable"] is False
        assert d["supported_abis"] == []

    def test_partial_extraction(self):
        """Verify that APKFeatures can be created with only some fields populated,
        simulating a partial extraction where some fields failed."""
        from redb.models.dataclasses import APKFeatures

        f = APKFeatures(
            package_name="com.example.app",
            # app_name failed to extract — left as None
            version_code=10,
            # version_name failed to extract — left as None
            is_debuggable=True,
            dex_count=2,
        )
        assert f.package_name == "com.example.app"
        assert f.app_name is None
        assert f.version_code == 10
        assert f.version_name is None
        assert f.is_debuggable is True
        assert f.dex_count == 2


# ============================================================================
# APKManifestComponent
# ============================================================================

class TestAPKManifestComponentDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKManifestComponent

        c = APKManifestComponent(
            component_type="activity",
            class_name="com.example.MainActivity",
            is_exported=True,
            intent_actions=["android.intent.action.MAIN"],
            intent_categories=["android.intent.category.LAUNCHER"],
        )
        assert c.component_type == "activity"
        assert c.class_name == "com.example.MainActivity"
        assert c.is_exported is True
        assert len(c.intent_actions) == 1
        assert len(c.intent_categories) == 1

    def test_defaults(self):
        from redb.models.dataclasses import APKManifestComponent

        c = APKManifestComponent(
            component_type="service",
            class_name="com.example.MyService",
            is_exported=False,
        )
        assert c.intent_actions == []
        assert c.intent_categories == []


# ============================================================================
# APKManifest
# ============================================================================

class TestAPKManifestDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=5,
            service_count=2,
            receiver_count=3,
            provider_count=1,
        )
        assert m.activity_count == 5
        assert m.service_count == 2
        assert m.receiver_count == 3
        assert m.provider_count == 1

    def test_optional_list_defaults(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=0,
            service_count=0,
            receiver_count=0,
            provider_count=0,
        )
        assert m.activities == []
        assert m.services == []
        assert m.receivers == []
        assert m.providers == []
        assert m.exported_components == []
        assert m.intent_filters_by_action == []
        assert m.intent_filters_by_category == []
        assert m.uses_features == []
        assert m.meta_data is None
        assert m.manifest_xml is None

    def test_fully_populated(self):
        from redb.models.dataclasses import APKManifest

        m = APKManifest(
            activity_count=2,
            service_count=1,
            receiver_count=1,
            provider_count=0,
            activities=["MainActivity", "SettingsActivity"],
            services=["SyncService"],
            receivers=["BootReceiver"],
            providers=[],
            exported_components=["MainActivity", "BootReceiver"],
            intent_filters_by_action=["android.intent.action.MAIN"],
            uses_features=["android.hardware.camera"],
            manifest_xml="<manifest>...</manifest>",
        )
        assert len(m.activities) == 2
        assert len(m.exported_components) == 2
        assert m.manifest_xml is not None


# ============================================================================
# APKPermission / APKPermissions
# ============================================================================

class TestAPKPermissionDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKPermission

        p = APKPermission(
            permission_name="android.permission.CAMERA",
            protection_level="dangerous",
        )
        assert p.permission_name == "android.permission.CAMERA"
        assert p.protection_level == "dangerous"
        assert p.is_custom is False

    def test_custom_permission(self):
        from redb.models.dataclasses import APKPermission

        p = APKPermission(
            permission_name="com.example.CUSTOM_PERM",
            protection_level="signature",
            is_custom=True,
        )
        assert p.is_custom is True


class TestAPKPermissionsDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKPermissions

        p = APKPermissions(
            total_permission_count=10,
            dangerous_permission_count=3,
        )
        assert p.total_permission_count == 10
        assert p.dangerous_permission_count == 3

    def test_defaults(self):
        from redb.models.dataclasses import APKPermissions

        p = APKPermissions(
            total_permission_count=0,
            dangerous_permission_count=0,
        )
        assert p.permissions == []
        assert p.dangerous_permissions == []
        assert p.custom_permissions == []
        assert p.permission_details == []
        assert p.permhash is None

    def test_with_permission_details(self):
        from redb.models.dataclasses import APKPermission, APKPermissions

        details = [
            APKPermission("android.permission.INTERNET", "normal"),
            APKPermission("android.permission.CAMERA", "dangerous"),
        ]
        p = APKPermissions(
            total_permission_count=2,
            dangerous_permission_count=1,
            permissions=["android.permission.INTERNET", "android.permission.CAMERA"],
            dangerous_permissions=["android.permission.CAMERA"],
            permission_details=details,
            permhash="abc123def456",
        )
        assert len(p.permission_details) == 2
        assert p.permhash == "abc123def456"


# ============================================================================
# APKCertificate / APKCodeSigningInfo
# ============================================================================

class TestAPKCertificateDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKCertificate

        c = APKCertificate(
            subject="CN=Android Debug",
            issuer="CN=Android Debug",
            serial_number="1234567890",
            valid_from="2024-01-01",
            valid_to="2054-01-01",
            thumbprint_sha1="aabbccdd" * 5,
            thumbprint_sha256="aabbccdd" * 8,
        )
        assert c.subject == "CN=Android Debug"
        assert c.issuer == "CN=Android Debug"
        assert c.is_self_signed is False

    def test_optional_fields(self):
        from redb.models.dataclasses import APKCertificate

        c = APKCertificate(
            subject="CN=Test",
            issuer="CN=CA",
            serial_number="1",
            valid_from="2024-01-01",
            valid_to="2025-01-01",
            thumbprint_sha1="aa" * 20,
            thumbprint_sha256="bb" * 32,
            algorithm="SHA256withRSA",
            key_size=2048,
            is_self_signed=True,
        )
        assert c.algorithm == "SHA256withRSA"
        assert c.key_size == 2048
        assert c.is_self_signed is True


class TestAPKCodeSigningInfoDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKCodeSigningInfo

        info = APKCodeSigningInfo(
            _id="abcdef1234567890" * 4,
            is_signed=True,
        )
        assert info.is_signed is True
        assert info.signature_scheme_versions == []
        assert info.number_of_certificates == 0
        assert info.x509_certificates is None
        assert info.apk_signer_subject is None
        assert info.apk_signer_issuer is None

    def test_fully_populated(self):
        from redb.models.dataclasses import APKCertificate, APKCodeSigningInfo

        cert = APKCertificate(
            subject="CN=Test",
            issuer="CN=Test",
            serial_number="1",
            valid_from="2024-01-01",
            valid_to="2025-01-01",
            thumbprint_sha1="aa" * 20,
            thumbprint_sha256="bb" * 32,
        )
        info = APKCodeSigningInfo(
            _id="cc" * 32,
            is_signed=True,
            signature_scheme_versions=[1, 2, 3],
            number_of_certificates=1,
            x509_certificates=[cert],
            apk_signer_subject="CN=Test",
            apk_signer_issuer="CN=Test",
        )
        assert len(info.signature_scheme_versions) == 3
        assert info.number_of_certificates == 1
        assert len(info.x509_certificates) == 1


# ============================================================================
# APKDexFile
# ============================================================================

class TestAPKDexFileDataclass:

    def test_required_fields(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=100,
            method_count=500,
            string_count=1000,
        )
        assert d.filename == "classes.dex"
        assert d.class_count == 100
        assert d.method_count == 500
        assert d.string_count == 1000

    def test_optional_fields_defaults(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes2.dex",
            sha256="bb" * 32,
            class_count=0,
            method_count=0,
            string_count=0,
        )
        assert d.tlsh is None
        assert d.top_packages is None
        assert d.api_usage is None
        assert d.obfuscation_indicators is None

    def test_tlsh_populated(self):
        from redb.models.dataclasses import APKDexFile

        tlsh_value = "T1" + "A" * 68
        d = APKDexFile(
            filename="classes.dex",
            sha256="aa" * 32,
            class_count=100,
            method_count=500,
            string_count=1000,
            tlsh=tlsh_value,
        )
        assert d.tlsh == tlsh_value

    def test_with_api_usage(self):
        from redb.models.dataclasses import APKDexFile

        d = APKDexFile(
            filename="classes.dex",
            sha256="cc" * 32,
            class_count=50,
            method_count=200,
            string_count=300,
            top_packages=[{"name": "com.example", "class_count": 30}],
            api_usage={
                "crypto": ["Ljavax/crypto/Cipher;->getInstance"],
                "reflection": ["Ljava/lang/Class;->forName"],
            },
            obfuscation_indicators={"short_class_names_ratio": 0.8, "single_char_methods_ratio": 0.5},
        )
        assert len(d.api_usage) == 2
        assert d.obfuscation_indicators["short_class_names_ratio"] == 0.8


# ============================================================================
# APKResource
# ============================================================================

class TestAPKResourceDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKResource

        r = APKResource(
            path="res/drawable/icon.png",
            size=1024,
            sha256="dd" * 32,
            filetype_magika="png",
        )
        assert r.path == "res/drawable/icon.png"
        assert r.size == 1024
        assert r.is_suspicious is False

    def test_suspicious_resource(self):
        from redb.models.dataclasses import APKResource

        r = APKResource(
            path="assets/payload.dex",
            size=50000,
            sha256="ee" * 32,
            filetype_magika="dex",
            is_suspicious=True,
        )
        assert r.is_suspicious is True


# ============================================================================
# APKNativeLib
# ============================================================================

class TestAPKNativeLibDataclass:

    def test_creation(self):
        from redb.models.dataclasses import APKNativeLib

        lib = APKNativeLib(
            abi="arm64-v8a",
            filename="libnative.so",
            size=200000,
            sha256="ff" * 32,
        )
        assert lib.abi == "arm64-v8a"
        assert lib.filename == "libnative.so"
        assert lib.is_known_packer is False

    def test_known_packer(self):
        from redb.models.dataclasses import APKNativeLib

        lib = APKNativeLib(
            abi="armeabi-v7a",
            filename="libjiagu.so",
            size=100000,
            sha256="aa" * 32,
            is_known_packer=True,
        )
        assert lib.is_known_packer is True


# ============================================================================
# APKInconsistencyTests
# ============================================================================

class TestAPKInconsistencyTestsDataclass:

    def test_all_defaults_none(self):
        from redb.models.dataclasses import APKInconsistencyTests

        t = APKInconsistencyTests()
        assert t.test_zip_bomb is None
        assert t.test_zip_duplicate_entries is None
        assert t.test_zip_path_traversal is None
        assert t.test_zip_suspicious_timestamps is None
        assert t.test_hidden_dex_files is None
        assert t.test_manifest_component_mismatch is None
        assert t.test_debuggable_release is None
        assert t.test_emulator_detection_strings is None
        assert t.test_debugger_detection is None
        assert t.test_root_detection is None

    def test_all_fields_populated(self):
        from redb.models.dataclasses import APKInconsistencyTests

        t = APKInconsistencyTests(
            test_zip_bomb=True,
            test_zip_duplicate_entries=False,
            test_zip_path_traversal=True,
            test_zip_suspicious_timestamps=False,
            test_hidden_dex_files=True,
            test_manifest_component_mismatch=False,
            test_debuggable_release=True,
            test_emulator_detection_strings=True,
            test_debugger_detection=False,
            test_root_detection=True,
        )
        assert t.test_zip_bomb is True
        assert t.test_debuggable_release is True
        # Count true values
        d = asdict(t)
        true_count = sum(1 for v in d.values() if v is True)
        assert true_count == 6

    def test_field_count(self):
        from redb.models.dataclasses import APKInconsistencyTests

        # Exactly 10 inconsistency tests per PDD specification
        assert len(fields(APKInconsistencyTests)) == 10


# ============================================================================
# Hashes dataclass — APK permhash field
# ============================================================================

class TestHashesAPKField:

    def test_permhash_default_none(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(md5="a", sha1="b", sha256="c", ssdeep_hash="d", tlsh_hash="e")
        assert h.permhash is None

    def test_permhash_populated(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(
            md5="a", sha1="b", sha256="c", ssdeep_hash="d", tlsh_hash="e",
            permhash="abc123" * 10 + "abcd",
        )
        assert h.permhash is not None
        assert len(h.permhash) == 64


# ============================================================================
# Tag enum — APK entries
# ============================================================================

class TestAPKTagEnum:

    def test_all_apk_tags_exist(self):
        from redb.extractors.enum import Tag

        expected_tags = [
            "APK_FEATURES", "APK_MANIFEST", "APK_PERMISSIONS", "APK_SIGNATURE",
            "APK_DEX", "APK_RESOURCES", "APK_NATIVE_LIBS", "APK_INCONSISTENCY_TESTS",
        ]
        for name in expected_tags:
            assert hasattr(Tag, name), f"Tag.{name} missing"

    def test_apk_tag_values(self):
        from redb.extractors.enum import Tag

        assert Tag.APK_FEATURES.value == "apk_features"
        assert Tag.APK_MANIFEST.value == "apk_manifest"
        assert Tag.APK_PERMISSIONS.value == "apk_permissions"
        assert Tag.APK_SIGNATURE.value == "apk_signature"
        assert Tag.APK_DEX.value == "apk_dex"
        assert Tag.APK_RESOURCES.value == "apk_resources"
        assert Tag.APK_NATIVE_LIBS.value == "apk_native_libs"
        assert Tag.APK_INCONSISTENCY_TESTS.value == "apk_inconsistency_tests"