Rafael Asenjo

73 papers A 3B 6C 5Misc 2Journal 35Unranked 22
YearRankTypeTitle / Venue / Authors
2025 J jnl
J. Supercomput.
Cristian Campos, Rafael Asenjo, Angeles G. Navarro
2025 J jnl
Concurr. Comput. Pract. Exp.
Cristian Campos, Rafael Asenjo, Javier Hormigo, Angeles G. Navarro
2024 J jnl
J. Comput. Sci.
Felipe Muñoz, Rafael Asenjo, Angeles G. Navarro, José Carlos Cabaleiro
2024 conf
Euro-Par Workshops (1)
Cristian Campos, Rafael Asenjo, Javier Hormigo, Angeles G. Navarro
2023 J jnl
Future Gener. Comput. Syst.
Jose Carlos Romero, Angeles G. Navarro, Andrés Rodríguez, Rafael Asenjo
2022 J jnl
J. Syst. Archit.
Andrés Rodríguez, Angeles G. Navarro, Kris Nikov, José L. Núñez-Yáñez, Ruben Gran, Darío Suárez Gracia, Rafael Asenjo
2021 J jnl
J. Supercomput.
Denisa-Andreea Constantinescu, Angeles G. Navarro, Francisco Corbera, Juan-Antonio Fernández-Madrigal, Rafael Asenjo
2021 J jnl
Future Gener. Comput. Syst.
Jose Carlos Romero, Angeles G. Navarro, Antonio Vilches, Andrés Rodríguez, Francisco Corbera, Rafael Asenjo
2020 J jnl
Sensors
Juan-Antonio Fernández-Madrigal, Angeles G. Navarro, Rafael Asenjo, Ana Cruz-Martín
2020 J jnl
CoRR
Kris Nikov, Mohammad Hosseinabady, Rafael Asenjo, Andrés Rodríguez, Angeles G. Navarro, José L. Núñez-Yáñez
2020 J jnl
J. Supercomput.
Andrés Rodríguez, Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Ruben Gran, Darío Suárez Gracia, José L. Núñez-Yáñez
2020 J jnl
J. Parallel Distributed Comput.
Denisa-Andreea Constantinescu, Angeles G. Navarro, Juan-Antonio Fernández-Madrigal, Rafael Asenjo
2020 J jnl
J. Supercomput.
Jose Carlos Romero, Antonio Vilches, Andrés Rodríguez, Angeles G. Navarro, Rafael Asenjo
2019 conf
BLOCKCHAIN
Daniel-Jesus Munoz, Denisa-Andreea Constantinescu, Rafael Asenjo, Lidia Fuentes
2019 J jnl
J. Supercomput.
José L. Núñez-Yáñez, Sam Amiri, Mohammad Hosseinabady, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Darío Suárez Gracia, Ruben Gran
2019 J jnl
J. Syst. Archit.
Andrés Rodríguez, Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Ruben Gran Tejero, Darío Suárez Gracia, José L. Núñez-Yáñez
2019 J jnl
Int. J. Parallel Program.
Angeles G. Navarro, Francisco Corbera, Andrés Rodríguez, Antonio Vilches, Rafael Asenjo
2019 J jnl
J. Supercomput.
José L. Núñez-Yáñez, Sam Amiri, Mohammad Hosseinabady, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Darío Suárez Gracia, Ruben Gran
2019 J jnl
J. Supercomput.
Alejandro Villegas, Angeles G. Navarro, Rafael Asenjo, Oscar G. Plata
2018 J jnl
J. Parallel Distributed Comput.
Luis Remis, María Jesús Garzarán, Rafael Asenjo, Angeles G. Navarro
2018 J jnl
IEEE Trans. Computers
Alejandro Villegas, Rafael Asenjo, Angeles G. Navarro, Oscar G. Plata, David R. Kaeli
2018 J jnl
J. Parallel Distributed Comput.
Guillermo Aparicio, Jose M. G. Salmerón, Leocadio G. Casado, Rafael Asenjo, Eligius M. T. Hendrix
2018 J jnl
CoRR
José L. Núñez-Yáñez, Mohammad Hosseinabady, Moslem Amiri, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Ruben Gran Tejero, Darío Suárez Gracia
2018 B conf
FPL
Sam Amiri, Mohammad Hosseinabady, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, José L. Núñez-Yáñez
2017 conf
Euro-Par
Alejandro Villegas, Rafael Asenjo, Angeles G. Navarro, Oscar G. Plata, Rafael Ubal, David R. Kaeli
2017 J jnl
J. Glob. Optim.
Juan F. R. Herrera, Jose M. G. Salmerón, Eligius M. T. Hendrix, Rafael Asenjo, Leocadio G. Casado
2017 conf
PARCO
José L. Núñez-Yáñez, Mohammad Hosseinabady, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Ruben Gran Tejero, Darío Suárez Gracia
2017 conf
PARCO
Alejandro Villegas, Angeles G. Navarro, Rafael Asenjo, Oscar G. Plata
2016 C conf
SBAC-PAD
Luis Remis, María Jesús Garzarán, Rafael Asenjo, Angeles G. Navarro
2016 J jnl
IEEE Trans. Parallel Distributed Syst.
Antonio Vilches, Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Ruben Gran, María Jesús Garzarán
2016 B ed.
PPoPP
Rafael Asenjo, Tim Harris
2015 Misc conf
ICCS
Antonio Vilches, Rafael Asenjo, Angeles G. Navarro, Francisco Corbera, Ruben Gran Tejero, María Jesús Garzarán
2015 conf
TrustCom/BigDataSE/ISPA (3)
Andrés Rodríguez, Angeles G. Navarro, Rafael Asenjo, Antonio Vilches, Francisco Corbera, María Jesús Garzarán
2015 conf
PARCO
Andrés Rodríguez, Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Antonio Vilches, María Jesús Garzarán
2015 J jnl
CoRR
Francisco Corbera, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Antonio Vilches, María Jesús Garzarán, Ismat Chaib Draa, Jamel Tayeb, Smaïl Niar, Mikael Desertot, Daniel Gregorek, Robert Schmidt, Alberto García Ortiz, Pedro López-García, Rémy Haemmerlé, Maximiliano Klemen, Umer Liqat, Manuel V. Hermenegildo, Radim Vavrík, Albert Saà-Garriga, David Castells-Rufas, Jordi Carrabina
2015 J jnl
CoRR
Francisco Corbera, Andrés Rodríguez, Rafael Asenjo, Angeles G. Navarro, Antonio Vilches, María Jesús Garzarán
2015 conf
PARCO
Rafael Asenjo, Angeles G. Navarro, Andrés Rodríguez, José L. Núñez-Yáñez
2014 J jnl
Parallel Comput.
Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Antonio J. Dios, Emilio L. Zapata
2014 conf
HPCS
Angeles G. Navarro, Antonio Vilches, Rafael Asenjo, Francisco Corbera
2014 J jnl
J. Supercomput.
Angeles G. Navarro, Antonio Vilches, Francisco Corbera, Rafael Asenjo
2012 J jnl
J. Parallel Distributed Comput.
Angeles G. Navarro, Francisco Corbera, Rafael Asenjo, Rosa Castillo, Emilio L. Zapata
2012 C conf
SBAC-PAD
Alberto Sanz, Rafael Asenjo, Juan López, Rafael Larrosa, Angeles G. Navarro, Vassily Litvinov, Sung-Eun Choi, Bradford L. Chamberlain
2011 conf
PARCO
Rafael Larrosa, Rafael Asenjo, Angeles G. Navarro, Bradford L. Chamberlain
2011 conf
PARCO
Antonio J. Dios, Angeles G. Navarro, Rafael Asenjo, Francisco Corbera, Emilio L. Zapata
2011 Misc conf
HiPC
Antonio J. Dios, Rafael Asenjo, Angeles G. Navarro, Francisco Corbera, Emilio L. Zapata
2010 C conf
HPCC
Antonio J. Dios, Rafael Asenjo, Angeles G. Navarro, Francisco Corbera, Emilio L. Zapata
2009 B conf
PACT
Angeles G. Navarro, Rafael Asenjo, Siham Tabik, Calin Cascaval
2009 conf
PARCO
Rosa Castillo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2009 A conf
ICS
Angeles G. Navarro, Rafael Asenjo, Siham Tabik, Calin Cascaval
2009 conf
ICPP Workshops
Adrian Tineo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2008 conf
Euro-Par Workshops
Rosa Castillo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2008 A conf
IPDPS
Rafael Asenjo, Rosa Castillo, Francisco Corbera, Angeles G. Navarro, Adrian Tineo, Emilio L. Zapata
2007 J jnl
J. Parallel Distributed Comput.
Angeles G. Navarro, Francisco Corbera, Adrian Tineo, Rafael Asenjo, Emilio L. Zapata
2006 conf
Euro-Par
Rosa Castillo, Adrian Tineo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2005 conf
PARCO
Adrian Tineo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2005 B conf
ICPP
Adrian Tineo, Francisco Corbera, Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata
2005 J jnl
Parallel Comput.
Oscar G. Plata, Rafael Asenjo, Eladio Gutiérrez, Francisco Corbera, Angeles G. Navarro, Emilio L. Zapata
2004 J jnl
IEEE Trans. Parallel Distributed Syst.
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
2004 conf
LCPC
Angeles G. Navarro, Francisco Corbera, Rafael Asenjo, Adrian Tineo, Oscar G. Plata, Emilio L. Zapata
2004 C conf
PDP
Rafael Asenjo, Francisco Corbera, Eladio Gutiérrez, M. Angeles Gonzales Navarro, Oscar G. Plata, Emilio L. Zapata
2002 J jnl
Int. J. Parallel Program.
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
2002 conf
LCPC
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
2001 B conf
ICPP
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
2000 conf
LCPC
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
2000 J jnl
Parallel Comput.
Eladio Gutiérrez, Rafael Asenjo, Oscar G. Plata, Emilio L. Zapata
1999 B conf
ICPP
Angeles G. Navarro, Rafael Asenjo, Emilio L. Zapata, David A. Padua
1999 J jnl
Parallel Comput.
Emilio L. Zapata, Oscar G. Plata, Rafael Asenjo, Guillermo P. Trabado
1999 A conf
International Conference on Supercomputing
Francisco Corbera, Rafael Asenjo, Emilio L. Zapata
1999 conf
ACPC
Rafael Asenjo, Emilio L. Zapata
1998 conf
LCPC
Rafael Asenjo, Oscar G. Plata, Juan Touriño, Ramon Doallo, Emilio L. Zapata
1995 conf
HPCN Europe
Rafael Asenjo, Emilio L. Zapata
1994 C conf
PDP
Manuel Ujaldon, Rafael Asenjo, Emilio L. Zapata, José Carlos Cabaleiro, José María Carazo
1993 J jnl
Microprocess. Microprogramming
Rafael Asenjo, Manuel Ujaldon, Emilio L. Zapata
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"