Raees Ahmad Khan

79 papers B 1Journal 64Unranked 14
YearRankTypeTitle / Venue / Authors
2025 conf
SC Workshops
Kuan-Chieh Hsu, Sairam Sri Vatsavai, Ozgur O. Kilic, Sankha Dutta, Yihui Ren, David K. Park, Tatiana Korchuganova, Joseph Boudreau, Tasnuva Chowdhury, Shengyu Feng, Raees Ahmad Khan, Jaehyung Kim, Norbert Podhorszki, Scott Klasky, Tadashi Maeno, Paul Nilsson, Verena Ingrid Martinez Outschoorn, Frédéric Suter, Wei Yang, Yiming Yang, Shinjae Yoo, Alexei Klimentov, Adolfy Hoisie
2025 J jnl
PeerJ Comput. Sci.
Wael Alosaimi, Abdullah Alharbi, Hashem Alyami, Bader Alouffi, Ahmed Almulihi, Masood Ahmad, Mohd Nadeem, Raees Ahmad Khan
2024 J jnl
Comput. Secur.
Suman, Raees Ahmad Khan
2024 J jnl
Netw. Secur.
Rajeev Kumar, Raees Ahmad Khan
2024 J jnl
BMC Medical Informatics Decis. Mak.
Abdullah Alharbi, Wael Alosaimi, Hashem Alyami, Bader Alouffi, Ahmed Almulihi, Mohd Nadeem, Mohd Asim Sayeed, Raees Ahmad Khan
2024 J jnl
Multim. Tools Appl.
Suman, Raees Ahmad Khan
2023 J jnl
Intell. Autom. Soft Comput.
Hosam Alhakami, Abdullah Baz, Mohammad Al-shareef, Rajeev Kumar, Alka Agrawal, Raees Ahmad Khan
2023 J jnl
J. Supercomput.
Jasleen Kaur, Rajeev Kumar, Alka Agrawal, Raees Ahmad Khan
2023 J jnl
Int. J. Fuzzy Log. Intell. Syst.
Sultan H. Almotiri, Mohd Nadeem, Mohammed A. Al Ghamdi, Raees Ahmad Khan
2023 conf
IC3I
Sandeep Kumar Verma, Mohd Nadeem, Vishal Verma, Mohd Asim Sayeed, Alka Agrawal, Raees Ahmad Khan
2023 J jnl
Comput. Syst. Sci. Eng.
Fawaz Alassery, Ahmed Alzahrani, Asif Irshad Khan, Kanika Sharma, Masood Ahmad, Raees Ahmad Khan
2023 J jnl
Int. J. Inf. Sec.
Jasleen Kaur, Alka Agrawal, Raees Ahmad Khan
2023 conf
IC3I
Satish Kumar, Mausmi Devi, Sunil Singh, Pawan Kumar Chaurasia, Raees Ahmad Khan
2022 J jnl
Comput. Syst. Sci. Eng.
Hosam Alhakami, Abdullah Baz, Wajdi Alhakami, Abhishek Kumar Pandey, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
Intell. Autom. Soft Comput.
Abdulaziz Attaallah, Hassan Alsuhabi, Sarita Shukla, Rajeev Kumar, Bineet Kumar Gupta, Raees Ahmad Khan
2022 J jnl
Intell. Autom. Soft Comput.
Hashem Alyami, Mohd Nadeem, Wael Alosaimi, Abdullah Alharbi, Rajeev Kumar, Bineet Kumar Gupta, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
Comput. Syst. Sci. Eng.
Abhishek Kumar Pandey, Jehad F. Al-Amri, Ahmad F. Subahi, Rajeev Kumar, Raees Ahmad Khan
2022 J jnl
Comput. Syst. Sci. Eng.
Mohammed Baz, Sabita Khatri, Abdullah Baz, Hosam Alhakami, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
EAI Endorsed Trans. Scalable Inf. Syst.
Md Tarique Jamal Ansari, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Jasleen Kaur, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
Comput. Syst. Sci. Eng.
Abdullah Alharbi, Masood Ahmad, Wael Alosaimi, Hashem Alyami, Alka Agrawal, Rajeev Kumar, Abdul Wahid, Raees Ahmad Khan
2022 J jnl
Int. J. Appl. Metaheuristic Comput.
Mohd Faizan, Fawaz Alsolami, Raees Ahmad Khan
2022 J jnl
Intell. Autom. Soft Comput.
Mohd Nadeem, Jehad F. Al-Amri, Ahmad F. Subahi, Adil Hussain Seh, Suhel Ahmad Khan, Alka Agrawal, Raees Ahmad Khan
2022 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Alka Agrawal, Mamdouh Alenezi, Suhel Ahmad Khan, Rajeev Kumar, Raees Ahmad Khan
2022 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Kanika Sharma, Alka Agrawal, Dhirendra Pandey, Raees Ahmad Khan, Shail Kumar Dinkar
2021 J jnl
KSII Trans. Internet Inf. Syst.
Rajeev Kumar, Md Tarique Jamal Ansari, Abdullah Baz, Hosam Alhakami, Alka Agrawal, Raees Ahmad Khan
2021 J jnl
IEEE Access
Sabita Khatri, Fahad Ahmed Al-Zahrani, Md Tarique Jamal Ansari, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Comput. Syst. Sci. Eng.
Hashem Alyami, Mohd Faizan, Wael Alosaimi, Abdullah Alharbi, Abhishek Kumar Pandey, Md Tarique Jamal Ansari, Alka Agrawal, Raees Ahmad Khan
2021 J jnl
Secur. Priv.
Shweta Sankhwar, Dhirendra Pandey, Raees Ahmad Khan, Sachi Nandan Mohanty
2021 J jnl
Comput. Syst. Sci. Eng.
Wajdi Alhakami, Ahmed Binmahfoudh, Abdullah Baz, Hosam Alhakami, Md Tarique Jamal Ansari, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Wael Alosaimi, Rajeev Kumar, Abdullah Alharbi, Hashem Alyami, Alka Agrawal, Gaurav Kaithwas, Sanjay Singh, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Abdulaziz Attaallah, Masood Ahmad, Md Tarique Jamal Ansari, Abhishek Kumar Pandey, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Symmetry
Wael Alosaimi, Md Tarique Jamal Ansari, Abdullah Alharbi, Hashem Alyami, Adil Hussain Seh, Abhishek Kumar Pandey, Alka Agrawal, Raees Ahmad Khan
2021 J jnl
IEEE Access
Abdullah Alharbi, Mohd Faizan, Wael Alosaimi, Hashem Alyami, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Wajdi Alhakami, Abdullah Baz, Hosam Alhakami, Masood Ahmad, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Mohammed Baz, Hosam Alhakami, Alka Agrawal, Abdullah Baz, Raees Ahmad Khan
2021 J jnl
Comput. Syst. Sci. Eng.
Wael Alosaimi, Abdullah Alharbi, Hashem Alyami, Masood Ahmad, Abhishek Kumar Pandey, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Adil Hussain Seh, Jehad F. Al-Amri, Ahmad F. Subahi, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Intell. Autom. Soft Comput.
Abdullah Alharbi, Wael Alosaimi, Hashem Alyami, Mohd Nadeem, Mohd Faizan, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2021 J jnl
Int. J. Syst. Dyn. Appl.
Adil Hussain Seh, Masood Ahmad, Mohd Nadeem, Abhishek Kumar Pandey, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
IEEE Access
Rajeev Kumar, Abdullah Baz, Hosam Alhakami, Wajdi Alhakami, Mohammed Baz, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
IEEE Access
Rajeev Kumar, Asif Irshad Khan, Yoosef B. Abushark, Md. Mottahir Alam, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
Symmetry
Alka Agrawal, Mamdouh Alenezi, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
IEEE Access
Rajeev Kumar, Asif Irshad Khan, Yoosef B. Abushark, Md. Mottahir Alam, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
PeerJ Comput. Sci.
Gayatri Kapil, Alka Agrawal, Abdulaziz Attaallah, Abdullah M. Algarni, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
Symmetry
Suhel Ahmad Khan, Mamdouh Alenezi, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
IEEE Access
Mamdouh Alenezi, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
IEEE Access
Mohammad Zarour, Md Tarique Jamal Ansari, Mamdouh Alenezi, Amal Krishna Sarkar, Mohd Faizan, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
IEEE Access
Alka Agrawal, Abhishek Kumar Pandey, Abdullah Baz, Hosam Alhakami, Wajdi Alhakami, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
Symmetry
Rajeev Kumar, Abhishek Kumar Pandey, Abdullah Baz, Hosam Alhakami, Wajdi Alhakami, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
IEEE Access
Abhishek Kumar Pandey, Asif Irshad Khan, Yoosef B. Abushark, Md. Mottahir Alam, Alka Agrawal, Rajeev Kumar, Raees Ahmad Khan
2020 conf
ICCCNT
Jasleen Kaur, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
Int. J. Wirel. Inf. Networks
Jasleen Kaur, Alka Agrawal, Raees Ahmad Khan
2020 J jnl
Symmetry
Alka Agrawal, Adil Hussain Seh, Abdullah Baz, Hosam Alhakami, Wajdi Alhakami, Mohammed Baz, Rajeev Kumar, Raees Ahmad Khan
2020 J jnl
Symmetry
Wajdi Alhakami, Abdullah Baz, Hosam Alhakami, Abhishek Kumar Pandey, Raees Ahmad Khan
2019 J jnl
Iran J. Comput. Sci.
Neeraj Kumar, Alka Agrawal, Raees Ahmad Khan
2019 J jnl
EAI Endorsed Trans. Scalable Inf. Syst.
Shweta Sankhwar, Dhirendra Pandey, Raees Ahmad Khan
2019 J jnl
First Monday
Mohd Faizan, Raees Ahmad Khan
2019 J jnl
Int. J. Comput. Intell. Syst.
Rajeev Kumar, Mohammad Zarour, Mamdouh Alenezi, Alka Agrawal, Raees Ahmad Khan
2019 J jnl
IEEE Access
Alka Agrawal, Mamdouh Alenezi, Rajeev Kumar, Raees Ahmad Khan
2019 J jnl
PeerJ Comput. Sci.
Alka Agrawal, Mohammad Zarour, Mamdouh Alenezi, Rajeev Kumar, Raees Ahmad Khan
2018 J jnl
Int. J. Appl. Evol. Comput.
Neeraj Kumar, Alka Agrawal, Raees Ahmad Khan
2018 conf
RICE
Neeraj Kumar, Alka Agrawal, Raees Ahmad Khan
2016 conf
ICACDS
Kanika, Alka Agrawal, Raees Ahmad Khan
2015 conf
SCSE
Bonthu Kotaiah, M. V. S. Prasad, Raees Ahmad Khan
2014 conf
FICTA (2)
Singh Sandeep, Raees Ahmad Khan, Alka Agrawal
2012 J jnl
ACM SIGSOFT Softw. Eng. Notes
Suhel Ahmad Khan, Raees Ahmad Khan
2011 J jnl
ACM SIGSOFT Softw. Eng. Notes
Shalini Chandra, Raees Ahmad Khan
2010 J jnl
CoRR
Mohd Nazir, Raees Ahmad Khan, Khurram Mustafa
2010 conf
IC3 (1)
Alka Agrawal, Raees Ahmad Khan
2009 B conf
ARES
Alka Agrawal, Shalini Chandra, Raees Ahmad Khan
2009 J jnl
ACM SIGSOFT Softw. Eng. Notes
Alka Agrawal, Raees Ahmad Khan
2009 J jnl
ACM SIGSOFT Softw. Eng. Notes
Raees Ahmad Khan, Khurram Mustafa
2009 conf
ITNG
Shalini Chandra, Raees Ahmad Khan, Alka Agrawal
2009 conf
ICISTM
S. Chandra, Raees Ahmad Khan, Alka Agrawal
2008 conf
CSREA EEE
Abdul Wahid, Khurram Mustafa, Raees Ahmad Khan
2007 J jnl
J. King Saud Univ. Comput. Inf. Sci.
Raees Ahmad Khan, Khurram Mustafa, Syed I. Ahson
2005 conf
ACIS-ICIS
K. Gowthaman, Khurram Mustafa, Raees Ahmad Khan
2004 conf
VVEIS
Raees Ahmad Khan, Khurram Mustafa
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"