Ramakanth Kavuluru

106 papers A* 3B 1C 4Misc 12Journal 50Unranked 36
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
Aviv Brokman, Xuguang Ai, Yuhang Jiang, Shashank Gupta, Ramakanth Kavuluru
2025 J jnl
Artif. Intell. Rev.
Isaac Hands, Ramakanth Kavuluru
2025 conf
NLDB (1)
Shashank Gupta, Xuguang Ai, Yuhang Jiang, Ramakanth Kavuluru
2025 conf
ICHI
Motasem S. Obeidat, Md Sultan Al Nahian, Ramakanth Kavuluru
2025 J jnl
CoRR
Motasem S. Obeidat, Md Sultan Al Nahian, Ramakanth Kavuluru
2025 conf
NLDB (1)
Aviv Brokman, Ramakanth Kavuluru
2025 J jnl
CoRR
Md Sultan Al Nahian, Chris Delcher, Daniel R. Harris, Peter Akpunonu, Ramakanth Kavuluru
2025 J jnl
CoRR
Yuhang Jiang, Ramakanth Kavuluru
2024 J jnl
CoRR
Md Sultan Al Nahian, Ramakanth Kavuluru
2024 J jnl
CoRR
Aviv Brokman, Ramakanth Kavuluru
2024 conf
ACL (Findings)
Monika Jain, Raghava Mutharaju, Kuldeep Singh, Ramakanth Kavuluru
2024 J jnl
CoRR
Monika Jain, Raghava Mutharaju, Kuldeep Singh, Ramakanth Kavuluru
2024 A* conf
AAAI
Monika Jain, Raghava Mutharaju, Ramakanth Kavuluru, Kuldeep Singh
2024 J jnl
CoRR
Monika Jain, Raghava Mutharaju, Ramakanth Kavuluru, Kuldeep Singh
2023 J jnl
IEEE J. Biomed. Health Informatics
Sajjad Fouladvand, Jeffery C. Talbert, Linda P. Dwoskin, Heather Bush, Amy Lynn Meadows, Lars E. Peterson, Yash R. Mishra, Steven K. Roggenkamp, Fei Wang, Ramakanth Kavuluru, Jin Chen
2023 J jnl
J. Am. Medical Informatics Assoc.
Sijia Liu, Andrew Wen, Liwei Wang, Huan He, Sunyang Fu, Robert T. Miller, Andrew E. Williams, Daniel R. Harris, Ramakanth Kavuluru, Mei Liu, Noor Abu-El-Rub, Dalton Schutte, Rui Zhang, Masoud Rouhizadeh, John D. Osborne, Yongqun He, Umit Topaloglu, Stephanie S. Hong, Joel H. Saltz, Thomas Schaffter, Emily R. Pfaff, Christopher G. Chute, Tim Duong, Melissa A. Haendel, Rafael Fuentes, Peter Szolovits, Hua Xu, Hongfang Liu
2023 conf
MedInfo
Yuhang Jiang, Ramakanth Kavuluru
2023 J jnl
CoRR
Yuhang Jiang, Ramakanth Kavuluru
2023 J jnl
CoRR
Shashank Gupta, Xuguang Ai, Ramakanth Kavuluru
2023 conf
ICHI
Xuguang Ai, Ramakanth Kavuluru
2023 J jnl
CoRR
Xuguang Ai, Ramakanth Kavuluru
2023 conf
ICHI
Yuhang Jiang, Ramakanth Kavuluru
2023 J jnl
CoRR
Yuhang Jiang, Ramakanth Kavuluru
2022 J jnl
IEEE J. Biomed. Health Informatics
Gongbo Liang, Connor Greenwell, Yu Zhang, Xin Xing, Xiaoqin Wang, Ramakanth Kavuluru, Nathan Jacobs
2022 J jnl
CoRR
Patrick J. Ward, April M. Young, Svetla Slavova, Madison Liford, Lara Daniels, Ripley Lucas, Ramakanth Kavuluru
2022 Misc conf
AMIA
Harry Hochheiser, Sean Finan, Zhou Yuan, John D. Levander, Eric B. Durbin, Isaac Hands, Ramakanth Kavuluru, Jeremy L. Warner, Guergana Savova
2022 J jnl
npj Digit. Medicine
Harrison G. Zhang, Arianna Dagliati, Zahra Shakeri Hossein Abad, Xin Xiong, Clara-Lea Bonzel, Zongqi Xia, Bryce W. Q. Tan, Paul Avillach, Gabriel A. Brat, Chuan Hong, Michele Morris, Shyam Visweswaran, Lav P. Patel, Alba Gutiérrez-Sacristán, David A. Hanauer, John H. Holmes, Malarkodi Jebathilagam Samayamuthu, Florence T. Bourgeois, Sehi L'Yi, Sarah E. Maidlow, Bertrand Moal, Shawn N. Murphy, Zachary H. Strasser, Antoine Neuraz, Kee Yuan Ngiam, Ne-Hooi Will Loh, Gilbert S. Omenn, Andrea Prunotto, Lauren A. Dalvin, Jeffrey G. Klann, Petra Schubert, Fernando J. Sanz Vidorreta, Vincent Benoit, Guillaume Verdy, Ramakanth Kavuluru, Hossein Estiri, Yuan Luo, Alberto Malovini, Valentina Tibollo, Riccardo Bellazzi, Kelly Cho, Yuk-Lam Ho, Amelia L. M. Tan, Byorn W. L. Tan, Nils Gehlenborg, Sara Lozano-Zahonero, Vianney Jouhet, Luca Chiovato, Bruce J. Aronow, Emma M. S. Toh, Wei Gen Scott Wong, Sara Pizzimenti, Kavishwar B. Wagholikar, Mauro Bucalo, Tianxi Cai, Andrew M. South, Isaac S. Kohane, Griffin M. Weber
2022 conf
WebSci
Jeevith Bopaiah, Kiran Garimella, Ramakanth Kavuluru
2022 J jnl
ACM Trans. Softw. Eng. Methodol.
Yu Zhao, Ting Su, Yang Liu, Wei Zheng, Xiaoxue Wu, Ramakanth Kavuluru, William G. J. Halfond, Tingting Yu
2022 J jnl
J. Am. Medical Informatics Assoc.
Jimmy Phuong, Naomi O. Riches, Luca Calzoni, Gora Datta, Deborah Duran, Asiyah Yu Lin, Ramesh P. Singh, Anthony E. Solomonides, Noreen Whysel, Ramakanth Kavuluru
2022 J jnl
Health Informatics J.
Sadie Bograd, Benjamin Chen, Ramakanth Kavuluru
2021 J jnl
CoRR
Sijia Liu, Andrew Wen, Liwei Wang, Huan He, Sunyang Fu, Robert T. Miller, Andrew E. Williams, Daniel R. Harris, Ramakanth Kavuluru, Mei Liu, Noor Abu-El-Rub, Rui Zhang, John D. Osborne, Masoud Rouhizadeh, Yongqun He, Emily R. Pfaff, Christopher G. Chute, Tim Duong, Melissa A. Haendel, Rafael Fuentes, Peter Szolovits, Hua Xu, Hongfang Liu
2021 conf
BCB
Anthony Rios, Eric B. Durbin, Isaac Hands, Ramakanth Kavuluru
2021 J jnl
ACM Trans. Comput. Heal.
Tung Tran, Ramakanth Kavuluru, Halil Kilicoglu
2021 Misc conf
AMIA
Sajjad Fouladvand, Jeffery C. Talbert, Linda P. Dwoskin, Heather M. Bush, Amy Lynn Meadows, Lars E. Peterson, Steve K. Roggenkamp, Ramakanth Kavuluru, Jin Chen
2021 J jnl
Int. J. Medical Informatics
Tung Tran, Melinda J. Ickes, Jakob W. Hester, Ramakanth Kavuluru
2021 J jnl
J. Biomed. Informatics
Jiho Noh, Ramakanth Kavuluru
2021 conf
BCB
Jiho Noh, Ramakanth Kavuluru
2021 J jnl
CoRR
Sajjad Fouladvand, Jeffery C. Talbert, Linda P. Dwoskin, Heather Bush, Amy Lynn Meadows, Lars E. Peterson, Ramakanth Kavuluru, Jin Chen
2021 conf
BIBM
Mohammad Soleymanpour, Sofia Saderholm, Ramakanth Kavuluru
2020 conf
EMNLP (Findings)
Jiho Noh, Ramakanth Kavuluru
2020 J jnl
CoRR
Jiho Noh, Ramakanth Kavuluru
2020 J jnl
CoRR
Jiho Noh, Ramakanth Kavuluru
2020 J jnl
CoRR
Gongbo Liang, Connor Greenwell, Yu Zhang, Xiaoqin Wang, Ramakanth Kavuluru, Nathan Jacobs
2019 J jnl
CoRR
Tung Tran, Ramakanth Kavuluru, Halil Kilicoglu
2019 J jnl
CoRR
Tung Tran, Ramakanth Kavuluru, Halil Kilicoglu
2019 Misc conf
AMIA
Jessica D. Tenenbaum, Ramakanth Kavuluru, Thomas H. McCoy, Özlem Uzuner, Sumithra Velupillai
2019 J jnl
J. Biomed. Informatics
Anthony Rios, Eric B. Durbin, Isaac Hands, Susanne M. Arnold, Darshil Shah, Stephen M. Schwartz, Bernardo H. L. Goulart, Ramakanth Kavuluru
2019 J jnl
Artif. Intell. Medicine
Tung Tran, Ramakanth Kavuluru
2019 A* conf
WWW
Manas Gaur, Amanuel Alambo, Joy Prakash Sain, Ugur Kursuncu, Krishnaprasad Thirunarayan, Ramakanth Kavuluru, Amit P. Sheth, Randy S. Welton, Jyotishman Pathak
2019 J jnl
CoRR
Tung Tran, Ramakanth Kavuluru
2019 J jnl
Artif. Intell. Medicine
Anthony Rios, Ramakanth Kavuluru
2019 Misc conf
AMIA
Mehmet G. Bakal, Halil Kilicoglu, Ramakanth Kavuluru
2019 J jnl
Database J. Biol. Databases Curation
Rezarta Islamaj Dogan, Sun Kim, Andrew Chatr-aryamontri, Chih-Hsuan Wei, Donald C. Comeau, Rui Antunes, Sérgio Matos, Qingyu Chen, Aparna Elangovan, Nagesh C. Panyam, Karin Verspoor, Hongfang Liu, Yanshan Wang, Zhuang Liu, Berna Altinel, Zehra Melce Hüsünbeyi, Arzucan Özgür, Aris Fergadis, Chen-Kai Wang, Hong-Jie Dai, Tung Tran, Ramakanth Kavuluru, Ling Luo, Albert Steppi, Jinfeng Zhang, Jinchan Qu, Zhiyong Lu
2018 conf
TAC
Tung Tran, Ramakanth Kavuluru, Halil Kilicoglu
2018 J jnl
Database J. Biol. Databases Curation
Tung Tran, Ramakanth Kavuluru
2018 J jnl
CoRR
Yifan Peng, Anthony Rios, Ramakanth Kavuluru, Zhiyong Lu
2018 J jnl
J. Am. Medical Informatics Assoc.
Abeed Sarker, Maksim Belousov, Jasper Friedrichs, Kai Hakala, Svetlana Kiritchenko, Farrokh Mehryary, Sifei Han, Tung Tran, Anthony Rios, Ramakanth Kavuluru, Berry de Bruijn, Filip Ginter, Debanjan Mahata, Saif M. Mohammad, Goran Nenadic, Graciela Gonzalez-Hernandez
2018 C conf
ICMLA
Jiho Noh, Ramakanth Kavuluru
2018 conf
NAACL-HLT
Anthony Rios, Ramakanth Kavuluru
2018 J jnl
J. Biomed. Informatics
Gokhan Bakal, Preetham Talari, Elijah V. Kakani, Ramakanth Kavuluru
2018 J jnl
Database J. Biol. Databases Curation
Yifan Peng, Anthony Rios, Ramakanth Kavuluru, Zhiyong Lu
2018 A* conf
EMNLP
Anthony Rios, Ramakanth Kavuluru
2018 J jnl
Bioinform.
Anthony Rios, Ramakanth Kavuluru, Zhiyong Lu
2018 conf
CLPsych@NAACL-HTL
Anthony Rios, Tung Tran, Ramakanth Kavuluru
2017 conf
ICHI
Ramakanth Kavuluru, Anthony Rios, Tung Tran
2017 C conf
BIBE
Akm Sabbir, Antonio Jimeno-Yepes, Ramakanth Kavuluru
2017 conf
BHI
Gokhan Bakal, Ramakanth Kavuluru
2017 conf
BDA
Jeevith Bopaiah, Ramakanth Kavuluru
2017 conf
CRI
Daniel R. Harris, Ramakanth Kavuluru, Jerzy W. Jaromczyk, Todd R. Johnson
2017 conf
MIKE
Tung Tran, Ramakanth Kavuluru
2017 conf
TREC
Jiho Noh, Ramakanth Kavuluru
2017 conf
SMM4H@AMIA
Sifei Han, Tung Tran, Anthony Rios, Ramakanth Kavuluru
2016 conf
BCB
Ramakanth Kavuluru, María Ramos-Morales, Tara Holaday, Amanda G. Williams, Laura Haye, Julie Cerel
2016 Misc conf
AMIA
Sifei Han, Ramakanth Kavuluru
2016 conf
SocInfo (2)
Sifei Han, Ramakanth Kavuluru
2016 J jnl
CoRR
A. K. M. Sabbir, Antonio Jimeno-Yepes, Ramakanth Kavuluru
2016 Misc conf
AMIA
Orhan Abar, Ramakanth Kavuluru
2016 conf
BCB
Orhan Abar, Richard J. Charnigo, Abner Rayapati, Ramakanth Kavuluru
2016 Misc conf
AMIA
Gokhan Bakal, Sergei Wallace, Ramakanth Kavuluru
2016 J jnl
J. Biomed. Informatics
Ramakanth Kavuluru, A. K. M. Sabbir
2015 J jnl
Artif. Intell. Medicine
Ramakanth Kavuluru, Anthony Rios, Yuan Lu
2015 conf
ICHI
Anthony Rios, Ramakanth Kavuluru
2015 Misc conf
AMIA
Ramakanth Kavuluru, Anthony Rios
2015 J jnl
J. Biomed. Informatics
Delroy Cameron, Ramakanth Kavuluru, Thomas C. Rindflesch, Amit P. Sheth, Krishnaprasad Thirunarayan, Olivier Bodenreider
2015 conf
BCB
Anthony Rios, Ramakanth Kavuluru
2015 conf
Canadian AI
Sifei Han, Ramakanth Kavuluru
2015 conf
MIKE
Gokhan Bakal, Ramakanth Kavuluru
2014 Misc conf
AMIA
Ramakanth Kavuluru, Anthony Rios, Brandon Kulengowski, Patrick McNamara
2014 J jnl
Data Knowl. Eng.
Ramakanth Kavuluru, Yuan Lu
2014 J jnl
IEEE J. Biomed. Health Informatics
Daniel R. Harris, Darren W. Henderson, Ramakanth Kavuluru, Arnold J. Stromberg, Todd R. Johnson
2013 Misc conf
FLAIRS
Anthony Rios, Robin Vanderpool, Pam Shaw, Ramakanth Kavuluru
2013 conf
ICMLA (1)
Zhiguo Yu, Todd R. Johnson, Ramakanth Kavuluru
2013 conf
ICHI
Anthony Rios, Ramakanth Kavuluru
2013 conf
Canadian AI
Ramakanth Kavuluru, Sifei Han, Daniel R. Harris
2013 C conf
NLDB
Ramakanth Kavuluru, Zhenghao He
2012 conf
COLING (Posters)
Ramakanth Kavuluru, Daniel R. Harris
2012 conf
IHI
Ramakanth Kavuluru, Christopher Thomas, Amit P. Sheth, Victor Chan, Wenbo Wang, Alan Smith, Armando Soto, Amy Walters
2012 Misc conf
AMIA
Darren W. Henderson, Daniel R. Harris, Ramakanth Kavuluru, Todd R. Johnson
2011 conf
CODASPY
Keke Chen, Ramakanth Kavuluru, Shumin Guo
2011 conf
BIBM
Delroy Cameron, Ramakanth Kavuluru, Olivier Bodenreider, Pablo N. Mendes, Amit P. Sheth, Krishnaprasad Thirunarayan
2009 J jnl
Des. Codes Cryptogr.
Ramakanth Kavuluru
2009 J jnl
Cryptogr. Commun.
Ramakanth Kavuluru, Andrew Klapper
2008 C conf
SETA
Ramakanth Kavuluru
2008 B conf
Selected Areas in Cryptography
Ramakanth Kavuluru, Andrew Klapper
2007 Misc conf
INDOCRYPT
Ramakanth Kavuluru, Andrew Klapper
tests/integration/test_basicproperties.py
← Index tests/integration/test_basicproperties.py python
"""
Integration tests for the BasicPropertiesExtractor class.
"""
import pytest
import os
from unittest.mock import Mock, patch, MagicMock

pytestmark = [pytest.mark.integration]


class TestBasicPropertiesExtractorInitialization:
    """Tests for BasicPropertiesExtractor initialization."""

    def test_initialization(self, elf_binary_path, mock_logger):
        """Test basic initialization."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            assert extractor.filepath == elf_binary_path
            assert extractor.basic_properties is None
            assert extractor.is_packed is None
            assert extractor.is_fat is None
            assert extractor.parent_sha256 is None
            assert extractor.child_sha256 is None
            assert extractor.child_architecture is None
            assert extractor.child_filetype is None

    def test_initialization_with_fat_params(self, elf_binary_path, mock_logger):
        """Test initialization with FAT Mach-O parameters."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            child_hashes = ["abc123", "def456"]
            child_archs = ["x86_64", "arm64"]
            child_types = ["macho", "macho"]

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                is_fat=True,
                child_sha256=child_hashes,
                child_architecture=child_archs,
                child_filetype=child_types
            )

            assert extractor.is_fat is True
            assert extractor.child_sha256 == child_hashes
            assert extractor.child_architecture == child_archs
            assert extractor.child_filetype == child_types

    def test_initialization_with_parent_sha256(self, elf_binary_path, mock_logger):
        """Test initialization with parent_sha256 for slice binaries."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            parent_hash = "parent_sha256_hash_here"

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                parent_sha256=parent_hash
            )

            assert extractor.parent_sha256 == parent_hash

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

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

            assert "-basic_properties" in extractor.elastic_index


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

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

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

            assert extractor.tag() == Tag.BASIC_PROPERTIES.value
            assert extractor.tag() == "basic_properties"


class TestBasicPropertiesExtract:
    """Tests for extract method."""

    def test_extract_elf_binary(self, elf_binary_path, mock_logger):
        """Test extracting properties from ELF binary."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor
        from redb.models.dataclasses import BasicProperties

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

            result = extractor.extract()

            assert result is not None
            assert isinstance(result, BasicProperties)
            assert result.sample_name == os.path.basename(elf_binary_path)
            assert result.filesize > 0
            assert result.file_entropy >= 0
            assert result.filetype is not None
            assert result.filetype_mime is not None
            assert result.filetype_magika is not None

    def test_extract_pe_binary(self, pe_binary_path, mock_logger):
        """Test extracting properties from PE binary."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor
        from redb.models.dataclasses import BasicProperties

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

            result = extractor.extract()

            assert result is not None
            assert isinstance(result, BasicProperties)
            assert result.filesize > 0
            # PE file should be detected
            assert "PE" in result.filetype or "executable" in result.filetype.lower()

    def test_extract_text_file(self, temp_text_file, mock_logger):
        """Test extracting properties from text file."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = BasicPropertiesExtractor(temp_text_file, mock_logger)

            result = extractor.extract()

            assert result is not None
            assert "text" in result.filetype.lower() or "ASCII" in result.filetype
            assert result.file_entropy >= 0

    def test_extract_stores_in_basic_properties(self, elf_binary_path, mock_logger):
        """Test that extract stores result in basic_properties attribute."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            assert extractor.basic_properties is None
            result = extractor.extract()
            assert extractor.basic_properties is result


class TestBasicPropertiesFiletype:
    """Tests for file type detection."""

    def test_elf_filetype(self, elf_binary_path, mock_logger):
        """Test ELF file type detection."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            # Should detect as ELF
            assert "ELF" in result.filetype

    def test_pe_filetype_mime(self, pe_binary_path, mock_logger):
        """Test PE file type MIME detection."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            # PE MIME types (varies by libmagic version)
            assert "dosexec" in result.filetype_mime or "x-msdownload" in result.filetype_mime or "portable-executable" in result.filetype_mime

    def test_text_filetype_mime(self, temp_text_file, mock_logger):
        """Test text file type MIME detection."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = BasicPropertiesExtractor(temp_text_file, mock_logger)

            result = extractor.extract()

            assert result is not None
            # Text MIME types
            assert "text" in result.filetype_mime


class TestBasicPropertiesEntropy:
    """Tests for entropy calculation in BasicPropertiesExtractor."""

    def test_entropy_reasonable_range(self, elf_binary_path, mock_logger):
        """Test that entropy is within reasonable range (0-8)."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            assert 0 <= result.file_entropy <= 8

    def test_entropy_rounded(self, elf_binary_path, mock_logger):
        """Test that entropy is rounded to 3 decimal places."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            # Check rounding to 3 decimal places
            entropy_str = str(result.file_entropy)
            if '.' in entropy_str:
                decimal_places = len(entropy_str.split('.')[1])
                assert decimal_places <= 3


class TestBasicPropertiesFilesize:
    """Tests for file size calculation."""

    def test_filesize_matches_actual(self, elf_binary_path, mock_logger):
        """Test that filesize matches actual file size."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            actual_size = os.path.getsize(elf_binary_path)
            assert result.filesize == actual_size

    def test_filesize_matches_binary_length(self, elf_binary_path, mock_logger, elf_binary_content):
        """Test that filesize matches binary content length."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result.filesize == len(elf_binary_content)


class TestBasicPropertiesPrepareExportData:
    """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.basicproperties import BasicPropertiesExtractor

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

            result = extractor.prepare_export_data("ElasticsearchExporter")

            assert result is extractor.basic_properties

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

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = BasicPropertiesExtractor(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 len(data) == 1  # One row
            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 'filesize' in column_names
            assert 'file_entropy' in column_names
            assert 'filetype' in column_names
            assert 'filetype_mime' in column_names
            assert 'filetype_magika' in column_names
            # New FAT/child columns
            assert 'parent_sha256' in column_names
            assert 'child_sha256' in column_names
            assert 'child_architecture' in column_names
            assert 'child_filetype' in column_names
            assert 'is_fat' in column_names

    def test_prepare_export_clickhouse_data_types(self, elf_binary_path, mock_logger):
        """Test that ClickHouse export data has correct types."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            data, column_names, column_type_names = extractor.prepare_export_data("ClickHouseExporter")

            row = data[0]

            # Check that sha256 is a string with correct length
            sha256_idx = column_names.index('sha256')
            assert isinstance(row[sha256_idx], str)
            assert len(row[sha256_idx]) == 64

            # Check that filesize is an integer
            filesize_idx = column_names.index('filesize')
            assert isinstance(row[filesize_idx], int)

            # Check that file_entropy is a float
            entropy_idx = column_names.index('file_entropy')
            assert isinstance(row[entropy_idx], float)


class TestBasicPropertiesClickHouseTable:
    """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.basicproperties import BasicPropertiesExtractor

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

            assert extractor.get_clickhouse_table() == "redb_basic_properties"


class TestBasicPropertiesExportData:
    """Tests for export_data method."""

    def test_export_data_with_print_exporter(self, elf_binary_path, mock_logger, mock_print_exporter, capsys):
        """Test export_data with PrintExporter."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                exporters=[mock_print_exporter]
            )

            result = extractor.export_data()

            assert result is True

    def test_export_data_empty_exporters(self, elf_binary_path, mock_logger):
        """Test export_data with no exporters."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                exporters=[]
            )

            result = extractor.export_data()

            # Should succeed with no exporters
            assert result is True


class TestBasicPropertiesMagika:
    """Tests for Magika file type detection."""

    def test_magika_elf_detection(self, elf_binary_path, mock_logger):
        """Test Magika detection of ELF files."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            # Magika should detect ELF
            assert result.filetype_magika == "elf" or "elf" in result.filetype_magika.lower()

    def test_magika_pe_detection(self, pe_binary_path, mock_logger):
        """Test Magika detection of PE files."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            # Magika should detect PE
            assert "pe" in result.filetype_magika.lower() or "exe" in result.filetype_magika.lower()


class TestBasicPropertiesFATSupport:
    """Tests for FAT Mach-O and child file support."""

    def test_extract_with_fat_flag(self, elf_binary_path, mock_logger):
        """Test extraction with is_fat flag set."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            assert result.is_fat is True

    def test_extract_with_child_hashes(self, elf_binary_path, mock_logger):
        """Test extraction with child_sha256 provided."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            child_hashes = ["abc123def456", "789ghi012jkl"]

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                child_sha256=child_hashes
            )

            result = extractor.extract()

            assert result is not None
            assert result.child_sha256 == child_hashes

    def test_extract_with_child_architecture(self, elf_binary_path, mock_logger):
        """Test extraction with child_architecture provided."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            child_archs = ["x86_64", "arm64"]

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                child_architecture=child_archs
            )

            result = extractor.extract()

            assert result is not None
            assert result.child_architecture == child_archs

    def test_extract_with_child_filetype(self, elf_binary_path, mock_logger):
        """Test extraction with child_filetype provided."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            child_types = ["macho", "macho"]

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                child_filetype=child_types
            )

            result = extractor.extract()

            assert result is not None
            assert result.child_filetype == child_types

    def test_clickhouse_export_with_fat_data(self, elf_binary_path, mock_logger):
        """Test ClickHouse export includes FAT-related fields correctly."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            child_hashes = ["abc123", "def456"]
            child_archs = ["x86_64", "arm64"]
            child_types = ["macho", "macho"]

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                is_fat=True,
                child_sha256=child_hashes,
                child_architecture=child_archs,
                child_filetype=child_types,
                parent_sha256=None  # FAT container has no parent
            )
            extractor.extract()

            data, column_names, column_type_names = extractor.prepare_export_data("ClickHouseExporter")
            row = data[0]

            # Check FAT fields
            is_fat_idx = column_names.index('is_fat')
            assert row[is_fat_idx] is True

            child_sha256_idx = column_names.index('child_sha256')
            assert row[child_sha256_idx] == child_hashes

            child_arch_idx = column_names.index('child_architecture')
            assert row[child_arch_idx] == child_archs

            child_type_idx = column_names.index('child_filetype')
            assert row[child_type_idx] == child_types

    def test_clickhouse_export_for_slice(self, elf_binary_path, mock_logger):
        """Test ClickHouse export for a slice binary with parent_sha256."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

        with patch('redb.settings.ELASTIC_BINARIES_COLLECTION', 'test'):
            parent_hash = "parent_container_sha256_hash"

            extractor = BasicPropertiesExtractor(
                elf_binary_path,
                mock_logger,
                parent_sha256=parent_hash
            )
            extractor.extract()

            data, column_names, column_type_names = extractor.prepare_export_data("ClickHouseExporter")
            row = data[0]

            parent_idx = column_names.index('parent_sha256')
            assert row[parent_idx] == parent_hash

    def test_default_fat_fields_are_none_or_empty(self, elf_binary_path, mock_logger):
        """Test that FAT-related fields default to None/empty for non-FAT binaries."""
        from redb.extractors.basicproperties import BasicPropertiesExtractor

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

            result = extractor.extract()

            assert result is not None
            assert result.is_fat is None
            assert result.child_sha256 is None
            assert result.child_architecture is None
            assert result.child_filetype is None


@pytest.mark.unit
@pytest.mark.dataclass
class TestBasicPropertiesDataclass:
    """Tests for BasicProperties dataclass structure."""

    def test_dataclass_has_all_expected_fields(self):
        """Test that BasicProperties dataclass has all expected fields."""
        from redb.models.dataclasses import BasicProperties

        # Create a sample instance
        bp = BasicProperties(
            filename="test.exe",
            sample_name="test.exe",
            filesize=1024,
            filetype="PE32",
            filetype_mime="application/x-dosexec",
            filetype_magika="pebin",
            file_entropy=6.5
        )

        # Check required fields
        assert bp.filename == "test.exe"
        assert bp.sample_name == "test.exe"
        assert bp.filesize == 1024
        assert bp.filetype == "PE32"
        assert bp.filetype_mime == "application/x-dosexec"
        assert bp.filetype_magika == "pebin"
        assert bp.file_entropy == 6.5

        # Check optional fields default to None
        assert bp.is_packed is None
        assert bp.is_fat is None
        assert bp.child_sha256 is None
        assert bp.child_architecture is None
        assert bp.child_filetype is None

    def test_dataclass_with_optional_fat_fields(self):
        """Test BasicProperties dataclass with FAT-related optional fields."""
        from redb.models.dataclasses import BasicProperties

        bp = BasicProperties(
            filename="universal.app",
            sample_name="universal.app",
            filesize=2048,
            filetype="Mach-O universal",
            filetype_mime="application/x-mach-binary",
            filetype_magika="macho",
            file_entropy=7.2,
            is_fat=True,
            child_sha256=["hash1", "hash2"],
            child_architecture=["x86_64", "arm64"],
            child_filetype=["macho", "macho"]
        )

        assert bp.is_fat is True
        assert bp.child_sha256 == ["hash1", "hash2"]
        assert bp.child_architecture == ["x86_64", "arm64"]
        assert bp.child_filetype == ["macho", "macho"]