Rakesh Nagi

135 papers A 3B 4C 24Misc 3Journal 79Unranked 21
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Darryl Teo, Adharsha Sam, Chuan Shen Marcus Koh, Rakesh Nagi, Nuno Antunes Ribeiro
2025 conf
CASE
Pusong Li, Kris Hauser, Rakesh Nagi
2025 A conf
IROS
Pusong Li, S. M. Bhagya P. Samarakoon, M. A. Viraj J. Muthugala, Prithvi Krishna Chittoor, Mohan Rajesh Elara, Rakesh Nagi
2025 J jnl
IEEE Trans Autom. Sci. Eng.
Raunak Sengupta, Rakesh Nagi, Ramavarapu S. Sreenivas
2024 conf
SoCC
Jungeun Shin, Diana Arroyo, Asser N. Tantawi, Chen Wang, Alaa Youssef, Rakesh Nagi
2024 J jnl
Optim. Lett.
Mohit Mahajan, Wen-Mei Hwu, Rakesh Nagi
2024 J jnl
J. Parallel Distributed Comput.
Mohit Mahajan, Rakesh Nagi
2024 J jnl
J. Parallel Distributed Comput.
Samiran Kawtikwar, Rakesh Nagi
2024 J jnl
IEEE Trans. Netw. Sci. Eng.
Vincent Léon, S. Rasoul Etesami, Rakesh Nagi
2024 J jnl
Int. J. Prod. Res.
Ketan Date, Rakesh Nagi
2024 J jnl
Int. J. Prod. Res.
Ketan Date, Rakesh Nagi
2024 J jnl
Int. J. Prod. Res.
Chengbin Chu, Feng Chu, Alexandre Dolgui, Rakesh Nagi, Xiaolan Xie
2023 J jnl
IEEE Trans Autom. Sci. Eng.
Samhita Vadrevu, Rakesh Nagi
2023 B conf
ICPP
Samiran Kawtikwar, Mohammad Almasri, Wen-Mei Hwu, Rakesh Nagi, Jinjun Xiong
2023 J jnl
IEEE Trans Autom. Sci. Eng.
Raunak Sengupta, Rakesh Nagi, Ramavarapu S. Sreenivas
2023 C conf
FUSION
Samiran Kawtikwar, Rakesh Nagi
2023 B conf
PACT
Mohammad Almasri, Yen-Hsiang Chang, Izzat El Hajj, Rakesh Nagi, Jinjun Xiong, Wen-mei W. Hwu
2023 conf
CASE
Rami Fouani, Raunak Sengupta, Rakesh Nagi, Ramavarapu S. Sreenivas
2022 J jnl
IISE Trans.
Rashid Anzoom, Rakesh Nagi, Chrysafis Vogiatzis
2022 conf
SoCC
Jungeun Shin, Diana Arroyo, Asser N. Tantawi, Chen Wang, Alaa Youssef, Rakesh Nagi
2022 J jnl
CoRR
Vincent Léon, S. Rasoul Etesami, Rakesh Nagi
2022 conf
CDC
Vincent Léon, S. Rasoul Etesami, Rakesh Nagi
2022 A conf
IPDPS
Vibhor Dodeja, Mohammad Almasri, Rakesh Nagi, Jinjun Xiong, Wen-Mei Hwu
2022 A conf
ICS
Mohammad Almasri, Izzat El Hajj, Rakesh Nagi, Jinjun Xiong, Wen-Mei Hwu
2022 J jnl
CoRR
Mohammad Almasri, Yen-Hsiang Chang, Izzat El Hajj, Rakesh Nagi, Jinjun Xiong, Wen-mei W. Hwu
2022 J jnl
IEEE Trans Autom. Sci. Eng.
Timothy Murray, Jugal Garg, Rakesh Nagi
2022 J jnl
IEEE Trans. Intell. Transp. Syst.
Ali Yekkehkhany, Rakesh Nagi
2021 conf
APMS (5)
Rashid Anzoom, Rakesh Nagi, Chrysafis Vogiatzis
2021 J jnl
IISE Trans.
Ali Yekkehkhany, Ebrahim Arian, Rakesh Nagi, Ilan Shomorony
2021 conf
CASE
Raunak Sengupta, Rakesh Nagi
2021 conf
HPEC
Mohammad Almasri, Neo Vasudeva, Rakesh Nagi, Jinjun Xiong, Wen-Mei Hwu
2021 J jnl
CoRR
Mohammad Almasri, Izzat El Hajj, Rakesh Nagi, Jinjun Xiong, Wen-mei W. Hwu
2021 J jnl
Eur. J. Oper. Res.
Timothy Murray, Jugal Garg, Rakesh Nagi
2021 C conf
FUSION
Michaela Lobato, William Robert Norris, Rakesh Nagi, Ahmet Soylemezoglu, Dustin Nottage
2021 J jnl
IEEE Trans. Comput. Soc. Syst.
Arash Ghayoori, Rakesh Nagi
2021 J jnl
Decis. Anal.
Ali Yekkehkhany, Timothy Murray, Rakesh Nagi
2021 J jnl
CoRR
Timothy Murray, Jugal Garg, Rakesh Nagi
2020 C conf
FUSION
Samhita Vadrevu, Rakesh Nagi
2020 conf
HPEC
Mert Hidayetoglu, Carl Pearson, Vikram Sharma Mailthody, Eiman Ebrahimi, Jinjun Xiong, Rakesh Nagi, Wen-Mei Hwu
2020 J jnl
IEEE/ACM Trans. Netw.
Ali Yekkehkhany, Rakesh Nagi
2020 J jnl
CoRR
Mert Hidayetoglu, Carl Pearson, Vikram Sharma Mailthody, Eiman Ebrahimi, Jinjun Xiong, Rakesh Nagi, Wen-mei W. Hwu
2020 J jnl
Parallel Comput.
Shardul Natu, Ketan Date, Rakesh Nagi
2020 J jnl
IEEE Trans Autom. Sci. Eng.
Omkar Thakoor, Jugal Garg, Rakesh Nagi
2020 J jnl
CoRR
Ali Yekkehkhany, Rakesh Nagi
2020 J jnl
CoRR
Ali Yekkehkhany, Timothy Murray, Rakesh Nagi
2020 J jnl
Comput. Ind. Eng.
McKenzie R. Worden, Chase C. Murray, Mark H. Karwan, Héctor J. Ortiz-Peña, Rakesh Nagi
2020 conf
ASP-DAC
Dae Hee Kim, Rakesh Nagi, Deming Chen
2019 conf
HPEC
Sitao Huang, Carl Pearson, Rakesh Nagi, Jinjun Xiong, Deming Chen, Wen-mei W. Hwu
2019 J jnl
Inf. Fusion
Gregory Tauer, Ketan Date, Rakesh Nagi, Moises Sudit
2019 J jnl
CoRR
Ali Yekkehkhany, Rakesh Nagi
2019 C conf
FUSION
Olivia Reynen, Samhita Vadrevu, Rakesh Nagi, Keith A. LeGrand
2019 J jnl
INFORMS J. Comput.
Ketan Date, Rakesh Nagi
2019 C conf
FUSION
Hossein Nick Zinat Matin, Ali Yekkehkhany, Rakesh Nagi
2019 conf
CDC
Ali Yekkehkhany, Ebrahim Arian, Mohammad Hassan Hajiesmaili, Rakesh Nagi
2019 J jnl
CoRR
Ali Yekkehkhany, Ebrahim Arian, Mohammad Hassan Hajiesmaili, Rakesh Nagi
2019 B conf
ASONAM
Arash Ghayoori, Rakesh Nagi
2019 conf
HPEC
Carl Pearson, Mohammad Almasri, Omer Anjum, Vikram S. Mailthody, Zaid Qureshi, Rakesh Nagi, Jinjun Xiong, Wen-mei W. Hwu
2019 conf
HPEC
Mohammad Almasri, Omer Anjum, Carl Pearson, Zaid Qureshi, Vikram S. Mailthody, Rakesh Nagi, Jinjun Xiong, Wen-mei W. Hwu
2018 conf
HPEC
Vikram S. Mailthody, Ketan Date, Zaid Qureshi, Carl Pearson, Rakesh Nagi, Jinjun Xiong, Wen-Mei Hwu
2018 C conf
FUSION
Ketan Date, Rakesh Nagi
2018 conf
HPEC
Sitao Huang, Mohamed El-Hadedy, Cong Hao, Qin Li, Vikram S. Mailthody, Ketan Date, Jinjun Xiong, Deming Chen, Rakesh Nagi, Wen-Mei Hwu
2017 conf
HPEC
Ketan Date, Keven Feng, Rakesh Nagi, Jinjun Xiong, Nam Sung Kim, Wen-mei W. Hwu
2017 J jnl
Oper. Res.
Yan Xia, Rajan Batta, Rakesh Nagi
2017 J jnl
CoRR
Ketan Date, Rakesh Nagi
2017 J jnl
Optim. Methods Softw.
Mohammadreza Samadi, Alexander G. Nikolaev, Rakesh Nagi
2016 J jnl
Soc. Netw. Anal. Min.
Sushant S. Khopkar, Rakesh Nagi, Gregory Tauer
2016 J jnl
Parallel Comput.
Ketan Date, Rakesh Nagi
2016 C conf
FUSION
Alexandra Chronopoulou, Rakesh Nagi
2016 J jnl
Inf. Fusion
Geoff A. Gross, Rakesh Nagi
2016 J jnl
IEEE Trans. Comput. Soc. Syst.
Alireza Farasat, Geoff A. Gross, Rakesh Nagi, Alexander G. Nikolaev
2015 J jnl
Comput. Oper. Res.
Simin Huang, Qian Wang, Rajan Batta, Rakesh Nagi
2015 C conf
FUSION
Geoff A. Gross, Eric Little, Ben Park, James Llinas, Rakesh Nagi
2015 J jnl
IEEE Trans. Serv. Comput.
Guisselle A. Garcia Llinas, Rakesh Nagi
2015 conf
SBP
Alireza Farasat, Geoff A. Gross, Rakesh Nagi, Alexander G. Nikolaev
2015 J jnl
Inf. Fusion
Michael P. Jenkins, Geoff A. Gross, Ann M. Bisantz, Rakesh Nagi
2014 J jnl
Inf. Fusion
Geoff A. Gross, Rakesh Nagi, Kedar Sambhoos
2014 J jnl
J. Simulation
N. Bednowitz, Rajan Batta, Rakesh Nagi
2014 J jnl
Comput. Oper. Res.
Ketan Date, Suryaansh Makked, Rakesh Nagi
2014 J jnl
Soc. Netw. Anal. Min.
Sushant S. Khopkar, Rakesh Nagi, Alexander G. Nikolaev, Vaibhav Bhembre
2014 C conf
FUSION
Geoff A. Gross, Ketan Date, Daniel R. Schlegel, Jason J. Corso, James Llinas, Rakesh Nagi, Stuart C. Shapiro
2014 C conf
FUSION
Ketan Date, Geoff A. Gross, Rakesh Nagi
2014 Misc conf
CogSIMA
Dana Kerker, Michael P. Jenkins, Geoff A. Gross, Ann M. Bisantz, Rakesh Nagi
2013 J jnl
Parallel Comput.
Gregory Tauer, Rakesh Nagi
2013 C conf
FUSION
Héctor J. Ortiz-Peña, Moises Sudit, Michael J. Hirsch, Mark H. Karwan, Rakesh Nagi
2013 C conf
FUSION
Ketan Date, Geoff A. Gross, Sushant S. Khopkar, Rakesh Nagi, Kedar Sambhoos
2013 conf
SBP
Kirk Ogaard, Heather Roy, Sue E. Kase, Rakesh Nagi, Kedar Sambhoos, Moises Sudit
2013 conf
MIM
Rakesh Nagi, Ketan Date
2013 J jnl
IEEE Trans Autom. Sci. Eng.
Jingyang Xu, Rakesh Nagi
2012 B conf
ASONAM
Sushant S. Khopkar, Rakesh Nagi, Alexander G. Nikolaev
2012 Misc conf
CogSIMA
Katie McConky, Rakesh Nagi, Moises Sudit, William Hughes
2012 J jnl
Comput. Oper. Res.
Frank Mufalli, Rajan Batta, Rakesh Nagi
2012 C conf
FUSION
Geoff A. Gross, Rakesh Nagi, Kedar Sambhoos, Daniel R. Schlegel, Stuart C. Shapiro, Gregory Tauer
2011 C conf
FUSION
Geoff A. Gross, Rakesh Nagi, Kedar Sambhoos
2011 C conf
FUSION
Katie McConky, Rakesh Nagi, Moises Sudit, William J. Rose, Gary J. Katz
2011 C conf
FUSION
Deven McMaster, Rakesh Nagi, Kedar Sambhoos
2011 Misc conf
CogSIMA
Michael P. Jenkins, Geoff A. Gross, Ann M. Bisantz, Rakesh Nagi
2010 C conf
FUSION
James Llinas, Rakesh Nagi, David L. Hall, John Lavery
2010 J jnl
Inf. Fusion
Kedar Sambhoos, Rakesh Nagi, Moises Sudit, Adam Stotz
2010 J jnl
Comput. Oper. Res.
Feng Pan, Rakesh Nagi
2010 C conf
FUSION
Geoff A. Gross, Rakesh Nagi, Kedar Sambhoos
2009 C conf
FUSION
Ying Zhang, Rakesh Nagi, Moises Sudit
2009 J jnl
J. Comput. Inf. Sci. Eng.
Kedar Sambhoos, Bahattin Koc, Rakesh Nagi
2009 J jnl
Eur. J. Oper. Res.
Min Zhang, Selçuk Savas, Rajan Batta, Rakesh Nagi
2009 J jnl
Comput. Oper. Res.
Avijit Sarkar, Rajan Batta, Rakesh Nagi
2009 C conf
FUSION
Adam Stotz, Rakesh Nagi, Moises Sudit
2009 J jnl
Manag. Sci.
Min Zhang, Rajan Batta, Rakesh Nagi
2009 J jnl
Ann. Oper. Res.
Simin Huang, Rajan Batta, Rakesh Nagi
2008 J jnl
OR Insight
Irene Casas, Robert Garrity, Deelesh Mandloi, Michelle Sunm, Jessica Weaver, Rakesh Nagi, Rajan Batta
2008 C conf
FUSION
Michael J. Hirsch, Rakesh Nagi, Moises Sudit
2008 J jnl
J. Adv. Inf. Fusion
Kedar Sambhoos, Rakesh Nagi, Moises Sudit, John T. Rickard
2008 J jnl
Comput. Oper. Res.
Vijay K. Shetty, Moises Sudit, Rakesh Nagi
2007 J jnl
Eur. J. Oper. Res.
Hari Kelachankuttu, Rajan Batta, Rakesh Nagi
2007 C conf
FUSION
Michael Holender, Rakesh Nagi, Moises Sudit, John T. Rickard
2007 J jnl
Eur. J. Oper. Res.
Avijit Sarkar, Rajan Batta, Rakesh Nagi
2006 C conf
FUSION
Moises Sudit, Rakesh Nagi, Adam Stotz, Kedar Sambhoos
2006 C conf
FUSION
Rakesh Nagi, Moises Sudit, James Llinas
2006 J jnl
Comput. Oper. Res.
Carol J. Romanowski, Rakesh Nagi, Moises Sudit
2006 J jnl
J. Oper. Res. Soc.
Satyaveer Singh Chauhan, Jean-Marie Proth, Ana María Sarmiento, Rakesh Nagi
2005 J jnl
Oper. Res.
Dipesh J. Patel, Rajan Batta, Rakesh Nagi
2005 J jnl
Comput. Aided Des.
Aditya Kelkar, Rakesh Nagi, Bahattin Koc
2005 J jnl
IEEE Trans. Syst. Man Cybern. Part A
Carol J. Romanowski, Rakesh Nagi
2005 J jnl
Comput. Oper. Res.
Satyaki Ghosh Dastidar, Rakesh Nagi
2005 J jnl
Ann. Oper. Res.
Simin Huang, Rajan Batta, Kathrin Klamroth, Rakesh Nagi
2004 J jnl
J. Comput. Inf. Sci. Eng.
Carol J. Romanowski, Rakesh Nagi
2003 conf
CE
Aihu Wang, Rakesh Nagi, Jianzhong Cha
2003 J jnl
Ann. Oper. Res.
Pavankumar Nandikonda, Rajan Batta, Rakesh Nagi
2002 J jnl
Oper. Res.
Selçuk Savas, Rajan Batta, Rakesh Nagi
2002 J jnl
Comput. Oper. Res.
Shoou-Jiun Wang, Joyendu Bhadury, Rakesh Nagi
2000 J jnl
Comput. Oper. Res.
Osman Kazan, Rakesh Nagi, Christopher M. Rump
1998 J jnl
Ann. Oper. Res.
Vishwanath Ramabhatta, Rakesh Nagi
1998 J jnl
J. Intell. Manuf.
Alfred L. Guiffrida, Rakesh Nagi
1996 J jnl
Ann. Oper. Res.
Subrata Ghosh, Ambuj Mahanti, Rakesh Nagi, Dana S. Nau
1995 J jnl
Comput. Oper. Res.
Michael C. Fu, Jian-Qiang Hu, Rakesh Nagi
1992 J jnl
Comput. Oper. Res.
Michael C. Fu, Jian-Qiang Hu, Rakesh Nagi
1991
Rakesh Nagi
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