Manu Sridharan

86 papers A* 21A 21B 2Journal 22Unranked 17
YearRankTypeTitle / Venue / Authors
2025 J jnl
Proc. ACM Softw. Eng.
Nima Karimipour, Erfan Arvan, Martin Kellogg, Manu Sridharan
2025 J jnl
CoRR
Nima Karimipour, Michael Pradel, Martin Kellogg, Manu Sridharan
2025 J jnl
Int. J. Softw. Tools Technol. Transf.
Narges Shadab, Pritam M. Gharat, Shrey Tiwari, Michael D. Ernst, Martin Kellogg, Shuvendu K. Lahiri, Akash Lal, Manu Sridharan
2025 J jnl
Dagstuhl Artifacts Ser.
Nima Karimipour, Kanak Das, Manu Sridharan, Behnaz Hassanshahi
2025 J jnl
CoRR
Nima Karimipour, Kanak Das, Manu Sridharan, Behnaz Hassanshahi
2025 A conf
ECOOP
Nima Karimipour, Kanak Das, Manu Sridharan, Behnaz Hassanshahi
2025 A* conf
SP
Guoren Li, Manu Sridharan, Zhiyun Qian
2025 A* conf
ASE
Sanjay Malakar, Michael D. Ernst, Martin Kellogg, Manu Sridharan
2025 J jnl
CoRR
Sanjay Malakar, Michael D. Ernst, Martin Kellogg, Manu Sridharan
2024 ed.
SPLASH Companion
Manu Sridharan
2024 A* conf
USENIX Security Symposium
Yizhuo Zhai, Zhiyun Qian, Chengyu Song, Manu Sridharan, Trent Jaeger, Paul L. Yu, Srikanth V. Krishnamurthy
2024 A conf
ECOOP
Madhurima Chakraborty, Aakash Gnanakumar, Manu Sridharan, Anders Møller
2024 J jnl
ACM Trans. Program. Lang. Syst.
Benno Stein, Bor-Yuh Evan Chang, Manu Sridharan
2023 J jnl
CoRR
Narges Shadab, Pritam M. Gharat, Shrey Tiwari, Michael D. Ernst, Martin Kellogg, Shuvendu K. Lahiri, Akash Lal, Manu Sridharan
2023 J jnl
Proc. ACM Program. Lang.
Narges Shadab, Pritam M. Gharat, Shrey Tiwari, Michael D. Ernst, Martin Kellogg, Shuvendu K. Lahiri, Akash Lal, Manu Sridharan
2023 conf
ESEC/SIGSOFT FSE
Nima Karimipour, Justin Pham, Lazaro Clapp, Manu Sridharan
2022 J jnl
Dagstuhl Artifacts Ser.
Martin Kellogg, Narges Shadab, Manu Sridharan, Michael D. Ernst
2022 A conf
ECOOP
Martin Kellogg, Narges Shadab, Manu Sridharan, Michael D. Ernst
2022 J jnl
Dagstuhl Artifacts Ser.
Madhurima Chakraborty, Renzo Olivares, Manu Sridharan, Behnaz Hassanshahi
2022 J jnl
CoRR
Madhurima Chakraborty, Renzo Olivares, Manu Sridharan, Behnaz Hassanshahi
2022 A conf
ECOOP
Madhurima Chakraborty, Renzo Olivares, Manu Sridharan, Behnaz Hassanshahi
2022 A* conf
NDSS
Yizhuo Zhai, Yu Hao, Zheng Zhang, Weiteng Chen, Guoren Li, Zhiyun Qian, Chengyu Song, Manu Sridharan, Srikanth V. Krishnamurthy, Trent Jaeger, Paul L. Yu
2022 J jnl
Sci. Comput. Program.
Manu Sridharan
2021 A ed.
ECOOP
Anders Møller, Manu Sridharan
2021 J jnl
CoRR
Benno Stein, Bor-Yuh Evan Chang, Manu Sridharan
2021 A* conf
PLDI
Benno Stein, Bor-Yuh Evan Chang, Manu Sridharan
2021 A conf
RAID
Sri Shaila G, Ahmad Darki, Michalis Faloutsos, Nael B. Abu-Ghazaleh, Manu Sridharan
2021 conf
ESEC/SIGSOFT FSE
Martin Kellogg, Narges Shadab, Manu Sridharan, Michael D. Ernst
2020 J jnl
Proc. ACM Program. Lang.
Umar Farooq, Zhijia Zhao, Manu Sridharan, Iulian Neamtiu
2020 conf
ICSE (SEIP)
Murali Krishna Ramanathan, Lazaro Clapp, Rajkishore Barik, Manu Sridharan
2020 A* conf
ICSE
Martin Kellogg, Manli Ran, Manu Sridharan, Martin Schäf, Michael D. Ernst
2019 conf
CSET @ USENIX Security Symposium
Sri Shaila G, Ahmad Darki, Michalis Faloutsos, Nael B. Abu-Ghazaleh, Manu Sridharan
2019 J jnl
CoRR
Subarno Banerjee, Lazaro Clapp, Manu Sridharan
2019 conf
ESEC/SIGSOFT FSE
Subarno Banerjee, Lazaro Clapp, Manu Sridharan
2019 J jnl
Proc. ACM Program. Lang.
Rajkishore Barik, Manu Sridharan, Murali Krishna Ramanathan, Milind Chabbi
2018 J jnl
CoRR
Benno Stein, Lazaro Clapp, Manu Sridharan, Bor-Yuh Evan Chang
2018 A* conf
ASE
Benno Stein, Lazaro Clapp, Manu Sridharan, Bor-Yuh Evan Chang
2017 conf
CAV (2)
Andrei Marian Dan, Manu Sridharan, Satish Chandra, Jean-Baptiste Jeannin, Martin T. Vechev
2017 conf
Onward!
Julie L. Newcomb, Satish Chandra, Jean-Baptiste Jeannin, Cole Schlesinger, Manu Sridharan
2017 A* conf
ICSE
Christoffer Quist Adamsen, Anders Møller, Rezwana Karim, Manu Sridharan, Frank Tip, Koushik Sen
2016 A conf
OOPSLA
Calvin Loncaric, Satish Chandra, Cole Schlesinger, Manu Sridharan
2016 J jnl
CoRR
Esben Andreasen, Colin S. Gordon, Satish Chandra, Manu Sridharan, Frank Tip, Koushik Sen
2016 A conf
ECOOP
Esben Andreasen, Colin S. Gordon, Satish Chandra, Manu Sridharan, Frank Tip, Koushik Sen
2016 J jnl
CoRR
Satish Chandra, Colin S. Gordon, Jean-Baptiste Jeannin, Cole Schlesinger, Manu Sridharan, Frank Tip, Young-Il Choi
2016 A conf
OOPSLA
Satish Chandra, Colin S. Gordon, Jean-Baptiste Jeannin, Cole Schlesinger, Manu Sridharan, Frank Tip, Young-Il Choi
2015 A conf
ISSTA
Liang Gong, Michael Pradel, Manu Sridharan, Koushik Sen
2015 J jnl
Commun. ACM
Benjamin Livshits, Manu Sridharan, Yannis Smaragdakis, Ondrej Lhoták, José Nelson Amaral, Bor-Yuh Evan Chang, Samuel Z. Guyer, Uday P. Khedker, Anders Møller, Dimitrios Vardoulakis
2015 conf
ESEC/SIGSOFT FSE
Simon Holm Jensen, Manu Sridharan, Koushik Sen, Satish Chandra
2015 conf
ESEC/SIGSOFT FSE
Stefan Heule, Manu Sridharan, Satish Chandra
2015 A conf
OOPSLA
Sam Blackshear, Bor-Yuh Evan Chang, Manu Sridharan
2014 conf
WODA+PERTEA@ISSTA
Manu Sridharan
2014 A conf
OOPSLA
Cosmin Radoi, Stephen J. Fink, Rodric M. Rabbah, Manu Sridharan
2013 ch.
Aliasing in Object-Oriented Programming
Manu Sridharan, Satish Chandra, Julian Dolby, Stephen J. Fink, Eran Yahav
2013 ch.
Aliasing in Object-Oriented Programming
Manu Sridharan
2013 A* conf
PLDI
Max Schäfer, Manu Sridharan, Julian Dolby, Frank Tip
2013 A conf
OOPSLA
Veselin Raychev, Martin T. Vechev, Manu Sridharan
2013 A* conf
ICSE
Asger Feldthaus, Max Schäfer, Manu Sridharan, Julian Dolby, Frank Tip
2013 J jnl
Dagstuhl Reports
Ondrej Lhoták, Yannis Smaragdakis, Manu Sridharan
2013 A conf
OOPSLA
Veselin Raychev, Max Schäfer, Manu Sridharan, Martin T. Vechev
2013 A* conf
PLDI
Sam Blackshear, Bor-Yuh Evan Chang, Manu Sridharan
2012 A* conf
CAV
Nishant Sinha, Nimit Singhania, Satish Chandra, Manu Sridharan
2012 A conf
ECOOP
Manu Sridharan, Julian Dolby, Satish Chandra, Max Schäfer, Frank Tip
2012 A conf
AAMAS
David F. Bacon, David C. Parkes, Yiling Chen, Malvika Rao, Ian A. Kash, Manu Sridharan
2012 A* conf
PLDI
Boris Petrov, Martin T. Vechev, Manu Sridharan, Julian Dolby
2011 A conf
OOPSLA
Manu Sridharan, Shay Artzi, Marco Pistoia, Salvatore Guarnieri, Omer Tripp, Ryan Berg
2011 A* conf
ICSE
Max Schäfer, Manu Sridharan, Julian Dolby, Frank Tip
2011 B conf
SAS
Sam Blackshear, Bor-Yuh Evan Chang, Sriram Sankaranarayanan, Manu Sridharan
2010 A conf
ECOOP
Max Schäfer, Julian Dolby, Manu Sridharan, Emina Torlak, Frank Tip
2010 conf
FoSER
David F. Bacon, Eric Bokelberg, Yiling Chen, Ian A. Kash, David C. Parkes, Malvika Rao, Manu Sridharan
2009 conf
ESEC/SIGSOFT FSE
Jan Wloka, Manu Sridharan, Frank Tip
2009 A conf
ECOOP
Guoqing Xu, Atanas Rountev, Manu Sridharan
2009 A* conf
PLDI
Satish Chandra, Stephen J. Fink, Manu Sridharan
2009 A* conf
PLDI
Omer Tripp, Marco Pistoia, Stephen J. Fink, Manu Sridharan, Omri Weisman
2009 B conf
SAS
Manu Sridharan, Stephen J. Fink
2007 A* conf
PLDI
Manu Sridharan, Stephen J. Fink, Rastislav Bodík
2006 A* conf
PLDI
Manu Sridharan, Rastislav Bodík
2005 A conf
OOPSLA
Manu Sridharan, Denis Gopan, Lexin Shan, Rastislav Bodík
2004 conf
SIGSOFT FSE
Roman Manevich, Manu Sridharan, Stephen Adams, Manuvir Das, Zhe Yang
2003 A* conf
ASE
Ilya Shlyakhter, Robert Seater, Daniel Jackson, Manu Sridharan, Mana Taghdiri
2003 conf
BioConcur@CONCUR
Bor-Yuh Evan Chang, Manu Sridharan
2002 A* conf
PLDI
Jong-Deok Choi, Keunwoo Lee, Alexey Loginov, Robert O'Callahan, Vivek Sarkar, Manu Sridharan
2001 A conf
IPDPS
Bowen Alpern, Jong-Deok Choi, Ton Ngo, Manu Sridharan, John M. Vlissides
2001 conf
ESEC / SIGSOFT FSE
Daniel Jackson, Ilya Shlyakhter, Manu Sridharan
2000 conf
OOPSLA Addendum
Bowen Alpern, Ton Ngo, Jong-Deok Choi, Manu Sridharan
2000 conf
ICMAS
Manu Sridharan, Gerald Tesauro
2000 A* conf
ICML
Manu Sridharan, Gerald Tesauro
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