Omar Fawzi

110 papers A* 11A 5B 12Journal 73Unranked 7
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Inf. Theory
Kun Fang, Hamza Fawzi, Omar Fawzi
2026 J jnl
IEEE Trans. Inf. Theory
Matthias Christandl, Omar Fawzi, Ashutosh Goswami
2026 J jnl
IEEE Trans. Inf. Theory
Kun Fang, Hamza Fawzi, Omar Fawzi
2025 J jnl
CoRR
Kun Fang, Hamza Fawzi, Omar Fawzi
2025 J jnl
CoRR
Idris Delsol, Omar Fawzi, Jan Kochanowski, Akshay Ramachandran
2025 J jnl
CoRR
Hamza Fawzi, Omar Fawzi
2025 J jnl
Trans. Mach. Learn. Res.
Hamza Fawzi, Omar Fawzi
2025 J jnl
CoRR
Victor Martinez, Armando Angrisani, Ekaterina Pankovets, Omar Fawzi, Daniel Stilck França
2025 J jnl
IEEE Trans. Inf. Theory
Omar Fawzi, Aadil Oufkir, Daniel Stilck França
2024 J jnl
IEEE Trans. Inf. Theory
Omar Fawzi, Paul Fermé
2024 J jnl
Quantum
Peter J. Brown, Hamza Fawzi, Omar Fawzi
2024 J jnl
CoRR
Kun Fang, Hamza Fawzi, Omar Fawzi
2024 J jnl
CoRR
Omar Fawzi, Richard Kueng, Damian Markham, Aadil Oufkir
2024 J jnl
Nat.
Bernardino Romera-Paredes, Mohammadamin Barekatain, Alexander Novikov, Matej Balog, M. Pawan Kumar, Emilien Dupont, Francisco J. R. Ruiz, Jordan S. Ellenberg, Pengming Wang, Omar Fawzi, Pushmeet Kohli, Alhussein Fawzi
2024 J jnl
IEEE Trans. Inf. Theory
Omar Fawzi, Paul Fermé
2024 B conf
ISIT
Mario Berta, Omar Fawzi, Aadil Oufkir
2024 J jnl
CoRR
Aadil Oufkir, Omar Fawzi, Mario Berta
2024 J jnl
Quantum
Stefan Bäuml, Carlos Pascual-García, Victoria Wright, Omar Fawzi, Antonio Acín
2023 ed.
TQC
Omar Fawzi, Michael Walter
2023 A conf
ITCS
Hamza Fawzi, Omar Fawzi, Samuel O. Scalet
2023 J jnl
Quantum
Hamza Fawzi, Omar Fawzi, Samuel O. Scalet
2023 J jnl
CoRR
Omar Fawzi, Paul Fermé
2023 J jnl
CoRR
Omar Fawzi, Aadil Oufkir, Daniel Stilck França
2023 J jnl
Trans. Mach. Learn. Res.
Omar Fawzi, Nicolas Flammarion, Aurélien Garivier, Aadil Oufkir
2023 A* conf
COLT
Omar Fawzi, Nicolas Flammarion, Aurélien Garivier, Aadil Oufkir
2023 J jnl
CoRR
Omar Fawzi, Nicolas Flammarion, Aurélien Garivier, Aadil Oufkir
2022 J jnl
IEEE Trans. Inf. Theory
Omar Fawzi, Ala Shayeghi, Hoang Ta
2022 A conf
ITCS
Omar Fawzi, Alexander Müller-Hermes, Ala Shayeghi
2022 J jnl
CoRR
Omar Fawzi, Alexander Müller-Hermes, Ala Shayeghi
2022 B conf
ISIT
Omar Fawzi, Paul Fermé
2022 J jnl
CoRR
Omar Fawzi, Paul Fermé
2022 A* conf
FOCS
Tony Metger, Omar Fawzi, David Sutter, Renato Renner
2022 J jnl
CoRR
Tony Metger, Omar Fawzi, David Sutter, Renato Renner
2022 A conf
ITCS
Matthias Christandl, Omar Fawzi, Hoang Ta, Jeroen Zuiddam
2022 conf
ASIACRYPT (4)
Julien Devevey, Omar Fawzi, Alain Passelègue, Damien Stehlé
2022 J jnl
IACR Cryptol. ePrint Arch.
Julien Devevey, Omar Fawzi, Alain Passelègue, Damien Stehlé
2022 J jnl
Math. Program.
Mario Berta, Francesco Borderi, Omar Fawzi, Volkher B. Scholz
2022 J jnl
CoRR
Omar Fawzi, Nicolas Flammarion, Aurélien Garivier, Aadil Oufkir
2022 J jnl
Math. Program.
Siddharth Barman, Omar Fawzi, Suprovat Ghoshal, Emirhan Gürpinar
2021 B conf
ISIT
Omar Fawzi, Ala Shayeghi, Hoang Ta
2021 J jnl
IEEE Trans. Inf. Theory
David Sutter, Omar Fawzi, Renato Renner
2021 J jnl
CoRR
Matthias Christandl, Omar Fawzi, Hoang Ta, Jeroen Zuiddam
2021 J jnl
Commun. ACM
Omar Fawzi, Antoine Grospellier, Anthony Leverrier
2021 J jnl
Quantum
Hamza Fawzi, Omar Fawzi
2021 J jnl
CoRR
Matthias Christandl, Omar Fawzi, Hoang Ta, Jeroen Zuiddam
2021 A* conf
ICALP
Hyejung H. Jee, Carlo Sparaciari, Omar Fawzi, Mario Berta
2021 A* conf
NeurIPS
Aadil Oufkir, Omar Fawzi, Nicolas Flammarion, Aurélien Garivier
2021 A conf
STACS
Siddharth Barman, Omar Fawzi, Paul Fermé
2020 B conf
ITW
Omar Fawzi, Lucien Grouès, Anthony Leverrier
2020 B conf
IPCO
Siddharth Barman, Omar Fawzi, Suprovat Ghoshal, Emirhan Gürpinar
2020 J jnl
CoRR
Siddharth Barman, Omar Fawzi, Paul Fermé
2019 J jnl
CoRR
Kun Fang, Omar Fawzi, Renato Renner, David Sutter
2019 B conf
ISIT
Omar Fawzi, Johanna Seif, Dániel Szilágyi
2019 J jnl
CoRR
David Sutter, Omar Fawzi, Renato Renner
2019 book
Omar Fawzi
2019 J jnl
IEEE Trans. Inf. Theory
Frédéric Dupuis, Omar Fawzi
2019 A* conf
NeurIPS
Alhussein Fawzi, Mateusz Malinowski, Hamza Fawzi, Omar Fawzi
2019 J jnl
CoRR
Alhussein Fawzi, Mateusz Malinowski, Hamza Fawzi, Omar Fawzi
2019 B conf
ISIT
Mario Berta, Francesco Borderi, Omar Fawzi, Volkher B. Scholz
2019 J jnl
CoRR
Siddharth Barman, Omar Fawzi, Suprovat Ghoshal, Emirhan Gürpinar
2018 A* conf
NeurIPS
Alhussein Fawzi, Hamza Fawzi, Omar Fawzi
2018 J jnl
CoRR
Alhussein Fawzi, Hamza Fawzi, Omar Fawzi
2018 J jnl
IEEE Trans. Inf. Theory
Siddharth Barman, Omar Fawzi
2018 J jnl
Mach. Learn.
Alhussein Fawzi, Omar Fawzi, Pascal Frossard
2018 A* conf
FOCS
Omar Fawzi, Antoine Grospellier, Anthony Leverrier
2018 J jnl
CoRR
Omar Fawzi, Antoine Grospellier, Anthony Leverrier
2018 A* conf
STOC
Omar Fawzi, Antoine Grospellier, Anthony Leverrier
2018 conf
ICLR (Poster)
Seyed-Mohsen Moosavi-Dezfooli, Alhussein Fawzi, Omar Fawzi, Pascal Frossard, Stefano Soatto
2018 A conf
AISTATS
Jean-Yves Franceschi, Alhussein Fawzi, Omar Fawzi
2018 J jnl
CoRR
Jean-Yves Franceschi, Alhussein Fawzi, Omar Fawzi
2017 J jnl
CoRR
Seyed-Mohsen Moosavi-Dezfooli, Alhussein Fawzi, Omar Fawzi, Pascal Frossard, Stefano Soatto
2017 J jnl
CoRR
Omar Fawzi, Antoine Grospellier, Anthony Leverrier
2017 J jnl
CoRR
Anil Ada, Omar Fawzi, Raghav Kulkarni
2017 J jnl
IEEE Trans. Inf. Theory
Mario Berta, Omar Fawzi, Volkher B. Scholz
2017 A* conf
CVPR
Seyed-Mohsen Moosavi-Dezfooli, Alhussein Fawzi, Omar Fawzi, Pascal Frossard
2016 B conf
ISIT
Siddharth Barman, Omar Fawzi
2016 J jnl
CoRR
Frédéric Dupuis, Omar Fawzi, Renato Renner
2016 B conf
ISIT
Mario Berta, Omar Fawzi, Marco Tomamichel
2016 J jnl
SIAM J. Optim.
Mario Berta, Omar Fawzi, Volkher B. Scholz
2016 J jnl
CoRR
Seyed-Mohsen Moosavi-Dezfooli, Alhussein Fawzi, Omar Fawzi, Pascal Frossard
2015 J jnl
CoRR
Siddharth Barman, Omar Fawzi
2015 J jnl
CoRR
Alhussein Fawzi, Omar Fawzi, Pascal Frossard
2015 J jnl
IEEE Trans. Inf. Theory
Frédéric Dupuis, Omar Fawzi, Stephanie Wehner
2015 J jnl
CoRR
Mario Berta, Omar Fawzi, Marco Tomamichel
2015 conf
TQC
Mario Berta, Omar Fawzi, Volkher B. Scholz
2015 J jnl
Comput. Complex.
Anil Ada, Arkadev Chattopadhyay, Omar Fawzi, Phuong Nguyen
2015 J jnl
CoRR
David Sutter, Omar Fawzi, Renato Renner
2014 J jnl
IEEE Trans. Inf. Theory
Mario Berta, Omar Fawzi, Stephanie Wehner
2014 B conf
ISIT
Mario Berta, Omar Fawzi, Volkher B. Scholz, Oleg Szehr
2013 conf
CRYPTO (2)
Frédéric Dupuis, Omar Fawzi, Stephanie Wehner
2013 J jnl
IACR Cryptol. ePrint Arch.
Frédéric Dupuis, Omar Fawzi, Stephanie Wehner
2013 J jnl
J. ACM
Omar Fawzi, Patrick M. Hayden, Pranab Sen
2013 B conf
ISIT
Lukas Drescher, Omar Fawzi
2013 J jnl
CoRR
Lukas Drescher, Omar Fawzi
2013 B conf
ISIT
Winton Brown, Omar Fawzi
2013 J jnl
CoRR
Winton Brown, Omar Fawzi
2012 J jnl
IEEE Trans. Inf. Theory
Omar Fawzi, Patrick M. Hayden, Ivan Savov, Pranab Sen, Mark M. Wilde
2012 J jnl
Random Struct. Algorithms
Luc Devroye, Omar Fawzi, Nicolas Fraiman
2012 J jnl
Comb. Probab. Comput.
Nicolas Broutin, Omar Fawzi
2012 A* conf
CRYPTO
Mario Berta, Omar Fawzi, Stephanie Wehner
2012 J jnl
CoRR
Omar Fawzi, Ivan Savov
2012 J jnl
CoRR
Anil Ada, Omar Fawzi, Hamed Hatami
2012 conf
APPROX-RANDOM
Anil Ada, Omar Fawzi, Hamed Hatami
2012 conf
ICALP (1)
Anil Ada, Arkadev Chattopadhyay, Omar Fawzi, Phuong Nguyen
2011 J jnl
CoRR
Omar Fawzi, Patrick M. Hayden, Ivan Savov, Pranab Sen, Mark M. Wilde
2011 A* conf
STOC
Omar Fawzi, Patrick M. Hayden, Pranab Sen
2011 conf
Allerton
Omar Fawzi, Patrick M. Hayden, Ivan Savov, Pranab Sen, Mark M. Wilde
2011 J jnl
CoRR
Ivan Savov, Omar Fawzi, Mark M. Wilde, Pranab Sen, Patrick M. Hayden
2011 J jnl
Electron. Colloquium Comput. Complex.
Anil Ada, Arkadev Chattopadhyay, Omar Fawzi, Phuong Nguyen
2010 J jnl
CoRR
Omar Fawzi, Patrick M. Hayden, Pranab Sen
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()