Carlos Duarte

102 papers A* 5A 9B 2Misc 4Journal 19Unranked 59
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Sérgio Alves, Carlos Duarte, Kyle Montague, Tiago João Guerreiro
2026 A* conf
CHI
Sérgio Alves, Carlos Duarte, Kyle Montague, Tiago João Vieira Guerreiro
2026 conf
CHI Extended Abstracts
Beatriz Patatas, Carlos Duarte, Letícia Seixas Pereira
2025 A* conf
CHI
Diogo Furtado, Renato Alexandre Ribeiro, Manuel Piçarra, Letícia Seixas Pereira, Carlos Duarte, André Rodrigues, João Guerreiro
2025 J jnl
J. Inf. Technol. Tour.
Rita Costa, José Coelho, Diogo Lima, Carlos Duarte, Pedro Moita
2025 J jnl
Univers. Access Inf. Soc.
Letícia Seixas Pereira, Carlos Duarte
2025 conf
IUI Companion
Carlos Duarte, Miguel Costa, Letícia Seixas Pereira, João Guerreiro
2025 J jnl
Univers. Access Inf. Soc.
Krzysztof Krejtz, Ann Marcus-Quinn, Carlos Duarte, Iga Stasiak, Letícia Seixas Pereira, Izabela Krejtz
2024 J jnl
Univers. Access Inf. Soc.
Beatriz Martins, Carlos Duarte
2024 J jnl
Comput. Graph. Forum
Diogo Duarte, Rita Costa, Pedro Bizarro, Carlos Duarte
2024 A* conf
CHI
Letícia Seixas Pereira, Maria Matos, Carlos Duarte
2024 J jnl
ACM Trans. Access. Comput.
Letícia Seixas Pereira, João Guerreiro, André Rodrigues, Tiago João Guerreiro, Carlos Duarte
2024 J jnl
CoRR
Xia Chen, Guoquan Lv, Xinwei Zhuang, Carlos Duarte, Stefano Schiavon, Philipp Geyer
2024 A* conf
CHI
Renato Alexandre Ribeiro, Inês Gonçalves, Manuel Piçarra, Letícia Seixas Pereira, Carlos Duarte, André Rodrigues, João Guerreiro
2024 J jnl
Univers. Access Inf. Soc.
Beatriz Martins, Carlos Duarte
2024 conf
W4A
Filipe Rosa Martins, Letícia Seixas Pereira, Carlos Duarte
2024 conf
HCI (68)
Carlos Simões, Letícia Seixas Pereira, Carlos Duarte
2023 conf
HCI (49)
Maria Matos, Letícia Seixas Pereira, Carlos Duarte
2022 J jnl
Univers. Access Inf. Soc.
Daniel Costa, Carlos Duarte
2022 A conf
ASSETS
Letícia Seixas Pereira, José Coelho, André Rodrigues, João Guerreiro, Tiago João Guerreiro, Carlos Duarte
2021 J jnl
CoRR
Letícia Seixas Pereira, José Coelho, André Rodrigues, João Guerreiro, Tiago João Guerreiro, Carlos Duarte
2021 conf
WebSci (Companion)
Carlos Duarte, Letícia Seixas Pereira, André R. B. Santos, João V. Vicente, André Rodrigues, João Guerreiro, José Coelho, Tiago João Guerreiro
2020 J jnl
Multim. Tools Appl.
Daniel Costa, Carlos Duarte
2020 conf
W4A
Rafael Almeida, Carlos Duarte
2020 conf
W4A
Tânia Frazão, Carlos Duarte
2020 ed.
W4A
Carlos Duarte, Ted Drake, Faustina Hwang, Clayton Lewis
2019 conf
W4A
Carlos Duarte, Carlos M. Duarte, Luís Carriço
2019 conf
INTERACT (1)
David Costa, Carlos Duarte
2019 ch.
Web Accessibility (2nd Ed.)
Carlos Duarte, Manuel J. Fonseca
2019 conf
W4A
Daniel Costa, Carlos Duarte
2019 J jnl
ACM Trans. Interact. Intell. Syst.
Fang Chen, Carlos Duarte, Wai-Tat Fu
2018 conf
W4A
Carlos Duarte, Ana Salvado, Mehmet Elgin Akpinar, Yeliz Yesilada, Luís Carriço
2018 B conf
QoMEX
Evangelos Alexiou, Touradj Ebrahimi, Marco V. Bernardo, Manuela Pereira, António M. G. Pinheiro, Luís Alberto da Silva Cruz, Carlos Duarte, Lovorka Gotal Dmitrovic, Emil Dumic, Dragan Matkovics, Athanassios N. Skodras
2018 conf
W4A
Carlos Duarte, Inês Matos, Luís Carriço
2017 J jnl
Int. J. Hum. Comput. Stud.
José Coelho, Fábio Rito, Carlos Duarte
2017 J jnl
Interact. Comput.
Xabier Valencia, J. Eduardo Pérez, Myriam Arrue, Julio Abascal, Carlos Duarte, Lourdes Moreno
2017 ed.
IUI Companion
George A. Papadopoulos, Tsvi Kuflik, Fang Chen, Carlos Duarte, Wai-Tat Fu
2017 J jnl
Frontiers ICT
Carlos Duarte, Simon Desart, David Costa, Bruno Dumas
2017 A ed.
IUI
George A. Papadopoulos, Tsvi Kuflik, Fang Chen, Carlos Duarte, Wai-Tat Fu
2017 conf
PPT@PERSUASIVE
Carlos Azevedo, Cristina Chesta, José Coelho, Davide Dimola, Carlos Duarte, Marco Manca, Jan Egil Nordvik, Fabio Paternò, Anne-Marthe Sanders, Carmen Santoro
2017 J jnl
Univers. Access Inf. Soc.
Daniel Costa, Carlos Duarte
2016 J jnl
Comput. Hum. Behav.
José Coelho, Carlos Duarte
2016 conf
W4A
Carlos Duarte, Inês Matos, João Vicente Messias, Ana Salvado, Carlos M. Duarte, Luís Carriço
2016 conf
CHI Extended Abstracts
Inês Rodolfo, Nuno Correia, Marta Sousa, Paulo Sá, Carlos Duarte
2016 conf
BCS HCI
Inês Rodolfo, Nuno Correia, Carlos Duarte, Carlota Louro, Rui Almeida
2015 A conf
IUI
David Costa, Carlos Duarte
2015 conf
INTERACT (1)
José Coelho, Fábio Rito, Nuno Luz, Carlos Duarte
2015 conf
INTERACT (1)
José Coelho, Carlos Duarte
2015 B conf
TEI
Rafael Nunes, Fábio Rito, Carlos Duarte
2015 conf
DSAI
Daniel Costa, Luís Carriço, Carlos Duarte
2014 conf
BCS HCI
Daniel Costa, Ricardo Dias, Carlos Duarte
2014 Misc conf
NordiCHI
Inês Rodolfo, Liliana Laranjo, Nuno Correia, Carlos Duarte
2014 conf
W4A
João Martins, José Carilho, Oliver Schnell, Carlos Duarte, Francisco M. Couto, Luís Carriço, Tiago João Guerreiro
2014 conf
CRIWG
André Silva, Diogo Marques, Carlos Duarte, Maria Ana Viana-Baptista, Luís Carriço
2014 conf
CHI Extended Abstracts
Carlos Duarte, Luís Carriço, Tiago João Guerreiro, Carla Almeida, Soraia Nobre, Ana Margarida Campos
2014 Misc conf
AMIA
Inês Rodolfo, Liliana Laranjo, Nuno Correia, Carlos Duarte
2014 conf
BCS HCI
Nádia Fernandes, André Rodrigues, Carlos Duarte, Raquel Hijón-Neira, Luís Carriço
2014 conf
CHI Extended Abstracts
Carlos Duarte, Luís Carriço, David Costa, Daniel Costa, André O. Falcão, Luís Tavares
2013 conf
W4A
Nádia Fernandes, Ana Sofia Batista, Daniel Costa, Carlos Duarte, Luís Carriço
2013 conf
INTERACT (1)
Daniel Costa, Nádia Fernandes, Sofia Neves, Carlos Duarte, Raquel Hijón-Neira, Luís Carriço
2012 A ed.
IUI
Carlos Duarte, Luís Carriço, Joaquim A. Jorge, Sharon L. Oviatt, Daniel Gonçalves
2012 conf
ICCHP (1)
Daniel Costa, Nádia Fernandes, Carlos Duarte, Luís Carriço
2012 Misc conf
CISIS
Pedro Feiteira, Carlos Duarte
2012 A conf
IUI
Pradipta Biswas, Patrick Langdon, Christoph Jung, Pascal Hamisu, Carlos Duarte, Luís Almeida
2012 conf
DSAI
Nádia Fernandes, Daniel Costa, Carlos Duarte, Luís Carriço
2012 conf
W4A
Nádia Fernandes, Daniel Costa, Sergio Neves, Carlos Duarte, Luís Carriço
2012 conf
PerDis
Nancy V. Diniz, Carlos Duarte, Nuno Guimarães
2011 conf
HCI (6)
Pascal Hamisu, Gregor Heinrich, Christoph Jung, Volker Hahn, Carlos Duarte, Patrick Langdon, Pradipta Biswas
2011 conf
HCI (5)
David Costa, Carlos Duarte
2011 conf
HCI (5)
Pedro Feiteira, Carlos Duarte
2011 A conf
ASSETS
José Coelho, Carlos Duarte, Pradipta Biswas, Patrick Langdon
2011 conf
ANT/MobiWIS
Carlos Duarte, Ana Paula Afonso
2011 conf
HCI (5)
Carlos Duarte, José Coelho, Pedro Feiteira, David Costa, Daniel Costa
2011 conf
EuroITV
Pradipta Biswas, Patrick Langdon, Carlos Duarte, José Coelho
2011 conf
HCI (5)
Daniel Costa, Carlos Duarte
2011 conf
HCI (5)
José Coelho, Carlos Duarte
2010 Misc conf
SAC
Inês Oliveira, Ovidiu Grigore, Nuno Guimarães, Carlos Duarte
2010 conf
AmI
Volker Hahn, Pascal Hamisu, Christoph Jung, Gregor Heinrich, Carlos Duarte, Patrick Langdon
2009 conf
ICEIS (5)
António Neto, Carlos Duarte
2009 conf
INTERACT (2)
António Neto, Carlos Duarte
2009 conf
CRIWG
Carlos Duarte, António Neto
2009 conf
HCI (4)
Joana Pereira, Luís Carriço, Carlos Duarte
2009 conf
HAID
Tiago Reis, Luís Carriço, Carlos Duarte
2009 conf
HCI (6)
Tiago Reis, Luís Carriço, Carlos Duarte
2009 conf
HCI (7)
Carlos Duarte, Luís Carriço
2007 conf
HCI (7)
Carlos Duarte, Luís Carriço
2007
Carlos Duarte
2007 J jnl
J. Digit. Inf.
Carlos Duarte, Luís Carriço
2007 conf
HCI (1)
Carlos Duarte, Luís Carriço, Nuno Guimarães
2007 conf
HCI (2)
Carlos Duarte, Luís Carriço, Fernando Morgado
2007 conf
HCIEd
Teresa Chambel, Pedro Antunes, Carlos Duarte, Luís Carriço, Nuno Guimarães
2007 conf
WEBIST (2)
Rui Lopes, Hugo Simões, Carlos Duarte, Luís Carriço
2006 A conf
IUI
Carlos Duarte, Luís Carriço
2006 A* conf
WWW
Rui Lopes, Luís Carriço, Carlos Duarte
2006 A conf
INTERSPEECH
Isabel Trancoso, Carlos Duarte, António Joaquim Serralheiro, Diamantino Caseiro, Luís Carriço, Céu Viana
2004 conf
ICEIS (5)
Carlos Duarte, Luís Carriço, Hugo Simões
2004 conf
CADUI
Luís Carriço, Carlos Duarte, Rui Lopes, Miguel Rodrigues Fornari, Nuno Guimarães
2004 A conf
IUI
Carlos Duarte, Luís Carriço
2004 conf
ICEIS (5)
Luís Carriço, Carlos Duarte, Nuno Guimarães, António Joaquim Serralheiro, Isabel Trancoso
2003 conf
ICWI
Carlos Duarte, Teresa Chambel, Luís Carriço, Nuno Guimarães, Hugo Simões
2003 conf
ICEIS (3)
Carlos Duarte, Luís Carriço, Teresa Chambel, Nuno Guimarães
2003 conf
HCI (4)
Luís Carriço, Nuno Guimarães, Carlos Duarte, Teresa Chambel, Hugo Simões
tests/unit/test_dataclasses.py
← Index tests/unit/test_dataclasses.py python
"""
Unit tests for redb.models.dataclasses.

These tests verify construction, field defaults, and type expectations for
every dataclass in the module (excluding Mach-O dataclasses, which are
covered by test_macho_dataclasses.py).
"""
import pytest
from dataclasses import asdict, fields

pytestmark = [pytest.mark.unit, pytest.mark.dataclass]


# ============================================================================
# Hash / Hashes
# ============================================================================

class TestHashDataclass:
    """Tests for the Hash dataclass."""

    def test_creation(self):
        from redb.models.dataclasses import Hash

        h = Hash(
            md5="d41d8cd98f00b204e9800998ecf8427e",
            sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709",
            sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        )
        assert h.md5 == "d41d8cd98f00b204e9800998ecf8427e"
        assert h.sha1 == "da39a3ee5e6b4b0d3255bfef95601890afd80709"
        assert h.sha256 == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

    def test_asdict(self):
        from redb.models.dataclasses import Hash

        h = Hash(md5="a", sha1="b", sha256="c")
        d = asdict(h)
        assert d == {"md5": "a", "sha1": "b", "sha256": "c"}


class TestHashesDataclass:
    """Tests for the Hashes dataclass."""

    def test_required_fields(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(
            md5="md5val",
            sha1="sha1val",
            sha256="sha256val",
            ssdeep_hash="ssdeep",
            tlsh_hash="tlsh",
        )
        assert h.md5 == "md5val"
        assert h.ssdeep_hash == "ssdeep"

    def test_optional_pe_fields_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.authentihash is None
        assert h.imphash is None
        assert h.richhash is None
        assert h.richpe_hash is None
        assert h.richpv_hash is None
        assert h.richpv_hash_sorted is None
        assert h.typerefhash is None
        assert h.impfuzzy is None

    def test_optional_elf_fields_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.import_hash is None
        assert h.export_hash is None
        assert h.section_hash is None
        assert h.symbol_hash is None
        assert h.dynamic_hash is None

    def test_optional_macho_fields_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.macho_dylib_hash is None
        assert h.macho_import_hash is None
        assert h.macho_export_hash is None
        assert h.macho_entitlement_hash is None
        assert h.macho_symhash is None

    def test_macho_fields_settable(self):
        from redb.models.dataclasses import Hashes

        h = Hashes(
            md5="a", sha1="b", sha256="c", ssdeep_hash="d", tlsh_hash="e",
            macho_dylib_hash="dylib_h",
            macho_import_hash="import_h",
            macho_export_hash="export_h",
            macho_entitlement_hash="ent_h",
            macho_symhash="sym_h",
        )
        assert h.macho_dylib_hash == "dylib_h"
        assert h.macho_import_hash == "import_h"
        assert h.macho_export_hash == "export_h"
        assert h.macho_entitlement_hash == "ent_h"
        assert h.macho_symhash == "sym_h"


# ============================================================================
# BasicProperties
# ============================================================================

class TestBasicPropertiesDataclass:
    """Tests for the BasicProperties dataclass."""

    def test_required_fields(self):
        from redb.models.dataclasses import BasicProperties

        bp = BasicProperties(
            filename="test.exe",
            sample_name="test.exe",
            filesize=1024,
            filetype="PE32",
            filetype_mime="application/x-dosexec",
            filetype_magika="pebin",
            file_entropy=6.5,
        )
        assert bp.filename == "test.exe"
        assert bp.filesize == 1024
        assert bp.file_entropy == 6.5

    def test_optional_fields_default_none(self):
        from redb.models.dataclasses import BasicProperties

        bp = BasicProperties(
            filename="x", sample_name="x", filesize=0,
            filetype="t", filetype_mime="m", filetype_magika="k", file_entropy=0.0,
        )
        assert bp.is_packed is None
        assert bp.is_fat is None
        assert bp.child_sha256 is None
        assert bp.child_architecture is None
        assert bp.child_filetype is None

    def test_fat_fields(self):
        from redb.models.dataclasses import BasicProperties

        bp = BasicProperties(
            filename="universal.app",
            sample_name="universal.app",
            filesize=2048,
            filetype="Mach-O universal",
            filetype_mime="application/x-mach-binary",
            filetype_magika="macho",
            file_entropy=7.2,
            is_fat=True,
            child_sha256=["hash1", "hash2"],
            child_architecture=["x86_64", "arm64"],
            child_filetype=["macho", "macho"],
        )
        assert bp.is_fat is True
        assert len(bp.child_sha256) == 2
        assert bp.child_architecture == ["x86_64", "arm64"]

    def test_asdict_roundtrip(self):
        from redb.models.dataclasses import BasicProperties

        bp = BasicProperties(
            filename="f", sample_name="s", filesize=10,
            filetype="t", filetype_mime="m", filetype_magika="k", file_entropy=1.0,
        )
        d = asdict(bp)
        assert d["filename"] == "f"
        assert d["is_fat"] is None


# ============================================================================
# DIEinfo / CAPA
# ============================================================================

class TestDIEinfoDataclass:
    def test_creation(self):
        from redb.models.dataclasses import DIEinfo

        d = DIEinfo(die_full_dump="dump_text")
        assert d.die_full_dump == "dump_text"
        assert d.die_info == {}

    def test_with_info(self):
        from redb.models.dataclasses import DIEinfo

        d = DIEinfo(die_full_dump="x", die_info={"packer": "UPX"})
        assert d.die_info["packer"] == "UPX"


class TestCAPADataclass:
    def test_creation(self):
        from redb.models.dataclasses import CAPA

        c = CAPA(
            capa_dump="dump",
            capabilities=["cap1"],
            namespaces=["ns1"],
            attack_dump="attack",
            tactics=["TA0001"],
            techniques=["T1059"],
            techniques_id=["T1059.001"],
            mbc_dump="mbc",
            mbc_objectives=["obj1"],
            mbc_behaviors=["beh1"],
            mbc_behaviors_id=["B0001"],
        )
        assert c.capa_dump == "dump"
        assert "cap1" in c.capabilities
        assert "TA0001" in c.tactics


# ============================================================================
# Malcontent
# ============================================================================

class TestMalcontentDataclass:
    def test_creation(self):
        from redb.models.dataclasses import Malcontent

        m = Malcontent(
            malcontent_dump='{"RiskScore": 2}',
            version="malcontent v1.0.0",
            risk_score=2,
            risk_level="MEDIUM"
        )
        assert m.malcontent_dump == '{"RiskScore": 2}'
        assert m.version == "malcontent v1.0.0"
        assert m.risk_score == 2
        assert m.risk_level == "MEDIUM"

    def test_with_json_content(self):
        from redb.models.dataclasses import Malcontent
        import json

        # Now stores unwrapped content (without Files/<path> wrapper)
        file_content = {
            "RiskScore": 3,
            "RiskLevel": "HIGH",
            "IsMalcontent": True,
            "Behaviors": [
                {"RuleName": "exec/shell", "RiskLevel": "HIGH", "Description": "executes shell commands"}
            ]
        }
        m = Malcontent(
            malcontent_dump=json.dumps(file_content),
            version="v0.5.0",
            risk_score=3,
            risk_level="HIGH"
        )
        parsed = json.loads(m.malcontent_dump)
        assert parsed["RiskLevel"] == "HIGH"
        assert parsed["Behaviors"][0]["RuleName"] == "exec/shell"

    def test_asdict(self):
        from redb.models.dataclasses import Malcontent
        from dataclasses import asdict

        m = Malcontent(malcontent_dump="{}", version="v1", risk_score=0, risk_level="")
        d = asdict(m)
        assert d == {"malcontent_dump": "{}", "version": "v1", "risk_score": 0, "risk_level": ""}


# ============================================================================
# String
# ============================================================================

class TestStringDataclass:
    def test_creation(self):
        from redb.models.dataclasses import String

        s = String(string="hello", string_length=5, string_entropy=2.3, string_frequency=10)
        assert s.string == "hello"
        assert s.md5 == []
        assert s.sha1 == []
        assert s.sha256 == []

    def test_with_hashes(self):
        from redb.models.dataclasses import String

        s = String(
            string="test", string_length=4, string_entropy=2.0, string_frequency=1,
            md5=["abc"], sha256=["def"],
        )
        assert s.md5 == ["abc"]
        assert s.sha256 == ["def"]


# ============================================================================
# PE Dataclasses
# ============================================================================

class TestPEDataclass:
    def test_required_fields(self):
        from redb.models.dataclasses import PE

        pe = PE(
            dos_header="dos", nt_header="nt", optional_header="opt",
            file_header="fh", magic="0x10b", entry_point="0x1000",
            major_linker_version=14, minor_linker_version=0,
            target_machine="I386", architecture="x86",
            compilation_time=1609459200, compilation_time_utc="2021-01-01T00:00:00",
            is_dotnet=False, is_signed=False, has_overlay=False,
            number_of_sections=4, number_of_imports=10,
            number_of_exports=0, number_of_resources=2,
            type="EXE",
        )
        assert pe.architecture == "x86"
        assert pe.type == "EXE"

    def test_optional_fields_default_none(self):
        from redb.models.dataclasses import PE

        pe = PE(
            dos_header="d", nt_header="n", optional_header="o",
            file_header="f", magic="m", entry_point="e",
            major_linker_version=0, minor_linker_version=0,
            target_machine="t", architecture="a",
            compilation_time=0, compilation_time_utc="",
            is_dotnet=False, is_signed=False, has_overlay=False,
            number_of_sections=0, number_of_imports=0,
            number_of_exports=0, number_of_resources=0,
            type="DLL",
        )
        assert pe.dbg_struct is None
        assert pe.tls_struct is None
        assert pe.rich_header_dump is None
        assert pe.version_info is None


class TestPEImportDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEImport

        pi = PEImport(pe_imports_total=5)
        assert pi.pe_imports_total == 5
        assert pi.pe_import_libraryName is None
        assert pi.pe_import_functions is None


class TestPESectionDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PESection

        ps = PESection(
            _id="sec_id", section_entropy=6.5, section_sha256="sha",
            section_md5="md5", section_name=".text", section_name_b64=".text",
            section_pointer_to_raw_data="0x400",
            section_size=4096, section_v_addr="0x1000",
            section_v_addr_hex="0x1000", section_v_size=8192,
        )
        assert ps.section_name == ".text"
        assert ps.section_entropy == 6.5


class TestPEResourceDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEResource

        pr = PEResource(
            _id="res_id", resource_type="RT_ICON", resource_entropy=3.5,
            resource_sha256="sha", resource_filetype="image/png",
            resource_magika="png", resource_language="LANG_ENGLISH",
            resource_sub_lang="SUBLANG_DEFAULT",
            resource_rva="0x2000", resource_size=1024,
        )
        assert pr.resource_type == "RT_ICON"


class TestPEOverlayDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEOverlay

        po = PEOverlay(
            _id="ovl_id", overlay_size=512, overlay_entropy=7.9,
            overlay_offset="0x5000", overlay_mimetype="application/octet-stream",
            overlay_type="data", overlay_magika="unknown",
            overlay_sha256="sha", overlay_sha1="sha1", overlay_md5="md5",
        )
        assert po.overlay_size == 512


class TestPESignerDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PESigner

        ps = PESigner(
            signer_serial_number="01", signer_subject="CN=Test",
            signer_issuer="CN=CA", signer_valid_from="2021-01-01",
            signer_valid_to="2025-01-01", signer_thumbprint="aabb",
            signer_algorithm="sha256WithRSAEncryption",
        )
        assert ps.signer_subject == "CN=Test"


class TestPECertificateDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PECertificate

        pc = PECertificate(
            certificate_serial_number="02", certificate_subject="CN=Cert",
            certificate_issuer="CN=CA", certificate_valid_from="2021-01-01",
            certificate_valid_to="2025-01-01", certificate_thumbprint="ccdd",
            certificate_algorithm="sha256",
        )
        assert pc.certificate_serial_number == "02"


class TestPECodeSigningInfoDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PECodeSigningInfo

        cs = PECodeSigningInfo(
            _id="cs_id", signature_verified=True, number_of_certificates=2,
        )
        assert cs.signature_verified is True
        assert cs.x509_certificates is None

    def test_with_certificates(self):
        from redb.models.dataclasses import PECodeSigningInfo

        cs = PECodeSigningInfo(
            _id="cs_id", signature_verified=False, number_of_certificates=0,
            x509_certificates=[{"cn": "test"}],
        )
        assert len(cs.x509_certificates) == 1


class TestPEExtraFindingDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEExtraFinding

        ef = PEExtraFinding(context="anomaly_detection")
        assert ef.context == "anomaly_detection"
        assert ef.finding is None


class TestPEDotNetDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEDotNet

        dn = PEDotNet()
        assert dn.dotnet == {}

    def test_with_data(self):
        from redb.models.dataclasses import PEDotNet

        dn = PEDotNet(dotnet={"runtime": "v4.0.30319"})
        assert dn.dotnet["runtime"] == "v4.0.30319"


class TestDotNetInconsistencyTestsDataclass:
    def test_creation(self):
        from redb.models.dataclasses import DotNetInconsistencyTests

        it = DotNetInconsistencyTests(
            test_dotnet_data_dir_hidden=False,
            test_dotnet_fake_types=True,
            test_dotnet_extra_data=None,
            test_dotnet_invalid_type_ref=False,
            test_dotnet_fake_datastreams=False,
            test_dotnet_extra_module_table=None,
            test_dotnet_extra_assembly_table=False,
            test_dotnet_invalid_strings_stream=False,
            test_dotnet_streams_mixed_case=True,
            test_dotnet_method_def_invalid_table=False,
            test_dotnet_max_len_exceeding_strings=False,
        )
        assert it.test_dotnet_fake_types is True
        assert it.test_dotnet_extra_data is None


class TestPEInconsistencyTestsDataclass:
    def test_creation(self):
        from redb.models.dataclasses import PEInconsistencyTests

        it = PEInconsistencyTests(
            test_rich_header_checksum=True,
            test_rich_header_duplicate=False,
            test_rich_header_linker=None,
            test_rich_header_import_count=True,
        )
        assert it.test_rich_header_checksum is True
        assert it.test_rich_header_linker is None


# ============================================================================
# YARA Dataclasses
# ============================================================================

class TestYaraRuleDataclass:
    def test_creation(self):
        from redb.models.dataclasses import YaraRule

        yr = YaraRule(
            rule_name="test_rule",
            rule_tags=["malware", "trojan"],
            rule_meta={"author": "test", "description": "A test rule"},
        )
        assert yr.rule_name == "test_rule"
        assert "malware" in yr.rule_tags


class TestYaraMatchDataclass:
    def test_creation(self):
        from redb.models.dataclasses import YaraMatch

        ym = YaraMatch(rule_name="test_rule", match_strings=["$s1", "$s2"])
        assert ym.rule_name == "test_rule"
        assert len(ym.match_strings) == 2


# ============================================================================
# ELF Dataclasses
# ============================================================================

class TestELFFeaturesDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFFeatures

        ef = ELFFeatures(
            ei_class=2, ei_data=1, ei_version=1, ei_osabi=0, ei_abiversion=0,
            e_type=2, e_machine=62, e_version=1, e_entry=0x400000, e_flags=0,
            ei_class_str="ELFCLASS64", ei_data_str="ELFDATA2LSB",
            ei_osabi_str="ELFOSABI_SYSV", e_type_str="ET_EXEC",
            e_machine_str="EM_X86_64",
            is_64bit=1, is_stripped=0, is_pie=0, has_canary=1, has_nx=1,
            has_relro=1, has_fortify=0,
            number_of_segments=9, number_of_sections=31,
            number_of_symbols=100, number_of_dynamic_symbols=50,
            number_of_relocations=25, number_of_dependencies=5,
            gnu_hash_present=1, has_debug_info=0,
        )
        assert ef.ei_class == 2
        assert ef.e_machine_str == "EM_X86_64"
        assert ef.build_id is None

    def test_with_build_id(self):
        from redb.models.dataclasses import ELFFeatures

        ef = ELFFeatures(
            ei_class=2, ei_data=1, ei_version=1, ei_osabi=0, ei_abiversion=0,
            e_type=3, e_machine=62, e_version=1, e_entry=0, e_flags=0,
            ei_class_str="64", ei_data_str="LE", ei_osabi_str="SYSV",
            e_type_str="DYN", e_machine_str="X86_64",
            is_64bit=1, is_stripped=1, is_pie=1, has_canary=0, has_nx=1,
            has_relro=1, has_fortify=0,
            number_of_segments=8, number_of_sections=28,
            number_of_symbols=0, number_of_dynamic_symbols=30,
            number_of_relocations=10, number_of_dependencies=3,
            gnu_hash_present=1, has_debug_info=0,
            build_id="abc123def456",
        )
        assert ef.build_id == "abc123def456"


class TestELFDependencyDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFDependency

        dep = ELFDependency(
            dependency_name="libc.so.6",
            dependency_type=1,
            dependency_type_str="NEEDED",
        )
        assert dep.dependency_name == "libc.so.6"


class TestELFImportDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFImport

        ei = ELFImport(elf_imports_total=3)
        assert ei.elf_imports_total == 3
        assert ei.elf_import_libraries == []
        assert ei.elf_import_functions == []


class TestELFExportDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFExport

        ee = ELFExport(elf_exports_total=5)
        assert ee.elf_exports_total == 5
        assert ee.elf_export_functions == []


class TestELFSectionDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFSection

        es = ELFSection(
            section_name=".text", section_type=1, section_type_str="SHT_PROGBITS",
            section_flags=6, section_flags_str=["SHF_ALLOC", "SHF_EXECINSTR"],
            section_addr=0x400000, section_offset=0x1000, section_size=4096,
            section_link=0, section_info=0, section_addralign=16, section_entsize=0,
            section_entropy=6.8, section_sha256="sha", section_md5="md5",
        )
        assert es.section_name == ".text"
        assert "SHF_ALLOC" in es.section_flags_str


class TestELFSegmentDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFSegment

        seg = ELFSegment(
            segment_type=1, segment_type_str="PT_LOAD",
            segment_flags=5, segment_flags_str=["PF_R", "PF_X"],
            segment_offset=0, segment_vaddr=0x400000, segment_paddr=0x400000,
            segment_filesz=0x1000, segment_memsz=0x1000, segment_align=0x200000,
            segment_entropy=5.5, segment_sha256="sha", segment_md5="md5",
        )
        assert seg.segment_type_str == "PT_LOAD"


class TestELFSymbolDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFSymbol

        sym = ELFSymbol(
            symbol_name="main", symbol_value=0x401000, symbol_size=100,
            symbol_type=2, symbol_type_str="STT_FUNC",
            symbol_bind=1, symbol_bind_str="STB_GLOBAL",
            symbol_visibility=0, symbol_visibility_str="STV_DEFAULT",
            symbol_section_index=14, symbol_section_index_str="14",
            is_dynamic=0,
        )
        assert sym.symbol_name == "main"
        assert sym.symbol_type_str == "STT_FUNC"


class TestELFRelocationDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFRelocation

        rel = ELFRelocation(
            relocation_offset=0x601000, relocation_type=7,
            relocation_type_str="R_X86_64_JUMP_SLOT",
            relocation_symbol_index=1, relocation_symbol_name="printf",
            relocation_section=".rela.plt",
        )
        assert rel.relocation_addend is None

    def test_with_addend(self):
        from redb.models.dataclasses import ELFRelocation

        rel = ELFRelocation(
            relocation_offset=0x601000, relocation_type=7,
            relocation_type_str="R_X86_64_JUMP_SLOT",
            relocation_symbol_index=1, relocation_symbol_name="printf",
            relocation_section=".rela.plt",
            relocation_addend=-4,
        )
        assert rel.relocation_addend == -4


class TestELFNoteDataclass:
    def test_creation(self):
        from redb.models.dataclasses import ELFNote

        note = ELFNote(
            note_name="GNU", note_type=3,
            note_type_str="NT_GNU_BUILD_ID",
            note_desc="abc123", note_section=".note.gnu.build-id",
        )
        assert note.note_name == "GNU"
        assert note.note_type_str == "NT_GNU_BUILD_ID"


# ============================================================================
# Decompiled
# ============================================================================

class TestDecompiledDataclass:
    def test_creation(self):
        from redb.models.dataclasses import Decompiled

        d = Decompiled(
            _id="func_hash",
            decompiled_function_name="main",
            decompiled_function_address="0x401000",
            decompiled_function="int main() { return 0; }",
        )
        assert d.decompiled_function_name == "main"