Xiangming Li

71 papers A* 1A 1B 9Journal 51Unranked 9
YearRankTypeTitle / Venue / Authors
2026 A conf
WSDM
Xiangming Li, Hua Chu, Chengyu Feng, Jianan Li, Yangtao Zhou, Qingshan Li, Wanqiang Yang
2026 J jnl
Appl. Soft Comput.
Yangtao Zhou, Qingshan Li, Ruoyu Li, Hua Chu, Jianan Li, Feifei Zhu, Xiangming Li, Chengyu Feng, Wanqiang Yang
2026 J jnl
Inf. Sci.
Yunzhu Chen, Neng Ye, Wenyu Zhang, Shenghui Song, Xiangming Li
2026 J jnl
IEEE Trans. Ind. Electron.
Shizheng Deng, Xiaoliang Chen, Yongsong Luo, Sheng Li, Yangtianyu Lu, Yang Liu, Yujiao Wang, Chunhui Wang, Hongmiao Tian, Xiangming Li, Zhengbing Yang, Jinyou Shao
2025 J jnl
IEEE Trans. Veh. Technol.
Xiang Li, Rongfei Fan, Han Hu, Xiangming Li, Shimin Gong, Jian Yang
2025 J jnl
Expert Syst. Appl.
Yunzhu Chen, Neng Ye, Wenyu Zhang, Jiaqi Fan, Shahid Mumtaz, Xiangming Li
2025 J jnl
Neurocomputing
Yunzhu Chen, Neng Ye, Wenyu Zhang, Sijia Lv, Liwei Shao, Xiangming Li
2024 J jnl
IEEE Trans. Cogn. Commun. Netw.
Neng Ye, Sirui Miao, Jianxiong Pan, Qiaolin Ouyang, Xiangming Li, Xiaolin Hou
2023 B conf
PIMRC
Sirui Miao, Neng Ye, Qiaolin Ouyang, Peisen Wang, Xiangming Li, Lian Zhao
2023 J jnl
IEEE Signal Process. Lett.
Wenyu Zhang, Xiangming Li, Yunzhu Chen, Neng Ye, Xiao-Ping Zhang
2023 J jnl
CoRR
Xiang Li, Rongfei Fan, Han Hu, Xiangming Li
2023 J jnl
IEEE Wirel. Commun. Lett.
Cuicui Lv, Yu Ren, Xiangming Li, Peijin Wang, Zhenbin Du, Guoxin Ma, Haokun Chi
2023 J jnl
Sensors
Cuicui Lv, Linchuang Yang, Xinxin Zhang, Xiangming Li, Peijin Wang, Zhenbin Du
2022 conf
CCIS
Cuicui Lv, Peijin Wang, Peng Wang, Zhenbin Du, Xiangming Li
2022 J jnl
Sensors
Xinran Zhuo, Jianxiong Pan, Huwei Wang, Xiangming Li, Neng Ye
2022 J jnl
IEEE Trans. Ind. Electron.
Guifang Liu, Xiaoliang Chen, Xiangming Li, Chunhui Wang, Hongmiao Tian, Xiaoming Chen, Bangbang Nie, Jinyou Shao
2021 J jnl
IEEE Trans. Veh. Technol.
Neng Ye, Xiangming Li, Jianxiong Pan, Wenjia Liu, Xiaolin Hou
2021 J jnl
IEEE Commun. Lett.
Chaofan Chen, Xiangming Li, Xiaqing Miao, Xiangyuan Bu, Shuai Wang
2021 B conf
IWCMC
Neng Ye, Jianxiong Pan, Xiaojuan Wang, Peisen Wang, Xiangming Li
2020 J jnl
Wirel. Commun. Mob. Comput.
Jianxiong Pan, Neng Ye, Aihua Wang, Xiangming Li
2020 conf
BMSB
Neng Ye, Lu Jiang, Xiangming Li, Aihua Wang
2020 B conf
IWCMC
Wei Wang, Yongfeng Ma, Siqi Ma, Jianguo Li, Xiangming Li
2020 J jnl
Int. J. Distributed Sens. Networks
Aihua Wang, Peisen Wang, Xiaqing Miao, Xiangming Li, Neng Ye, Yun Liu
2020 J jnl
IEEE Trans. Broadcast.
Jianguo Li, Xiangming Li, Aihua Wang, Neng Ye
2020 J jnl
IEEE Trans. Wirel. Commun.
Neng Ye, Xiangming Li, Hanxiao Yu, Lian Zhao, Wenjia Liu, Xiaolin Hou
2020 B conf
IWCMC
Xuhui Ding, Yongfeng Ma, Jiwen Wang, Wei Wang, Jianguo Li, Xiangming Li
2020 J jnl
IEEE Wirel. Commun. Lett.
Xiaqing Miao, Dongning Guo, Xiangming Li
2019 J jnl
IEEE Trans. Ind. Informatics
Neng Ye, Xiangming Li, Hanxiao Yu, Aihua Wang, Wenjia Liu, Xiaolin Hou
2019 B conf
IWCMC
Lu Jiang, Xiangming Li, Neng Ye, Aihua Wang
2019 A* conf
AAAI
Yiyi Zhou, Rongrong Ji, Jinsong Su, Xiangming Li, Xiaoshuai Sun
2019 J jnl
IEEE Access
Chaofan Chen, Li Li, Li Wang, Shuai Wang, Xiangming Li, George K. Karagiannidis
2019 conf
BMSB
He Wang, Xiangming Li, Neng Ye, Aihua Wang
2019 J jnl
Wirel. Commun. Mob. Comput.
Jianguo Li, Xiangming Li, Aihua Wang, Neng Ye
2019 conf
BMSB
Jianguo Li, Xiangming Li, Neng Ye, Aihua Wang
2019 J jnl
CoRR
Chen Shen, Rongrong Ji, Fuhai Chen, Xiaoshuai Sun, Xiangming Li
2019 B conf
IWCMC
He Wang, Xiangming Li, Neng Ye, Aihua Wang
2018 conf
ICSAI
Ben Nie, Xiangming Li
2018 J jnl
IEEE Access
Ping Tang, Xiangming Li, Shuai Wang
2018 J jnl
Br. J. Educ. Technol.
Xiangming Li, Shuqiang Song
2018 J jnl
IEEE Commun. Lett.
Neng Ye, Aihua Wang, Xiangming Li, Wenjia Liu, Xiaolin Hou, Hanxiao Yu
2018 J jnl
Wirel. Commun. Mob. Comput.
Neng Ye, Aihua Wang, Xiangming Li, Wenjia Liu, Xiaolin Hou, Hanxiao Yu
2017 conf
VTC Spring
Neng Ye, Aihua Wang, Xiangming Li, Hanxiao Yu, Anxin Li, Huiling Jiang
2017 J jnl
IEEE Commun. Lett.
Hao Zheng, Xiangming Li, Neng Ye
2016 J jnl
IEEE Trans. Veh. Technol.
Rongfei Fan, Yu Zheng, Jianping An, Hai Jiang, Xiangming Li
2016 J jnl
IEEE Trans. Veh. Technol.
Xiaoming Dai, Kenichi Higuchi, Zhongshan Zhang, Keping Long, Xu Jin, Xiangming Li, Weiguo Ma
2016 J jnl
IEEE Trans. Wirel. Commun.
Xiangming Li, Rongfei Fan, Xiaoli Ma, Jianping An, Tao Jiang
2015 J jnl
Wirel. Commun. Mob. Comput.
Xiangming Li, Tao Jiang, Jianping An
2015 J jnl
Secur. Commun. Networks
Lintao Li, Jianping An, Zhongyong Wang, Xiangming Li
2014 J jnl
CoRR
Jihua Lu, Jianping An, Xiangming Li, Jie Yang, Lei Yang
2014 J jnl
CoRR
Jihua Lu, Xiangming Li, Dan Liu
2013 J jnl
Int. J. Wirel. Mob. Comput.
Weijia Lei, Xianzhong Xie, Xiangming Li
2013 conf
WCNC Workshops
Jihua Lu, Xiangming Li, Dan Liu
2013 J jnl
Wirel. Commun. Mob. Comput.
Xiangming Li, Tao Jiang
2012 J jnl
KSII Trans. Internet Inf. Syst.
Jihua Lu, Jianping An, Xiangming Li, Jie Yang, Lei Yang
2012 conf
UIC/ATC
Yufeng Wang, Xiangming Li, Qun Jin, Jianhua Ma
2012 J jnl
IEEE Trans. Veh. Technol.
Xiaoming Dai, Runmin Zou, Jianping An, Xiangming Li, Shaohui Sun, Yingming Wang
2011 J jnl
J. Networks
Jing (Jonas) Yang, Jianping An, Xiangming Li, Lei Yuan
2011 J jnl
Wirel. Commun. Mob. Comput.
Jianping An, Tao Jiang, Xiangming Li, Anxin Li, Hidetoshi Kayama
2011 J jnl
Eur. Trans. Telecommun.
Jing (Jonas) Yang, Jianping An, Xiangming Li, Lei Yuan
2010 B conf
IWCMC
Lei Yuan, Jianping An, Xiangming Li, Jing (Jonas) Yang
2010 J jnl
KSII Trans. Internet Inf. Syst.
Weijia Lei, Xianzhong Xie, Xiangming Li
2010 J jnl
IEEE Wirel. Commun.
Xiangming Li, Tao Jiang, Shuguang Cui, Jianping An, Qian Zhang
2010 B conf
IWCMC
Jing (Jonas) Yang, Jianping An, Xiangming Li, Lei Yuan, Nan (Jonas) Yang
2010 J jnl
IEEE Trans. Veh. Technol.
Tao Jiang, Xiangming Li
2009 B conf
PIMRC
Keke Liu, Zesong Fei, Jingming Kuang, Xiangming Li
2009 J jnl
IEEE J. Sel. Areas Commun.
Xiangming Li, Tao Jiang, Qian Zhang, Lan Wang
2009 J jnl
IEEE Trans. Wirel. Commun.
Xiangming Li, Hsiao-Hwa Chen, Yi Qian, Bo Rong, M. Reza Soleymani
2008 J jnl
IEEE Trans. Broadcast.
Bo Rong, Tao Jiang, Xiangming Li, M. Reza Soleymani
2007 conf
ICC
Anxin Li, Mingshu Wang, Xiangming Li, Hidetoshi Kayama
2005 J jnl
IEEE Trans. Wirel. Commun.
Q. T. Zhang, Xiaowei Cui, Xiangming Li
2001 J jnl
IEEE Trans. Commun.
Xiangming Li, Tao Luo, Guangxin Yue, Changchuan Yin
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"]