Habib Mehrez

119 papers A 6B 2C 8Misc 3Journal 28Unranked 71
YearRankTypeTitle / Venue / Authors
2023 J jnl
Microprocess. Microsystems
Umer Farooq, Imran Baig, Muhammad Khurram Bhatti, Habib Mehrez, Arun Kumar, Manoj Gupta
2021 J jnl
J. Electron. Test.
Umer Farooq, Habib Mehrez
2018 J jnl
Des. Autom. Embed. Syst.
Umer Farooq, Habib Mehrez, Muhammad Khurram Bhatti
2018 J jnl
Microprocess. Microsystems
Umer Farooq, Roselyne Chotin-Avot, Muhammad Moazam Azeem, Maminionja Ravoson, Habib Mehrez
2017 J jnl
J. Signal Process. Syst.
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2017 conf
ReConFig
Umer Farooq, Habib Mehrez, Muhammad Khurram Bhatti
2017 conf
HPCS
Sonda Chtourou, Mohamed Abid, Zied Marrakchi, Emna Amouri, Habib Mehrez
2017 J jnl
Turkish J. Electr. Eng. Comput. Sci.
Sonda Chtourou, Zied Marrakchi, Emna Amouri, Vinod Pangracious, Mohamed Abid, Habib Mehrez
2016 conf
CS2@HiPEAC
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2016 conf
IDT
Sonda Chtourou, Mohamed Abid, Zied Marrakchi, Emna Amouri, Habib Mehrez
2016 C conf
PDP
Sonda Chtourou, Zied Marrakchi, Emna Amouri, Vinod Pangracious, Habib Mehrez, Mohamed Abid
2016 J jnl
Microprocess. Microsystems
Sonda Chtourou, Zied Marrakchi, Emna Amouri, Vinod Pangracious, Mohamed Abid, Habib Mehrez
2016 C conf
RSP
Umer Farooq, Roselyne Chotin-Avot, Muhammad Moazam Azeem, Maminionja Ravoson, Mariem Turki, Habib Mehrez
2016 conf
IDT
Muhammad Moazam Azeem, Roselyne Chotin-Avot, Umer Farooq, Maminionja Ravoson, Habib Mehrez
2016 conf
HPCS
Sonda Chtourou, Mohamed Abid, Zied Marrakchi, Emna Amouri, Habib Mehrez
2016 C conf
DSD
Umer Farooq, Roselyne Chotin-Avot, Muhammad Moazam Azeem, Zouha Cherif, Maminionja Ravoson, Saqib Khan, Habib Mehrez
2015 J jnl
IEEE Micro
Vinod Pangracious, Zied Marrakchi, Habib Mehrez
2015 J jnl
IET Comput. Digit. Tech.
Nidhameddine Belhadj, Nejmeddine Bahri, Zied Marrakchi, Mohamed Ali Ben Ayed, Nouri Masmoudi, Habib Mehrez
2015 conf
ARC
Sonda Chtourou, Zied Marrakchi, Vinod Pangracious, Emna Amouri, Habib Mehrez, Mohamed Abid
2015 J jnl
Des. Autom. Embed. Syst.
Mariem Turki, Zied Marrakchi, Habib Mehrez, Mohamed Abid
2015 book
Vinod Pangracious, Zied Marrakchi, Habib Mehrez
2014 J jnl
Int. J. Reconfigurable Comput.
Alp Kiliç, Zied Marrakchi, Habib Mehrez
2014 conf
NEWCAS
Jung Kyu Chae, Paul Mougeat, Jean-Arnaud Francois, Roselyne Chotin-Avot, Habib Mehrez
2014 J jnl
Microelectron. J.
Vinod Pangracious, Emna Amouri, Zied Marrakchi, Habib Mehrez
2014 J jnl
Microprocess. Microsystems
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2014 B conf
FPL
Emna Amouri, Shivam Bhasin, Yves Mathieu, Tarik Graba, Jean-Luc Danger, Habib Mehrez
2014 conf
DTIS
Vinod Pangracious, Zied Marrakchi, Nizar Beltaief, Habib Mehrez, Umer Farooq
2014 conf
ARC
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2014 conf
SoCC
Abdulfattah Mohammad Obeid, Syed Manzoor Qasim, Mohammed S. BenSaleh, Zied Marrakchi, Habib Mehrez, Heni Ghariani, Mohamed Abid
2014 A conf
FPGA
Qingshan Tang, Matthieu Tuna, Habib Mehrez
2014 conf
ISVLSI
Saif-Ur Rehman, Adrien Blanchardon, Arwa Ben Dhia, Mounir Benabdenbi, Roselyne Chotin-Avot, Lirida A. B. Naviner, Lorena Anghel, Habib Mehrez, Emna Amouri, Zied Marrakchi
2014 conf
ReConFig
Adrien Blanchardon, Roselyne Chotin-Avot, Habib Mehrez, Emna Amouri
2014 B conf
FPL
Adrien Blanchardon, Roselyne Chotin-Avot, Habib Mehrez, Emna Amouri
2014 J jnl
Int. J. Embed. Syst.
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2014 C conf
ISCAS
Alp Kiliç, Delaram Haghighitalab, Habib Mehrez, Hassan Aboushady
2014 J jnl
Int. J. Embed. Real Time Commun. Syst.
Nidhameddine Belhadj, Zied Marrakchi, Mohamed Ali Ben Ayed, Nouri Masmoudi, Habib Mehrez
2014 Misc conf
ATSIP
Nidhameddine Belhadj, Mohamed Ali Ben Ayed, Nouri Masmoudi, Zied Marrakchi, Habib Mehrez
2014 conf
ICSAMOS
Qingshan Tang, Habib Mehrez, Matthieu Tuna
2014 conf
SoCC
Vinod Pangracious, Mohamed Sahbi Marrakchi, Habib Mehrez, Zied Marrakchi
2014 Misc conf
FCCM
Qingshan Tang, Matthieu Tuna, Habib Mehrez
2014 conf
DTIS
Sonda Chtourou, Mohamed Abid, Zied Marrakchi, Habib Mehrez
2014 J jnl
Microelectron. Reliab.
Boukary Ouattara, Lise Doyen, David Ney, Habib Mehrez, Pirouz Bazargan-Sabet
2014 conf
3DIC
Sonda Chtourou, Mohamed Abid, Vinod Pangracious, Emna Amouri, Zied Marrakchi, Habib Mehrez
2014 A conf
FPGA
Karim M. Abdellatif, Roselyne Chotin-Avot, Zied Marrakchi, Habib Mehrez, Qingshan Tang
2013 J jnl
Microelectron. Reliab.
Arwa Ben Dhia, Samuel N. Pagliarini, Lirida Alves de Barros Naviner, Habib Mehrez, Philippe Matherat
2013 conf
FPT
Arwa Ben Dhia, Saif-Ur Rehman, Adrien Blanchardon, Lirida A. B. Naviner, Mounir Benabdenbi, Roselyne Chotin-Avot, Emna Amouri, Habib Mehrez, Zied Marrakchi
2013 conf
SoCC
Jung Kyu Chae, Paul Mougeat, Jean-Arnaud Francois, Roselyne Chotin-Avot, Habib Mehrez
2013 conf
COOL Chips
Vinod Pangracious, Habib Mehrez, Zied Marrakchi
2013 conf
ARC
Qingshan Tang, Matthieu Tuna, Zied Marrakchi, Habib Mehrez
2013 conf
SSD
Nidhameddine Belhadj, Nejmeddine Bahri, Mohamed Ali Ben Ayed, Zied Marrakchi, Habib Mehrez
2013 conf
FPT
Vinod Pangracious, Zied Marrakchi, Habib Mehrez
2013 conf
NEWCAS
Vinod Pangracious, Habib Mehrez, Zied Marrakchi
2013 conf
3DIC
Vinod Pangracious, Habib Mehrez, Zied Marrakchi
2013 conf
MWSCAS
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2013 conf
ReConFig
Emna Amouri, Adrien Blanchardon, Roselyne Chotin-Avot, Habib Mehrez, Zied Marrakchi
2013 conf
MWSCAS
Jung Kyu Chae, Severine Bertrand, Pierre-Francois Ollagnon, Paul Mougeat, Jean-Arnaud Francois, Roselyne Chotin-Avot, Habib Mehrez
2013 J jnl
Microelectron. J.
Umer Farooq, Husain Parvez, Habib Mehrez, Zied Marrakchi
2013 conf
ReConFig
Vinod Pangracious, Habib Mehrez, Nizar Beltaief, Zied Marrakchi, Umer Farooq
2013 J jnl
Integr.
Sophie Belloeil-Dupuis, Roselyne Chotin-Avot, Habib Mehrez
2013 J jnl
Int. J. Reconfigurable Comput.
Mariem Turki, Zied Marrakchi, Habib Mehrez, Mohamed Abid
2013 conf
FPGAworld
Vinod Pangracious, Habib Mehrez, Umer Farooq, Zied Marrakchi
2013 conf
Wireless Days
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2013 J jnl
Int. J. Reconfigurable Comput.
Emna Amouri, Habib Mehrez, Zied Marrakchi
2013 conf
ReConFig
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2013 conf
ARC
Mariem Turki, Zied Marrakchi, Habib Mehrez, Mohamed Abid
2013 conf
ReConFig
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2013 conf
ISSoC
Mariem Turki, Habib Mehrez, Zied Marrakchi, Mohamed Abid
2013 conf
ARC
Vinod Pangracious, Zied Marrakchi, Emna Amouri, Habib Mehrez
2013 conf
ACM Great Lakes Symposium on VLSI
Vinod Pangracious, Emna Amouri, Habib Mehrez, Zied Marrakchi
2013 conf
NEWCAS
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2013 C conf
RSP
Qingshan Tang, Matthieu Tuna, Habib Mehrez
2013 conf
ICICDT
Vinod Pangracious, Habib Mehrez, Zied Marrakchi
2012 conf
DTIS
Alp Kiliç, Zied Marrakchi, Matthieu Tuna, Habib Mehrez
2012 J jnl
Microprocess. Microsystems
Umer Farooq, Husain Parvez, Habib Mehrez, Zied Marrakchi
2012 C conf
RSP
Qingshan Tang, Habib Mehrez, Matthieu Tuna
2012 conf
ReConFig
Karim M. Abdellatif, Roselyne Chotin-Avot, Habib Mehrez
2012 conf
ReConFig
Mariem Turki, Habib Mehrez, Zied Marrakchi
2011 J jnl
ACM Trans. Reconfigurable Technol. Syst.
Husain Parvez, Zied Marrakchi, Alp Kiliç, Habib Mehrez
2011 conf
ARC
Umer Farooq, Husain Parvez, Zied Marrakchi, Habib Mehrez
2011 conf
ReCoSoC
Emna Amouri, Zied Marrakchi, Habib Mehrez
2011 J jnl
Int. J. Reconfigurable Comput.
Umer Farooq, Husain Parvez, Habib Mehrez, Zied Marrakchi
2011 conf
ISQED
Sophie Belloeil-Dupuis, Roselyne Chotin-Avot, Habib Mehrez
2010 conf
ICECS
Ludovic Noury, Habib Mehrez
2010 conf
ARC
Husain Parvez, Zied Marrakchi, Habib Mehrez
2010 conf
APCCAS
Emna Amouri, Zied Marrakchi, Habib Mehrez
2010 conf
ReCoSoC
Umer Farooq, Husain Parvez, Zied Marrakchi, Habib Mehrez
2010 A conf
FPGA
Husain Parvez, Zied Marrakchi, Habib Mehrez
2010 conf
APCCAS
Zied Marrakchi, Husain Parvez, Alp Kiliç, Habib Mehrez, Hmaied Marrakchi
2010 conf
IDT
Mariem Turki, Mohamed Abid, Zied Marrakchi, Habib Mehrez
2009 conf
FPT
Husain Parvez, Zied Marrakchi, Habib Mehrez
2009 J jnl
Int. J. Reconfigurable Comput.
Zied Marrakchi, Hayder Mrabet, Umer Farooq, Habib Mehrez
2009 conf
ReConFig
Emna Amouri, Hayder Mrabet, Zied Marrakchi, Habib Mehrez
2009 conf
ICECS
Emna Amouri, Hayder Mrabet, Zied Marrakchi, Habib Mehrez
2008 conf
FPT
Husain Parvez, Zied Marrakchi, Umer Farooq, Habib Mehrez
2008 conf
ISVLSI
Sophie Belloeil, Roselyne Chotin-Avot, Habib Mehrez
2008 conf
ACM Great Lakes Symposium on VLSI
Zied Marrakchi, Hayder Mrabet, Emna Amouri, Habib Mehrez
2008 conf
ReConFig
Husain Parvez, Zied Marrakchi, Habib Mehrez
2008 J jnl
Tech. Sci. Informatiques
Ana Abril, Habib Mehrez, Frédéric Pétrot, Jean Gobert, Carolina Miro
2008 conf
ReConFig
Umer Farooq, Zied Marrakchi, Hayder Mrabet, Habib Mehrez
2007 conf
FPT
Zied Marrakchi, Hayder Mrabet, Christian Masson, Habib Mehrez
2007 conf
NOCS
Zied Marrakchi, Hayder Mrabet, Christian Masson, Habib Mehrez
2006 A conf
FPGA
Hayder Mrabet, Zied Marrakchi, Pierre Souillot, Habib Mehrez
2006 conf
ISVLSI
Zied Marrakchi, Hayder Mrabet, Habib Mehrez
2006 A conf
FPGA
Zied Marrakchi, Hayder Mrabet, Habib Mehrez
2006 conf
ReCoSoC
Hayder Mrabet, Zied Marrakchi, Pierre Souillot, Habib Mehrez, André Tissot
2006 A conf
ICCAD
Hayder Mrabet, Zied Marrakchi, Pierre Souillot, Habib Mehrez
2005 conf
ReConFig
Zied Marrakchi, Hayder Mrabet, Habib Mehrez
2005 conf
ReCoSoC
Hayder Mrabet, Zied Marrakchi, Habib Mehrez, André Tissot
2004 J jnl
Numer. Algorithms
Roselyne Avot-Chotin, Habib Mehrez
2002 conf
ICECS
Roselyne Chotin, Habib Mehrez
2002 conf
ICECS
Ana Belén Abril García, Jean Gobert, Thomas Dombek, Habib Mehrez, Frédéric Pétrot
2001 conf
ISCAS (4)
Yannick Dumonteix, Yann Bajot, Habib Mehrez
2001 conf
ISCAS (4)
Yann Bajot, Habib Mehrez
2000 conf
CAMP
Mourad Aberbour, Habib Mehrez, François Durbin, Jacques Haussy, P. Lalande, André Tissot
2000 C conf
ISCAS
Yannick Dumonteix, Habib Mehrez
1998 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Mourad Aberbour, A. Houelle, Habib Mehrez, Nicolas Vaucher, Alain Guyot
1997 conf
MSE
Mourad Aberbour, Anne Derieux, Habib Mehrez, Nicolas Vaucher
1995 C conf
IEEE Symposium on Computer Arithmetic
A. Houelle, Habib Mehrez, Nicolas Vaucher, Luis A. Montalvo, Alain Guyot
1995 Misc conf
VLSI Design
Alain Guyot, Luis A. Montalvo, A. Houelle, Habib Mehrez, Nicolas Vaucher
tests/unit/test_database_exporters.py
← Index tests/unit/test_database_exporters.py python
"""
Unit tests for database exporters.
"""
import pytest
import json
from dataclasses import dataclass, asdict
from datetime import datetime, timezone
from unittest.mock import Mock, patch, MagicMock

pytestmark = [pytest.mark.unit, pytest.mark.exporters]


# ============================================================================
# Sample Dataclass for Testing
# ============================================================================

@dataclass
class SampleData:
    """Sample dataclass for export testing."""
    sha256: str = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    name: str = "test_sample"
    value: int = 42
    _id: str = "test_id"


# ============================================================================
# PrintExporter Tests
# ============================================================================

class TestPrintExporter:
    """Tests for PrintExporter class."""

    def test_initialization(self, mock_logger):
        """Test PrintExporter initialization."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")

        assert exporter.index_prefix == "test_index"
        assert exporter.log is mock_logger

    def test_export_dataclass(self, mock_logger, capsys):
        """Test exporting a dataclass."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")
        sample = SampleData()

        result = exporter.export(sample)

        assert result is True
        captured = capsys.readouterr()
        assert "test_sample" in captured.out

    def test_export_list_of_dataclasses(self, mock_logger, capsys):
        """Test exporting a list of dataclasses."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")
        samples = [SampleData(name="sample1"), SampleData(name="sample2")]

        result = exporter.export(samples)

        assert result is True
        captured = capsys.readouterr()
        assert "sample1" in captured.out
        assert "sample2" in captured.out

    def test_export_dict(self, mock_logger, capsys):
        """Test exporting a dictionary."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")
        data = {"key": "value", "number": 42}

        result = exporter.export(data)

        assert result is True
        captured = capsys.readouterr()
        assert "key" in captured.out
        assert "value" in captured.out

    def test_export_none(self, mock_logger):
        """Test exporting None."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")

        result = exporter.export(None)

        assert result is True

    def test_export_empty_list(self, mock_logger):
        """Test exporting empty list."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")

        result = exporter.export([])

        assert result is True


# ============================================================================
# ElasticsearchExporter Tests
# ============================================================================

class TestElasticsearchExporter:
    """Tests for ElasticsearchExporter class."""

    def test_initialization(self, mock_logger):
        """Test ElasticsearchExporter initialization."""
        with patch('redb.settings.get_elasticsearch_client') as mock_client:
            mock_client.return_value = Mock()
            from redb.extractors.database_exporters import ElasticsearchExporter

            exporter = ElasticsearchExporter(mock_logger, "test_index")

            assert exporter.index_prefix == "test_index"
            assert exporter.log is mock_logger
            assert exporter.client is not None

    def test_export_dataclass(self, mock_logger):
        """Test exporting a dataclass to Elasticsearch."""
        with patch('redb.settings.get_elasticsearch_client') as mock_get_client:
            mock_client = Mock()
            mock_get_client.return_value = mock_client

            from redb.extractors.database_exporters import ElasticsearchExporter

            exporter = ElasticsearchExporter(mock_logger, "test_index")
            sample = SampleData()

            result = exporter.export(
                sample,
                index="test_index",
                tag="test_tag",
                hashes={"sha256": sample.sha256}
            )

            assert result is True
            mock_client.index.assert_called()

    def test_export_list(self, mock_logger):
        """Test exporting a list to Elasticsearch."""
        with patch('redb.settings.get_elasticsearch_client') as mock_get_client:
            mock_client = Mock()
            mock_get_client.return_value = mock_client

            from redb.extractors.database_exporters import ElasticsearchExporter

            exporter = ElasticsearchExporter(mock_logger, "test_index")
            samples = [SampleData(name="sample1"), SampleData(name="sample2")]

            result = exporter.export(
                samples,
                index="test_index",
                tag="test_tag",
                hashes={"sha256": "test_hash"}
            )

            assert result is True
            # Should be called twice (once per sample)
            assert mock_client.index.call_count == 2

    def test_export_failure(self, mock_logger):
        """Test handling export failure."""
        with patch('redb.settings.get_elasticsearch_client') as mock_get_client:
            mock_client = Mock()
            mock_client.index.side_effect = Exception("Connection failed")
            mock_get_client.return_value = mock_client

            from redb.extractors.database_exporters import ElasticsearchExporter

            exporter = ElasticsearchExporter(mock_logger, "test_index")
            sample = SampleData()

            result = exporter.export(
                sample,
                index="test_index",
                tag="test_tag",
                hashes={"sha256": sample.sha256}
            )

            assert result is False
            mock_logger.error.assert_called()

    def test_export_with_custom_id(self, mock_logger):
        """Test exporting with custom _id field."""
        with patch('redb.settings.get_elasticsearch_client') as mock_get_client:
            mock_client = Mock()
            mock_get_client.return_value = mock_client

            from redb.extractors.database_exporters import ElasticsearchExporter

            exporter = ElasticsearchExporter(mock_logger, "test_index")
            sample = SampleData(_id="custom_id")

            result = exporter.export(
                sample,
                index="test_index",
                tag="test_tag",
                hashes={"sha256": sample.sha256}
            )

            assert result is True


# ============================================================================
# ClickHouseExporter Tests
# ============================================================================

class TestClickHouseExporter:
    """Tests for ClickHouseExporter class."""

    def test_initialization(self, mock_logger):
        """Test ClickHouseExporter initialization."""
        from redb.extractors.database_exporters import ClickHouseExporter

        mock_client = Mock()
        exporter = ClickHouseExporter(mock_logger, "test_index", client=mock_client)

        assert exporter.index_prefix == "test_index"
        assert exporter.log is mock_logger
        assert exporter.client is mock_client

    def test_export_tuple_data(self, mock_logger):
        """Test exporting tuple data to ClickHouse."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.return_value = True
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            data = [["hash123", "sample.exe", 1024]]
            column_names = ["sha256", "name", "size"]
            column_type_names = ["String", "String", "UInt64"]

            result = exporter.export(
                (data, column_names, column_type_names),
                table="test_table"
            )

            assert result is True

    def test_export_multi_table(self, mock_logger):
        """Test exporting multi-table data to ClickHouse."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.return_value = True
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            data = {
                'multi_table': True,
                'table1': {
                    'table': 'test_table1',
                    'data': [["hash123", "sample.exe"]],
                    'column_names': ["sha256", "name"],
                    'column_type_names': ["String", "String"]
                }
            }

            result = exporter.export(data)

            assert result is True

    def test_export_failure(self, mock_logger):
        """Test handling export failure."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.side_effect = Exception("Connection failed")
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            data = [["hash123", "sample.exe", 1024]]
            column_names = ["sha256", "name", "size"]
            column_type_names = ["String", "String", "UInt64"]

            result = exporter.export(
                (data, column_names, column_type_names),
                table="test_table"
            )

            assert result is False

    def test_export_missing_table(self, mock_logger):
        """Test export without table name raises error."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            data = [["hash123", "sample.exe", 1024]]
            column_names = ["sha256", "name", "size"]
            column_type_names = ["String", "String", "UInt64"]

            result = exporter.export(
                (data, column_names, column_type_names)
                # Missing table parameter
            )

            assert result is False

    def test_get_client(self, mock_logger):
        """Test get_client method."""
        from redb.extractors.database_exporters import ClickHouseExporter

        mock_client = Mock()
        exporter = ClickHouseExporter(mock_logger, "test_index", client=mock_client)

        result = exporter.get_client()

        assert result is mock_client

    def test_get_client_creates_new(self, mock_logger):
        """Test get_client creates new client if none exists."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_new_client = Mock()
            mock_create.return_value = mock_new_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            result = exporter.get_client()

            assert result is mock_new_client


# ============================================================================
# DatabaseExporter Abstract Base Class Tests
# ============================================================================

class TestDatabaseExporter:
    """Tests for DatabaseExporter abstract base class."""

    def test_cannot_instantiate_abstract(self):
        """Test that DatabaseExporter cannot be instantiated directly."""
        from redb.extractors.database_exporters import DatabaseExporter

        with pytest.raises(TypeError):
            DatabaseExporter()

    def test_subclass_must_implement_export(self):
        """Test that subclasses must implement export method."""
        from redb.extractors.database_exporters import DatabaseExporter

        # Define incomplete subclass
        class IncompleteExporter(DatabaseExporter):
            pass

        with pytest.raises(TypeError):
            IncompleteExporter()


# ============================================================================
# Null/Edge Case Tests
# ============================================================================

class TestExporterEdgeCases:
    """Tests for edge cases in exporters."""

    def test_print_exporter_with_complex_nested_data(self, mock_logger, capsys):
        """Test PrintExporter with complex nested data."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")
        data = {
            "level1": {
                "level2": {
                    "level3": [1, 2, 3]
                }
            },
            "array": [{"a": 1}, {"b": 2}]
        }

        result = exporter.export(data)

        assert result is True
        captured = capsys.readouterr()
        assert "level1" in captured.out

    def test_clickhouse_null_handling(self, mock_logger):
        """Test ClickHouse exporter handles null values."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.return_value = True
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            # Multi-table data with null values
            data = {
                'multi_table': True,
                'table1': {
                    'table': 'test_table',
                    'data': [[None, "sample.exe", None]],
                    'column_names': ["sha256", "name", "size"],
                    'column_type_names': ["Nullable(String)", "String", "Nullable(UInt64)"]
                }
            }

            result = exporter.export(data)

            # Should handle nulls appropriately
            assert result is True

    def test_clickhouse_array_handling(self, mock_logger):
        """Test ClickHouse exporter handles array types."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.return_value = True
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            data = {
                'multi_table': True,
                'table1': {
                    'table': 'test_table',
                    'data': [["hash", ["tag1", "tag2"]]],
                    'column_names': ["sha256", "tags"],
                    'column_type_names': ["String", "Array(String)"]
                }
            }

            result = exporter.export(data)

            assert result is True


# ============================================================================
# Type Conversion Tests
# ============================================================================

class TestExporterTypeConversions:
    """Tests for type conversions in exporters."""

    def test_clickhouse_datetime_handling(self, mock_logger):
        """Test ClickHouse exporter handles datetime values."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_client.insert.return_value = True
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            now = datetime.now(timezone.utc)
            data = {
                'multi_table': True,
                'table1': {
                    'table': 'test_table',
                    'data': [["hash", now]],
                    'column_names': ["sha256", "timestamp"],
                    'column_type_names': ["String", "DateTime64(3, 'UTC')"]
                }
            }

            result = exporter.export(data)

            assert result is True

    def test_print_exporter_datetime_serialization(self, mock_logger, capsys):
        """Test PrintExporter handles datetime serialization."""
        from redb.extractors.database_exporters import PrintExporter

        exporter = PrintExporter(mock_logger, "test_index")
        now = datetime.now(timezone.utc)
        data = {"timestamp": now, "name": "test"}

        result = exporter.export(data)

        assert result is True
        captured = capsys.readouterr()
        assert "timestamp" in captured.out


# ============================================================================
# Connection Context Manager Tests
# ============================================================================

class TestClickHouseConnectionManager:
    """Tests for ClickHouse connection context manager."""

    def test_clickhouse_connection_context(self, mock_logger):
        """Test clickhouse_connection context manager."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            with exporter.clickhouse_connection() as client:
                assert client is mock_client

            # Client should be closed after context exits
            mock_client.close.assert_called()

    def test_clickhouse_connection_close_on_error(self, mock_logger):
        """Test client is closed even if operation fails."""
        with patch('redb.settings.create_clickhouse_client') as mock_create:
            mock_client = Mock()
            mock_create.return_value = mock_client

            from redb.extractors.database_exporters import ClickHouseExporter

            exporter = ClickHouseExporter(mock_logger, "test_index")

            try:
                with exporter.clickhouse_connection() as client:
                    raise ValueError("Test error")
            except ValueError:
                pass

            # Client should still be closed
            mock_client.close.assert_called()