Hannes Tschofenig

129 papers A* 2B 3C 5Misc 1Journal 109Unranked 7
YearRankTypeTitle / Venue / Authors
2025 J jnl
RFC
Hannes Tschofenig, Simon Frost, Mathias Brossard, Adrian Shaw, Thomas Fossati
2025 conf
USENIX ATC
Carsten Weinhold, Muhammad Usama Sardar, Ionut Mihalcea, Yogesh Deshpande, Hannes Tschofenig, Yaron Sheffer, Thomas Fossati, Michael Roitzsch
2024 J jnl
RFC
Kohei Isobe, Hannes Tschofenig, Orie Steele
2024 J jnl
IEEE Access
Muhammad Usama Sardar, Arto Niemi, Hannes Tschofenig, Thomas Fossati
2023 J jnl
RFC
Russ Housley, Hannes Tschofenig
2023 J jnl
RFC
Mingliang Pei, Hannes Tschofenig, Dave Thaler, David Wheeler
2022 J jnl
RFC
Brendan Moran, Hannes Tschofenig, Henk Birkholz
2022 J jnl
RFC
Ludwig Seitz, Göran Selander, Erik Wahlstroem, Samuel Erdtman, Hannes Tschofenig
2022 J jnl
RFC
Eric Rescorla, Hannes Tschofenig, Thomas Fossati, Achim Kraus
2022 J jnl
RFC
Eric Rescorla, Hannes Tschofenig, Nagendra Modadugu
2021 J jnl
RFC
Brendan Moran, Hannes Tschofenig, David Brown, Milosch Meriac
2020 C conf
PEMWN
Gabriele Restuccia, Hannes Tschofenig, Emmanuel Baccelli
2020 J jnl
CoRR
Gabriele Restuccia, Hannes Tschofenig, Emmanuel Baccelli
2020 J jnl
RFC
Brian Rosen, Henning Schulzrinne, Hannes Tschofenig, Randall Gellens
2020 J jnl
RFC
Michael B. Jones, Ludwig Seitz, Göran Selander, Samuel Erdtman, Hannes Tschofenig
2020 J jnl
RFC
Brian Campbell, John Bradley, Hannes Tschofenig
2019
Hannes Tschofenig
2019 J jnl
IEEE Secur. Priv.
Hannes Tschofenig, Emmanuel Baccelli
2019 J jnl
RFC
William Denniss, John Bradley, Michael B. Jones, Hannes Tschofenig
2019 J jnl
IEEE Access
Koen Zandberg, Kaspar Schleiser, Francisco Acosta Padilla, Hannes Tschofenig, Emmanuel Baccelli
2018 J jnl
RFC
Michael B. Jones, Erik Wahlstroem, Samuel Erdtman, Hannes Tschofenig
2018 J jnl
RFC
Carsten Bormann, Simon Lemay, Hannes Tschofenig, Klaus Hartke, Bilhanan Silverajan, Brian Raymor
2018 J jnl
RFC
Jaime Jimenez, Hannes Tschofenig, David Thaler
2017 J jnl
RFC
Randall Gellens, Hannes Tschofenig
2017 J jnl
RFC
Randall Gellens, Brian Rosen, Hannes Tschofenig
2017 J jnl
RFC
Hannes Tschofenig, Stephen Farrell
2016 J jnl
RFC
James Winterbottom, Hannes Tschofenig, Laura Liess
2016 J jnl
RFC
Randall Gellens, Brian Rosen, Hannes Tschofenig, Roger Marshall, James Winterbottom
2016 J jnl
RFC
Josh Howlett, Sam Hartman, Hannes Tschofenig, Jim Schaad
2016 J jnl
Datenschutz und Datensicherheit
Hannes Tschofenig
2016 J jnl
RFC
Tero Kivinen, Paul Wouters, Hannes Tschofenig
2016 J jnl
RFC
Michael B. Jones, John Bradley, Hannes Tschofenig
2016 J jnl
RFC
Hannes Tschofenig, Jouni Korhonen, Glen Zorn, Kervin Pillay
2016 J jnl
RFC
Hannes Tschofenig, Thomas Fossati
2016 J jnl
RFC
Stefan Santesson, Hannes Tschofenig
2015 J jnl
RFC
William J. Mills, Tim Showalter, Hannes Tschofenig
2015 J jnl
RFC
Hannes Tschofenig, Jari Arkko, David Thaler, Danny McPherson
2015 J jnl
RFC
Stephen Farrell, Rigo Wenning, Bert Bos, Marc Blanchet, Hannes Tschofenig
2014 J jnl
RFC
Lionel Morand, Victor Fajardo, Hannes Tschofenig
2014 J jnl
RFC
Henning Schulzrinne, Stephen McCann, Gabor Bajko, Hannes Tschofenig, Dirk Kröselberg
2014 J jnl
RFC
Richard L. Barnes, Martin Thomson, James Winterbottom, Hannes Tschofenig
2014 J jnl
RFC
Stephen Farrell, Hannes Tschofenig
2014 J jnl
RFC
Henning Schulzrinne, Hannes Tschofenig, Christer Holmberg, Milan Patel
2014 J jnl
RFC
Hannes Tschofenig, Lars Eggert, Zaheduzzaman Sarker
2014 J jnl
RFC
Johannes Gilger, Hannes Tschofenig
2014 J jnl
RFC
Jon Peterson, Henning Schulzrinne, Hannes Tschofenig
2014 J jnl
IEEE Internet Things J.
Sye Loong Keoh, Sandeep S. Kumar, Hannes Tschofenig
2014 J jnl
RFC
Hannes Tschofenig, Henning Schulzrinne, Bernard Aboba
2014 J jnl
RFC
Paul Wouters, Hannes Tschofenig, John Gilmore, Samuel Weiler, Tero Kivinen
2013 J jnl
RFC
Jon Peterson, Olaf M. Kolkman, Hannes Tschofenig, Bernard Aboba
2013 conf
Future Network & Mobile Summit
Lei Jiao, Roy Friedman, Xiaoming Fu, Stefano Secci, Zbigniew Smoreda, Hannes Tschofenig
2013 J jnl
RFC
Henning Schulzrinne, Hannes Tschofenig, Jorge Ricardo Cuellar, James M. Polk, John B. Morris, Martin Thomson
2013 book
Hannes Tschofenig, Henning Schulzrinne
2013 J jnl
RFC
Alissa Cooper, Hannes Tschofenig, Bernard Aboba, Jon Peterson, John B. Morris, Marit Hansen, Rhys Smith
2012 J jnl
RFC
James Winterbottom, Hannes Tschofenig, Henning Schulzrinne, Martin Thomson
2012 J jnl
RFC
Eliot Lear, Hannes Tschofenig, Henry Mauldin, Simon Josefsson
2012 J jnl
RFC
Brian Campbell, Hannes Tschofenig
2012 J jnl
RFC
Rohan Mahy, Brian Rosen, Hannes Tschofenig
2012 J jnl
RFC
Henning Schulzrinne, Laura Liess, Hannes Tschofenig, Barbara Stark, Andres Kuett
2012 J jnl
RFC
Jouni Korhonen, Basavaraj Patil, Hannes Tschofenig, Dirk Kröselberg
2012 J jnl
RFC
Hannes Tschofenig, Jari Arkko
2012 J jnl
RFC
Henning Schulzrinne, Hannes Tschofenig
2011 J jnl
RFC
Richard L. Barnes, Matt Lepinski, Alissa Cooper, John B. Morris, Hannes Tschofenig, Henning Schulzrinne
2011 J jnl
RFC
Yaron Sheffer, Glen Zorn, Hannes Tschofenig, Scott R. Fluhrer
2011 J jnl
RFC
Jukka Manner, Martin Stiemerling, Hannes Tschofenig, Roland Bless
2011 J jnl
RFC
Takako Sanda, Xiaoming Fu, Seong-Ho Jeong, Jukka Manner, Hannes Tschofenig
2011 J jnl
Commun. ACM
Hannes Tschofenig
2011 conf
Future Internet Assembly
Theodore B. Zahariadis, Dimitri Papadimitriou, Hannes Tschofenig, Stephan Haller, Petros Daras, George D. Stamoulis, Manfred Hauswirth
2011 J jnl
RFC
James Winterbottom, Martin Thomson, Hannes Tschofenig, Richard L. Barnes
2010 J jnl
RFC
Yoav Nir, Hannes Tschofenig, Hui Deng, Rajeshwar Singh
2010 J jnl
RFC
Pasi Eronen, Hannes Tschofenig, Yaron Sheffer
2010 J jnl
RFC
Miika Komu, Thomas R. Henderson, Hannes Tschofenig, Jan Melén, Ari Keränen
2010 J jnl
RFC
Jouni Korhonen, Hannes Tschofenig, Julien Bournelle, Gerardo Giaretta, Madjid Nakhjiri
2010 J jnl
RFC
Dong Sun, Peter J. McCann, Hannes Tschofenig, Tina Tsou, Avri Doria, Glen Zorn
2010 J jnl
RFC
Henning Schulzrinne, Vishal Kumar Singh, Hannes Tschofenig, Martin Thomson
2010 J jnl
RFC
Jason Fischl, Hannes Tschofenig, Eric Rescorla
2010 J jnl
RFC
Hannes Tschofenig, Henning Schulzrinne
2010 J jnl
RFC
Tseno Tsenov, Hannes Tschofenig, Xiaoming Fu, Cedric Aoun, Elwyn B. Davies
2010 J jnl
Int. J. Crit. Infrastructure Prot.
Hannes Tschofenig, Mayutan Arumaithurai, Henning Schulzrinne, Bernard Aboba
2010 J jnl
RFC
Yaron Sheffer, Hannes Tschofenig
2010 J jnl
RFC
Martin Stiemerling, Hannes Tschofenig, Cedric Aoun, Elwyn B. Davies
2010 J jnl
RFC
Hassnaa Moustafa, Hannes Tschofenig, Stefaan De Cnodder
2010 J jnl
RFC
Jouni Korhonen, Hannes Tschofenig, Mayutan Arumaithurai, Mark Jones, Avi Lior
2010 J jnl
RFC
Dan Romascanu, Hannes Tschofenig
2009 J jnl
RFC
Hannes Tschofenig, Farid Adrangi, Mark Jones, Avi Lior, Bernard Aboba
2009 J jnl
RFC
Jouni Korhonen, Julien Bournelle, Hannes Tschofenig, Charles E. Perkins, Kuntal Chowdhury
2009 J jnl
RFC
T. Charles Clancy, Hannes Tschofenig
2009 J jnl
RFC
James Winterbottom, Martin Thomson, Hannes Tschofenig
2009 J jnl
IEEE/ACM Trans. Netw.
Xiaoming Fu, Henning Schulzrinne, Hannes Tschofenig, Christian Dickmann, Dieter Hogrefe
2009 J jnl
RFC
Jouni Korhonen, Hannes Tschofenig, Elwyn B. Davies
2009 J jnl
RFC
Dan Wing, Steffen Fries, Hannes Tschofenig, François Audet
2008 J jnl
RFC
Henning Schulzrinne, James M. Polk, Hannes Tschofenig
2008 J jnl
RFC
Ted Hardie, Andrew Newton, Henning Schulzrinne, Hannes Tschofenig
2008 B conf
GLOBECOM
Mayutan Arumaithurai, Xiaoming Fu, Bernd Schloer, Hannes Tschofenig
2008 J jnl
RFC
Dan Forsberg, Yoshihiro Ohba, Basavaraj Patil, Hannes Tschofenig, Alper E. Yegin
2008 J jnl
RFC
Tom Taylor, Hannes Tschofenig, Henning Schulzrinne, Murugaraj Shanmugam
2008 J jnl
RFC
Hannes Tschofenig, Dirk Kröselberg, Andreas Pashalidis, Yoshihiro Ohba, Florent Bersani
2008 J jnl
RFC
Joseph Salowey, Hao Zhou, Pasi Eronen, Hannes Tschofenig
2007 conf
WICON
Niklas Steinleitner, Xiaoming Fu, Dieter Hogrefe, Thomas Schreck, Hannes Tschofenig
2007 J jnl
RFC
Henning Schulzrinne, Hannes Tschofenig, John B. Morris, Jorge Ricardo Cuellar, James M. Polk, Jonathan D. Rosenberg
2007 C conf
IPCCC
Henning Schulzrinne, Hannes Tschofenig, Andrew Newton, Ted Hardie
2007 J jnl
ACM Queue
Jason Fischl, Hannes Tschofenig
2007 J jnl
RFC
Michael Myers, Hannes Tschofenig
2007 C conf
IPCCC
Hannes Tschofenig, Henning Schulzrinne, Murugaraj Shanmugam, Andrew Newton
2007 J jnl
RFC
Florent Bersani, Hannes Tschofenig
2007 J jnl
RFC
Richard Graveman, Mohan Parthasarathy, Pekka Savola, Hannes Tschofenig
2006 J jnl
Comput. Networks
Xiaoming Fu, Hannes Tschofenig, Dieter Hogrefe
2006 J jnl
RFC
Steffen Fries, Hannes Tschofenig
2006 A* conf
INFOCOM
Fang-Chun Kuo, Hannes Tschofenig, Fabian Meyer, Xiaoming Fu
2006 J jnl
RFC
Tero Kivinen, Hannes Tschofenig
2006 B conf
PIMRC
Seppo Heikkinen, Hannes Tschofenig
2006 J jnl
RFC
Henning Schulzrinne, Hannes Tschofenig
2006 J jnl
RFC
Franck Le, Stefano M. Faccin, Basavaraj Patil, Hannes Tschofenig
2006 A* conf
INFOCOM
Xiaoming Fu, Henning Schulzrinne, Hannes Tschofenig, Christian Dickmann, Dieter Hogrefe
2006 J jnl
Int. J. Internet Protoc. Technol.
Hannes Tschofenig, Xiaoming Fu
2006 J jnl
RFC
Jon Peterson, James M. Polk, Douglas C. Sicker, Hannes Tschofenig
2006 J jnl
RFC
Joseph Salowey, Hao Zhou, Pasi Eronen, Hannes Tschofenig
2006 J jnl
IEEE Netw.
Hannes Tschofenig, Rainer Falk, Jon Peterson, Jeff Hodges, Douglas C. Sicker, James M. Polk
2005 conf
MATA
Raffaele Giaffreda, Hannes Tschofenig, Theo Kanter, Christoph Reichert
2005 J jnl
IEEE Commun. Mag.
Xiaoming Fu, Henning Schulzrinne, Attila Báder, Dieter Hogrefe, Cornelia Kappler, Georgios Karagiannis, Hannes Tschofenig, Sven Van den Bosch
2005 J jnl
RFC
Pasi Eronen, Hannes Tschofenig
2005 C conf
QSHINE
Attila Báder, Georgios Karagiannis, Lars Westberg, Cornelia Kappler, Tom Phelan, Hannes Tschofenig, Geert J. Heijenk
2005 B conf
IWQoS
Tseno Tsenov, Hannes Tschofenig
2005 J jnl
RFC
Hannes Tschofenig, Richard Graveman
2005 C conf
SecureComm
Jukka Ylitalo, Patrik Salmela, Hannes Tschofenig
2005 J jnl
RFC
Hannes Tschofenig, Dirk Kröselberg
2005 conf
WAC
Xiaoyuan Gu, Xiaoming Fu, Hannes Tschofenig, Lars C. Wolf
2005 Misc conf
ACISP
Hannes Tschofenig, Andrei V. Gurtov, Jukka Ylitalo, Aarthi Nagarajan, Murugaraj Shanmugam
2004 conf
ECUMN
Julien Bournelle, Maryline Laurent-Maknavicius, Hannes Tschofenig, Yacine El Mghazli
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"]