M. Howard Williams

161 papers A* 3B 8C 10Journal 76Unranked 57
YearRankTypeTitle / Venue / Authors
2015 conf
KES-AMSTA
Eliza Papadopoulou, Alex Stobart, Nick K. Taylor, M. Howard Williams
2015 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Diana S. Bental, Elizabeth Papadopoulou, Nicholas K. Taylor, M. Howard Williams, Fraser R. Blackmun, Idris Skloul Ibrahim, Mei Yii Lim, Ioannis Mimtsoudis, Stuart W. Whyte, Edel Jennings
2014 J jnl
Pervasive Mob. Comput.
Sarah Gallacher, Elizabeth Papadopoulou, Yussuf Abu-Shaaban, Nick K. Taylor, M. Howard Williams
2013 conf
UbiComp (Adjunct Publication)
Nicholas K. Taylor, Elizabeth Papadopoulou, Mei Yii Lim, Patrick Skillen, Fraser R. Blackmun, M. Howard Williams
2013 J jnl
ACM Trans. Auton. Adapt. Syst.
Sarah Gallacher, Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams
2013 conf
CITA
Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams, Sarah Gallacher
2012 J jnl
Pervasive Mob. Comput.
Elizabeth Papadopoulou, Sarah Gallacher, Nick K. Taylor, M. Howard Williams
2012 conf
ICCASA
Elizabeth Papadopoulou, Sarah Gallacher, Nick K. Taylor, M. Howard Williams, Fraser R. Blackmun
2012 conf
UIC/ATC
Sarah Gallacher, Elizabeth Papadopoulou, Nick K. Taylor, Fraser R. Blackmun, M. Howard Williams
2012 conf
UIC/ATC
Sarah Gallacher, Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams
2011 conf
ISD
Nicholas K. Taylor, Elizabeth Papadopoulou, Sarah Gallacher, M. Howard Williams
2011 B conf
ICCCN
Sarah Gallacher, Elizabeth Papadopoulou, Nick K. Taylor, Fraser R. Blackmun, M. Howard Williams, Ioanna Roussaki, Nikos Kalatzis, Nicolas Liampotis, Daqing Zhang
2010 C conf
MobiQuitous
Sarah Gallacher, Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams, Fraser R. Blackmun
2010 conf
UIC/ATC Workshops
Elizabeth Papadopoulou, Sarah Gallacher, Nick K. Taylor, M. Howard Williams
2010 conf
Future Internet Assembly
Ioanna Roussaki, Nikos Kalatzis, Kevin Doolin, Nick K. Taylor, Guido P. Spadotto, Nicolas Liampotis, M. Howard Williams
2010 conf
ICISTM
Elizabeth Papadopoulou, Yussuf Abu-Shaaban, Sarah Gallacher, Nick K. Taylor, M. Howard Williams
2009 conf
CSE (3)
Nicolas Liampotis, Ioanna Roussaki, Elizabeth Papadopoulou, Yussuf Abu-Shaaban, M. Howard Williams, Nicholas K. Taylor, Sarah McBurney, Kajetan Dolinar
2009 conf
ICONS
Sarah McBurney, Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams
2009 B conf
Mobile Data Management
Claudio Venezia, Nick K. Taylor, M. Howard Williams, Kevin Doolin, Ioanna Roussaki
2008 C conf
ISPA
Elizabeth Papadopoulou, Sarah McBurney, Nick K. Taylor, M. Howard Williams
2008 conf
AmI Workshops
Michael Crotty, Nick K. Taylor, M. Howard Williams, Korbinian Frank, Ioanna Roussaki, Mark Roddy
2008 C conf
ISPA
Sarah McBurney, Elizabeth Papadopoulou, Nick K. Taylor, M. Howard Williams
2008 conf
Web Intelligence
Elizabeth Papadopoulou, Sarah McBurney, Nick K. Taylor, M. Howard Williams
2008 conf
ICONS
Elizabeth Papadopoulou, Sarah McBurney, Nick K. Taylor, M. Howard Williams, Kajetan Dolinar, Martin Neubauer
2007 J jnl
Int. J. Web Inf. Syst.
Alasdair J. G. Gray, Werner Nutt, M. Howard Williams
2007 conf
AICT
Sarah McBurney, M. Howard Williams, Nick K. Taylor, Elizabeth Papadopoulou
2007 J jnl
Web Intell. Agent Syst.
Yuping Yang, M. Howard Williams
2006 C conf
iiWAS
Alasdair J. G. Gray, M. Howard Williams, Werner Nutt
2006 C conf
UIC
Yuping Yang, Fiona Mahon, M. Howard Williams, Tom Pfeifer
2006 conf
ICEBE
Yuping Yang, M. Howard Williams, Rob Pooley, Rick G. Dewar
2006 conf
ICN/ICONS/MCL
Yuping Yang, M. Howard Williams
2006 conf
ICPS
Yuping Yang, Richard M. Everson, Richard G. Dewar, M. Howard Williams
2006 conf
BNCOD
Alasdair J. G. Gray, Werner Nutt, M. Howard Williams
2005 conf
Web Intelligence
Yuping Yang, M. Howard Williams, Lachlan M. MacKinnon, Rob Pooley
2005 J jnl
IEEE Trans. Educ.
Euan W. Dempster, M. Howard Williams, Albert G. Burger, Hamish Taylor
2005 J jnl
Int. J. Bus. Data Commun. Netw.
Yuping Yang, M. Howard Williams
2005 conf
ICPS
M. Howard Williams, Ioanna Roussaki, Maria Strimpakou, Yuping Yang, Lachlan M. MacKinnon, Richard G. Dewar, Nestor Milyaev, Carsten Pils, Miltiades E. Anagnostou
2004 conf
ICWI
Dimitris Halvatzaras, M. Howard Williams
2004 J jnl
Parallel Comput.
Neven Tomov, Euan W. Dempster, M. Howard Williams, Albert G. Burger, Hamish Taylor, Peter J. B. King, Phil Broughton
2004 C conf
SDH
M. Howard Williams, Omar Dreza
2004 conf
BNCOD
Alison Cawsey, Euan W. Dempster, Daniel Pacey, M. Howard Williams, David H. Marwick, Lachlan M. MacKinnon
2004 conf
ICWI
Babak A. Farshchian, Josip Zoric, Lars Mehrmann, Alison Cawsey, M. Howard Williams, Patrick Robertson, Christian Hauser
2004 ed.
BNCOD
M. Howard Williams, Lachlan M. MacKinnon
2003 conf
Web Intelligence
Daniel Pacey, Euan W. Dempster, M. Howard Williams, Alison Cawsey, David H. Marwick, Lachlan M. MacKinnon
2003 J jnl
Distributed Parallel Databases
Euan W. Dempster, Neven Tomov, M. Howard Williams, Hamish Taylor, Albert G. Burger, Philip W. Trinder, Jiang Lü, Phil Broughton
2003 conf
ICWI
M. Howard Williams, Dimitris Halvatzaras, Lars Mehrmann
2003 conf
ICWI
Yuping Yang, M. Howard Williams
2003 conf
ICWI
Daniel Pacey, M. Howard Williams, Euan W. Dempster, Alison Cawsey, David H. Marwick, Lachlan M. MacKinnon
2003 conf
BNCOD
Euan W. Dempster, Daniel Pacey, M. Howard Williams, Alison Cawsey, David H. Marwick, Lachlan M. MacKinnon
2002 B conf
COMPSAC
Yuping Yang, M. Howard Williams
2002 conf
AH
Alison Cawsey, Euan W. Dempster, Diana Bental, Daniel Pacey, M. Howard Williams, Lachlan M. MacKinnon, David H. Marwick
2002 J jnl
Comput. J.
Hazem Turki El Khatib, M. Howard Williams, David H. Marwick, Lachlan M. MacKinnon
2001 J jnl
Inf. Softw. Technol.
Chai Seng Pua, M. Howard Williams, David H. Marwick
2001 J jnl
IEEE Trans. Inf. Technol. Biomed.
M. Howard Williams, Gavin Venters, George Venters, David H. Marwick
2001 conf
BCS HCI/IHM
Diana Bental, Lachlan M. MacKinnon, M. Howard Williams, David H. Marwick, Daniel Pacey, Euan W. Dempster, Alison Cawsey
2000 J jnl
Inf. Softw. Technol.
Hazem Turki El Khatib, M. Howard Williams, Lachlan M. MacKinnon, David H. Marwick
2000 J jnl
Parallel Comput.
Chai Seng Pua, M. Howard Williams, David H. Marwick
2000 conf
Computer Performance Evaluation / TOOLS
Euan W. Dempster, M. Howard Williams, Neven Tomov, Chai Seng Pua, Albert G. Burger, Peter J. B. King
2000 conf
BNCOD
Norman W. Paton, M. Howard Williams, Kosmas Dietrich, Olive Liew, Andrew Dinn, Alan Patrick
1999 conf
MIE
M. Howard Williams, Olive Liew, Ken Boddy, Athanasios Varias, Mairin Eydmann
1999 J jnl
Inf. Syst.
Andrew Dinn, Norman W. Paton, M. Howard Williams
1999 J jnl
Concurr. Pract. Exp.
M. Howard Williams, Euan W. Dempster, Neven Tomov, Chai Seng Pua, Hamish Taylor, Albert G. Burger, Jiang Lü, Phil Broughton
1999 J jnl
Comput. J.
Neven Tomov, Euan W. Dempster, M. Howard Williams, Peter J. B. King, Albert G. Burger
1999 conf
MIE
M. Howard Williams, Gavin Venters, George Venters, David H. Marwick
1999 J jnl
Inf. Softw. Technol.
Alvaro A. A. Fernandes, Andrew Dinn, Norman W. Paton, M. Howard Williams, Olive Liew
1999 ch.
Active Rules in Database Systems
Norman W. Paton, Andrew Dinn, M. Howard Williams
1999 ch.
Active Rules in Database Systems
Andrew Dinn, Norman W. Paton, M. Howard Williams
1999 conf
HPCN Europe
Neven Tomov, Euan W. Dempster, M. Howard Williams, Albert G. Burger, Hamish Taylor, Peter J. B. King, Phil Broughton
1998 J jnl
J. Intell. Inf. Syst.
Lachlan M. MacKinnon, David H. Marwick, M. Howard Williams
1998 J jnl
Knowl. Based Syst.
M. Howard Williams, Kam-Fai Wong
1998 conf
ESM
John Gregor, Albert G. Burger, M. Howard Williams, Mike Gerrard, Paul Wonnaccot
1998 conf
Euro-Par
Euan W. Dempster, Neven Tomov, Jiang Lü, Chai Seng Pua, M. Howard Williams, Albert G. Burger, Hamish Taylor, Phil Broughton
1997 J jnl
New Gener. Comput.
Alvaro A. A. Fernandes, M. Howard Williams, Norman W. Paton
1997 B conf
MASCOTS
Shaoyu Zhou, Neven Tomov, M. Howard Williams, Albert G. Burger, Hamish Taylor
1997 B conf
SOFSEM
M. Howard Williams, Norman W. Paton
1997 A* conf
ICDE
Andrew Dinn, M. Howard Williams, Norman W. Paton
1997 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Jack Campin, Norman W. Paton, M. Howard Williams
1997 J jnl
J. Syst. Integr.
Andrew Dinn, Norman W. Paton, M. Howard Williams, Alvaro A. A. Fernandes, Maria L. Barja
1997 J jnl
Inf. Softw. Technol.
Alvaro A. A. Fernandes, Maria L. Barja, Norman W. Paton, M. Howard Williams
1996 conf
BNCOD
Andrew Dinn, Norman W. Paton, M. Howard Williams, Alvaro A. A. Fernandes
1996 conf
HPCN Europe
M. Howard Williams, Shaoyu Zhou, Hamish Taylor, Neven Tomov
1996 J jnl
Softw. Eng. J.
Shaoyu Zhou, M. Howard Williams, Hamish Taylor
1995 J jnl
Inf. Softw. Technol.
Jack Campin, Norman W. Paton, M. Howard Williams
1995 J jnl
Inf. Syst.
Maria L. Barja, Alvaro A. A. Fernandes, Norman W. Paton, M. Howard Williams, Andrew Dinn, Alia I. Abdelmoty
1995 conf
Rules in Database Systems
Norman W. Paton, Jack Campin, Alvaro A. A. Fernandes, M. Howard Williams
1995 conf
DOOD
Andrew Dinn, Norman W. Paton, M. Howard Williams, Alvaro A. A. Fernandes, Maria L. Barja
1994 A* conf
VLDB
Maria L. Barja, Norman W. Paton, Alvaro A. A. Fernandes, M. Howard Williams, Andrew Dinn
1994 conf
AGDM
Alia I. Abdelmoty, M. Howard Williams
1994 book
Database programming languages - deductive, functional, persistent and object-oriented approaches.
Norman W. Paton, M. Howard Williams, Richard Cooper, Philip W. Trinder
1994 C conf
DEXA
Alia I. Abdelmoty, Norman W. Paton, M. Howard Williams, Alvaro A. A. Fernandes, Maria L. Barja, Andrew Dinn
1994 C conf
ENTER
W. J. Austin, E. K. Hutchinson, John Kalmus, Lachlan M. MacKinnon, Keith G. Jeffery, David H. Marwick, M. Howard Williams, Michael D. Wilson
1994 conf
DAISD
Alvaro A. A. Fernandes, Maria L. Barja, Norman W. Paton, M. Howard Williams, Andrew Dinn, Imara P. Diaz, Alia I. Abdelmoty
1994 ed.
Rules in Database Systems
Norman W. Paton, M. Howard Williams
1994 J jnl
Data Knowl. Eng.
Quinzheng Kong, M. Howard Williams, G. Chen
1993 conf
BNCOD
Alvaro A. A. Fernandes, Maria L. Barja, Norman W. Paton, M. Howard Williams
1993 conf
Rules in Database Systems
Alvaro A. A. Fernandes, Norman W. Paton, M. Howard Williams
1993 J jnl
Inf. Softw. Technol.
Alia I. Abdelmoty, M. Howard Williams, J. M. P. Quinn
1993 conf
Open Distributed Processing
Dirk Lutzebäck, Bernd Mahr, Gavin Venters, M. Howard Williams
1993 conf
SSD
Alia I. Abdelmoty, M. Howard Williams, Norman W. Paton
1993 conf
Rules in Database Systems
Norman W. Paton, Oscar Díaz, M. Howard Williams, Jack Campin, Andrew Dinn, Arturo Jaime
1993 J jnl
Inf. Softw. Technol.
J. Hu, M. Howard Williams
1993 conf
PARLE
Kam-Fai Wong, M. Howard Williams, S. Leunig, Martin L. Kersten, M. Jean-Noel, Béatrice Finance, Benoît Dageville, Michel Couprie, Phil Broughton, Didier Boudigue, Björn Bergsten, Frédéric Andrès
1992 J jnl
Inf. Softw. Technol.
Alvaro A. A. Fernandes, Norman W. Paton, M. Howard Williams, Andrew Bowles
1992 C conf
DEXA
María-Blanca Ibáñez-Espiga, M. Howard Williams
1992 conf
IDS
M. Howard Williams, G. Muirhead
1991 B conf
DASFAA
Kam-Fai Wong, M. Howard Williams
1991 J jnl
Comput. J.
K. Wicovsky, Peter Thanisch, M. Howard Williams
1990 conf
SIGSMALL/PC Symposium
Kam-Fai Wong, M. Howard Williams
1990 J jnl
Comput. J.
K. G. Waugh, M. Howard Williams, Quinzheng Kong, S. Salvini, G. Chen
1990 conf
ALPUK
Subrata Kumar Das, M. Howard Williams
1990 C conf
IPMU
M. Howard Williams, Quinzheng Kong
1989 J jnl
Data Knowl. Eng.
Subrata Kumar Das, M. Howard Williams
1989 A* conf
ISCA
Kam-Fai Wong, M. Howard Williams
1988 J jnl
Comput. J.
M. Howard Williams, K. A. Nicholson
1988 ch.
Prolog and Databases
M. Howard Williams, P. A. Massey, Jim A. Crammond
1988 conf
JCDKB
Kam-Fai Wong, M. Howard Williams
1988 ch.
Prolog and Databases
F. Mouta, M. Howard Williams, J. C. Neves
1988 J jnl
Data Knowl. Eng.
M. Howard Williams, Quinzheng Kong
1988 conf
SIGSMALL/PC
Kam-Fai Wong, M. Howard Williams
1988 J jnl
Knowl. Based Syst.
M. Howard Williams, G. Chen, D. Ferbrache, P. A. Massey, S. Salvini, Hamish Taylor, Kam-Fai Wong
1987 J jnl
Data Knowl. Eng.
P. Chisholm, G. Chen, D. Ferbrache, Peter Thanisch, M. Howard Williams
1986 J jnl
Softw. Pract. Exp.
M. Howard Williams, I. M. Pattison, J. C. Neves
1986 J jnl
Comput. J.
M. Howard Williams, J. Riddall
1986 J jnl
Inf. Process. Lett.
G. Chen, M. Howard Williams
1986 J jnl
Comput. J.
M. Howard Williams, G. Chen
1985 J jnl
Comput. J.
M. Howard Williams
1985 J jnl
Comput. J.
M. Howard Williams, G. Chen
1985 J jnl
Comput. J.
M. Howard Williams
1984 J jnl
IEEE Computer Graphics and Applications
J. C. González, M. Howard Williams, I. E. Aitchison
1984 J jnl
Comput. J.
M. Howard Williams, K. T. Milne
1983 J jnl
Comput. J.
M. Howard Williams
1983 J jnl
Inf. Process. Lett.
M. Howard Williams
1983 B conf
Logic Programming Workshop
M. Howard Williams, J. C. Neves, Stuart Oliver Anderson
1983 J jnl
Inf. Process. Lett.
M. Howard Williams
1983 B conf
Logic Programming Workshop
J. C. Neves, M. Howard Williams
1982 J jnl
Comput. J.
M. Howard Williams
1982 J jnl
ACM Trans. Program. Lang. Syst.
M. Howard Williams
1982 J jnl
Softw. Pract. Exp.
M. Howard Williams
1982 J jnl
Microprocess. Microsystems
M. Howard Williams, A. J. Stewart
1982 J jnl
Comput. J.
M. Howard Williams
1981 J jnl
Inf. Process. Lett.
M. Howard Williams
1981 J jnl
Microprocess. Microsystems
M. Howard Williams
1981 J jnl
Comput. Lang.
M. Howard Williams
1980 J jnl
Comput. Lang.
M. Howard Williams
1980 J jnl
Microprocess. Microsystems
M. Howard Williams, A. G. Sartori-Angus, G. P. Stromberg
1980 J jnl
Inf. Process. Lett.
M. Howard Williams
1980 J jnl
Inf. Process. Lett.
M. Howard Williams
1979 J jnl
Inf. Process. Lett.
M. Howard Williams, A. R. Bulmer
1979 J jnl
Comput. J.
M. Howard Williams
1979 J jnl
Softw. Pract. Exp.
M. Howard Williams
1978 J jnl
Comput. J.
M. Howard Williams, Elizabeth V. C. Fielding
1978 J jnl
Comput. J.
M. Howard Williams, H. L. Ossher
1978 J jnl
Comput. J.
M. Howard Williams
1978 J jnl
Softw. Pract. Exp.
M. Howard Williams, A. R. Bulmer
1978 conf
ACM Annual Conference (2)
M. Howard Williams
1977 J jnl
Softw. Pract. Exp.
M. Howard Williams, A. R. Bulmer
1977 J jnl
Inf. Process. Lett.
M. Howard Williams
1977 J jnl
Comput. J.
M. Howard Williams
1976 J jnl
ACM SIGPLAN Notices
M. Howard Williams
1975 J jnl
Comput. J.
M. Howard Williams, H. L. Ossher
1975 J jnl
ACM SIGPLAN Notices
M. Howard Williams
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