Oliver L. Haimson

77 papers A* 21A 6Misc 1Journal 32Unranked 16
YearRankTypeTitle / Venue / Authors
2026 A* conf
CHI
Calvin A. Liang, Kat Brewster, Kathryn Macapagal, Oliver L. Haimson
2026 A* conf
CHI
Denny L. Starks, Hibby Thach, Aloe DeGuia, Tawanna R. Dillahunt, Oliver L. Haimson
2026 A* conf
CHI
Denny L. Starks, Hibby Thach, Aloe DeGuia, Tawanna R. Dillahunt, Oliver L. Haimson
2026 A* conf
CHI
Sena A. Kojah, Hibby Thach, Oliver L. Haimson, Michaelanne Thomas
2025 J jnl
Proc. ACM Hum. Comput. Interact.
Sena A. Kojah, Ben Zefeng Zhang, Carolina Are, Daniel Delmonaco, Oliver L. Haimson
2025 A* conf
CHI
Kat Brewster, Aloe DeGuia, Samuel Mayworm, F. Ria Khan, Mel Monier, Denny L. Starks, Oliver L. Haimson
2025 conf
FAccT
Oliver L. Haimson, Samuel Reiji Mayworm, Alexis Shore Ingber, Nazanin Andalibi
2025 A* conf
CHI
F. Ria Khan, Kat Brewster, Aloe DeGuia, Denny L. Starks, Malaya Manacop, Samuel Mayworm, Tawanna R. Dillahunt, Oliver L. Haimson
2025 conf
CSCW Companion
Chris Geeng, Lucy Qin, Allison McDonald, Amna Batool, Diana Freed, Oliver L. Haimson, Jevan A. Hutson, Elissa M. Redmiles, Zahra Stardust, Miranda Wei, Douglas Zytko
2025 conf
FAccT
Alexis Shore Ingber, Oliver L. Haimson, Nazanin Andalibi
2025 J jnl
Proc. ACM Hum. Comput. Interact.
Sena A. Kojah, Kentaro Toyama, Oliver L. Haimson
2025 conf
FAccT
Francesca Lameiro, Lavinia Dunagan, Dallas Card, Eric Gilbert, Oliver L. Haimson
2025 A* conf
CHI
Ben Zefeng Zhang, Tianling Yang, Milagros Miceli, Oliver L. Haimson, Michaelanne Thomas
2025 A conf
Conference on Designing Interactive Systems (Companion Volume)
F. Ria Khan, Apryl Williams, Tawanna R. Dillahunt, Oliver L. Haimson
2025 A* conf
CHI
Caoyang Shen, Oliver L. Haimson
2025 conf
CHI Extended Abstracts
Rose Bohrer, Shano Liang, Michelle V. Cormier, Takao Fujii, Phoebe O. Toups Dugas, Rua Mae Williams, Amy J. Ko, Katie Seaborn, Oliver L. Haimson
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Cassidy Pyle, Ben Zefeng Zhang, Oliver L. Haimson, Nazanin Andalibi
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Daniel Delmonaco, Samuel Mayworm, Hibby Thach, Josh Guberman, Aurelia Augusta, Oliver L. Haimson
2024 J jnl
New Media Soc.
Hibby Thach, Samuel Mayworm, Daniel Delmonaco, Oliver L. Haimson
2024 J jnl
ACM Trans. Soc. Comput.
Samuel Mayworm, Michael Ann DeVito, Daniel Delmonaco, Hibby Thach, Oliver L. Haimson
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Oliver L. Haimson, Aloe DeGuia, Rana Saber, Kat Brewster
2024 A conf
Conference on Designing Interactive Systems (Companion Volume)
Anh-Ton Tran, Annabel Rothschild, Kay Kender, Ekat Osipova, Brian Kinnee, Jordan Taylor, Louie Søs Meyer, Oliver L. Haimson, Ann Light, Carl DiSalvo
2024 conf
FAccT
Samuel Mayworm, Kendra Albert, Oliver L. Haimson
2024 conf
CSCW Companion
Tamara L. Clegg, Tawanna R. Dillahunt, Sheena Erete, Oliver L. Haimson, Neha Kumar, Amanda Lazar, Yolanda A. Rankin, Katta Spiel
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Samuel Mayworm, Shannon Li, Hibby Thach, Daniel Delmonaco, Christian Paneda, Andrea Wegner, Oliver L. Haimson
2024 J jnl
Proc. ACM Hum. Comput. Interact.
Li Qiwei, Allison McDonald, Oliver L. Haimson, Sarita Schoenebeck, Eric Gilbert
2024 J jnl
CoRR
Li Qiwei, Allison McDonald, Oliver L. Haimson, Sarita Schoenebeck, Eric Gilbert
2024 conf
FAccT
Hibby Thach, Samuel Mayworm, Michaelanne Thomas, Oliver L. Haimson
2023 A* conf
CHI
Oliver L. Haimson, Kai Nham, Hibby Thach, Aloe DeGuia
2023 A* conf
CHI
Lauren Wilcox, Renee Shelby, Rajesh Veeraraghavan, Oliver L. Haimson, Gabriela Cruz Erickson, Michael Turken, Rebecca Gulotta
2023 J jnl
First Monday
Joshua Guberman, Oliver L. Haimson
2023 J jnl
ACM Trans. Comput. Hum. Interact.
Oliver L. Haimson, Megh Marathe
2022 J jnl
Proc. ACM Hum. Comput. Interact.
Ben Zefeng Zhang, Tianxiao Liu, Shanley Corvite, Nazanin Andalibi, Oliver L. Haimson
2022 J jnl
Proc. ACM Hum. Comput. Interact.
Shanley Corvite, Ben Zefeng Zhang, Oliver L. Haimson
2022 J jnl
Proc. ACM Hum. Comput. Interact.
Ben Zefeng Zhang, Oliver L. Haimson, Michaelanne Thomas
2021 J jnl
Proc. ACM Hum. Comput. Interact.
Oliver L. Haimson, Daniel Delmonaco, Peipei Nie, Andrea Wegner
2021 J jnl
New Media Soc.
Sarita Schoenebeck, Oliver L. Haimson, Lisa Nakamura
2021 A* conf
CHI
Laima Augustaitis, Leland A. Merrill, Kristi E. Gamarel, Oliver L. Haimson
2021 J jnl
Proc. ACM Hum. Comput. Interact.
Oliver L. Haimson, Tianxiao Liu, Ben Zefeng Zhang, Shanley Corvite
2021 J jnl
J. Assoc. Inf. Sci. Technol.
Oliver L. Haimson, Albert J. Carter, Shanley Corvite, Brookelyn Wheeler, Lingbo Wang, Tianxiao Liu, Alexxus Lige
2020 A* conf
CHI
Oliver L. Haimson, Dykee Gorrell, Denny L. Starks, Zu Weinger
2020 conf
CSCW Companion
Tianxiao Liu, Jasmine Glover, Oliver L. Haimson
2020 conf
ASIST
Daniel Delmonaco, Gabriela Marcu, Oliver L. Haimson
2020 J jnl
Proc. ACM Hum. Comput. Interact.
Oliver L. Haimson, Justin Buss, Zu Weinger, Denny L. Starks, Dykee Gorrell, Briar Sweetbriar Baron
2019 A conf
Conference on Designing Interactive Systems (Companion Volume)
Denny L. Starks, Tawanna Dillahunt, Oliver L. Haimson
2019 J jnl
Interactions
Katta Spiel, Oliver L. Haimson, Danielle M. Lottridge
2019 conf
CSCW Companion
Oliver L. Haimson, Bryan C. Semaan, Brianna Dym, Joey Chiao-Yin Hsiao, Daniel Herron, Wendy Moncur
2019 J jnl
J. Am. Medical Informatics Assoc.
Oliver L. Haimson
2019 J jnl
Proc. ACM Hum. Comput. Interact.
Koustuv Saha, Sang Chan Kim, Manikanta D. Reddy, Albert J. Carter, Eva Sharma, Oliver L. Haimson, Munmun De Choudhury
2018 A* conf
CHI
Samantha Jaroszewski, Danielle M. Lottridge, Oliver L. Haimson, Katie Quehl
2018 J jnl
First Monday
Mia Fischer, Oliver L. Haimson, Carmen Rios, Adrienne Shaw, Mitali Thakor, Jen Jack Gieseking, Daniel Cockayne
2018 conf
GenderIT
Blake W. Hawkins, Oliver L. Haimson
2018 conf
ASIST
Blake W. Hawkins, Nazanin Andalibi, Oliver L. Haimson
2018 J jnl
New Media Soc.
Oliver L. Haimson, Nazanin Andalibi, Munmun De Choudhury, Gillian R. Hayes
2018 J jnl
Proc. ACM Hum. Comput. Interact.
Oliver L. Haimson
2018 J jnl
ACM Trans. Comput. Hum. Interact.
Nazanin Andalibi, Oliver L. Haimson, Munmun De Choudhury, Andrea Forte
2018
Oliver L. Haimson
2017 A conf
ICWSM
Oliver L. Haimson, Gillian R. Hayes
2017 A* conf
CHI
Eugenia Ha Rim Rho, Oliver L. Haimson, Nazanin Andalibi, Melissa Mazmanian, Gillian R. Hayes
2017 J jnl
XRDS
Oliver L. Haimson
2017 conf
CHI Extended Abstracts
Oliver L. Haimson
2017 J jnl
ACM Trans. Access. Comput.
Mark S. Baldwin, Gillian R. Hayes, Oliver L. Haimson, Jennifer Mankoff, Scott E. Hudson
2017 A* conf
CHI
Oliver L. Haimson, John C. Tang
2016 A conf
CSCW
Jessica Annette Pater, Oliver L. Haimson, Nazanin Andalibi, Elizabeth D. Mynatt
2016 J jnl
First Monday
Oliver L. Haimson, Anna Lauren Hoffmann
2016 A* conf
CHI
Oliver L. Haimson, Jed R. Brubaker, Lynn Dombrowski, Gillian R. Hayes
2016 A* conf
KDD
Michael A. Madaio, Shang-Tse Chen, Oliver L. Haimson, Wenwen Zhang, Xiang Cheng, Matthew Hinds-Aldrich, Duen Horng Chau, Bistra Dilkina
2016 J jnl
CoRR
Michael A. Madaio, Shang-Tse Chen, Oliver L. Haimson, Wenwen Zhang, Xiang Cheng, Matthew Hinds-Aldrich, Duen Horng Chau, Bistra Dilkina
2016 Misc conf
NordiCHI
Daniel Herron, Nazanin Andalibi, Oliver L. Haimson, Wendy Moncur, Elise van den Hoven
2016 A* conf
CHI
Nazanin Andalibi, Oliver L. Haimson, Munmun De Choudhury, Andrea Forte
2015 conf
CHI Extended Abstracts
Sarah Vieweg, Oliver L. Haimson, Michael Massimi, Kenton O'Hara, Elizabeth F. Churchill
2015 A conf
CSCW
Oliver L. Haimson, Jed R. Brubaker, Lynn Dombrowski, Gillian R. Hayes
2015 J jnl
ACM Trans. Access. Comput.
LouAnne E. Boyd, Kathryn E. Ringland, Oliver L. Haimson, Helen Fernandez, Maria Bistarkey, Gillian R. Hayes
2015 conf
CSCW Companion
Mark J. Handel, Rena Bivens, Jed R. Brubaker, Oliver L. Haimson, Jessa Lingel, Svetlana Yarosh
2015 A* conf
CHI
Anne E. Bowser, Oliver L. Haimson, Edward F. Melcer, Elizabeth F. Churchill
2015 A* conf
CHI
Oliver L. Haimson, Anne E. Bowser, Edward F. Melcer, Elizabeth F. Churchill
2014 A* conf
CHI
Oliver L. Haimson, Jed R. Brubaker, Gillian R. Hayes
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"