Jan Gulliksen

92 papers A 1B 5C 1Misc 9Journal 37Unranked 31
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Access
Tanya Karin Osborne, Hugo-Henrik Hachem, Dan Paulin, Ola Hultkrantz, Ulrika Lundqvist, Kent Thorén, Jan Gulliksen, Fredrik Heintz, Amy Loutfi, Francis Lee, Mattias Wiggberg
2026 J jnl
Behav. Inf. Technol.
Stefan Johansson, Marika Jonsson, Jan Gulliksen, Catharina Gustavsson
2025 J jnl
Interact. Comput.
Marika Jonsson, Catharina Gustavsson, Linda Pettersson, Jan Gulliksen, Stefan Johansson
2025 J jnl
Univers. Access Inf. Soc.
Marika Jonsson, Catharina Gustavsson, Jan Gulliksen, Stefan Johansson
2024 conf
HCSE
Dena Hussain, Jan Gulliksen
2023 conf
INTERACT (4)
David Gollasch, Meinhardt Branig, Kathrin Gerling, Jan Gulliksen, Oussama Metatla, Katta Spiel, Gerhard Weber
2023 J jnl
Interact. Comput.
Jan Gulliksen, Joakim Lilliesköld, Stefan Stenbom
2023 conf
INTERACT Workshops (1)
Masood Rangraz, Anne-Kathrin Peters, Jan Gulliksen
2023 conf
INTERACT (4)
Britta Nordin Forsberg, Anders Lundström, Jan Gulliksen
2023 conf
INTERACT (4)
Jan Gulliksen
2022 J jnl
IEEE Access
Mattias Wiggberg, Jan Gulliksen, Åsa Cajander, Arnold Pears
2021 conf
INTERACT (2)
Jan Gulliksen
2021 J jnl
Univers. Access Inf. Soc.
Stefan Johansson, Jan Gulliksen, Catharina Gustavsson
2020 conf
HCSE
Dena Hussain, Jan Gulliksen, Olga Viberg, Rebekah Cupitt
2020 C conf
ICT4AWE
Jan Gulliksen
2019 J jnl
Commun. ACM
Jan Gulliksen
2019 J jnl
Behav. Inf. Technol.
Marta Kristín Lárusdóttir, Jan Gulliksen, Niklas Hallberg
2018 J jnl
Interactions
Gavin J. Doherty, Åsa Cajander, Jan Gulliksen, Conor Linehan
2017 J jnl
J. Syst. Softw.
Marta Kristín Lárusdóttir, Jan Gulliksen, Åsa Cajander
2016 ch.
Integrating User-Centred Design in Agile Development
Marta Lárusdóttir, Åsa Cajander, Gudbjörg Erlingsdottir, Thomas Lind, Jan Gulliksen
2016 Misc conf
NordiCHI
Elina Eriksson, Daniel Pargman, Oliver Bates, Maria Normark, Jan Gulliksen, Mikael Anneroth, Johan Berndtsson
2016 ed.
HCSE/HESSD
Cristian Bogdan, Jan Gulliksen, Stefan Sauer, Peter Forbrig, Marco Winckler, Chris W. Johnson, Philippe A. Palanque, Regina Bernhaupt, Filip Kis
2016 J jnl
Found. Trends Hum. Comput. Interact.
Jonathan Lazar, Julio Abascal, Simone D. J. Barbosa, Jeremy T. Barksdale, Batya Friedman, Jens Grossklags, Jan Gulliksen, Jeff A. Johnson, Tom McEwan, Loïc Martínez Normand, Wibke Michalk, Janice Y. Tsai, Gerrit C. van der Veer, Hans von Axelson, Åke Walldius, Gill Whitney, Marco Winckler, Volker Wulf, Elizabeth F. Churchill, Lorrie Faith Cranor, Janet Davis, Alan Hedge, Harry Hochheiser, Juan Pablo Hourcade, Clayton Lewis, Lisa P. Nathan, Fabio Paternò, Blake Reid, Whitney Quesenbery, Ted Selker, Brian Wentz
2015 J jnl
Univers. Access Inf. Soc.
Johan Borg, Ann Lantz, Jan Gulliksen
2015 conf
INTERACT (1)
Stefan Johansson, Jan Gulliksen, Ann Lantz
2015 conf
RoCHI
Jan Gulliksen
2015 conf
Aarhus Conference on Critical Alternatives
Åke Walldius, Jan Gulliksen, Yngve Sundblad
2015 conf
INTERACT (4)
Jan Gulliksen, Simone Diniz Junqueira Barbosa, Anirudha Joshi, Shaun W. Lawson, Philippe A. Palanque
2015 J jnl
Univers. Access Inf. Soc.
Hans Persson, Henrik Åhman, Alexander Yngling, Jan Gulliksen
2015 A conf
ASSETS
Stefan Johansson, Jan Gulliksen, Ann Lantz
2015 conf
INTERACT (1)
Christiane Grünloh, Åke Walldius, Gerhard Hartmann, Jan Gulliksen
2014 conf
IHC
Jan Gulliksen
2014 J jnl
Behav. Inf. Technol.
Marta Kristín Lárusdóttir, Åsa Cajander, Jan Gulliksen
2014 B conf
ITiCSE
Jan Gulliksen
2014 Misc conf
NordiCHI
Marta Kristín Lárusdóttir, Åsa Cajander, Jan Gulliksen, Gilbert Cockton, Peggy Gregory, Dina Salah
2013 conf
INTERACT (3)
Åsa Cajander, Marta Lárusdóttir, Jan Gulliksen
2013 conf
CHI Extended Abstracts
Jonathan Lazar, Simone Diniz Junqueira Barbosa, Jan Gulliksen, Tom McEwan, Loïc Martínez Normand, Philippe A. Palanque, Raquel Oliveira Prates, Janice Y. Tsai, Marco Winckler, Volker Wulf
2012 J jnl
Interactions
Jonathan Lazar, Julio Abascal, Janet Davis, Vanessa Evers, Jan Gulliksen, Joaquim A. Jorge, Tom McEwan, Fabio Paternò, Hans Persson, Raquel Oliveira Prates, Hans von Axelson, Marco Winckler, Volker Wulf
2012 conf
I-UxSED
Marta Lárusdóttir, Åsa Cajander, Jan Gulliksen
2011 conf
SIGRAD
Jan Gulliksen
2010 J jnl
Interactions
Jan Gulliksen, Hans von Axelson, Hans Persson, Bengt Göransson
2010 ed.
HCSE
Regina Bernhaupt, Peter Forbrig, Jan Gulliksen, Marta Lárusdóttir
2010 Misc ed.
NordiCHI
Ebba Þóra Hvannberg, Marta Kristín Lárusdóttir, Ann Blandford, Jan Gulliksen
2010 conf
HCIS
Marta Kristín Lárusdóttir, Emma Run Bjarnadottir, Jan Gulliksen
2010 conf
HCIS
Åsa Cajander, Elina Eriksson, Jan Gulliksen
2009 conf
INTERACT (2)
Regina Bernhaupt, Peter Forbrig, Jan Gulliksen, Janet Wesson
2009 conf
INTERACT (2)
Elina Eriksson, Åsa Cajander, Jan Gulliksen
2009 ed.
INTERACT (1)
Tom Gross, Jan Gulliksen, Paula Kotzé, Lars Oestreicher, Philippe A. Palanque, Raquel Oliveira Prates, Marco Winckler
2009 ed.
INTERACT (2)
Tom Gross, Jan Gulliksen, Paula Kotzé, Lars Oestreicher, Philippe A. Palanque, Raquel Oliveira Prates, Marco Winckler
2009 conf
INTERACT (2)
Asbjørn Følstad, Petter Bae Brandtzæg, Jan Gulliksen, Mikael Börjeson, Pirjo Näkki
2009 J jnl
Behav. Inf. Technol.
Åke Walldius, Yngve Sundblad, Lars Bengtsson, Bengt L. Sandblad, Jan Gulliksen
2009 J jnl
Int. J. Technol. Hum. Interact.
Jan Gulliksen, Åsa Cajander, Bengt L. Sandblad, Elina Eriksson, Iordanis Kavathatzopoulos
2008 ed.
EHCI/DS-VIS
Jan Gulliksen, Morten Borup Harning, Philippe A. Palanque, Gerrit C. van der Veer, Janet Wesson
2008 Misc conf
NordiCHI
Elina Eriksson, Jan Gulliksen, Åsa Cajander
2008 Misc conf
NordiCHI
Dag Svanæs, Jan Gulliksen
2008 ch.
Maturing Usability
Åsa Cajander, Inger Boivie, Jan Gulliksen
2007 conf
INTERACT (2)
Andy Smith, Anirudha Joshi, Zhengjie Liu, Liam J. Bannon, Jan Gulliksen, Maria Cecília Calani Baranauskas
2007 conf
INTERACT (2)
Andy Smith, Anirudha Joshi, Zhengjie Liu, Liam J. Bannon, Jan Gulliksen, Christina Li
2006 conf
DSV-IS
Jan Gulliksen
2006 Misc conf
NordiCHI
Asbjørn Følstad, Ida Bark, Jan Gulliksen
2006 Misc conf
NordiCHI
Åsa Cajander, Jan Gulliksen, Inger Boivie
2006 ed.
BCS HCI
Tom McEwan, Jan Gulliksen, David Benyon
2006 J jnl
Interact. Comput.
Inger Boivie, Jan Gulliksen, Bengt Göransson
2006 J jnl
Interact. Comput.
Jan Gulliksen, Inger Boivie, Bengt Göransson
2005 conf
BCS HCI
Andy Smith, Jan Gulliksen, Liam Bannon
2005 conf
BCS HCI
Ida Bark, Asbjørn Følstad, Jan Gulliksen
2004 J jnl
Univers. Access Inf. Soc.
Jan Gulliksen, Hans Andersson, Per Lundgren
2004 J jnl
Univers. Access Inf. Soc.
Jan Gulliksen, Susan Harker, Gregg C. Vanderheiden
2004 Misc conf
NordiCHI
Jan Gulliksen, Inger Boivie, Jenny Persson, Anders Hektor, Lena Herulf
2004 J jnl
Univers. Access Inf. Soc.
Jan Gulliksen, Susan Harker
2003 J jnl
Int. J. Hum. Comput. Interact.
Jan Gulliksen, Ann Lantz
2003 J jnl
Int. J. Hum. Comput. Interact.
Ann Lantz, Jan Gulliksen
2003 J jnl
Interact. Comput.
Carl Åborg, Bengt L. Sandblad, Jan Gulliksen, Magnus Lif
2003 J jnl
Behav. Inf. Technol.
Jan Gulliksen, Bengt Göransson, Inger Boivie, Stefan Blomkvist, Jenny Persson, Åsa Cajander
2003 B conf
INTERACT
Anders Hektor, Jan Gulliksen
2003 J jnl
Softw. Process. Improv. Pract.
Bengt Göransson, Jan Gulliksen, Inger Boivie
2003 conf
DSV-IS
Bengt Göransson, Magnus Lif, Jan Gulliksen
2003 B conf
INTERACT
Jan Gulliksen, Bengt Göransson
2003 J jnl
Behav. Inf. Technol.
Bengt L. Sandblad, Jan Gulliksen, Carl Åborg, Inger Boivie, Jenny Persson, Bengt Göransson, Iordanis Kavathatzopoulos, Stefan Blomkvist, Åsa Cajander
2001 Misc conf
HCI
Jan Gulliksen, Clemens Lutsch, Susan Harker
2001 B conf
INTERACT
Jan Gulliksen, Bengt Göransson
2001 B conf
INTERACT
Jan Gulliksen, Inger Boivie
2001 J jnl
Inf. Technol. People
Magnus Lif, Eva Olsson, Jan Gulliksen, Bengt L. Sandblad
1999 J jnl
Int. J. Hum. Comput. Interact.
Eva Olsson, Jan Gulliksen
1999 conf
HCI (1)
Jan Gulliksen
1999 J jnl
ACM SIGCHI Bull.
Jan Gulliksen, Lars Oestreicher
1999 J jnl
ACM SIGCHI Bull.
Jan Gulliksen, Ann Lantz, Inger Boivie
1998 J jnl
ACM SIGCHI Bull.
John Artim, Mark van Harmelen, Keith Butler, Jan Gulliksen, Austin Henderson, Srdjan Kovacevic, Shijian Lu, Scott Overmyer, Ray Reaux, Dave Roberts, Jean-Claude Tarby, Keith Vander Linden
1997 conf
HCI (1)
Jan Gulliksen
1997 J jnl
Int. J. Hum. Comput. Interact.
Jan Gulliksen, Magnus Lif, Mats Lind, Else Nygren, Bengt L. Sandblad
1995 J jnl
Int. J. Hum. Comput. Interact.
Jan Gulliksen, Bengt L. Sandblad
1993 conf
HCI (2)
Jan Gulliksen, Mats Johnson, Mats Lind, Else Nygren, Bengt L. Sandblad
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"