Carlos Henggeler Antunes

113 papers A 4B 14C 8Journal 60Unranked 24
YearRankTypeTitle / Venue / Authors
2026 J jnl
Eur. J. Oper. Res.
Paulo Jorge Nascimento, Cristóvão Silva, Carlos Henggeler Antunes, Christos T. Maravelias, Samuel Moniz
2025 conf
EvoApplications (2)
Vahid Rasouli, Álvaro Gomes, Carlos Henggeler Antunes
2024 J jnl
IEEE Trans. Ind. Electron.
Vítor Monteiro, Carlos L. Moreira, João Abel Peças Lopes, Carlos Henggeler Antunes, Gerardo J. Osório, João P. S. Catalão, João Luiz Afonso
2024 conf
ICCAIS
Jônatas Augusto Manzolli, João Pedro F. Trovão, Carlos Henggeler Antunes
2024 J jnl
IEEE Trans. Commun.
Filipe Conceição, Marco Gomes, Vítor Silva, Rui Dinis, Carlos Henggeler Antunes
2024 J jnl
Eur. J. Oper. Res.
Paulo Jorge Nascimento, Cristóvão Silva, Carlos Henggeler Antunes, Samuel Moniz
2024 J jnl
Math. Methods Oper. Res.
Carlos Henggeler Antunes, Carlos M. Fonseca, Luís Paquete, Michael Stiglmayr
2023 J jnl
Comput. Oper. Res.
Inês Soares, Maria João Alves, Carlos Henggeler Antunes
2023 conf
ISC2
Nuno Mendes, Pedro Moura, Jérôme Mendes, Carlos Henggeler Antunes, Javad Mohammadi
2023 conf
GECCO Companion
Carlos Henggeler Antunes, Maria João Alves
2022 J jnl
Eur. J. Oper. Res.
Maria João Alves, Carlos Henggeler Antunes
2022 C conf
IECON
Rodrigo Salles, Jérôme Mendes, Carlos Henggeler Antunes, Pedro Moura, Joana Dias
2022 C conf
IECON
Jônatas Augusto Manzolli, João Pedro F. Trovão, Carlos Henggeler Antunes
2022 conf
MIC
Maria João Alves, Carlos Henggeler Antunes, Inês Soares
2022 J jnl
IEEE Trans. Commun.
Filipe Conceição, Carlos Henggeler Antunes, Marco Gomes, Vítor Silva, Rui Dinis
2022 conf
ICCAIS
Jônatas Augusto Manzolli, João Pedro F. Trovão, Carlos Henggeler Antunes
2022 conf
CSNDSP
João Martins, Carlos Henggeler Antunes, Marco Gomes, Vítor Silva, Rui Dinis
2022 conf
VTC Spring
Filipe Conceição, Carlos Henggeler Antunes, Marco Gomes, Vítor Silva, Rui Dinis
2021 J jnl
Eur. J. Oper. Res.
Inês Soares, Maria João Alves, Carlos Henggeler Antunes
2021 J jnl
Int. Trans. Oper. Res.
Inês Soares, Maria João Alves, Carlos Henggeler Antunes
2021 J jnl
EAI Endorsed Trans. Energy Web
Pedro M. L. P. Magalhães, Carlos Henggeler Antunes
2021 J jnl
Oper. Res.
Maria João Alves, Carlos Henggeler Antunes, João Paulo Costa
2020 B conf
EvoCOP
Maria João Alves, Carlos Henggeler Antunes, Inês Soares
2020 J jnl
IEEE Trans. Veh. Technol.
Louis Pelletier, Félix-Antoine LeBel, Carlos Henggeler Antunes, João Pedro F. Trovão
2019 B conf
EvoApplications
André M. Silva, Fernando J. T. E. Ferreira, Carlos Henggeler Antunes
2019 conf
GECCO (Companion)
Inês Soares, Maria João Alves, Carlos Henggeler Antunes
2019 conf
SESC
Pedro M. L. P. Magalhães, Carlos Henggeler Antunes
2019 conf
RNDM
Luís Alçada-Almeida, Teresa Gomes, Carlos Henggeler Antunes
2018 J jnl
IEEE Trans. Veh. Technol.
Hugo Neves de Melo, João Pedro F. Trovão, Paulo G. Pereirinha, Humberto M. Jorge, Carlos Henggeler Antunes
2018 J jnl
Comput. Oper. Res.
Maria João Alves, Carlos Henggeler Antunes
2018 conf
GreeNets
Inês F. G. Reis, Marta A. R. Lopes, Paula F. V. Ferreira, Carlos Henggeler Antunes, Madalena Araújo
2018 J jnl
IEEE Trans. Smart Grid
Maricica Nistor, Carlos Henggeler Antunes
2018 A conf
GECCO
Ivo Gonçalves, Álvaro Gomes, Carlos Henggeler Antunes
2018 J jnl
J. Oper. Res. Soc.
Maria do Castelo Gouveia, Elisabete Duarte Neves, Luís Cândido Dias, Carlos Henggeler Antunes
2017 J jnl
IEEE Trans. Ind. Informatics
Ana Soares, Álvaro Gomes, Carlos Henggeler Antunes, Carlos Oliveira
2017 conf
MOD
Maria João Alves, Carlos Henggeler Antunes
2017 J jnl
Inf. Sci.
Pedro Carrasqueira, Maria João Alves, Carlos Henggeler Antunes
2016 conf
EvoApplications (1)
Maria João Alves, Carlos Henggeler Antunes, Pedro Carrasqueira
2016 J jnl
OR Spectr.
Maria do Castelo Gouveia, Luis C. Dias, Carlos Henggeler Antunes, M. A. Mota, E. M. Duarte, E. M. Tenreiro
2016 conf
SSCI
Maria João Alves, Carlos Henggeler Antunes
2016 conf
SSCI
Andreia M. Carreiro, Carlos Henggeler Antunes, Humberto Jorge
2016 conf
VTC Fall
Pedro Bento, Carlos Henggeler Antunes, Marco Alexandre Cravo Gomes, Rui Dinis, Vítor Manuel Mendes da Silva
2016 J jnl
Ann. Oper. Res.
Carlos Oliveira, Dulce Helena Carvalho Coelho, Carlos Henggeler Antunes
2016 J jnl
IEEE Trans. Veh. Technol.
Felipe Machado, João Pedro F. Trovão, Carlos Henggeler Antunes
2016 B conf
CEC
Carlos Henggeler Antunes, Dolores Margarida
2016 C conf
ICORES
Carlos Henggeler Antunes, Maria João Alves, Joana Dias, Teresa Gomes, Benjamim Cardoso, José Freitas
2015 conf
EMO (1)
Pedro Carrasqueira, Maria João Alves, Carlos Henggeler Antunes
2015 A conf
GECCO
Maria João Alves, Carlos Henggeler Antunes, Pedro Carrasqueira
2015 J jnl
IEEE Trans. Ind. Electron.
João Pedro F. Trovão, Victor D. N. Santos, Carlos Henggeler Antunes, Paulo G. Pereirinha, Humberto M. Jorge
2015 B conf
EvoApplications
Andreia M. Carreiro, Carlos Oliveira, Carlos Henggeler Antunes, Humberto M. Jorge
2015 ed.
EMO (1)
António Gaspar-Cunha, Carlos Henggeler Antunes, Carlos A. Coello Coello
2015 ed.
EMO (2)
António Gaspar-Cunha, Carlos Henggeler Antunes, Carlos A. Coello Coello
2015 J jnl
CoRR
Eugénio Rodrigues, Ana Rita Amaral, Adélio Rodrigues Gaspar, Álvaro Gomes, Manuel Carlos Gameiro da Silva, Carlos Henggeler Antunes
2015 J jnl
Comput. Appl. Eng. Educ.
Maria João Alves, Carlos Henggeler Antunes, João C. N. Clímaco
2015 conf
GECCO (Companion)
Dolores Margarida, Carlos Henggeler Antunes
2015 J jnl
CoRR
David Sousa-Rodrigues, Mafalda Teixeira de Sampayo, Eugénio Rodrigues, Adélio Rodrigues Gaspar, Álvaro Gomes, Carlos Henggeler Antunes
2014 conf
MCDM
Eunice Oliveira, Carlos Henggeler Antunes, Álvaro Gomes
2014 B conf
EvoApplications
Pedro Carrasqueira, Maria João Alves, Carlos Henggeler Antunes
2014 conf
SMARTGREENS
Andreia M. Carreiro, Carlos Henggeler Antunes, Humberto M. Jorge
2014 conf
ICCSA (2)
Carolina Raposo, Carlos Henggeler Antunes, João Pedro Barreto
2014 J jnl
Neurocomputing
Tiago Matias, Francisco Souza, Rui Araújo, Carlos Henggeler Antunes
2014 J jnl
Int. J. Syst. Sci.
Carlos Henggeler Antunes, David Ríos Insua, Luís Cândido Dias
2013 J jnl
Comput. Oper. Res.
Eunice Oliveira, Carlos Henggeler Antunes, Álvaro Gomes
2013 conf
GECCO (Companion)
Eunice Oliveira, Carlos Henggeler Antunes, Álvaro Gomes
2013 C conf
IECON
João Pedro F. Trovão, Victor D. N. Santos, Paulo G. Pereirinha, Humberto M. Jorge, Carlos Henggeler Antunes
2013 J jnl
Neurocomputing
Symone G. Soares, Carlos Henggeler Antunes, Rui Araújo
2013 C conf
IECON
Felipe Machado, João Pedro F. Trovão, Carlos Henggeler Antunes
2013 B conf
EvoApplications
Ana Soares, Álvaro Gomes, Carlos Henggeler Antunes, Hugo Cardoso
2013 C conf
ETFA
Tiago Matias, Rui Araújo, Carlos Henggeler Antunes, Dulce Gabriel
2013 J jnl
J. Oper. Res. Soc.
Maria do Castelo Gouveia, Luis C. Dias, Carlos Henggeler Antunes
2012 C conf
ICORES
Paulo Freitas, Carlos Henggeler Antunes, Jorge Dias
2012 A conf
GECCO
Symone G. Soares, Carlos Henggeler Antunes, Rui Araújo
2012 J jnl
Intell. Decis. Technol.
Luis C. Dias, Carlos Henggeler Antunes, David Ríos Insua
2012 J jnl
Intell. Decis. Technol.
Luís Cândido Dias, Carlos Henggeler Antunes, David Ríos Insua
2011 J jnl
Decis. Support Syst.
João Manuel Coutinho-Rodrigues, Ana Simão, Carlos Henggeler Antunes
2011 J jnl
Decis. Support Syst.
Luís Santos, João Manuel Coutinho-Rodrigues, Carlos Henggeler Antunes
2011 A conf
GECCO
Francisco Vasconcelos, Carlos Henggeler Antunes, João Pedro Barreto
2011 J jnl
Int. J. Nat. Comput. Res.
Eunice Oliveira, Carlos Henggeler Antunes, Álvaro Gomes
2010 B conf
SMC
David Portugal, Carlos Henggeler Antunes, Rui P. Rocha
2010 B conf
EvoCOP
Eunice Oliveira, Carlos Henggeler Antunes
2010 B conf
SMC
Eunice Oliveira, Carlos Henggeler Antunes
2010 J jnl
Int. J. Adv. Intell. Paradigms
Álvaro Gomes, Carlos Henggeler Antunes, Antonio Gomes Martins
2010 B conf
IEEE Congress on Evolutionary Computation
Filipe M. Ferreira, Paulo E. M. de Almeida, Carlos Henggeler Antunes, Henrique J. A. da Silva
2009 J jnl
Eur. J. Oper. Res.
Reinhard Madlener, Carlos Henggeler Antunes, Luis C. Dias
2009 J jnl
Eur. J. Oper. Res.
Carlos Henggeler Antunes, Álvaro Gomes
2009 B conf
EvoCOP
Carlos Barrico, Carlos Henggeler Antunes, Dulce Fernão Pires
2009 J jnl
Eur. J. Oper. Res.
L. P. Neves, Luis C. Dias, Carlos Henggeler Antunes, Antonio Gomes Martins
2009 C conf
IJCCI
Álvaro Gomes, Carlos Henggeler Antunes, Antonio Gomes Martins, João Melo
2008 J jnl
J. Oper. Res. Soc.
Maria do Castelo Gouveia, Luis C. Dias, Carlos Henggeler Antunes
2008 J jnl
Comput. Oper. Res.
Álvaro Gomes, Carlos Henggeler Antunes, Antonio Gomes Martins
2008 conf
KES (1)
Álvaro Gomes, Carlos Henggeler Antunes, Antonio Gomes Martins
2008 J jnl
Comput. Oper. Res.
Maria João Alves, João C. N. Clímaco, Carlos Henggeler Antunes, Humberto Jorge, Antonio Gomes Martins
2007 J jnl
Decis. Support Syst.
Eduardo Natividade-Jesus, João Manuel Coutinho-Rodrigues, Carlos Henggeler Antunes
2007 ch.
Evolutionary Computation in Dynamic and Uncertain Environments
Carlos Barrico, Carlos Henggeler Antunes
2007 J jnl
Decis. Support Syst.
Carlos Henggeler Antunes, Luis C. Dias
2007 J jnl
Eur. J. Oper. Res.
Carlos Henggeler Antunes, Luis C. Dias
2007 J jnl
Eur. J. Oper. Res.
Carla Oliveira Henriques, Carlos Henggeler Antunes
2007 B conf
SMC
Ana Rosa Pereira Borges, Carlos Henggeler Antunes
2006 J jnl
Eur. J. Oper. Res.
Carlos Henggeler Antunes
2006 J jnl
Eur. J. Oper. Res.
Carlos Henggeler Antunes
2006 B conf
IEEE Congress on Evolutionary Computation
Carlos Barrico, Carlos Henggeler Antunes
2004 J jnl
Eur. J. Oper. Res.
Carla Oliveira Henriques, Carlos Henggeler Antunes
2004 B conf
EvoCOP
Álvaro Gomes, Carlos Henggeler Antunes, Antonio Gomes Martins
2004 J jnl
J. Oper. Res. Soc.
L. M. P. Neves, Antonio Gomes Martins, Carlos Henggeler Antunes, Luis C. Dias
2003 J jnl
Eur. J. Oper. Res.
Ana Rosa Pereira Borges, Carlos Henggeler Antunes
2003 J jnl
Decis. Support Syst.
Ana Rosa Pereira Borges, Carlos Henggeler Antunes
2003 J jnl
Ann. Oper. Res.
Carlos Henggeler Antunes, Antonio Gomes Martins
2002 J jnl
Eur. J. Oper. Res.
Ana Rosa Pereira Borges, Carlos Henggeler Antunes
1998 J jnl
Eur. J. Oper. Res.
Carlos Henggeler Antunes, José M. F. Craveirinha, João C. N. Clímaco
1994 J jnl
Decis. Support Syst.
Carlos Henggeler Antunes, Luís Alçada-Almeida, Virgínia Lopes, João C. N. Clímaco
1994 J jnl
Ann. Oper. Res.
João C. N. Clímaco, Carlos Henggeler Antunes
1992 J jnl
Comput. Oper. Res.
Carlos Henggeler Antunes, Maria João Alves, Ana L. Silva, João C. N. Clímaco
1992 J jnl
Oper. Res. Lett.
Carlos Henggeler Antunes, João C. N. Clímaco
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"