Hamish Cunningham

97 papers A* 3A 4B 17C 3Misc 9Journal 24Unranked 33
YearRankTypeTitle / Venue / Authors
2024 conf
UCAmI
Mary Hewitt, Hamish Cunningham
2022 J jnl
CoRR
Mary Hewitt, Hamish Cunningham
2022 C conf
IoTBDS
Steph Rudd, Hamish Cunningham
2022 Misc conf
FRUCT
Steph Rudd, Hamish Cunningham
2021 Misc conf
FRUCT
Steph Rudd, Hamish Cunningham
2021 J jnl
CoRR
Steph Rudd, Hamish Cunningham
2015 J jnl
J. Web Semant.
Valentin Tablan, Kalina Bontcheva, Ian Roberts, Hamish Cunningham
2014 conf
ESWC (Satellite Events)
Marin Dimitrov, Hamish Cunningham, Ian Roberts, Petar Kostov, Alex Simov, Philippe Rigaux, Helen Lippell
2013 conf
ACL (Conference System Demonstrations)
Valentin Tablan, Kalina Bontcheva, Ian Roberts, Hamish Cunningham, Marin Dimitrov
2013 J jnl
Lang. Resour. Evaluation
Kalina Bontcheva, Hamish Cunningham, Ian Roberts, Angus Roberts, Valentin Tablan, Niraj Aswani, Genevieve Gorrell
2013 J jnl
PLoS Comput. Biol.
Hamish Cunningham, Valentin Tablan, Angus Roberts, Kalina Bontcheva
2013 J jnl
J. Web Semant.
Danica Damljanovic, Milan Agatonovic, Hamish Cunningham, Kalina Bontcheva
2013 conf
MedInfo
Niraj Aswani, Thomas Beckers, Erich Birngruber, Célia Boyer, Andreas Burner, Jakub Bystron, Khalid Choukri, Sarah Cruchet, Hamish Cunningham, Jan Dedek, Ljiljana Dolamic, René Donner, Sebastian Dungs, Ivan Eggel, Antonio Foncubierta-Rodríguez, Norbert Fuhr, Adam Funk, Alba Garcia Seco de Herrera, Arnaud Gaudinat, Georgi Georgiev, Julien Gobeill, Lorraine Goeuriot, Paz Gomez, Robert Mark Greenwood, Manfred Gschwandtner, Allan Hanbury, Jan Hajic, Jaroslava Hlavácová, Markus Holzer, Gareth J. F. Jones, Blanca Jordan, Matthias Jordan, Klemens Kaderk, Franz Kainberger, Liadh Kelly, Sascha Kriewel, Marlene Kritz, Georg Langs, Nolan Lawson, Dimitrios Markonis, Iván Martínez, Vassil Momtchev, Alexandre Masselot, Hélène Mazo, Henning Müller, João R. M. Palotti, Pavel Pecina, Konstantin Pentchev, Deyan Peychev, Natalia Pletneva, Diana Pottecher, Angus Roberts, Patrick Ruch, Alexander Sachs, Matthias Samwald, Priscille Schneller, Veronika Stefanov, Miguel Angel Tinte, Zdenka Uresová, Alejandro Vargas, Dina Vishnyakova
2013 conf
PROMISE Winter School
Kalina Bontcheva, Valentin Tablan, Hamish Cunningham
2012 J jnl
CoRR
Hamish Cunningham
2011 J jnl
Dagstuhl Reports
Hamish Cunningham, Norbert Fuhr, Benno Stein
2011 conf
ESWC Workshops
Danica Damljanovic, Milan Agatonovic, Hamish Cunningham
2011 ch.
Current Challenges in Patent Information Retrieval
Hamish Cunningham, Valentin Tablan, Ian Roberts, Mark A. Greenwood, Niraj Aswani
2011 conf
ESWC Workshops
Danica Damljanovic, Johann Petrak, Mihai Lupu, Hamish Cunningham, Mats Carlsson, Gunnar Engstrom, Bo Andersson
2011 conf
RED@ESWC
Danica Damljanovic, Johann Petrak, Mihai Lupu, Hamish Cunningham, Mats Carlsson, Gunnar Engstrom, Bo Andersson
2011 ch.
Handbook of Semantic Web Technologies
Kalina Bontcheva, Hamish Cunningham
2010 ed.
IRFC
Hamish Cunningham, Allan Hanbury, Stefan M. Rüger
2010 B conf
LREC
Danica Damljanovic, Milan Agatonovic, Hamish Cunningham
2010 conf
ESWC (1)
Danica Damljanovic, Milan Agatonovic, Hamish Cunningham
2010 conf
IRFC
Hamish Cunningham, Allan Hanbury, Stefan M. Rüger
2010 J jnl
Int. J. Semantic Web Inf. Syst.
Brian Davis, Pradeep Dantuluri, Siegfried Handschuh, Hamish Cunningham
2009 J jnl
Nat. Lang. Eng.
Yaoyong Li, Kalina Bontcheva, Hamish Cunningham
2009 conf
CNL (Pre-Proceedings)
Brian Davis, Pradeep Varma, Siegfried Handschuh, Laura Dragan, Hamish Cunningham
2009 B conf
ESWC
Brian Davis, Pradeep Varma, Siegfried Handschuh, Laura Dragan, Hamish Cunningham
2009 conf
CNL
Brian Davis, Pradeep Dantuluri, Laura Dragan, Siegfried Handschuh, Hamish Cunningham
2008 B conf
LREC
Milena Yankova, Horacio Saggion, Hamish Cunningham
2008 conf
OBI
Milena Yankova, Horacio Saggion, Hamish Cunningham
2008 J jnl
SIGIR Forum
Yaoyong Li, Hamish Cunningham
2008 conf
PaIR
Milan Agatonovic, Niraj Aswani, Kalina Bontcheva, Hamish Cunningham, Thomas Heitz, Yaoyong Li, Ian Roberts, Valentin Tablan
2008 Misc conf
ISWC
Brian Davis, Ahmad Ali Iqbal, Adam Funk, Valentin Tablan, Kalina Bontcheva, Hamish Cunningham, Siegfried Handschuh
2008 conf
ICSC
Dieter Fensel, Frank van Harmelen, Bo Andersson, Paul Brennan, Hamish Cunningham, Emanuele Della Valle, Florian Fischer, Zhisheng Huang, Atanas Kiryakov, Tony Kyung-il Lee, Lael Schooler, Volker Tresp, Stefan Wesner, Michael Witbrock, Ning Zhong
2007 conf
ISWC/ASWC
Adam Funk, Valentin Tablan, Kalina Bontcheva, Hamish Cunningham, Brian Davis, Siegfried Handschuh
2007 conf
NTCIR
Yaoyong Li, Kalina Bontcheva, Hamish Cunningham
2007 conf
EVIA@NTCIR
Yaoyong Li, Hamish Cunningham
2007 conf
NTCIR
Yaoyong Li, Kalina Bontcheva, Hamish Cunningham
2006 B conf
ESWC
Ting Wang, Yaoyong Li, Kalina Bontcheva, Hamish Cunningham, Ji Wang
2006 B conf
LREC
Valentin Tablan, Wim Peters, Diana Maynard, Hamish Cunningham
2006 conf
SAAW@ISWC
Brian Davis, Siegfried Handschuh, Hamish Cunningham, Valentin Tablan
2006 Misc conf
ISWC
Niraj Aswani, Kalina Bontcheva, Hamish Cunningham
2006 B conf
LREC
Valentin Tablan, Tamara Polajnar, Hamish Cunningham, Kalina Bontcheva
2005 conf
Web Intelligence
Ting Wang, Diana Maynard, Wim Peters, Kalina Bontcheva, Hamish Cunningham
2005 J jnl
J. Knowl. Manag.
Hamish Cunningham, Kalina Bontcheva, Yaoyong Li
2005 conf
SIGHAN@IJCNLP 2005
Yaoyong Li, Chuanjiang Miao, Kalina Bontcheva, Hamish Cunningham
2005 B conf
CoNLL
Yaoyong Li, Kalina Bontcheva, Hamish Cunningham
2005 A* conf
WWW
Mike Dowman, Valentin Tablan, Hamish Cunningham, Borislav Popov
2004 Misc conf
AIMSA
Diana Maynard, Milena Yankova, Niraj Aswani, Hamish Cunningham
2004 B conf
LREC
Diana Maynard, Kalina Bontcheva, Hamish Cunningham
2004 J jnl
Lit. Linguistic Comput.
Paul Baker, Andrew Hardie, Tony McEnery, Richard Xiao, Kalina Bontcheva, Hamish Cunningham, Robert J. Gaizauskas, Oana Hamza, Diana Maynard, Valentin Tablan, Cristian Ursu, B. D. Jayaram, Mark Leisher
2004 J jnl
Nat. Lang. Eng.
Kalina Bontcheva, Valentin Tablan, Diana Maynard, Hamish Cunningham
2004 B conf
LREC
Louise Guthrie, Roberto Basili, Fabio Massimo Zanzotto, Kalina Bontcheva, Hamish Cunningham, David Guthrie, Jia Cui, Marco Cammisa, Jerry Cheng-Chieh Liu, Cassia Farria Martin, Kristiyan Haralambiev, Martin Holub, Klaus Macherey, Frederick Jelinek
2004 J jnl
Data Knowl. Eng.
Horacio Saggion, Hamish Cunningham, Kalina Bontcheva, Diana Maynard, Oana Hamza, Yorick Wilks
2004 C conf
NLDB
Mary McGee Wood, Susannah J. Lydon, Valentin Tablan, Diana Maynard, Hamish Cunningham
2004 conf
Deterministic and Statistical Methods in Machine Learning
Yaoyong Li, Kalina Bontcheva, Hamish Cunningham
2004 J jnl
Nat. Lang. Eng.
Hamish Cunningham, Donia Scott
2003 A conf
EACL
Horacio Saggion, Hamish Cunningham, Jan Kuper, Thierry Declerck, Peter Wittenburg
2003 A* conf
IJCAI
Jan Kuper, Horacio Saggion, Hamish Cunningham, Thierry Declerck, Franciska de Jong, Dennis Reidsma, Yorick Wilks, Peter Wittenburg
2003 A conf
EACL
Diana Maynard, Hamish Cunningham, Kalina Bontcheva
2003 conf
NER@ACL
Diana Maynard, Valentin Tablan, Hamish Cunningham
2003 J jnl
ACM Trans. Asian Lang. Inf. Process.
Diana Maynard, Valentin Tablan, Kalina Bontcheva, Hamish Cunningham
2003 A conf
EACL
Horacio Saggion, Kalina Bontcheva, Hamish Cunningham
2003 Misc conf
RANLP
Mary McGee Wood, Susannah J. Lydon, Valentin Tablan, Diana Maynard, Hamish Cunningham
2002 B conf
LREC
Valentin Tablan, Cristian Ursu, Kalina Bontcheva, Hamish Cunningham, Diana Maynard, Oana Hamza, Tony McEnery, Paul Baker, Mark Leisher
2002 A* conf
ACL
Hamish Cunningham, Diana Maynard, Kalina Bontcheva, Valentin Tablan
2002 C conf
NLDB
Horacio Saggion, Hamish Cunningham, Kalina Bontcheva, Diana Maynard, Cristian Ursu, Oana Hamza, Yorick Wilks
2002 Misc conf
AIMSA
Diana Maynard, Hamish Cunningham, Kalina Bontcheva, Marin Dimitrov
2002 J jnl
Nat. Lang. Eng.
Diana Maynard, Valentin Tablan, Hamish Cunningham, Cristian Ursu, Horacio Saggion, Kalina Bontcheva, Yorick Wilks
2002 conf
DEXA Workshops
Kalina Bontcheva, Hamish Cunningham, Diana Maynard, Valentin Tablan, Horacio Saggion
2002 B conf
LREC
Paul Baker, Andrew Hardie, Tony McEnery, Hamish Cunningham, Robert J. Gaizauskas
2002 B conf
LREC
Horacio Saggion, Hamish Cunningham, Diana Maynard, Kalina Bontcheva, Oana Hamza, Cristian Ursu, Yorick Wilks
2002 J jnl
Comput. Humanit.
Hamish Cunningham
2002 B conf
LREC
Katerina Pastra, Diana Maynard, Oana Hamza, Hamish Cunningham, Yorick Wilks
2002 conf
ECDL
Kalina Bontcheva, Hamish Cunningham
2002 conf
ECDL
Kalina Bontcheva, Diana Maynard, Hamish Cunningham, Horacio Saggion
2001 conf
HTLKM@ACL
Thierry Declerck, Peter Wittenburg, Hamish Cunningham
2001 conf
HTLKM@ACL
Kalina Bontcheva, Christopher Brewster, Fabio Ciravegna, Hamish Cunningham, Louise Guthrie, Robert J. Gaizauskas, Yorick Wilks
2000 B conf
LREC
Hamish Cunningham, Kalina Bontcheva, Valentin Tablan, Yorick Wilks
2000
Hamish Cunningham
1999 J jnl
Nat. Lang. Eng.
Hamish Cunningham
1998 B conf
CoNLL
Hamish Cunningham, Mark Stevenson, Yorick Wilks
1998 A conf
ECAI
Mark Stevenson, Hamish Cunningham, Yorick Wilks
1998 Misc conf
MUC
Kevin Humphreys, Robert J. Gaizauskas, Saliha Azzam, Charles Huyck, Brian Mitchell, Hamish Cunningham, Yorick Wilks
1997 conf
ANLP
Hamish Cunningham, Kevin Humphreys, Robert J. Gaizauskas, Yorick Wilks
1997 J jnl
CoRR
Hamish Cunningham
1997 J jnl
CoRR
Hamish Cunningham, Kevin Humphreys, Robert J. Gaizauskas, Yorick Wilks
1997 conf
ANLP
Hamish Cunningham, Kevin Humphreys, Robert J. Gaizauskas, Yorick Wilks
1997 conf
VL
Peter J. Rodgers, Robert J. Gaizauskas, Kevin Humphreys, Hamish Cunningham
1996 J jnl
CoRR
Hamish Cunningham, Robert J. Gaizauskas, Yorick Wilks
1996 B conf
COLING
Hamish Cunningham, Yorick Wilks, Robert J. Gaizauskas
1996 B conf
ICTAI
Robert J. Gaizauskas, Hamish Cunningham, Yorick Wilks, Peter J. Rodgers, Kevin Humphreys
1996 J jnl
CoRR
Hamish Cunningham, Yorick Wilks, Robert J. Gaizauskas
1996 conf
TIPSTER
Hamish Cunningham, Kevin Humphreys, Robert J. Gaizauskas, Yorick Wilks
1995 Misc conf
MUC
Robert J. Gaizauskas, Kevin Humphreys, Hamish Cunningham, Yorick Wilks
tests/integration/test_pe_extractors.py
← Index tests/integration/test_pe_extractors.py python
"""
Integration tests for PE-specific extractors.
"""
import pytest
from unittest.mock import Mock, patch, MagicMock

pytestmark = [pytest.mark.integration, pytest.mark.pe]


# ============================================================================
# PEFeaturesExtractor Tests
# ============================================================================

class TestPEFeaturesExtractor:
    """Tests for PEFeaturesExtractor class."""

    def test_extract_valid_pe(self, pe_binary_path, mock_logger):
        """Test extracting features from valid PE file."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor
        from redb.models.dataclasses import PE

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            assert result is not None
            assert isinstance(result, PE)

    def test_extract_pe_type(self, pe_binary_path, mock_logger):
        """Test PE type detection (DLL, EXE, DRIVER)."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            assert result.type in ["DLL", "EXE", "DRIVER"]

    def test_extract_architecture(self, pe_binary_path, mock_logger):
        """Test architecture detection."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Architecture should be detected
            assert result.architecture is not None

    def test_extract_entry_point(self, pe_binary_path, mock_logger):
        """Test entry point extraction."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Entry point should be a hex string
            assert result.entry_point.startswith("0x")

    def test_extract_compilation_time(self, pe_binary_path, mock_logger):
        """Test compilation time extraction."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Compilation time should be an integer timestamp
            assert isinstance(result.compilation_time, int)
            assert result.compilation_time_utc is not None

    def test_extract_dotnet_detection(self, pe_binary_path, mock_logger):
        """Test .NET detection."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Should be True for the test .NET binary
            assert isinstance(result.is_dotnet, bool)
            assert result.is_dotnet is True  # Test file is .NET

    def test_extract_headers(self, pe_binary_path, mock_logger):
        """Test header extraction."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            assert result.dos_header is not None
            assert result.nt_header is not None
            assert result.file_header is not None
            assert result.optional_header is not None

    def test_extract_counts(self, pe_binary_path, mock_logger):
        """Test section/import/export counts."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            assert isinstance(result.number_of_sections, int)
            assert isinstance(result.number_of_imports, int)
            assert isinstance(result.number_of_exports, int)
            assert isinstance(result.number_of_resources, int)

    def test_extract_rich_header(self, pe_binary_path, mock_logger):
        """Test Rich header extraction."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Rich header may or may not be present
            # If present, should be JSON string
            if result.rich_header_dump is not None:
                assert isinstance(result.rich_header_dump, str)

    def test_extract_version_info(self, pe_binary_path, mock_logger):
        """Test version info extraction."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # Version info may or may not be present
            if result.version_info is not None:
                assert isinstance(result.version_info, list)


# ============================================================================
# PEImportExtractor Tests
# ============================================================================

class TestPEImportExtractor:
    """Tests for PEImportExtractor class."""

    def test_extract_imports(self, pe_binary_path, mock_logger):
        """Test import extraction."""
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor
        from redb.models.dataclasses import PEImport

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None:
                assert isinstance(result, PEImport)
                assert isinstance(result.pe_imports_total, int)

    def test_extract_import_libraries(self, pe_binary_path, mock_logger):
        """Test import library extraction."""
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None and result.pe_import_libraryName is not None:
                assert isinstance(result.pe_import_libraryName, list)

    def test_extract_import_functions(self, pe_binary_path, mock_logger):
        """Test import function extraction."""
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None and result.pe_import_functions is not None:
                assert isinstance(result.pe_import_functions, list)

    def test_prepare_export_clickhouse(self, pe_binary_path, mock_logger):
        """Test ClickHouse export preparation."""
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.prepare_export_data("ClickHouseExporter")

            if result is not None:
                data, column_names, column_type_names = result
                assert 'library_name' in column_names
                assert 'function_name' in column_names


# ============================================================================
# PESectionExtractor Tests
# ============================================================================

class TestPESectionExtractor:
    """Tests for PESectionExtractor class."""

    def test_extract_sections(self, pe_binary_path, mock_logger):
        """Test section extraction."""
        from redb.extractors.pe_extractors.pe_sections import PESectionExtractor
        from redb.models.dataclasses import PESection

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            assert result is not None
            assert isinstance(result, list)
            assert len(result) > 0
            assert isinstance(result[0], PESection)

    def test_section_properties(self, pe_binary_path, mock_logger):
        """Test section property extraction."""
        from redb.extractors.pe_extractors.pe_sections import PESectionExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None and len(result) > 0:
                section = result[0]
                assert section.section_name is not None
                assert section.section_entropy >= 0
                assert section.section_sha256 is not None
                assert section.section_md5 is not None
                assert section.section_size >= 0

    def test_section_entropy_range(self, pe_binary_path, mock_logger):
        """Test that section entropy is in valid range."""
        from redb.extractors.pe_extractors.pe_sections import PESectionExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None:
                for section in result:
                    assert 0 <= section.section_entropy <= 8

    def test_prepare_export_clickhouse(self, pe_binary_path, mock_logger):
        """Test ClickHouse export preparation."""
        from redb.extractors.pe_extractors.pe_sections import PESectionExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.prepare_export_data("ClickHouseExporter")

            if result is not None:
                data, column_names, column_type_names = result
                assert 'section_name' in column_names
                assert 'section_entropy' in column_names
                assert 'section_sha256' in column_names


# ============================================================================
# PEResourceExtractor Tests
# ============================================================================

class TestPEResourceExtractor:
    """Tests for PEResourceExtractor class."""

    def test_extract_resources(self, pe_binary_path, mock_logger):
        """Test resource extraction."""
        from redb.extractors.pe_extractors.pe_resources import PEResourceExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # May be None if no resources
            if result is not None:
                assert isinstance(result, list)

    def test_resource_properties(self, pe_binary_path, mock_logger):
        """Test resource property extraction."""
        from redb.extractors.pe_extractors.pe_resources import PEResourceExtractor
        from redb.models.dataclasses import PEResource

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            if result is not None and len(result) > 0:
                resource = result[0]
                assert isinstance(resource, PEResource)
                assert resource.resource_type is not None


# ============================================================================
# PEOverlayExtractor Tests
# ============================================================================

class TestPEOverlayExtractor:
    """Tests for PEOverlayExtractor class."""

    def test_extract_overlay(self, pe_binary_path, mock_logger):
        """Test overlay extraction."""
        from redb.extractors.pe_extractors.pe_overlay import PEOverlayExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # May be None if no overlay
            # If present, should have overlay properties
            if result is not None:
                assert hasattr(result, 'overlay_size')

    def test_has_overlay_check(self, pe_binary_path, mock_logger):
        """Test overlay detection."""
        from redb.extractors.pe_extractors.pe_overlay import PEOverlayExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            has_overlay = extractor._has_overlay()
            assert isinstance(has_overlay, bool)


# ============================================================================
# PESignatureExtractor Tests
# ============================================================================

class TestPESignatureExtractor:
    """Tests for PESignatureExtractor class."""

    def test_extract_signature(self, pe_binary_path, mock_logger):
        """Test signature extraction."""
        from redb.extractors.pe_extractors.pe_signature import PESignatureExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # May be None if not signed
            # Result type depends on implementation

    def test_is_signed_check(self, pe_binary_path, mock_logger):
        """Test signature detection."""
        from redb.extractors.pe_extractors.pe_signature import PESignatureExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            is_signed = extractor._is_signed()
            assert isinstance(is_signed, bool)


# ============================================================================
# PEDotNetExtractor Tests
# ============================================================================

class TestPEDotNetExtractor:
    """Tests for PEDotNetExtractor class."""

    def test_extract_dotnet(self, pe_binary_path, mock_logger):
        """Test .NET metadata extraction."""
        from redb.extractors.pe_extractors.pe_dotnet import PEDotNetExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # The test file is a .NET binary
            if extractor._check_dotnet():
                assert result is not None

    def test_check_dotnet(self, pe_binary_path, mock_logger):
        """Test .NET detection."""
        from redb.extractors.pe_extractors.pe_dotnet import PEDotNetExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            is_dotnet = extractor._check_dotnet()
            assert isinstance(is_dotnet, bool)
            # Test file should be .NET
            assert is_dotnet is True


# ============================================================================
# PEInconsistencyTestsExtractor Tests
# ============================================================================

class TestPEInconsistencyTestsExtractor:
    """Tests for PEInconsistencyTestsExtractor class."""

    def test_extract_inconsistency_tests(self, pe_binary_path, mock_logger):
        """Test inconsistency tests extraction."""
        from redb.extractors.pe_extractors.pe_inconsistency_tests import PEInconstistencyTestsExtractor as PEInconsistencyTestsExtractor

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # extract() returns True if tests were performed, False otherwise
            # The actual test results are stored in extractor.pe_inconsistency_tests
            # and extractor.dotnet_inconsistency_tests
            assert result in (True, False)

            if result:
                # Check that test results were stored
                assert extractor.pe_inconsistency_tests is not None or extractor.dotnet_inconsistency_tests is not None


# ============================================================================
# PEExtraFindings Tests
# ============================================================================

class TestPEExtraFindings:
    """Tests for PEExtraFindings class."""

    def test_extract_extra_findings(self, pe_binary_path, mock_logger):
        """Test extra findings extraction."""
        from redb.extractors.pe_extractors.pe_extra_findings import PEExtraFindings

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

            if extractor.pe is None:
                pytest.skip("PE parsing failed")

            result = extractor.extract()

            # May return None or list of findings
            if result is not None:
                assert isinstance(result, list)


# ============================================================================
# Integration Tests
# ============================================================================

class TestPEExtractorIntegration:
    """Integration tests for PE extractors."""

    def test_all_extractors_same_pe_object(self, pe_binary_path, mock_logger, pe_object):
        """Test that extractors can share the same PE object."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor
        from redb.extractors.pe_extractors.pe_sections import PESectionExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            # Create extractors sharing the same PE object
            features_ext = PEFeaturesExtractor(pe_binary_path, mock_logger, pe=pe_object)
            imports_ext = PEImportExtractor(pe_binary_path, mock_logger, pe=pe_object)
            sections_ext = PESectionExtractor(pe_binary_path, mock_logger, pe=pe_object)

            # All should use the same PE object
            assert features_ext.pe is pe_object
            assert imports_ext.pe is pe_object
            assert sections_ext.pe is pe_object

            # All should extract successfully
            features_result = features_ext.extract()
            imports_result = imports_ext.extract()
            sections_result = sections_ext.extract()

            assert features_result is not None
            # imports and sections may be None if not present

    def test_hash_consistency_across_extractors(self, pe_binary_path, mock_logger):
        """Test that hashes are consistent across all extractors."""
        from redb.extractors.pe_extractors.pe_features import PEFeaturesExtractor
        from redb.extractors.pe_extractors.pe_imports import PEImportExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            features_ext = PEFeaturesExtractor(pe_binary_path, mock_logger)
            imports_ext = PEImportExtractor(pe_binary_path, mock_logger)

            # Hashes should be the same
            assert features_ext.sha256 == imports_ext.sha256
            assert features_ext.md5 == imports_ext.md5
            assert features_ext.sha1 == imports_ext.sha1