Neil P. Chue Hong

61 papers A 1B 1Journal 39Unranked 15
YearRankTypeTitle / Venue / Authors
2025 J jnl
Comput. Sci. Eng.
Stephan Druskat, Nasir U. Eisty, Robert Chisholm, Neil P. Chue Hong, Ryan C. Cocking, Myra B. Cohen, Michael Felderer, Lars Grunske, Sarah A. Harris, Wilhelm Hasselbring, Thomas Krause, Jan Linxweiler, Colin C. Venters
2025 J jnl
CoRR
Stuart M. Allen, Neil P. Chue Hong, Stephan Druskat, Toby Hodges, Daniel S. Katz, Jan Linxweiler, Frank Löffler, Lars Grunske, Heidi Seibold, Jan Philipp Thiele, Samantha Wittke
2025 J jnl
Patterns
Neil P. Chue Hong, Selina Aragon, Simon Hettrick, Caroline Jay
2024 J jnl
CoRR
Stephan Druskat, Neil P. Chue Hong, Sammie Buzzard, Olexandr Konovalov, Patrick Kornek
2024 J jnl
PeerJ Comput. Sci.
Daniel S. Katz, Neil P. Chue Hong
2024 J jnl
IEEE Access
Jeanette Falk, Alexander Nolte, Daniela Huppenkothen, Marion Weinzierl, Kiev Gama, Daniel Spikol, Erik J. Tollerud, Neil P. Chue Hong, Ines Knäpper, Linda Bailey Hayden
2022 J jnl
CoRR
Jeanette Falk, Alexander Nolte, Daniela Huppenkothen, Marion Weinzierl, Kiev Gama, Daniel Spikol, Erik J. Tollerud, Neil P. Chue Hong, Ines Knäpper, Linda Bailey Hayden
2021 conf
BoKSS@ICSE
Daniel S. Katz, Jeffrey C. Carver, Neil P. Chue Hong, Sandra Gesing, Simon Hettrick, Tom Honeyman, Karthik Ram, Nicholas M. Weber
2021 J jnl
CoRR
Daniel S. Katz, Jeffrey C. Carver, Neil P. Chue Hong, Sandra Gesing, Simon Hettrick, Tom Honeyman, Karthik Ram, Nicholas M. Weber
2021 J jnl
IEEE Softw.
Jeremy Cohen, Daniel S. Katz, Michelle Barker, Neil P. Chue Hong, Robert Haines, Caroline Jay
2021 conf
ICCS (6)
Neil P. Chue Hong, Jeremy Cohen, Caroline Jay
2021 J jnl
CoRR
Neil P. Chue Hong, Jeremy Cohen, Caroline Jay
2020 J jnl
CoRR
Alain Monteil, Alejandra N. González-Beltrán, Alexandros Ioannidis, Alice Allen, Allen Lee, Anita E. Bandrowski, Bruce E. Wilson, Bryce D. Mecum, Caifan Du, Carly Robinson, Daniel Garijo, Daniel S. Katz, David Long, Genevieve Milliken, Hervé Ménager, Jessica Hausman, Jurriaan H. Spaaks, Katrina Fenlon, Kristin Vanderbilt, Lorraine J. Hwang, Lynn Davis, Martin Fenner, Michael R. Crusoe, Michael Hucka, Mingfang Wu, Neil P. Chue Hong, Peter J. Teuben, Shelley Stall, Stephan Druskat, Ted Carnevale, Thomas Morrell
2020 J jnl
CoRR
Daniel S. Katz, Sudhir Malik, Mark S. Neubauer, Graeme Andrew Stewart, Kétévi A. Assamagan, Erin A. Becker, Neil P. Chue Hong, Ian A. Cosden, Samuel Meehan, Edward J. W. Moyse, Adrian M. Price-Whelan, Elizabeth Sexton-Kennedy, Meirin Oan Evans, Matthew Feickert, Clemens Lange, Kilian Lieret, Rob Quick, Arturo Sánchez Pineda, Christopher D. Tunnell
2020 J jnl
Comput. Sci. Eng.
Daniel S. Katz, Neil P. Chue Hong, Tim Clark, Martin Fenner, Maryann E. Martone
2020 conf
DaMaLOS
Leyla J. García, Michelle Barker, Neil P. Chue Hong, Fotis E. Psomopoulos, Jennifer L. Harrow, Daniel S. Katz, Mateusz Kuzak, Paula Andrea Martínez, Allegra Via
2020 J jnl
CoRR
Jeremy Cohen, Daniel S. Katz, Michelle Barker, Neil P. Chue Hong, Robert Haines, Caroline Jay
2020 J jnl
Data Sci.
Anna-Lena Lamprecht, Leyla J. García, Mateusz Kuzak, Carlos Martinez-Ortiz, Ricardo Arcila, Eva Martín del Pico, Victoria Dominguez Del Angel, Stephanie van de Sandt, Jon C. Ison, Paula Andrea Martínez, Peter McQuilton, Alfonso Valencia, Jennifer L. Harrow, Fotis E. Psomopoulos, Josep Lluís Gelpí, Neil P. Chue Hong, Carole A. Goble, Salvador Capella-Gutiérrez
2019 J jnl
Comput. Sci. Eng.
Daniel S. Katz, Lois Curfman McInnes, David E. Bernholdt, Abigail Cabunoc Mayes, Neil P. Chue Hong, Jonah Duckles, Sandra Gesing, Michael A. Heroux, Simon Hettrick, Rafael C. Jiménez, Marlon E. Pierce, Belinda Weaver, Nancy Wilkins-Diehr
2019 J jnl
CoRR
Daniel S. Katz, Daina Bouquin, Neil P. Chue Hong, Jessica Hausman, Catherine Mary Jones, Daniel Chivvis, Tim Clark, Mercè Crosas, Stephan Druskat, Martin Fenner, Tom Gillespie, Alejandra N. González-Beltrán, Morane Gruenpeter, Ted Habermann, Robert Haines, Melissa Harrison, Edwin A. Henneken, Lorraine J. Hwang, Matthew B. Jones, Alastair A. Kelly, David N. Kennedy, Katrin Leinweber, Fernando Rios, Carly Robinson, Ilian T. Todorov, Mingfang Wu, Qian Zhang
2019 J jnl
CoRR
Daniel S. Katz, Patrick Aerts, Neil P. Chue Hong, Anshu Dubey, Sandra Gesing, Henry Neeman, David E. Pearah
2019 J jnl
Future Gener. Comput. Syst.
Michelle Barker, Sílvia Delgado Olabarriaga, Nancy Wilkins-Diehr, Sandra Gesing, Daniel S. Katz, Shayan Shahand, Scott Henwood, Tristan Glatard, Keith G. Jeffery, Brian Corrie, Andrew E. Treloar, Helen M. Glaves, Lesley Wyborn, Neil P. Chue Hong, Alessandro Costa
2018 conf
eScience
Jeremy Cohen, Daniel S. Katz, Michelle Barker, Robert Haines, Neil P. Chue Hong
2018 J jnl
CoRR
Jeremy Cohen, Daniel S. Katz, Michelle Barker, Robert Haines, Neil P. Chue Hong
2018 J jnl
CoRR
Daniel S. Katz, Lois Curfman McInnes, David E. Bernholdt, Abigail Cabunoc Mayes, Neil P. Chue Hong, Jonah Duckles, Sandra Gesing, Michael A. Heroux, Simon Hettrick, Rafael C. Jiménez, Marlon E. Pierce, Belinda Weaver, Nancy Wilkins-Diehr
2018 ed.
SE4Science@ICSE
Jeffrey C. Carver, Neil P. Chue Hong, Caroline Jay
2018 conf
ICMS
Daniel S. Katz, Neil P. Chue Hong
2018 J jnl
CoRR
Daniel S. Katz, Neil P. Chue Hong
2018 J jnl
Inform. Spektrum
Neil P. Chue Hong
2017 conf
SE4Science@ICSE
Jeffrey C. Carver, Neil P. Chue Hong
2017 J jnl
F1000Research
Rafael C. Jiménez, Mateusz Kuzak, Monther Alhamdoosh, Michelle Barker, Bérénice Batut, Mikael Borg, Salvador Capella-Gutiérrez, Neil P. Chue Hong, Martin Cook, Manuel Corpas, Madison Flannery, Leyla J. García, Josep Lluís Gelpí, Simon L. Gladman, Carole A. Goble, Montserrat González Ferreiro, Alejandra N. González-Beltrán, Philippa C. Griffin, Björn A. Grüning, Jonas Hagberg, Petr Holub, Rob W. W. Hooft, Jon C. Ison, Daniel S. Katz, Brane Leskosek, Federico López-Gómez, Luis J. Oliveira, David Mellor, Rowland Mosbergen, Nicola J. Mulder, Yasset Pérez-Riverol, Robert Pergl, Horst Pichler, Bernard J. Pope, Ferran Sanz, Maria Victoria Schneider, Victoria Stodden, Radoslaw Suchecki, Radka Svobodová Vareková, Harry-Anton Talvik, Ilian T. Todorov, Andrew E. Treloar, Sonika Tyagi, Maarten van Gompel, Daniel Vaughan, Allegra Via, Xiaochuan Wang, Nathan S. Watson-Haigh, Steve Crouch
2017 J jnl
Concurr. Comput. Pract. Exp.
Shantenu Jha, Daniel S. Katz, André Luckow, Neil P. Chue Hong, Omer F. Rana, Yogesh Simmhan
2017 J jnl
CoRR
Daniel S. Katz, Kyle E. Niemeyer, Sandra Gesing, Lorraine J. Hwang, Wolfgang Bangerth, Simon Hettrick, Ray Idaszak, Jean Salac, Neil P. Chue Hong, Santiago Núñez-Corrales, Alice Allen, R. Stuart Geiger, Jonah Miller, Emily Chen, Anshu Dubey, Patricia Lago
2017 J jnl
Comput. Sci. Eng.
Jeffrey C. Carver, Neil P. Chue Hong, Selim Ciraci
2016 J jnl
CoRR
Shantenu Jha, Daniel S. Katz, André Luckow, Omer F. Rana, Yogesh Simmhan, Neil P. Chue Hong
2016 J jnl
PeerJ Prepr.
Amy V. Beeston, Larisa Blazic, Neil P. Chue Hong, Richard Domander, Ross Mounce, Robin T. Wilson
2016 J jnl
F1000Research
Haydee Artaza, Neil P. Chue Hong, Manuel Corpas, Angel Corpuz, Rob W. W. Hooft, Rafael C. Jiménez, Brane Leskosek, Brett G. Olivier, Jan Stourac, Radka Svobodová Vareková, Thomas Van Parys, Daniel Vaughan
2015 ed.
SE4HPCS@ICSE
Jeffrey C. Carver, Paolo Ciancarini, Neil P. Chue Hong
2015 J jnl
CoRR
Daniel S. Katz, Sou-Cheng T. Choi, Nancy Wilkins-Diehr, Neil P. Chue Hong, Colin C. Venters, James Howison, Frank J. Seinstra, Matthew Jones, Karen Cranston, Thomas L. Clune, Miguel de Val-Borro, Richard Littauer
2015 conf
ICSE (2)
Jeffrey C. Carver, Neil P. Chue Hong, Paolo Ciancarini
2015 J jnl
Sci. Program.
Jeffrey C. Carver, Neil P. Chue Hong, Selim Ciraci
2015 J jnl
CoRR
Neil P. Chue Hong, Tom Crick, Ian P. Gent, Lars Kotthoff, Kenji Takeda
2014 J jnl
CoRR
Daniel S. Katz, Gabrielle Allen, Neil P. Chue Hong, Karen Cranston, Manish Parashar, David Proctor, Matthew Turk, Colin C. Venters, Nancy Wilkins-Diehr
2014 conf
TRUST@PLDI
Shoaib Sufi, Neil P. Chue Hong, Simon Hettrick, Mario Antonioletti, Stephen Crouch, Alexander Hay, Devasena Inupakutika, Mike Jackson, Aleksandra Pawlik, Giacomo Peru, John Robinson, Les Carr, David De Roure, Carole A. Goble, Mark Parsons
2013 J jnl
CoRR
Daniel S. Katz, Gabrielle Allen, Neil P. Chue Hong, Manish Parashar, David Proctor
2013 ed.
SE-HPCCSE@SC
Jeffrey C. Carver, Neil P. Chue Hong, Selim Ciraci
2013 J jnl
CoRR
Jeremy Cohen, Chris D. Cantwell, Neil P. Chue Hong, David Moxey, Malcolm Illingworth, Andrew Turner, John Darlington, Spencer J. Sherwin
2013 J jnl
Comput. Sci. Eng.
Stephen Crouch, Neil P. Chue Hong, Simon Hettrick, Mike Jackson, Aleksandra Pawlik, Shoaib Sufi, Les Carr, David De Roure, Carole A. Goble, Mark Parsons
2012 J jnl
CoRR
Dhavide A. Aruliah, C. Titus Brown, Neil P. Chue Hong, Matt Davis, Richard T. Guy, Steven H. D. Haddock, Katy Huff, Ian Mitchell, Mark D. Plumbley, Ben Waugh, Ethan P. White, Greg Wilson, Paul Wilson
2011 ch.
Grid and Cloud Database Management
Michael J. Jackson, Mario Antonioletti, Bartosz Dobrzelecki, Neil P. Chue Hong
2011 ch.
Grid and Cloud Database Management
Bartosz Dobrzelecki, Amrey Krause, Michal Piotrowski, Neil P. Chue Hong
2010 conf
GRID
Neil P. Chue Hong
2010 conf
DASFAA Workshops
Isao Kojima, Kento Aida, Geoffrey C. Fox, Neil P. Chue Hong, Masatoshi Ohishi
2008 conf
HealthGrid
Joel H. Saltz, Shannon Hastings, Stephen Langella, Scott Oster, Tahsin M. Kurç, Philip R. O. Payne, Renato Ferreira, Beth Plale, Carole A. Goble, David Ervin, Ashish Sharma, Tony Pan, Justin Permar, Peter Brezany, Frank Siebenlist, Ravi K. Madduri, Ian T. Foster, Krishnakant Shanbhag, Charlie Mead, Neil P. Chue Hong
2008 conf
eScience
Neil P. Chue Hong, Alex Voss
2006 conf
PARA
Mario Antonioletti, Malcolm P. Atkinson, Neil P. Chue Hong, Bartosz Dobrzelecki, Alastair C. Hume, Mike Jackson, Konstantinos Karasavvas, Amy Krause, Jennifer M. Schopf, Tom Sugden, Elias Theocharopoulos
2005 conf
Knowledge and Data Management in GRIDs
Neil P. Chue Hong, Mario Antonioletti, Konstantinos Karasavvas, Malcolm P. Atkinson
2005 J jnl
Concurr. Pract. Exp.
Mario Antonioletti, Malcolm P. Atkinson, Robert M. Baxter, Andrew Borley, Neil P. Chue Hong, Brian Collins, Neil Hardman, Alastair C. Hume, Alan Knox, Mike Jackson, Amrey Krause, Simon Laws, James Magowan, Norman W. Paton, Dave Pearson, Tom Sugden, Paul Watson, Martin Westhead
2004 B conf
SSDBM
Ewa Deelman, Gurmeet Singh, Malcolm P. Atkinson, Ann L. Chervenak, Neil P. Chue Hong, Carl Kesselman, Sonal Patil, Laura Pearlman, Mei-Hui Su
2004 conf
SAG
Konstantinos Karasavvas, Mario Antonioletti, Malcolm P. Atkinson, Neil P. Chue Hong, Tom Sugden, Alastair C. Hume, Mike Jackson, Amrey Krause, Charaka Palansuriya
2002 A conf
HPDC
Robert M. Baxter, Neil P. Chue Hong, Richard A. Baldock, Bill Hill, James Sharpe
tests/integration/test_hashes.py
← Index tests/integration/test_hashes.py python
"""
Integration tests for the HashExtractor class.
"""
import pytest
import hashlib
from unittest.mock import Mock, patch, MagicMock

pytestmark = [pytest.mark.integration]


class TestHashExtractorInitialization:
    """Tests for HashExtractor initialization."""

    def test_initialization_elf(self, elf_binary_path, mock_logger):
        """Test initialization with ELF file."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            assert extractor.filepath == elf_binary_path
            assert extractor.hashes is None
            assert extractor.filetype == "elf"
            assert extractor.macho is None

    def test_initialization_with_macho_object(self, elf_binary_path, mock_logger):
        """Test initialization with pre-parsed macho object."""
        from redb.extractors.hashes import HashExtractor

        mock_macho = MagicMock()
        mock_macho.get_architectures.return_value = ["x86_64"]

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger, macho=mock_macho)

            assert extractor.macho is mock_macho

    def test_initialization_pe(self, pe_binary_path, mock_logger):
        """Test initialization with PE file."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            assert extractor.filepath == pe_binary_path
            assert extractor.filetype == "pebin"
            # PE object should be created
            assert extractor.pe is not None

    def test_elastic_index_suffix(self, elf_binary_path, mock_logger):
        """Test that elastic_index has correct suffix."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            assert "-hashes" in extractor.elastic_index


class TestHashExtractorTag:
    """Tests for tag method."""

    def test_tag_value(self, elf_binary_path, mock_logger):
        """Test that tag returns correct value."""
        from redb.extractors.hashes import HashExtractor
        from redb.extractors.enum import Tag

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            assert extractor.tag() == Tag.HASH.value
            assert extractor.tag() == "hash"


class TestHashExtractorBasicHashes:
    """Tests for basic hash extraction."""

    def test_extract_md5(self, elf_binary_path, mock_logger, known_hashes):
        """Test MD5 hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert result.md5 == known_hashes['md5']

    def test_extract_sha1(self, elf_binary_path, mock_logger, known_hashes):
        """Test SHA1 hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert result.sha1 == known_hashes['sha1']

    def test_extract_sha256(self, elf_binary_path, mock_logger, known_hashes):
        """Test SHA256 hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert result.sha256 == known_hashes['sha256']

    def test_extract_ssdeep(self, elf_binary_path, mock_logger):
        """Test ssdeep hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # ssdeep should be a string
            assert isinstance(result.ssdeep_hash, str)

    def test_extract_tlsh(self, elf_binary_path, mock_logger):
        """Test TLSH hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # TLSH should be a string
            assert isinstance(result.tlsh_hash, str)


class TestHashExtractorPEHashes:
    """Tests for PE-specific hash extraction."""

    def test_extract_imphash(self, pe_binary_path, mock_logger):
        """Test imphash extraction for PE file."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Imphash should be set for PE files
            if extractor.pe is not None:
                assert result.imphash is not None or result.imphash is None  # May or may not have imports

    def test_extract_authentihash(self, pe_binary_path, mock_logger):
        """Test authentihash extraction for PE file."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Authentihash should be set for PE files
            if extractor.pe is not None:
                assert result.authentihash is not None

    def test_pe_hashes_not_set_for_elf(self, elf_binary_path, mock_logger):
        """Test that PE-specific hashes are not set for ELF files."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # PE-specific hashes should be None for ELF
            assert result.imphash is None
            assert result.authentihash is None
            assert result.richhash is None


class TestHashExtractorRichHeaderHashes:
    """Tests for Rich header hash extraction."""

    def test_compute_richhash(self, pe_binary_path, mock_logger):
        """Test Rich header hash computation."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Rich hash may or may not be present depending on the PE
            if result.richhash is not None:
                assert isinstance(result.richhash, str)
                assert len(result.richhash) == 32  # MD5 hex length

    def test_compute_richpe_hash(self, pe_binary_path, mock_logger):
        """Test RichPE hash computation."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # RichPE hash may or may not be present
            if result.richpe_hash is not None:
                assert isinstance(result.richpe_hash, str)
                assert len(result.richpe_hash) == 32  # MD5 hex length

    def test_compute_richpv_hash(self, pe_binary_path, mock_logger):
        """Test RichPV hash computation."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # RichPV hashes may or may not be present
            if result.richpv_hash is not None:
                assert isinstance(result.richpv_hash, str)
            if result.richpv_hash_sorted is not None:
                assert isinstance(result.richpv_hash_sorted, str)


class TestHashExtractorELFHashes:
    """Tests for ELF-specific hash extraction."""

    def test_extract_elf_import_hash(self, elf_binary_path, mock_logger):
        """Test ELF import hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Import hash may or may not be present
            if result.import_hash is not None:
                assert isinstance(result.import_hash, str)
                assert len(result.import_hash) == 32

    def test_extract_elf_export_hash(self, elf_binary_path, mock_logger):
        """Test ELF export hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Export hash may or may not be present
            if result.export_hash is not None:
                assert isinstance(result.export_hash, str)

    def test_extract_elf_section_hash(self, elf_binary_path, mock_logger):
        """Test ELF section hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Section hash should be present for valid ELF
            if result.section_hash is not None:
                assert isinstance(result.section_hash, str)

    def test_extract_elf_symbol_hash(self, elf_binary_path, mock_logger):
        """Test ELF symbol hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Symbol hash (symhash) may or may not be present
            if result.symbol_hash is not None:
                assert isinstance(result.symbol_hash, str)

    def test_extract_elf_dynamic_hash(self, elf_binary_path, mock_logger):
        """Test ELF dynamic hash extraction."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Dynamic hash may or may not be present
            if result.dynamic_hash is not None:
                assert isinstance(result.dynamic_hash, str)


class TestHashExtractorPrepareExportData:
    """Tests for prepare_export_data method."""

    def test_prepare_export_elasticsearch(self, elf_binary_path, mock_logger):
        """Test prepare_export_data for Elasticsearch."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)
            extractor.extract()

            result = extractor.prepare_export_data("ElasticsearchExporter")

            assert result is extractor.hashes

    def test_prepare_export_clickhouse(self, elf_binary_path, mock_logger):
        """Test prepare_export_data for ClickHouse."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)
            extractor.extract()

            result = extractor.prepare_export_data("ClickHouseExporter")

            # Should return tuple of (data, column_names, column_type_names)
            assert isinstance(result, tuple)
            assert len(result) == 3

            data, column_names, column_type_names = result

            assert isinstance(data, list)
            assert isinstance(column_names, list)
            assert isinstance(column_type_names, list)

            # Check expected columns
            assert 'sha256' in column_names
            assert 'md5' in column_names
            assert 'sha1' in column_names
            assert 'ssdeep_hash' in column_names
            assert 'tlsh_hash' in column_names

    def test_prepare_export_clickhouse_pe(self, pe_binary_path, mock_logger):
        """Test prepare_export_data for ClickHouse with PE file."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)
            extractor.extract()

            result = extractor.prepare_export_data("ClickHouseExporter")

            data, column_names, column_type_names = result

            # PE-specific columns should be present
            assert 'authentihash' in column_names
            assert 'imphash' in column_names
            assert 'richhash' in column_names

    def test_prepare_export_clickhouse_has_macho_columns(self, elf_binary_path, mock_logger):
        """Test prepare_export_data for ClickHouse includes Mach-O hash columns."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)
            extractor.extract()

            result = extractor.prepare_export_data("ClickHouseExporter")

            data, column_names, column_type_names = result

            # Mach-O hash columns should be present
            assert 'macho_dylib_hash' in column_names
            assert 'macho_import_hash' in column_names
            assert 'macho_export_hash' in column_names
            assert 'macho_entitlement_hash' in column_names
            assert 'macho_symhash' in column_names


class TestHashExtractorClickHouseTable:
    """Tests for get_clickhouse_table method."""

    def test_clickhouse_table_name(self, elf_binary_path, mock_logger):
        """Test correct ClickHouse table name."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            assert extractor.get_clickhouse_table() == "redb_hashes"


@pytest.mark.unit
@pytest.mark.dataclass
class TestHashExtractorHashesDataclass:
    """Tests for Hashes dataclass structure."""

    def test_hashes_dataclass_structure(self, elf_binary_path, mock_logger):
        """Test that Hashes dataclass has expected structure."""
        from redb.extractors.hashes import HashExtractor
        from redb.models.dataclasses import Hashes

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert isinstance(result, Hashes)
            # Required fields
            assert hasattr(result, 'md5')
            assert hasattr(result, 'sha1')
            assert hasattr(result, 'sha256')
            assert hasattr(result, 'ssdeep_hash')
            assert hasattr(result, 'tlsh_hash')
            # Optional fields
            assert hasattr(result, 'authentihash')
            assert hasattr(result, 'imphash')
            assert hasattr(result, 'richhash')

    def test_hashes_dataclass_has_macho_fields(self):
        """Test that Hashes dataclass has Mach-O hash fields."""
        from redb.models.dataclasses import Hashes

        # Create instance with default values
        hashes = Hashes(
            md5="d41d8cd98f00b204e9800998ecf8427e",
            sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709",
            sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            ssdeep_hash="",
            tlsh_hash=""
        )

        # Verify Mach-O hash fields exist and default to None
        assert hasattr(hashes, 'macho_dylib_hash')
        assert hasattr(hashes, 'macho_import_hash')
        assert hasattr(hashes, 'macho_export_hash')
        assert hasattr(hashes, 'macho_entitlement_hash')
        assert hasattr(hashes, 'macho_symhash')

        assert hashes.macho_dylib_hash is None
        assert hashes.macho_import_hash is None
        assert hashes.macho_export_hash is None
        assert hashes.macho_entitlement_hash is None
        assert hashes.macho_symhash is None

    def test_hashes_dataclass_with_macho_values(self):
        """Test that Hashes dataclass can be created with Mach-O hash values."""
        from redb.models.dataclasses import Hashes

        hashes = Hashes(
            md5="d41d8cd98f00b204e9800998ecf8427e",
            sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709",
            sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            ssdeep_hash="",
            tlsh_hash="",
            macho_dylib_hash="abc123def456789012345678901234567",
            macho_import_hash="def456abc123789012345678901234567",
            macho_export_hash="789012abc123def456345678901234567",
            macho_entitlement_hash="345678abc123def456789012901234567",
            macho_symhash="901234abc123def456789012345678567"
        )

        assert hashes.macho_dylib_hash == "abc123def456789012345678901234567"
        assert hashes.macho_import_hash == "def456abc123789012345678901234567"
        assert hashes.macho_export_hash == "789012abc123def456345678901234567"
        assert hashes.macho_entitlement_hash == "345678abc123def456789012901234567"
        assert hashes.macho_symhash == "901234abc123def456789012345678567"


class TestHashExtractorErrorHandling:
    """Tests for error handling in HashExtractor."""

    def test_extract_handles_hash_errors(self, elf_binary_path, mock_logger):
        """Test that extract handles hash computation errors gracefully."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            # Even if some hashes fail, we should get a result
            result = extractor.extract()

            assert result is not None

    def test_extract_with_invalid_pe(self, elf_binary_path, mock_logger):
        """Test extraction when PE parsing fails."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            # Force filetype to be 'pebin' but use ELF file
            with patch.object(HashExtractor, '__init__', lambda self, *args, **kwargs: None):
                extractor = HashExtractor.__new__(HashExtractor)
                extractor.filepath = elf_binary_path
                extractor.log = mock_logger
                extractor.hashes = None
                extractor.pe = None
                extractor.filetype = 'pebin'

                with open(elf_binary_path, 'rb') as f:
                    extractor.binary = f.read()

                # Should not crash
                result = extractor._extract_hashes()
                assert result is not None


class TestHashExtractorMachoHashes:
    """Tests for Mach-O specific hash extraction."""

    def test_macho_hashes_not_set_for_elf(self, elf_binary_path, mock_logger):
        """Test that Mach-O hashes are not set for ELF files."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert result.macho_dylib_hash is None
            assert result.macho_import_hash is None
            assert result.macho_export_hash is None
            assert result.macho_entitlement_hash is None
            assert result.macho_symhash is None

    def test_macho_hashes_not_set_for_pe(self, pe_binary_path, mock_logger):
        """Test that Mach-O hashes are not set for PE files."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(pe_binary_path, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert result.macho_dylib_hash is None
            assert result.macho_import_hash is None
            assert result.macho_export_hash is None
            assert result.macho_entitlement_hash is None
            assert result.macho_symhash is None

    def test_extract_macho_hashes_with_mock(self, elf_binary_path, mock_logger):
        """Test Mach-O hash extraction with mocked macho object."""
        from redb.extractors.hashes import HashExtractor

        # Create mock macho object
        mock_macho = MagicMock()
        mock_macho.get_architectures.return_value = ["x86_64"]
        mock_macho.get_similarity_hashes.return_value = {
            'dylib_hash': 'abc123def456789012345678901234ab',
            'import_hash': 'def456abc789012345678901234567cd',
            'export_hash': '789012abc456def345678901234567ef',
            'entitlement_hash': '345678abc123def789012901234567gh',
            'symhash': '901234abc123def456789012345678ij'
        }

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger, macho=mock_macho)
            # Override filetype to trigger macho hash extraction
            extractor.filetype = 'macho'

            result = extractor.extract()

            assert result is not None
            assert result.macho_dylib_hash == 'abc123def456789012345678901234ab'
            assert result.macho_import_hash == 'def456abc789012345678901234567cd'
            assert result.macho_export_hash == '789012abc456def345678901234567ef'
            assert result.macho_entitlement_hash == '345678abc123def789012901234567gh'
            assert result.macho_symhash == '901234abc123def456789012345678ij'

    def test_extract_macho_hashes_fat_binary_mock(self, elf_binary_path, mock_logger):
        """Test Mach-O hash extraction for FAT binary with mocked macho object."""
        from redb.extractors.hashes import HashExtractor

        # Create mock macho object for FAT binary
        mock_macho = MagicMock()
        mock_macho.get_architectures.return_value = ["x86_64", "arm64"]  # Multiple archs = FAT
        mock_macho.get_similarity_hashes.return_value = {
            'fat': {
                'dylib_hash': 'fat_dylib_hash_12345678901234567',
                'import_hash': 'fat_import_hash_12345678901234567',
            },
            'combined': {
                'dylib_hash': 'combined_dylib_hash_1234567890123',
            }
        }

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger, macho=mock_macho)
            extractor.filetype = 'macho'

            result = extractor.extract()

            assert result is not None
            # Should use 'fat' key for FAT binaries
            assert result.macho_dylib_hash == 'fat_dylib_hash_12345678901234567'
            assert result.macho_import_hash == 'fat_import_hash_12345678901234567'

    def test_extract_macho_hashes_handles_empty(self, elf_binary_path, mock_logger):
        """Test Mach-O hash extraction handles empty hash dict."""
        from redb.extractors.hashes import HashExtractor

        mock_macho = MagicMock()
        mock_macho.get_architectures.return_value = ["x86_64"]
        mock_macho.get_similarity_hashes.return_value = {}

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger, macho=mock_macho)
            extractor.filetype = 'macho'

            result = extractor.extract()

            # Should not crash, hashes should be None
            assert result is not None
            assert result.macho_dylib_hash is None

    def test_extract_macho_hashes_handles_none(self, elf_binary_path, mock_logger):
        """Test Mach-O hash extraction handles None return."""
        from redb.extractors.hashes import HashExtractor

        mock_macho = MagicMock()
        mock_macho.get_architectures.return_value = ["x86_64"]
        mock_macho.get_similarity_hashes.return_value = None

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger, macho=mock_macho)
            extractor.filetype = 'macho'

            result = extractor.extract()

            # Should not crash
            assert result is not None


class TestHashExtractorConsistency:
    """Tests for hash consistency."""

    def test_hash_consistency_across_extractions(self, elf_binary_path, mock_logger):
        """Test that hashes are consistent across multiple extractions."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor1 = HashExtractor(elf_binary_path, mock_logger)
            result1 = extractor1.extract()

            extractor2 = HashExtractor(elf_binary_path, mock_logger)
            result2 = extractor2.extract()

            assert result1.md5 == result2.md5
            assert result1.sha1 == result2.sha1
            assert result1.sha256 == result2.sha256

    def test_hash_values_are_lowercase(self, elf_binary_path, mock_logger):
        """Test that hash values are lowercase hex strings."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert result.md5 == result.md5.lower()
            assert result.sha1 == result.sha1.lower()
            assert result.sha256 == result.sha256.lower()

    def test_hash_lengths_correct(self, elf_binary_path, mock_logger):
        """Test that hash lengths are correct."""
        from redb.extractors.hashes import HashExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = HashExtractor(elf_binary_path, mock_logger)

            result = extractor.extract()

            assert len(result.md5) == 32  # MD5 = 128 bits = 32 hex chars
            assert len(result.sha1) == 40  # SHA1 = 160 bits = 40 hex chars
            assert len(result.sha256) == 64  # SHA256 = 256 bits = 64 hex chars