Xiang Fu

64 papers A* 1A 2B 4C 3Journal 38Unranked 14
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Robotics Autom. Lett.
Yujie Jiang, Chao Qin, Chengxi Zhong, Xiang Fu, You-Fu Li, Song Liu
2026 J jnl
CoRR
Xiang Fu, Shiman Meng, Weiping Zhang, Luanzheng Guo, Kento Sato, Dong H. Ahn, Ignacio Laguna, Gregory L. Lee, Martin Schulz
2026 J jnl
Knowl. Based Syst.
Xiang Fu, Haiyang Yu, Han Jiang, Minda Li, Zhiyong Cui, Yilong Ren
2026 J jnl
CoRR
Xin Huang, Weiping Zhang, Shiman Meng, Wubiao Xu, Xiang Fu, Luanzheng Guo, Kento Sato
2025 J jnl
CoRR
Jianyi Yu, Tengxiao Wang, Yuxuan Wang, Xiang Fu, Fei Qiao, Ying Wang, Rui Yuan, Liyuan Liu, Cong Shi
2025 J jnl
Pattern Recognit.
Hu Su, Ying Li, Yifan Xu, Xiang Fu, Song Liu
2025 J jnl
Complex.
Zhenhua Qin, Qilai Liang, Xiang Fu
2025 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Guanyu Chen, Mingju Chen, Tengxiao Wang, Haibing Wang, Xiang Fu, Yingcheng Lin, Liyuan Liu, Cong Shi
2025 J jnl
Expert Syst. Appl.
Xiang Fu, Yilong Ren, Han Jiang, Jiancheng Lv, Zhiyong Cui, Haiyang Yu
2025 J jnl
CoRR
Xiang Fu
2025 J jnl
CoRR
Chong Zhong, Yang Li, Jinfeng Xu, Xiang Fu, Yunhao Liu, Qiuyi Huang, Danjuan Yang, Meiyan Li, Aiyi Liu, Alan H. Welsh, Xingtao Zhou, Bo Fu, Catherine C. Liu
2025 J jnl
CoRR
Yanshu Li, Hongyang He, Yi Cao, Qisen Cheng, Xiang Fu, Ruixiang Tang
2025 J jnl
Clust. Comput.
Xiang Fu, Qianfeng Ruan, Maojia Tang, Jiaqi Wan, Zitai Xiao, Yipeng Yin, Xilong Zhang, Tianqi Yang
2025 conf
MMAsia
Mengmeng Yu, Xiang Fu, Huizheng Yu, Caiyun Fan
2025 J jnl
IEEE Trans. Affect. Comput.
Weihao Zheng, Jialong Li, Songyu Yang, Xiang Fu, Yalin Wang, Zhijun Yao, Minqiang Yang, Bin Hu
2025 J jnl
IEEE Trans Autom. Sci. Eng.
Ying Li, Xiang Fu, Yanqin Ma, Hu Su, Song Liu
2024 J jnl
Expert Syst. Appl.
Chenquan Gan, Xiang Fu, Qingdong Feng, Qingyi Zhu, Yang Cao, Ye Zhu
2024 A conf
SC
Xiang Fu, Weiping Zhang, Shiman Meng, Xin Huang, Wubiao Xu, Luanzheng Guo, Kento Sato
2024 J jnl
CoRR
Xiang Fu, Weiping Zhang, Xin Huang, Shiman Meng, Wubiao Xu, Luanzheng Guo, Kento Sato
2024 A* conf
ICRA
Yujie Jiang, Xiang Fu, Chengxi Zhong, Teng Li, Haojian Lu, Song Liu
2024 conf
IPDPS (Workshops)
Xiang Fu, Xin Huang, Wubiao Xu, Weiping Zhang, Shiman Meng, Luanzheng Guo, Kento Sato
2024 C conf
ISPA
Moheng Lin, Peichang Shi, Xiang Fu, Feng Jiang, Guodong Yi
2024 J jnl
IEEE Trans. Comput. Soc. Syst.
Xiang Fu, Ying Wang, Jialong Li, Hongmin Cai, Xinyan Zhang, Zhijun Yao, Minqiang Yang, Weihao Zheng
2024 C conf
CLUSTER
Xiang Fu, Shiman Meng, Weiping Zhang, Luanzheng Guo, Kento Sato, Dong H. Ahn, Ignacio Laguna, Gregory L. Lee, Martin Schulz
2024 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Cong Shi, Xiang Fu, Haibing Wang, Yingcheng Lin, Ying Jiang, Liyuan Liu, Nanjian Wu, Min Tian
2024 conf
HPEC
Xiang Fu, Xinpeng Zhang, Jixiang Ma, Peng Zhao, Shuai Lu, Xu T. Liu
2024 J jnl
CoRR
Xiang Fu, Xinpeng Zhang, Jixiang Ma, Peng Zhao, Shuai Lu, Xu T. Liu
2024 J jnl
IEEE Control. Syst. Lett.
Heng Zhang, Xiang Fu, Song Liu, Yang Wang
2024 J jnl
Remote. Sens.
Hong Tang, Yixin Zhao, Lijuan Wen, Matti Leppäranta, Ruijia Niu, Xiang Fu
2024 A conf
IROS
Xiang Fu, Yifan Xu, Shudong Wang, Haojian Lu, Jiaqi Li, Youfu Li, Hu Su, Song Liu
2024 J jnl
IEEE Trans. Biomed. Eng.
Teng Li, Yujie Jiang, Xiang Fu, Zhenhuan Sun, Yiheng Yan, You Fu Li, Song Liu
2024 conf
SC Workshops
Xin Huang, Wubiao Xu, Shiman Meng, Weiping Zhang, Xiang Fu, Luanzheng Guo, Kento Sato
2024 J jnl
Knowl. Based Syst.
Chenquan Gan, Yu Tang, Xiang Fu, Qingyi Zhu, Deepak Kumar Jain, Salvador García
2024 J jnl
IEEE Trans Autom. Sci. Eng.
Teng Li, Yuting Yang, Xiang Fu, Zhenhuan Sun, You Fu Li, Song Liu
2023 conf
IPDPS Workshops
Xiang Fu, Hao Tang, Huimin Liao, Xin Huang, Wubiao Xu, Shiman Meng, Weiping Zhang, Luanzheng Guo, Kento Sato
2023 J jnl
IACR Cryptol. ePrint Arch.
Xiang Fu
2023 conf
ICA3PP (7)
Haoliang Ma, Peichang Shi, Xiang Fu, Guodong Yi
2023 conf
ICTA
Fengchun Tian, Xiang Fu, Haibing Wang, Jingya Zhang, Haoran Gao, Shukai Duan, Lidan Wang, Min Tian
2023 J jnl
IACR Cryptol. ePrint Arch.
Xiang Fu
2023 J jnl
IEEE Trans. Instrum. Meas.
Xiang Fu, Yuting Yang, Zhenhuan Sun, Hu Su, Youfu Li, Teng Li, Song Liu
2022 J jnl
Appl. Intell.
Wenyan Cao, Ranfeng Wang, Minqiang Fan, Xiang Fu, Haoran Wang, Yulong Wang
2022 conf
ICACT
Hanji Shen, Jun Li, Xiang Fu
2021 conf
ICCIR
Xiang Fu, Hongpeng Liu, Baojun Wang, Guiyong Yuan, Hao Zhang
2021 J jnl
Int. J. Mach. Learn. Cybern.
Wenyan Cao, Ranfeng Wang, Minqiang Fan, Xiang Fu, Yulong Wang, Zhongtian Guo, Fubo Fan
2020 J jnl
CoRR
Lifang Deng, Jin Niu, Angulia Yang, Qidi Xu, Xiang Fu, Jiandong Zhang, Anxiang Zeng
2019 J jnl
Clust. Comput.
Bin Huang, Sen Wu, Song Huang, Xiang Fu, Yunyun Yang
2018 J jnl
J. Comput.
Xiang Fu, Yi Jiang, Yong Huang, Guimei Zhang, Ying Chen
2018 ch.
Encyclopedia of Database Systems (2nd ed.)
Ying Li, Xiang Fu
2017 J jnl
IEICE Electron. Express
Junli Peng, Qi Wang, Xiang Fu, Zongliang Huo
2013 conf
ICB
Xiang Fu, Chongjin Liu, Junjie Bian, Jufu Feng, Han Wang, Ziwei Mao
2012 B conf
ICPR
Chongjin Liu, Junjie Bian, Xiang Fu, Jufu Feng
2012 B conf
ICPR
Yuelong Li, Jufu Feng, Chongjin Liu, Xiang Fu
2012 B conf
ICPR
Xiang Fu, Chongjin Liu, Junjie Bian, Jufu Feng
2011 B conf
ICIP
Chongjin Liu, Jia Cao, Xin Gao, Xiang Fu, Jufu Feng
2011 J jnl
Comput. Math. Appl.
Xiang Fu, Anqiang Li, Liping Wang, Changming Ji
2010 C conf
SEKE
Xiang Fu, Chung-Chih Li
2010 J jnl
Knowl. Based Syst.
Tiesong Hu, Xuning Guo, Xiang Fu, Yibing Lv
2010 conf
NASA Formal Methods
Xiang Fu, Chung-Chih Li
2010 ed.
TAV-WEB
Gwen Salaün, Xiang Fu, Sylvain Hallé
2008 conf
IIH-MSP
Xiang Fu, Baolong Guo
2008 conf
ICNC (5)
Yunyi Yan, Baolong Guo, ZhanLong Yang, Xiang Fu
2007 conf
ICNC (4)
Baolong Guo, Yunyi Yan, Xiang Fu
1999 J jnl
Comput. Commun.
Xiang Fu
1999 J jnl
Comput. Commun.
Xiang Fu
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"]