Kai-Chiang Wu

82 papers A* 6A 17C 2Misc 9Journal 30Unranked 18
YearRankTypeTitle / Venue / Authors
2026 A* conf
AAAI
Yu-Chen Lu, Sheng-Feng Yu, Hui-Hsien Weng, Pei-Shuo Wang, Yu-Fang Hu, Liang Hung-Chun, Hung-Yueh Chiang, Kai-Chiang Wu
2025 A* conf
EMNLP
Yu-Chen Lu, Chong-Yan Chen, Chi-Chih Chang, Yu-Fang Hu, Kai-Chiang Wu
2025 J jnl
CoRR
Yu-Chen Lu, Chong-Yan Chen, Chi-Chih Chang, Yu-Fang Hu, Kai-Chiang Wu
2025 A conf
GECCO
Chih-Ling Chen, Kai-Chiang Wu, Ning-Chi Huang
2025 A conf
ICCAD
Chung-Han Chou, Chih-Jen (Jacky) Hsu, Hung-Chun Chiu, Kai-Chiang Wu, Yu-Guang Chen, Zhuo Li
2025 A* conf
ICLR
Chi-Chih Chang, Wei-Cheng Lin, Chien-Yu Lin, Chong-Yan Chen, Yu-Fang Hu, Pei-Shuo Wang, Ning-Chi Huang, Luis Ceze, Mohamed S. Abdelfattah, Kai-Chiang Wu
2025 A* conf
ICML
Hung-Yueh Chiang, Chi-Chih Chang, Natalia Frumkin, Kai-Chiang Wu, Mohamed S. Abdelfattah, Diana Marculescu
2025 J jnl
CoRR
Hung-Yueh Chiang, Chi-Chih Chang, Natalia Frumkin, Kai-Chiang Wu, Mohamed S. Abdelfattah, Diana Marculescu
2025 A* conf
ICLR
Hung-Yueh Chiang, Chi-Chih Chang, Natalia Frumkin, Kai-Chiang Wu, Diana Marculescu
2025 J jnl
CoRR
Tien-Yu Chi, Hung-Yueh Chiang, Diana Marculescu, Kai-Chiang Wu
2025 J jnl
CoRR
Yu-Chen Lu, Sheng-Feng Yu, Hui-Hsien Weng, Pei-Shuo Wang, Yu-Fang Hu, Liang Hung-Chun, Hung-Yueh Chiang, Kai-Chiang Wu
2025 J jnl
CoRR
Pei-Shuo Wang, Jian-Jia Chen, Chun-Che Yang, Chi-Chih Chang, Ning-Chi Huang, Mohamed S. Abdelfattah, Kai-Chiang Wu
2025 A conf
FPGA
Endri Taka, Ning-Chi Huang, Chi-Chih Chang, Kai-Chiang Wu, Aman Arora, Diana Marculescu
2025 J jnl
CoRR
Endri Taka, Ning-Chi Huang, Chi-Chih Chang, Kai-Chiang Wu, Aman Arora, Diana Marculescu
2025 J jnl
CoRR
Hung-Yueh Chiang, Chi-Chih Chang, Yu-Chen Lu, Chien-Yu Lin, Kai-Chiang Wu, Mohamed S. Abdelfattah, Diana Marculescu
2025 J jnl
CoRR
Chi-Chih Chang, Chien-Yu Lin, Yash Akhauri, Wei-Cheng Lin, Kai-Chiang Wu, Luis Ceze, Mohamed S. Abdelfattah
2024 conf
CVPR Workshops
Ning-Chi Huang, Chi-Chih Chang, Wei-Cheng Lin, Endri Taka, Diana Marculescu, Kai-Chiang Wu
2024 J jnl
CoRR
Ning-Chi Huang, Chi-Chih Chang, Wei-Cheng Lin, Endri Taka, Diana Marculescu, Kai-Chiang Wu
2024 A conf
WACV
Chi-Chih Chang, Yuan-Yao Sung, Shixing Yu, Ning-Chi Huang, Diana Marculescu, Kai-Chiang Wu
2024 J jnl
CoRR
Chi-Chih Chang, Wei-Cheng Lin, Chien-Yu Lin, Chong-Yan Chen, Yu-Fang Hu, Pei-Shuo Wang, Ning-Chi Huang, Luis Ceze, Kai-Chiang Wu
2024 J jnl
CoRR
Hung-Yueh Chiang, Chi-Chih Chang, Natalia Frumkin, Kai-Chiang Wu, Diana Marculescu
2024 J jnl
IEEE Trans. Reliab.
Shiuhpyng Winston Shieh, Jeffrey M. Voas, Phil Laplante, Jason W. Rupe, Christian K. Hansen, Yu-Sung Wu, Yi-Ting Chen, Chi-Yu Li, Kai-Chiang Wu
2024 conf
DSN-S
Yu-Chen Hsiao, Chia-Heng Yen, Bo-Yang Ke, Kai-Chiang Wu
2024 Misc conf
VTS
Cheng-Che Lu, Chi-Chih Chang, Chia-Heng Yen, Shuo-Wen Chang, Ying-Hua Chu, Kai-Chiang Wu, Mango Chia-Tso Chao
2024 J jnl
CoRR
Tien-Yu Chi, Hung-Yueh Chiang, Chi-Chih Chang, Ning-Chi Huang, Kai-Chiang Wu
2024 A conf
ITC
Shu-Wen Li, Chia-Heng Yen, Shuo-Wen Chang, Ying-Hua Chu, Kai-Chiang Wu, Mango Chia-Tso Chao
2023 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Chia-Heng Yen, Chun-Teng Chen, Cheng-Yen Wen, Ying-Yen Chen, Jih-Nung Lee, Shu-Yi Kao, Kai-Chiang Wu, Mango Chia-Tso Chao
2023 conf
ISQED
Ning-Chi Huang, Min-Syue Yang, Ya-Chu Chang, Kai-Chiang Wu
2023 A conf
ITC
Ching-Min Liu, Chia-Heng Yen, Shu-Wen Lee, Kai-Chiang Wu, Mango Chia-Tso Chao
2023 J jnl
CoRR
Chi-Chih Chang, Yuan-Yao Sung, Shixing Yu, Ning-Chi Huang, Diana Marculescu, Kai-Chiang Wu
2023 conf
ICFPT
Endri Taka, Aman Arora, Kai-Chiang Wu, Diana Marculescu
2023 J jnl
CoRR
Endri Taka, Aman Arora, Kai-Chiang Wu, Diana Marculescu
2023 Misc conf
VTS
Chin-Kuan Lin, Cheng-Che Lu, Shuo-Wen Chang, Ying-Hua Chu, Kai-Chiang Wu, Mango Chia-Tso Chao
2023 conf
ICME Workshops
Chi-Chih Chang, Wei-Cheng Lin, Pei-Shuo Wang, Sheng-Feng Yu, Yu-Chen Lu, Kuan-Cheng Lin, Kai-Chiang Wu
2023 J jnl
CoRR
Chi-Chih Chang, Wei-Cheng Lin, Pei-Shuo Wang, Sheng-Feng Yu, Yu-Chen Lu, Kuan-Cheng Lin, Kai-Chiang Wu
2023 Misc conf
VTS
Yu-Teng Nien, Chen-Hong Li, Pei-Yin Wu, Yung-Jheng Wang, Kai-Chiang Wu, Mango C.-T. Chao
2023 conf
ISQED
Chia-Heng Yen, Jung-Che Tsai, Kai-Chiang Wu
2022 A conf
DATE
Dong-Zhen Lee, Ying-Yen Chen, Kai-Chiang Wu, Mango C.-T. Chao
2022 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Yu-Teng Nien, Kai-Chiang Wu, Dong-Zhen Lee, Ying-Yen Chen, Po-Lin Chen, Mason Chern, Jih-Nung Lee, Shu-Yi Kao, Mango Chia-Tso Chao
2022 Misc conf
VTS
Ho-Chieh Hsu, Cheng-Che Lu, Shih-Wei Wang, Kelly Jones, Kai-Chiang Wu, Mango C.-T. Chao
2022 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Shuo-Wen Chang, Yu-Teng Nien, Yu-Pang Hu, Kai-Chiang Wu, Chi Chun Wang, Fu-Sheng Huang, Yi-Lun Tang, Yung-Chen Chen, Ming-Chien Chen, Mango C.-T. Chao
2022 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Ning-Chi Huang, Chao-Wei Cheng, Kai-Chiang Wu
2021 Misc conf
VTS
Ning-Chi Huang, Wei-Kai Tseng, Huan-Jan Chou, Kai-Chiang Wu
2021 conf
ICCVW
Chia-Hsiang Liu, Yu-Shin Han, Yuan-Yao Sung, Yi Lee, Hung-Yueh Chiang, Kai-Chiang Wu
2021 J jnl
CoRR
Chia-Hsiang Liu, Yu-Shin Han, Yuan-Yao Sung, Yi Lee, Hung-Yueh Chiang, Kai-Chiang Wu
2021 J jnl
Adv. Intell. Syst.
Li-Wei Chen, Wei-Chun Wang, Shao-Han Ko, Chien-Yu Chen, Chih-Ting Hsu, Fu-Ching Chiao, Tse-Wei Chen, Kai-Chiang Wu, Hao-Wu Lin
2021 J jnl
Adv. Intell. Syst.
Li-Wei Chen, Wei-Chun Wang, Shao-Han Ko, Chien-Yu Chen, Chih-Ting Hsu, Fu-Ching Chiao, Tse-Wei Chen, Kai-Chiang Wu, Hao-Wu Lin
2021 Misc conf
VTS
Cheng-Hao Yang, Chia-Heng Yen, Ting-Rui Wang, Chun-Teng Chen, Mason Chern, Ying-Yen Chen, Jih-Nung Lee, Shu-Yi Kao, Kai-Chiang Wu, Mango Chia-Tso Chao
2021 conf
VLSI-DAT
Samuel Liu, Jen-Ho Kuo, Luba Tang, Ning-Chi Huang, Der-Yu Tsai, M.-H. Yang, Kai-Chiang Wu
2021 conf
AICAS
Xiao Hu, Ming-Ching Chang, Yuwei Chen, Rahul Sridhar, Zhenyu Hu, Yunhe Xue, Zhenyu Wu, Pengcheng Pi, Jiayi Shen, Jianchao Tan, Xiangru Lian, Ji Liu, Zhangyang Wang, Chia-Hsiang Liu, Yu-Shin Han, Yuan-Yao Sung, Yi Lee, Kai-Chiang Wu, Wei-Xiang Guo, Rick Lee, Shengwen Liang, Zerun Wang, Guiguang Ding, Gang Zhang, Teng Xi, Yubei Chen, Han Cai, Ligeng Zhu, Zhekai Zhang, Song Han, Seonghwan Jeong, YoungMin Kwon, Tianzhe Wang, Jeffery Pan
2020 Misc conf
VTS
Chun-Teng Chen, Chia-Heng Yen, Cheng-Yen Wen, Cheng-Hao Yang, Kai-Chiang Wu, Mason Chern, Ying-Yen Chen, Chun-Yi Kuo, Jih-Nung Lee, Shu-Yi Kao, Mango Chia-Tso Chao
2020 conf
VLSI-DAT
Shu-Ming Liu, Luba Tang, Ning-Chi Huang, Der-Yu Tsai, Ming-Xue Yang, Kai-Chiang Wu
2020 J jnl
ACM Trans. Design Autom. Electr. Syst.
Tien-Hung Tseng, Chung-Han Chou, Kai-Chiang Wu
2020 conf
ISPD
Hao-Chun Chang, Li-An Huang, Kai-Chiang Wu, Yu-Guang Chen
2020 conf
ITC-Asia
Yu-Pang Hu, Shuo-Wen Chang, Kai-Chiang Wu, Chi Chun Wang, Fu-Sheng Huang, Yi-Lun Tang, Yung-Chen Chen, Ming-Chien Chen, Mango C.-T. Chao
2019 conf
ASP-DAC
Yun-Ting Wang, Kai-Chiang Wu, Chung-Han Chou, Shih-Chieh Chang
2019 conf
ISVLSI
Ning-Chi Huang, Yu-Guang Chen, Kai-Chiang Wu
2019 C conf
IOLTS
Kai-Chiang Wu, Wei-Tao Huang, Chiao-Yang Huang
2019 Misc conf
VTS
Tse-Wei Wu, Dong-Zhen Lee, Yu-Hao Huang, Mango C.-T. Chao, Kai-Chiang Wu, Shu-Yi Kao, Ying-Yen Chen, Po-Lin Chen, Mason Chern, Jih-Nung Lee
2019 A conf
ITC
Yu-Teng Nien, Kai-Chiang Wu, Dong-Zhen Lee, Ying-Yen Chen, Po-Lin Chen, Mason Chern, Jih-Nung Lee, Shu-Yi Kao, Mango Chia-Tso Chao
2019 A conf
DATE
Ning-Chi Huang, Szu-Ying Chen, Kai-Chiang Wu
2018 conf
ATS
Tien-Hung Tseng, Shou-Chun Li, Kai-Chiang Wu
2018 A conf
DATE
Kai-Chiang Wu, Tien-Hung Tseng, Shou-Chun Li
2018 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Chung-Han Chou, Tsui-Yun Chang, Kai-Chiang Wu, Shih-Chieh Chang
2017 A conf
DATE
Chang-Lin Tsai, Chao-Wei Cheng, Ning-Chi Huang, Kai-Chiang Wu
2017 Misc conf
VTS
Kao-Chi Lee, Kai-Chiang Wu, Chih-Ying Tsai, Mango Chia-Tso Chao
2017 conf
DSC
Tien-Hung Tseng, Shu-Sheng Wang, Jian-You Chen, Kai-Chiang Wu
2014 J jnl
IEEE Trans. Comput. Aided Des. Integr. Circuits Syst.
Kai-Chiang Wu, Ing-Chao Lin, Yao-Te Wang, Shuen-Shiang Yang
2014 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Ing-Chao Lin, Kuan-Hui Li, Chia-Hao Lin, Kai-Chiang Wu
2014 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Kai-Chiang Wu, Diana Marculescu
2013 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Kai-Chiang Wu, Diana Marculescu
2012 A conf
DATE
Kai-Chiang Wu, Ming-Chao Lee, Diana Marculescu, Shih-Chieh Chang
2011 A conf
DATE
Kai-Chiang Wu, Diana Marculescu
2011 A conf
ISLPED
Kai-Chiang Wu, Diana Marculescu, Ming-Chao Lee, Shih-Chieh Chang
2010 A conf
DATE
Kai-Chiang Wu, Diana Marculescu
2009 A conf
DATE
Kai-Chiang Wu, Diana Marculescu
2008 C conf
ICCD
Kai-Chiang Wu, Diana Marculescu
2008 A conf
ICCAD
Natasa Miskov-Zivanov, Kai-Chiang Wu, Diana Marculescu
2008 conf
ASP-DAC
Kai-Chiang Wu, Diana Marculescu
2007 J jnl
IEEE Trans. Control. Syst. Technol.
Shyh-Leh Chen, Kai-Chiang Wu
2006 conf
ASP-DAC
Kai-Chiang Wu, Cheng-Tao Hsieh, Shih-Chieh Chang
2004 A* conf
DAC
Shih-Chieh Chang, Cheng-Tao Hsieh, Kai-Chiang Wu
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"