Manlio Bacco

49 papers A 1B 3C 3Journal 21Unranked 21
YearRankTypeTitle / Venue / Authors
2025 conf
IS-EUD
Chiara Mannari, Tommaso Turchi, Caterina Frosali, Manlio Bacco, Alessio Ferrari, Cristina Conati, Alessio Malizia
2025 conf
REW
Chiara Mannari, Tommaso Turchi, Manlio Bacco, Alessio Malizia
2025 B conf
REFSQ
Chiara Mannari, Mino Sportelli, Harika Meesala, Ogochukwu Felicitas Okoye, Fabio Lepore, Manlio Bacco, Gianluca Brunori, Alessio Malizia, Alessio Ferrari
2024 C conf
FedCSIS
Manlio Bacco, Alexander Kocian, Antonino Crivello, Marco Gori, Giovanna Maria Dimitri, Paolo Barsocchi, Gianluca Brunori, Stefano Chessa
2024 conf
CoPDA@AVI
Chiara Mannari, Elisa Anichini, Manlio Bacco, Alessio Ferrari, Tommaso Turchi, Alessio Malizia
2024 J jnl
ERCIM News
Chiara Mannari, Alessio Ferrari, Manlio Bacco
2024 conf
RE Workshops
Chiara Mannari, Manlio Bacco, Giorgio Oronzo Spagnolo, Alessio Malizia, Alessio Ferrari
2023 conf
REFSQ Workshops
Chiara Mannari, Giorgio Oronzo Spagnolo, Manlio Bacco, Alessio Malizia
2023 A conf
RE
Chiara Mannari, Elisa Anichini, Manlio Bacco, Alessio Ferrari, Tommaso Turchi, Alessio Malizia
2022 J jnl
IEEE Commun. Mag.
Achilles Machumilane, Alberto Gotta, Pietro Cassarà, Manlio Bacco
2022 J jnl
Veh. Commun.
Manlio Bacco, Pietro Cassarà, Alberto Gotta
2022 J jnl
Inf. Softw. Technol.
Alessio Ferrari, Manlio Bacco, Kirsten Gaber, Andreas Jedlitschka, Steffen Hess, Jouni Kaipainen, Panagiota Koltsida, Eleni Toli, Gianluca Brunori
2022 J jnl
CoRR
Manlio Bacco, Franca Delmastro, Erina Ferro, Alberto Gotta
2022 J jnl
ERCIM News
Alessio Ferrari, Manlio Bacco
2022 J jnl
Sensors
Francesco Alessio Dicandia, Nelson J. G. Fonseca, Manlio Bacco, Sara Mugnaini, Simone Genovesi
2021 J jnl
CoRR
Alessio Ferrari, Manlio Bacco, Kirsten Moore, Andreas Jedlitschka, Steffen Hess, Jouni Kaipainen, Panagiota Koltsida, Eleni Toli, Gianluca Brunori
2021 conf
COINS
Davide Bacciu, Siranush Akarmazyan, Eric Armengaud, Manlio Bacco, George Bravos, Calogero Calandra, Emanuele Carlini, Antonio Carta, Pietro Cassarà, Massimo Coppola, Charalampos Davalas, Patrizio Dazzi, Maria Carmela De Gennaro, Daniele Di Sarli, Jürgen Dobaj, Claudio Gallicchio, Sylvain Girbal, Alberto Gotta, Riccardo Groppo, Vincenzo Lomonaco, Georg Macher, Daniele Mazzei, Gabriele Mencagli, Dimitrios Michail, Alessio Micheli, Roberta Peroglio, Salvatore Petroni, Rosaria Potenza, Farank Pourdanesh, Christos Sardianos, Konstantinos Tserpes, Fulvio Tagliabo, Jakob Valtl, Iraklis Varlamis, Omar Veledar
2021 J jnl
CoRR
Davide Bacciu, Siranush Akarmazyan, Eric Armengaud, Manlio Bacco, George Bravos, Calogero Calandra, Emanuele Carlini, Antonio Carta, Pietro Cassarà, Massimo Coppola, Charalampos Davalas, Patrizio Dazzi, Maria Carmela De Gennaro, Daniele Di Sarli, Jürgen Dobaj, Claudio Gallicchio, Sylvain Girbal, Alberto Gotta, Riccardo Groppo, Vincenzo Lomonaco, Georg Macher, Daniele Mazzei, Gabriele Mencagli, Dimitrios Michail, Alessio Micheli, Roberta Peroglio, Salvatore Petroni, Rosaria Potenza, Farank Pourdanesh, Christos Sardianos, Konstantinos Tserpes, Fulvio Tagliabo, Jakob Valtl, Iraklis Varlamis, Omar Veledar
2020 conf
ADHOC-NOW
Manlio Bacco, Pietro Cassarà, Alberto Gotta, Massimo Puddu
2020 conf
GIoTS
Manlio Bacco, Gianluca Brunori, Alessio Ferrari, Panagiota Koltsida, Eleni Toli
2020 J jnl
IEEE Access
Manlio Bacco, Paolo Barsocchi, Pietro Cassarà, Danila Germanese, Alberto Gotta, Giuseppe Riccardo Leone, Davide Moroni, Maria Antonietta Pascali, Marco Tampucci
2020 conf
REFSQ Workshops
Manlio Bacco, Gianluca Brunori, Felice Dell'Orletta, Alessio Ferrari
2019 conf
ICC
Manlio Bacco, Pietro Cassarà, Alberto Gotta, Tomaso de Cola
2019 J jnl
ERCIM News
Manlio Bacco, Pietro Cassarà, Alberto Gotta
2019 J jnl
IEEE Wirel. Commun.
Manlio Bacco, Luca Boero, Pietro Cassarà, Marco Colucci, Alberto Gotta, Mario Marchese, Fabio Patrone
2019 conf
5G World Forum
Manlio Bacco, Franco Davoli, Giovanni Giambene, Alberto Gotta, Michele Luglio, Mario Marchese, Fabio Patrone, Cesare Roseti
2019 conf
VTC Fall
Manlio Bacco, Pietro Cassarà, Alberto Gotta, Vincenzo Pellegrini
2019 J jnl
Int. J. Satell. Commun. Netw.
Manlio Bacco, Marco Colucci, Alberto Gotta, Charilaos I. Kourogiorgas, Athanasios D. Panagopoulos
2019 J jnl
IEEE Trans. Aerosp. Electron. Syst.
Manlio Bacco, Tomaso de Cola, Giovanni Giambene, Alberto Gotta
2019 J jnl
Array
Manlio Bacco, Paolo Barsocchi, Erina Ferro, Alberto Gotta, Massimiliano Ruggeri
2018 J jnl
IEEE Commun. Lett.
Manlio Bacco, Andrea Berton, Alberto Gotta, Luca Caviglione
2018 J jnl
IEEE J. Sel. Areas Commun.
Manlio Bacco, Pietro Cassarà, Marco Colucci, Alberto Gotta
2018 B conf
GLOBECOM
Manlio Bacco, Matteo Catena, Tomaso de Cola, Alberto Gotta, Nicola Tonellotto
2017 conf
WISATS
Manlio Bacco, Pietro Cassarà, Marco Colucci, Alberto Gotta, Mario Marchese, Fabio Patrone
2017 J jnl
CoRR
Manlio Bacco, Marco Colucci, Alberto Gotta
2017 conf
ICC
Manlio Bacco, Marco Colucci, Alberto Gotta
2017 J jnl
Int. J. Satell. Commun. Netw.
Manlio Bacco, Alberto Gotta
2017 conf
WISATS
Manlio Bacco, Stefano Chessa, Marco Di Benedetto, Davide Fabbri, Michele Girolami, Alberto Gotta, Davide Moroni, Maria Antonietta Pascali, Vincenzo Pellegrini
2016 J jnl
CoRR
Manlio Bacco, Tomaso de Cola, Giovanni Giambene, Alberto Gotta
2015 conf
BlackSeaCom
Manlio Bacco, Alberto Gotta, Michele Luglio, Cesare Roseti, Francesco Zampognaro
2015 conf
ISWCS
Manlio Bacco, Tomaso de Cola, Giovanni Giambene, Alberto Gotta
2015 conf
WISATS
Giovanni Giambene, Muhammad Muhammad, Doanh Kim Luong, Manlio Bacco, Alberto Gotta, Nedo Celandroni, Esua Kinyuy Jaff, Misfa Susanto, Yim-Fun Hu, Prashant Pillai, Muhammad Ali, Tomaso de Cola
2015 B conf
GLOBECOM
Manlio Bacco, Tomaso de Cola, Alberto Gotta
2014 conf
ASMS/SPSC
Manlio Bacco, Alberto Gotta, Cesare Roseti, Francesco Zampognaro
2014 J jnl
EAI Endorsed Trans. Mob. Commun. Appl.
Manlio Bacco, Pietro Cassarà, Alberto Gotta
2014 C conf
MobiQuitous
Manlio Bacco, Erina Ferro, Alberto Gotta
2014 conf
PSATS
Manlio Bacco, Luca Caviglione, Alberto Gotta
2013 conf
PSATS
Manlio Bacco, Pietro Cassarà, Erina Ferro, Alberto Gotta
2011 C conf
ISCC
Andrea Martelli, Luigi Alfredo Grieco, Manlio Bacco, Gennaro Boggia, Pietro Camarda
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()