James M. Ferryman

98 papers A 4B 35C 5Misc 1Journal 29Unranked 23
YearRankTypeTitle / Venue / Authors
2026 J jnl
ACM Comput. Surv.
Thanet Markchom, Huizhi Liang, James M. Ferryman
2025 conf
SDF
Kilian Wohlleben, Michael Hubner, Thanet Markchom, Jonathan Boyle, James M. Ferryman, Stephan Veigl, Andreas Opitz, Anastasios Gkamaris, Romaios Bratskas
2025 J jnl
Trans. Recomm. Syst.
Thanet Markchom, Huizhi Liang, James M. Ferryman
2025 B conf
AVSS
Thanet Markchom, Jonathan Boyle, Lulu Chen, James M. Ferryman, Matteo Marturini, Stephan Veigl, Andreas Opitz, Andreas Kriechbaum-Zabini, Romaios Bratskas, Anastasios Gkamaris, Dimitris Papachristos, George Leventakis, Wenjun Fan, Hsiang-Wei Huang, Jeng-Neng Hwang, Pyong-Kun Kim, Kwangju Kim, Chung-I Huang, Kenta Saito, Shunta Kaneko, Kyoko Sudo, Nguyen Thanh Thien, Meng-Yu Kao, Jun-Wei Hsieh, Teepakorn Lilek, Tossapol Pomsuwan, Jinjie Gu, Tianyang Xu, Xuefeng Zhu, Xiaojun Wu, Josef Kittler, Stephanie Stacy, Alfredo Gabaldon, Peter Tu, Sangwon Kim, Dongyoung Kim, Kyoungoh Lee
2025 B conf
IEEE Big Data
Eleftheria Katsoura, James M. Ferryman, Georgios Stavropoulos, Andreas Uhl, Henryk Gierszal, Arkadiusz Kruszynski, Piotr Tyczka, Sarah Murray, Mariano Martín Zamorano Barrios, Eileen Murphy, Konstantinos Votis
2024 J jnl
CoRR
Thanet Markchom, Huizhi Liang, James M. Ferryman
2024 J jnl
IEEE Access
Shahab Uddin, Tahir Nawaz, James M. Ferryman, Nasir Rashid, Md. Asaduzzaman, Raheel Nawaz
2023 J jnl
Knowl. Based Syst.
Thanet Markchom, Huizhi Liang, James M. Ferryman
2022 J jnl
Sensors
Jose Luis Patino, Michael Hubner, Rachel King, Martin Litzenberger, Laure Roupioz, Kacper Michon, Lukasz Szklarski, Julian Pegoraro, Nikolai Stoianov, James M. Ferryman
2021 B conf
AVSS
Jose Luis Patino, Tom Cane, James M. Ferryman
2021 B conf
AVSS
Lulu Chen, Jonathan Boyle, Antonios Danelakis, James M. Ferryman, Simone Ferstl, Damjan Gicic, Artur Grudzien, André Howe, Marcin Kowalski, Krzysztof Mierzejewski, Theoharis Theoharis
2021 B conf
AVSS
Jose Luis Patino, Jonathan Boyle, James M. Ferryman, Jonas Auer, Julian Pegoraro, Roman P. Pflugfelder, Mertcan Cokbas, Janusz Konrad, Prakash Ishwar, Giulia Slavic, Lucio Marcenaro, Yifan Jiang, Youngsaeng Jin, Hanseok Ko, Guangliang Zhao, Guy Ben-Yosef, Jianwei Qiu
2020 J jnl
IET Biom.
Chiara Galdi, Jonathan Boyle, Lulu Chen, Valeria Chiesa, Luca Debiasi, Jean-Luc Dugelay, James M. Ferryman, Artur Grudzien, Christof Kauba, Simon Kirchgasser, Marcin Kowalski, Michael Linortner, Patryk Maik, Kacper Michon, Jose Luis Patino, Bernhard Prommegger, Ana Filipa Sequeira, Lukasz Szklarski, Andreas Uhl
2020 conf
IWBF
Simon Kirchgasser, Luca Debiasi, Rudolf Schraml, Heinz Hofbauer, Andreas Uhl, Jonathan Boyle, James M. Ferryman
2019 J jnl
J. Electronic Imaging
Longzhen Li, Tahir Nawaz, James M. Ferryman
2018 B conf
AVSS
Tom Cane, James M. Ferryman
2018 conf
BTAS
Heinz Hofbauer, Ehsaneddin Jalilian, Ana Filipa Sequeira, James M. Ferryman, Andreas Uhl
2018 conf
BIOSIG
Ana Filipa Sequeira, Lulu Chen, James M. Ferryman, Chiara Galdi, Valeria Chiesa, Jean-Luc Dugelay, Patryk Maik, Piotr Gmitrowicz, Lukasz Szklarski, Bernhard Prommegger, Christof Kauba, Simon Kirchgasser, Andreas Uhl, Artur Grudzien, Marcin Kowalski
2017 J jnl
Signal Image Video Process.
Tahir Nawaz, Anna Ellis, James M. Ferryman
2017 B conf
IJCB
Ana Filipa Sequeira, Lulu Chen, James M. Ferryman, Peter Wild, Fernando Alonso-Fernandez, Josef Bigün, Kiran B. Raja, Ramachandra Raghavendra, Christoph Busch, Tiago de Freitas Pereira, Sébastien Marcel, Sushree Sangeeta Behera, Mahesh Gour, Vivek Kanhangad
2017 B conf
AVSS
Jonathan Boyle, Tahir Nawaz, James M. Ferryman
2017 J jnl
J. Electronic Imaging
Tahir Nawaz, Amanda Berg, James M. Ferryman, Jörgen Ahlberg, Michael Felsberg
2017 conf
IWBF
Azim Zaliha Abd Aziz, Hong Wei, James M. Ferryman
2017 conf
CVPR Workshops
Jose Luis Patino, James M. Ferryman
2017 conf
CVPR Workshops
Jose Luis Patino, Tahir Nawaz, Tom Cane, James M. Ferryman
2016 conf
TSP
Ana Filipa Sequeira, Shejin Thavalengal, James M. Ferryman, Peter Corcoran, Jaime S. Cardoso
2016 J jnl
IEEE Trans. Geosci. Remote. Sens.
Karolina D. Fieber, Ian J. Davenport, James M. Ferryman, Robert J. Gurney, Victor M. Becerra, Jeffrey P. Walker, Jörg M. Hacker
2016 conf
BIOSIG
Ana Filipa Sequeira, Lulu Chen, Peter Wild, James M. Ferryman, Fernando Alonso-Fernandez, Kiran B. Raja, Ramachandra Raghavendra, Christoph Busch, Josef Bigün
2016 B conf
AVSS
Jose Luis Patino, James M. Ferryman
2016 conf
CVPR Workshops
Jose Luis Patino, Tom Cane, Alain Vallee, James M. Ferryman
2016 J jnl
EURASIP J. Inf. Secur.
Peter Wild, Heinz Hofbauer, James M. Ferryman, Andreas Uhl
2016 J jnl
Pattern Recognit.
Peter Wild, Petru Radu, Lulu Chen, James M. Ferryman
2016 conf
CVPR Workshops
Tom Cane, James M. Ferryman
2016 conf
CVPR Workshops
Jose Luis Patino, James M. Ferryman
2016 conf
EISIC
Maria Andersson, Ronnie Johansson, Karl-Göran Stenborg, Robert Forsgren, Thomas Cane, Grzegorz Taberski, Jose Luis Patino, James M. Ferryman
2016 conf
ICDSC
Tahir Habib Nawaz, Bernhard Rinner, James M. Ferryman
2016 B conf
AVSS
Tewodros Atanaw Biresaw, Tahir Nawaz, James M. Ferryman, Anthony I. Dell
2015 conf
BTAS
Petru Radu, James M. Ferryman, Peter Wild
2015 B conf
AVSS
Jose Luis Patino, James M. Ferryman, Csaba Beleznai
2015 B conf
AVSS
Tahir Nawaz, James M. Ferryman
2015 conf
BTAS
Lulu Chen, James M. Ferryman
2015 J jnl
IET Biom.
Peter Wild, James M. Ferryman, Andreas Uhl
2015 B conf
AVSS
Jose Luis Patino, James M. Ferryman
2015 C conf
ICMV
Azim Zaliha Abd Aziz, Hong Wei, James M. Ferryman
2015 conf
ICB
Peter Wild, Petru Radu, James M. Ferryman
2015 B conf
AVSS
Longzhen Li, Anna Ellis, James M. Ferryman
2015 B conf
AVSS
Longzhen Li, Tahir Nawaz, James M. Ferryman
2015 conf
BIOSIG
Peter Wild, Heinz Hofbauer, James M. Ferryman, Andreas Uhl
2015 B conf
AVSS
Christopher J. Osborne, Tom Cane, Tahir Nawaz, James M. Ferryman
2015 B conf
AVSS
Tahir Nawaz, Jonathan Boyle, Longzhen Li, James M. Ferryman
2015 B conf
AVSS
Jonathan N. Boyle, James M. Ferryman
2014 J jnl
Image Vis. Comput.
Gerard Sanroma, Jose Luis Patino, Gertjan J. Burghouts, Klamer Schutte, James M. Ferryman
2014 J jnl
Comput. Vis. Image Underst.
Anna-Louise Ellis, James M. Ferryman
2014 J jnl
IEEE Geosci. Remote. Sens. Lett.
Karolina D. Fieber, Ian J. Davenport, Mihai A. Tanase, James M. Ferryman, Robert J. Gurney, Jeffrey P. Walker, Jörg M. Hacker
2014 B conf
AVSS
Jose Luis Patino, James M. Ferryman
2014 J jnl
Appl. Soft Comput.
Jose Luis Patino, James M. Ferryman
2014 B conf
AVSS
Jose Luis Patino, James M. Ferryman
2014 J jnl
Pattern Recognit. Lett.
James M. Ferryman, Anna-Louise Ellis
2014 J jnl
Pattern Recognit. Lett.
Lulu Chen, Hong Wei, James M. Ferryman
2014 B conf
IJCB
Peter Wild, Petru Radu, Lulu Chen, James M. Ferryman
2013 J jnl
Pattern Recognit. Lett.
Lulu Chen, Hong Wei, James M. Ferryman
2013 B conf
AVSS
Maria Andersson, Jose Luis Patino, Gertjan J. Burghouts, Adam Flizikowski, Murray Evans, David Gustafsson, Henrik Petersson, Klamer Schutte, James M. Ferryman
2013 B conf
AVSS
Murray Evans, Christopher J. Osborne, James M. Ferryman
2013 C conf
IGARSS
Karolina D. Fieber, Ian J. Davenport, Mihai A. Tanase, James M. Ferryman, Robert J. Gurney, Jeffrey P. Walker, Jörg M. Hacker
2013 J jnl
Pattern Recognit. Lett.
James M. Ferryman, David C. Hogg, Jan Sochman, Ardhendu Behera, José A. Rodríguez-Serrano, Simon F. Worgan, Longzhen Li, Valerie Leung, Murray Evans, Philippe Cornic, Stéphane Herbin, Stefan Schlenger, Michael Dose
2013 J jnl
IEEE Signal Process. Mag.
Fatih Porikli, François Brémond, Shiloh L. Dockstader, James M. Ferryman, Anthony Hoogs, Brian C. Lovell, Sharath Pankanti, Bernhard Rinner, Peter H. Tu, Péter L. Venetianer
2012 B conf
AVSS
Murray Evans, Longzhen Li, James M. Ferryman
2012 conf
ICPRAM (2)
Murray Evans, Jonathan N. Boyle, James M. Ferryman
2011 ch.
Visual Analysis of Humans
Anna-Louise Ellis, James M. Ferryman
2011 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Maria Valera, Sergio A. Velastin, Anna Ellis, James M. Ferryman
2011 C conf
ICVS
Jose Luis Patino, Murray Evans, James M. Ferryman, François Brémond, Monique Thonnat
2010 B conf
ICPR
Ali Shahrokni, Darren Gawley, James M. Ferryman
2010 B conf
AVSS
Anna Ellis, James M. Ferryman
2010 B conf
AVSS
James M. Ferryman, Anna Ellis
2010 B conf
AVSS
Murray Evans, James M. Ferryman
2010 B conf
AVSS
Jose Luis Patino, François Brémond, Murray Evans, Ali Shahrokni, James M. Ferryman
2008 conf
VNBA
David Tweed, James M. Ferryman
2008 C conf
ICVS
Nicholas L. Carter, James M. Ferryman
2007 J jnl
EURASIP J. Adv. Signal Process.
David Thirde, Mark Borg, Josep Aguilera, Horst Wildenauer, James M. Ferryman, Martin Kampel
2007 J jnl
Mach. Vis. Appl.
Florent Fusier, Valéry Valentin, François Brémond, Monique Thonnat, Mark Borg, David Thirde, James M. Ferryman
2006 conf
ICPR (1)
Nicholas L. Carter, David Paul Young, James M. Ferryman
2006 C conf
ICVS
David Thirde, Mark Borg, James M. Ferryman, Florent Fusier, Valéry Valentin, François Brémond, Monique Thonnat
2006 B conf
AVSS
Marc Bartels, Hong Wei, James M. Ferryman
2006 conf
ICPR (1)
Murray Evans, James M. Ferryman
2006 B conf
AVSS
Murray Evans, James M. Ferryman
2006 B conf
AVSS
Nicholas L. Carter, David Paul Young, James M. Ferryman
2005 conf
Australian Conference on Artificial Intelligence
James M. Ferryman, Mark Borg, David Thirde, Florent Fusier, Valéry Valentin, François Brémond, Monique Thonnat, Josep Aguilera, Martin Kampel
2005 Misc conf
ISVC
David Thirde, Mark Borg, James M. Ferryman, Josep Aguilera, Martin Kampel
2005 B conf
AVSS
David Paul Young, James M. Ferryman
2005 B conf
AVSS
Murray Evans, James M. Ferryman
2005 B conf
AVSS
Mark Borg, David Thirde, James M. Ferryman, Florent Fusier, Valéry Valentin, François Brémond, Monique Thonnat
2002 J jnl
Robotics Auton. Syst.
James M. Ferryman, Anthony D. Worrall
2000 J jnl
Int. J. Comput. Vis.
James M. Ferryman, Stephen J. Maybank, Anthony D. Worrall
1998 A conf
BMVC
James M. Ferryman, Anthony D. Worrall, Stephen J. Maybank
1997 A conf
BMVC
James M. Ferryman, Stephen J. Maybank, Anthony D. Worrall
1997 J jnl
Robotics Auton. Syst.
James M. Ferryman, Anthony D. Worrall, Geoffrey D. Sullivan, Keith D. Baker
1995 A conf
BMVC
James M. Ferryman, Anthony D. Worrall, Geoffrey D. Sullivan, Keith D. Baker
1995 A conf
BMVC
Anthony D. Worrall, James M. Ferryman, Geoffrey D. Sullivan, Keith D. Baker
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"