Xianyi Zeng

132 papers A* 1B 4Misc 9Journal 97Unranked 16
YearRankTypeTitle / Venue / Authors
2026 J jnl
Knowl. Based Syst.
Yangyu Lai, Xianyi Zeng, Yan Hong, Xiaoqun Dai
2026 J jnl
Expert Syst. Appl.
Di Sha, Arne Johannssen, Xianyi Zeng, Ruolin Wang, Kim Phuc Tran
2025 J jnl
Int. J. Comput. Intell. Syst.
Di Sha, Xianyi Zeng, Kim Phuc Tran, Lin Xia, Ruolin Wang
2025 J jnl
J. Comput. Phys.
Xianyi Zeng, Ting Song, Guglielmo Scovazzi
2025 J jnl
Int. J. Comput. Intell. Syst.
Mengru Li, Zhenya Zhang, Xianyi Zeng, Zhenglei He
2025 J jnl
CoRR
Xianyi Zeng
2025 J jnl
IEEE Trans Autom. Sci. Eng.
Zhenglei He, Guojian Chen, Mengna Hong, Qingang Xiong, Xianyi Zeng, Yi Man
2024 J jnl
IEEE Trans. Ind. Informatics
Xingyuan Wang, Yufei Xue, Jie Zhang, Yan Hong, Song Guo, Xianyi Zeng
2024 J jnl
Comput. Biol. Medicine
Marc Junior Nkengue, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao, François Dassonville, Nicolas Dumont, Shixin Ye-Lehmann, Yvette Akwa, Hanwen Ye
2024 J jnl
Expert Syst. Appl.
Kehui Song, Xianyi Zeng, Julien de Jonckheere, Ludovic Koehl, Xiaojie Yuan
2024 J jnl
Int. J. Bifurc. Chaos
Yaqi Chen, Xianyi Zeng, Ben Niu
2024 A* conf
ICML
Ning Liu, Yiming Fan, Xianyi Zeng, Milan Klöwer, Lu Zhang, Yue Yu
2024 J jnl
IEEE Netw.
Yan Hong, Song Guo, Xianyi Zeng, Jie Zhang
2024 conf
BIOSTEC (1)
Marc Junior Nkengue, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao, François Dassonville, Nicolas Dumont
2024 J jnl
Biomed. Signal Process. Control.
Marc Junior Nkengue, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao
2023 J jnl
J. Comput. Appl. Math.
Md Mahmudul Hasan, Xianyi Zeng
2023 J jnl
Multim. Tools Appl.
Kaixuan Liu, Chun Zhu, Xuyuan Tao, Pascal Bruniaux, Xianyi Zeng, Jianping Wang
2023 J jnl
CoRR
Xianyi Zeng
2023 J jnl
Int. J. Comput. Intell. Syst.
Zhujun Wang, Xuyuan Tao, Xianyi Zeng, Yingmei Xing, Zhenzhen Xu, Pascal Bruniaux
2023 Misc conf
ISKE
Kaichen Wang, Shan Xiong, Zhiwei Huang, Qing Li, Zhebin Xue, Xianyi Zeng
2023 J jnl
CoRR
Ning Liu, Yiming Fan, Xianyi Zeng, Milan Klöwer, Yue Yu
2023 Misc conf
ISKE
Zaohao Lu, Mengna Hong, Yi Man, Xianyi Zeng, Zhenglei He
2023 J jnl
Vis. Comput.
Pengpeng Cheng, Jianping Wang, Xianyi Zeng, Pascal Bruniaux, Xuyuan Tao, Daoling Chen
2022 J jnl
Multim. Tools Appl.
Zhujun Wang, Yingmei Xing, Jianping Wang, Xianyi Zeng, Yalan Yang, Shuo Xu
2022 J jnl
CoRR
Xianyi Zeng, Giovanni Stabile, Efthymios N. Karatzas, Guglielmo Scovazzi, Gianluigi Rozza
2021 J jnl
Comput. Ind.
Zhenglei He, Kim Phuc Tran, Sébastien Thomassey, Xianyi Zeng, Jie Xu, Changhai Yi
2021 J jnl
Knowl. Based Syst.
Kehui Song, Xianyi Zeng, Ying Zhang, Julien de Jonckheere, Xiaojie Yuan, Ludovic Koehl
2021 J jnl
Int. J. Comput. Intell. Syst.
Zhujun Wang, Jianping Wang, Xianyi Zeng, Xuyuan Tao, Yingmei Xing, Pascal Bruniaux
2021 J jnl
Comput. Ind.
Mulat Alubel Abtew, Maria Kulinska, Xianyi Zeng, Pascal Bruniaux
2021 J jnl
Sensors
Shukla Sharma, Ludovic Koehl, Pascal Bruniaux, Xianyi Zeng, Zhujun Wang
2021 conf
APMS (1)
Sébastien Thomassey, Xianyi Zeng
2021 J jnl
CoRR
Ali Raza, Kim Phuc Tran, Ludovic Koehl, Shujun Li, Xianyi Zeng, Khaled Benzaidi
2020 J jnl
CoRR
Zhenglei He, Kim Phuc Tran, Sébastien Thomassey, Xianyi Zeng, Jie Xu, Haiyi Chang
2020 J jnl
CoRR
Zhenglei He, Kim Phuc Tran, Sébastien Thomassey, Xianyi Zeng, Changhai Yi
2020 J jnl
IEEE Trans. Aerosp. Electron. Syst.
Hao Sun, Qinglin Sun, Xianyi Zeng, Shu-Zhen Luo, Wannan Wu, Zengqiang Chen
2020 conf
APPIS
Yanni Xu, Sébastien Thomassey, Xianyi Zeng
2020 J jnl
Inf. Sci.
Min Dong, Xianyi Zeng, Ludovic Koehl, Junjie Zhang
2020 J jnl
Ann. Oper. Res.
Ke Ma, Sébastien Thomassey, Xianyi Zeng
2020 J jnl
IEEE Access
Shengfei Liu, Liwu Wang, Chun Li, Qinglin Sun, Zengqiang Chen, Mingwei Sun, Xianyi Zeng
2020 J jnl
IEEE Trans. Ind. Informatics
Xianyi Zeng, Qinglin Sun
2020 J jnl
IEEE Access
Linfeng Gou, Yawen Shen, Hua Zheng, Xianyi Zeng
2020 J jnl
CoRR
Zhenglei He, Kim Phuc Tran, Sébastien Thomassey, Xianyi Zeng, Jie Xu, Changhai Yi
2020 J jnl
CoRR
Xianyi Zeng, Md Mahmudul Hasan
2019 J jnl
IEEE Access
Chandadevi Giri, Sheenam Jain, Xianyi Zeng, Pascal Bruniaux
2019 J jnl
IEEE Access
Linfeng Gou, Xianyi Zeng, Zhaohui Wang, Guangjie Han, Chuan Lin, Xu Cheng
2019 J jnl
Comput. Math. Appl.
Xianyi Zeng, Kangan Li, Guglielmo Scovazzi
2019 Misc conf
ISKE
Xiaohong Liu, Xianyi Zeng
2019 conf
ICPS
Xin Zhao, Xianyi Zeng, Ludovic Koehl, Guillaume Tartare, Julien de Jonckheere, Kehui Song
2019 J jnl
IEEE Access
Kaixuan Liu, Xianyi Zeng, Xuyuan Tao, Pascal Bruniaux
2019 J jnl
Int. J. Comput. Intell. Syst.
Kaichen Wang, Vijay Kumar, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao, Yan Chen
2019 J jnl
Int. J. Comput. Intell. Syst.
Chandadevi Giri, Sébastien Thomassey, Xianyi Zeng
2019 J jnl
IEEE Access
Yan Hong, Tianyu Wu, Xianyi Zeng, Yuyang Wang, Wen Yang, Zhijuan Pan
2019 J jnl
Adv. Comput. Math.
Xianyi Zeng
2019 J jnl
Adv. Comput. Math.
Xianyi Zeng, Mashriq Ahmed Saleh, Jianjun Paul Tian
2019 B conf
FUZZ-IEEE
Kaichen Wang, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao, Yan Chen
2019 J jnl
CoRR
Huu Du Nguyen, Kim Phuc Tran, Xianyi Zeng, Ludovic Koehl, Guillaume Tartare
2018 J jnl
Comput. Aided Des.
Kaixuan Liu, Xianyi Zeng, Pascal Bruniaux, Xuyuan Tao, Xiaofeng Yao, Victoria Li, Jianping Wang
2018 J jnl
Comput. Ind. Eng.
Xuyuan Tao, Xiao Chen, Xianyi Zeng, Ludovic Koehl
2018 J jnl
Knowl. Based Syst.
Jizi Li, Xianyi Zeng, Chunling Liu, Xinjian Zhou
2018 J jnl
Knowl. Based Syst.
Yan Hong, Xianyi Zeng, Yuyang Wang, Pascal Bruniaux, Yan Chen
2018 J jnl
Knowl. Based Syst.
Xianyi Zeng, Jie Lu
2018 conf
ICPS
Guillaume Tartare, Xianyi Zeng, Ludovic Koehl
2018 J jnl
Int. J. Comput. Intell. Syst.
Junjie Zhang, Xianyi Zeng, Ludovic Koehl, Min Dong
2018 J jnl
Comput. Intell. Neurosci.
Jianli Liu, Edwin Lughofer, Xianyi Zeng, Zhengxin Li
2017 Misc conf
ISKE
Xiaohong Liu, Xianyi Zeng
2017 J jnl
J. Comput. Phys.
Alex Main, Xianyi Zeng, Philip Avery, Charbel Farhat
2017 J jnl
Knowl. Based Syst.
Kaixuan Liu, Xianyi Zeng, Pascal Bruniaux, Jianping Wang, Edwin Kamalha, Xuyuan Tao
2017 conf
ISIE
Marie-Pierre Pacaux-Lemoine, Lydia Habib, Guillaume Tartare, Ludovic Koehl, Xianyi Zeng
2017 conf
AHFE (6)
Yan Hong, Xianyi Zeng, Pascal Bruniaux, Antonela Curteza, Yan Chen
2017 J jnl
Comput. Intell. Neurosci.
Jianli Liu, Edwin Lughofer, Xianyi Zeng
2016 J jnl
SIAM J. Sci. Comput.
Xianyi Zeng
2016 J jnl
J. Comput. Phys.
Xianyi Zeng, Guglielmo Scovazzi
2015 J jnl
Frontiers Comput. Neurosci.
Jianli Liu, Edwin Lughofer, Xianyi Zeng
2015 Misc conf
ISKE
Jianli Liu, Edwin Lughofer, Xianyi Zeng, Lei Wang
2015 J jnl
Knowl. Based Syst.
Xiao Chen, Xuyuan Tao, Xianyi Zeng, Ludovic Koehl, Julie Boulenguez-Phippen
2015 J jnl
Neurocomputing
Jianli Liu, Edwin Lughofer, Xianyi Zeng
2015 Misc conf
ISKE
Zhebin Xue, Xianyi Zeng, Ludovic Koehl, Lei Shen
2015 Misc conf
ISKE
Xiaohong Liu, Xianyi Zeng, Yang Xu
2015 J jnl
IEEE Trans. Hum. Mach. Syst.
Lichuan Wang, Xianyi Zeng, Ludovic Koehl, Yan Chen
2014 J jnl
J. Comput. Phys.
Xianyi Zeng, Guglielmo Scovazzi
2014 J jnl
Eng. Appl. Artif. Intell.
Zhebin Xue, Xianyi Zeng, Ludovic Koehl, Yan Chen
2014 conf
IPMU (2)
Xiaon Chen, Xianyi Zeng, Ludovic Koehl, Xuyuan Tao, Julie Boulenguez-Phippen
2014 J jnl
Multim. Tools Appl.
Jianli Liu, Baoqi Zuo, Xianyi Zeng
2013 J jnl
CoRR
Xianyi Zeng
2013 conf
IFSA/NAFIPS
Xianyi Zeng, Ludovic Koehl, Lichuan Wang, Yan Chen
2013 conf
A Tribute to Prof. Dr. Da Ruan
Xianyi Zeng, Ludovic Koehl, Mauricio Camargo, Bernadette Bouchon-Meunier
2013 J jnl
Int. J. Adv. Oper. Manag.
Lichuan Wang, Xianyi Zeng, Ludovic Koehl, Yan Chen
2013 J jnl
Eng. Appl. Artif. Intell.
Radhia Abd Jelil, Xianyi Zeng, Ludovic Koehl, Anne Perwuelz
2012 J jnl
CoRR
Xianyi Zeng
2012 J jnl
J. Comput. Phys.
Xianyi Zeng, Charbel Farhat
2012 conf
MFI
Zhebin Xue, Xianyi Zeng, Ludovic Koehl, Yan Chen
2011 J jnl
Biomed. Signal Process. Control.
Han Kang, Antonio Pinti, Abdelmalik Taleb-Ahmed, Xianyi Zeng
2011 J jnl
J. Glob. Optim.
Xiaoguang Deng, Xianyi Zeng, Philippe Vroman, Ludovic Koehl
2011 J jnl
IEEE Trans. Ind. Electron.
Jie Lu, Jun Ma, Guangquan Zhang, Yijun Zhu, Xianyi Zeng, Ludovic Koehl
2011 J jnl
Neurocomputing
Jianli Liu, Baoqi Zuo, Xianyi Zeng, Philippe Vroman, Besoa Rabenasolo
2011 J jnl
Expert Syst. Appl.
Jianli Liu, Baoqi Zuo, Xianyi Zeng, Philippe Vroman, Besoa Rabenasolo
2010 J jnl
Soft Comput.
Xianyi Zeng, Yijun Zhu, Ludovic Koehl, Mauricio Camargo, Christian Fonteix, François Delmotte
2010 J jnl
Int. J. Comput. Intell. Syst.
Yijun Zhu, Da Ruan, Xianyi Zeng, Ludovic Koehl, Cyril Chaigneau
2010 conf
IEEE ICCI
Xianyi Zeng, Ludovic Koehl
2010 B conf
SMC
Xiaoguang Deng, Philippe Vroman, Xianyi Zeng, Brahim Laouisset
2010 J jnl
Expert Syst. Appl.
Jianli Liu, Baoqi Zuo, Xianyi Zeng, Philippe Vroman, Besoa Rabenasolo
2010 J jnl
Eng. Appl. Artif. Intell.
Xiaoguang Deng, Xianyi Zeng, Philippe Vroman, Ludovic Koehl
2010 Misc conf
ISKE
Lichuan Wang, Xianyi Zeng, Ludovic Koehl, Yan Chen
2009 J jnl
Fuzzy Optim. Decis. Mak.
Jie Lu, Yijun Zhu, Xianyi Zeng, Ludovic Koehl, Jun Ma, Guangquan Zhang
2009 J jnl
Eng. Appl. Artif. Intell.
Yan Chen, Xianyi Zeng, Michel Happiette, Pascal Bruniaux, R. Ng, Winnie Yu
2008 conf
Australasian Conference on Artificial Intelligence
Jie Lu, Yijun Zhu, Xianyi Zeng, Ludovic Koehl, Jun Ma, Guangquan Zhang
2008 J jnl
Math. Comput. Simul.
Xiaohong Liu, Xianyi Zeng, Yang Xu, Ludovic Koehl
2008 B conf
FUZZ-IEEE
Jie Lu, Xiaoguang Deng, Philippe Vroman, Xianyi Zeng, Jun Ma, Guangquan Zhang
2008 J jnl
Int. J. Inf. Technol. Decis. Mak.
Ya Gao, Guangquan Zhang, Jie Lu, Tharam S. Dillon, Xianyi Zeng
2008 J jnl
Int. J. Uncertain. Fuzziness Knowl. Based Syst.
Bin Zhou, Xianyi Zeng, Ludovic Koehl, Yongsheng Ding
2008 conf
ICNC (7)
Xianyi Zeng, Ludovic Koehl
2008 Misc conf
ISKE
Ludovic Koehl, Xianyi Zeng, Mauricio Camargo, Christian Fonteix, François Delmotte
2008 J jnl
Int. J. Comput. Intell. Syst.
Philippe Vroman, Ludovic Koehl, Xianyi Zeng, Ting Chen
2008 conf
ICNC (7)
Xia Chen, Xianyi Zeng, Ludovic Koehl
2008 J jnl
Math. Comput. Simul.
Xianyi Zeng, Yongsheng Ding
2008 J jnl
Math. Comput. Simul.
Caihong Hou, Yongsheng Ding, Xianyi Zeng
2008 J jnl
Math. Comput. Simul.
Ludovic Koehl, Xianyi Zeng, Bin Zhou, Yongsheng Ding
2008 J jnl
Math. Comput. Simul.
Xianyi Zeng, Da Ruan, Ludovic Koehl
2007 ch.
E-Service Intelligence
Bin Zhou, Xianyi Zeng, Ludovic Koehl, Yongsheng Ding
2007 J jnl
Int. J. Inf. Technol. Decis. Mak.
Yang Xu, Xianyi Zeng, Ludovic Koehl
2007 book
Xianyi Zeng, Yi Li, Da Ruan, Ludovic Koehl
2007 B conf
WISE
Chao Wang, Jie Lu, Guangquan Zhang, Xianyi Zeng
2007 ch.
Computational Textile
Nicolas Ansel, Sébastien Thomassey, Pascal Bruniaux, Xianyi Zeng
2007 ch.
Computational Textile
Ludovic Koehl, Jawad Chraïbi Miou, Xianyi Zeng
2007 conf
EUSFLAT Conf. (2)
Abbas Khosravi, Jie Lu, Xianyi Zeng, Roohollah Barzamini
2005 J jnl
Inf. Sci.
Xianyi Zeng, Zeyi Liu
2005 ch.
Intelligent Data Mining
Ludovic Koehl, Xianyi Zeng, Bin Zhou, Yongsheng Ding
2004 J jnl
Int. J. Gen. Syst.
Xianyi Zeng, Ludovic Koehl, M. Sanoun, M. A. Bueno, M. Renner
2003 J jnl
Int. J. Intell. Syst.
Xianyi Zeng, Ludovic Koehl
2001 J jnl
Pattern Recognit.
Xianyi Zeng, Ludovic Koehl, C. Vasseur
2000 J jnl
Autom.
Xianyi Zeng, J. Zhou, C. Vasseur
1998 J jnl
Eur. J. Oper. Res.
Besoa Rabenasolo, Xianyi Zeng, Michel Happiette
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"