Weibin Liu

85 papers B 4C 6Misc 3Journal 48Unranked 23
YearRankTypeTitle / Venue / Authors
2025 J jnl
IEEE Trans. Ind. Electron.
Weibin Liu, Zhehao Jin, Ning Wang, Chenguang Yang
2025 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Huaqing Hao, Weibin Liu, Weiwei Xing
2025 J jnl
Eng. Appl. Artif. Intell.
Qian Zhang, Xiaopei Cai, Jijun Wang, Weibin Liu, Yilin Zhong, Moyan Zhang, Ji Wang
2024 conf
ACCV (3)
Haichen He, Weibin Liu, Weiwei Xing
2024 C conf
ISPA
Zheng Wang, Weiwei Xing, Yue Cheng, Weibin Liu, Zhiyuan Zou, Zhi Wang, Genxiang Chen, Wei Lu
2024 J jnl
Comput. Biol. Medicine
Yumeng Song, Yin Dai, Weibin Liu, Yue Liu, Xinpeng Liu, Qiming Yu, Xinghan Liu, Ningfeng Que, Mingzhe Li
2024 conf
PRCV (2)
Jingsi Cao, Weibin Liu, Weiwei Xing
2024 J jnl
Neural Comput. Appl.
Xiaoyu Guo, Weiwei Xing, Xiang Wei, Weibin Liu, Jian Zhang, Wei Lu
2024 C conf
ISPA
Zhenjie Wei, Weiwei Xing, Weibin Liu, Zhiyuan Zou, Genxiang Chen
2024 C conf
ISPA
Haichen He, Weibin Liu, Yinan Zhang, Shasha Song, Yue Cheng, Ziheng Liu, Weiwei Xing
2023 B conf
ICPADS
Guanjia Zhang, Weiwei Xing, Shuzhong Yang, Weibin Liu, Xiang Wei, Jian Zhang, Shunli Zhang
2023 J jnl
Robotics Auton. Syst.
Jing Luo, Weibin Liu, Wen Qi, Jianwen Hu, Junming Chen, Chenguang Yang
2023 J jnl
IEEE Trans. Multim.
Weiwei Xing, Jie Yao, Zixia Liu, Weibin Liu, Shunli Zhang, Liqiang Wang
2023 J jnl
Vis. Comput.
Xiukun Zhang, Weibin Liu, Weiwei Xing, Xiang Wei
2023 J jnl
Signal Image Video Process.
Dandan Cao, Weibin Liu, Weiwei Xing, Xiang Wei
2023 J jnl
Vis. Comput.
Jia Xu, Weibin Liu, Weiwei Xing, Xiang Wei
2023 J jnl
Appl. Intell.
Zhiyuan Zou, Weibin Liu, Weiwei Xing, Shunli Zhang
2023 J jnl
IEEE Trans. Fuzzy Syst.
Yue Cheng, Weiwei Xing, Witold Pedrycz, Sidong Xian, Weibin Liu
2023 J jnl
Int. J. Mach. Learn. Cybern.
Zhiyuan Zou, Weibin Liu, Weiwei Xing, Shunli Zhang
2022 J jnl
Appl. Intell.
Hui Wang, Weibin Liu, Weiwei Xing
2022 J jnl
Pattern Recognit.
Zhiyuan Zou, Weibin Liu, Weiwei Xing
2022 J jnl
J. Inf. Knowl. Manag.
Bing Xiao, Weibin Liu, Xiaolin Wu, Yanyong Lan
2022 J jnl
J. Interconnect. Networks
Bing Xiao, Yanyong Lan, Huiming Zhao, Xiaolin Wu, Weibin Liu
2022 J jnl
Genom. Proteom. Bioinform.
Zhuye Jie, Chen Chen, Lilan Hao, Fei Li, Liju Song, Xiaowei Zhang, Jie Zhu, Liu Tian, Xin Tong, Kaiye Cai, Zhe Zhang, Yanmei Ju, Xinlei Yu, Ying Li, Hongcheng Zhou, Haorong Lu, Xuemei Qiu, Qiang Li, Yunli Liao, Dongsheng Zhou, Heng Lian, Yong Zuo, Xiaomin Chen, Weiqiao Rao, Yan Ren, Yuan Wang, Jin Zi, Rong Wang, Na Liu, Jinghua Wu, Wei Zhang, Xiao Liu, Yang Zong, Weibin Liu, Liang Xiao, Yong Hou, Xun Xu, Huanming Yang, Jian Wang, Karsten Kristiansen, Huijue Jia
2022 J jnl
Signal Image Video Process.
Haitao Xu, Weibin Liu, Weiwei Xing, Xiang Wei
2022 J jnl
Pattern Recognit.
Huaqing Hao, Weibin Liu, Weiwei Xing, Shunli Zhang
2022 conf
SmartWorld/UIC/ScalCom/DigitalTwin/PriComp/Meta
Yang Pei, Weiwei Xing, Xiang Wei, Weibin Liu, Mingquan Wang, Fuyong Sun
2022 J jnl
Neurocomputing
Hui Wang, Weibin Liu, Weiwei Xing, Shunli Zhang
2021 J jnl
J. Electronic Imaging
Yuxin Wang, Weibin Liu, Weiwei Xing
2021 conf
CNIOT
Jiayi Yin, Weibin Liu, Weiwei Xing, Yuan Xiao
2021 B conf
IJCNN
Yanhao Cheng, Weibin Liu, Weiwei Xing
2021 J jnl
Neurocomputing
Huaqing Hao, Weibin Liu, Weiwei Xing
2021 J jnl
J. Vis. Commun. Image Represent.
Hui Wang, Weibin Liu, Weiwei Xing
2021 book
Weiwei Xing, Weibin Liu, Jun Wang, Shunli Zhang, Lihui Wang, Yuxiang Yang, Bowen Song
2021 J jnl
J. Electronic Imaging
Yanhao Cheng, Weibin Liu, Weiwei Xing
2020 J jnl
IEEE Access
Cheng Liu, Weibin Liu, Weiwei Xing
2020 J jnl
Neurocomputing
Jun Wang, Weibin Liu, Weiwei Xing, Liqiang Wang, Shunli Zhang
2020 conf
CNIOT
Ying Shi, Weibin Liu, Weiwei Xing
2020 J jnl
KSII Trans. Internet Inf. Syst.
Xiaopin Zhao, Weibin Liu, Weiwei Xing, Xiang Wei
2020 conf
IntelliSys (1)
Xinjie Wang, Weibin Liu, Weiwei Xing
2020 conf
CNIOT
Xiaopin Zhao, Weibin Liu, Weiwei Xing
2020 J jnl
Comput. Animat. Virtual Worlds
Wang Bin, Weibin Liu, Weiwei Xing
2019 J jnl
KSII Trans. Internet Inf. Syst.
Xiaofei Zan, Weibin Liu, Weiwei Xing
2019 C conf
SEKE
Yaru Cheng, Weibin Liu, Weiwei Xing
2019 C conf
SEKE
Menglei Jin, Weibin Liu, Weiwei Xing
2019 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Menglei Jin, Weibin Liu, Weiwei Xing
2019 J jnl
Signal Process. Image Commun.
Jun Wang, Weibin Liu, Weiwei Xing, Shunli Zhang
2019 J jnl
KSII Trans. Internet Inf. Syst.
Menglei Jin, Weibin Liu, Weiwei Xing
2019 J jnl
J. Vis. Commun. Image Represent.
Cheng Liu, Weibin Liu, Weiwei Xing
2019 conf
SmartWorld/SCALCOM/UIC/ATC/CBDCom/IOP/SCI
Xing Liu, Weibin Liu, Weiwei Xing
2018 J jnl
J. Electronic Imaging
Chuanmin Zhang, Weibin Liu, Weiwei Xing
2018 J jnl
Signal Process. Image Commun.
Jun Wang, Weibin Liu, Weiwei Xing, Shunli Zhang
2017 conf
DASC/PiCom/DataCom/CyberSciTech
Ziyi Wu, Weibin Liu, Weiwei Xing
2017 J jnl
Signal Process.
Cheng Liu, Weibin Liu, Weiwei Xing
2017 J jnl
J. Vis. Lang. Comput.
Xiaomin Yu, Weibin Liu, Weiwei Xing
2017 conf
DMSVLSS
Weibin Liu, Weiwei Xing, Jiaqian Qi
2017 conf
DASC/PiCom/DataCom/CyberSciTech
Sisi Han, Weibin Liu, Weiwei Xing
2017 conf
DASC/PiCom/DataCom/CyberSciTech
Le Li, Weibin Liu, Weiwei Xing
2017 J jnl
Neurocomputing
Wei Lu, Xiang Wei, Weiwei Xing, Weibin Liu
2017 J jnl
Neurocomputing
Jun Wang, Weibin Liu, Weiwei Xing, Shunli Zhang
2016 conf
DMS
Weibin Liu, Weiwei Xing, Xiaomin Yu
2015 conf
DMS
Ruxiang Wei, Weibin Liu, Weiwei Xing
2015 J jnl
J. Vis. Lang. Comput.
Xiaohui Zhang, Weibin Liu, Weiwei Xing
2015 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Weibin Liu, Kin Fun Li
2015 conf
DMS
Xiaohui Zhang, Weibin Liu, Weiwei Xing
2015 conf
DMS
Ruixue Yin, Weibin Liu, Weiwei Xing
2014 conf
DMS
Jing Cui, Weibin Liu, Weiwei Xing
2014 J jnl
J. Vis. Lang. Comput.
Jing Cui, Weibin Liu, Weiwei Xing
2014 J jnl
J. Vis. Lang. Comput.
Xinyi Chong, Weibin Liu, Pengfei Huang, Norman I. Badler
2014 J jnl
J. Vis. Lang. Comput.
Weibin Liu, Xinyi Chong, Pengfei Huang, Norman I. Badler
2014 J jnl
IEICE Trans. Inf. Syst.
Kai Kang, Weibin Liu, Weiwei Xing
2014 conf
DMS
Song Song, Weibin Liu, Ruxiang Wei, Weiwei Xing, Cheng Ren
2014 J jnl
J. Vis. Lang. Comput.
Song Song, Weibin Liu, Ruxiang Wei, Weiwei Xing, Cheng Ren
2010 C conf
ISCC
Weibin Liu, Liang Zhou, Weiwei Xing, Baozong Yuan
2009 conf
SSME
Weibin Liu
2009 Misc conf
GrC
Hongmei Chen, Tianrui Li, Weibin Liu, Weili Zou
2008 J jnl
Int. J. Cogn. Informatics Nat. Intell.
Weiwei Xing, Weibin Liu, Baozong Yuan
2007 B conf
SMC
Weiwei Xing, Weibin Liu, Baozong Yuan
2007 conf
IMECS
Weibin Liu, Jie Hao, Weiwei Xing, Baozong Yuan
2006 conf
IEEE ICCI
Weiwei Xing, Weibin Liu, Baozong Yuan
2005 Misc conf
Visualization and Data Analysis
Weibin Liu, Yusuke Uehara, Yi Liu, Jiantao Pu, Hao Yu, Daiki Masumoto, Hongbin Zha
2005 B conf
MMM
Weibin Liu, Yusuke Uehara, Hao Yu, Daiki Masumoto, Yi Liu, Jiantao Pu, Hongbin Zha
2004 conf
3DPVT
Jiantao Pu, Yi Liu, Guyu Xin, Hongbin Zha, Weibin Liu, Yusuke Uehara
2004 Misc conf
PG
Yi Liu, Jiantao Pu, Guyu Xin, Hongbin Zha, Weibin Liu, Yusuke Uehara
2004 conf
3DPVT
Yi Liu, Jiantao Pu, Hongbin Zha, Weibin Liu, Yusuke Uehara
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"