Vandana Pursnani Janeja

47 papers A* 3A 1C 5Misc 3Journal 16Unranked 18
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
Bayu Adhi Tama, Mansa Krishna, Homayra Alam, Mostafa Cham, Omar Faruque, Gong Cheng, Jianwu Wang, Mathieu Morlighem, Vandana Pursnani Janeja
2025 conf
ICDM (Workshops)
Alabi Ahmed, Vandana Pursnani Janeja, Sanjay Purushotham
2024 J jnl
CoRR
Bayu Adhi Tama, Vandana Pursnani Janeja, Sanjay Purushotham
2024 conf
SIGCSE (2)
Noshaba Nasir Bhalli, Vandana Pursnani Janeja, David Harding
2015 C conf
ISI
Josephine M. Namayanja, Vandana Pursnani Janeja
2015 C conf
ISI
Faisal Quader, Vandana Pursnani Janeja, Justin Stauffer
2015 conf
ICCABS
Yuanyuan Feng, Vandana Pursnani Janeja, Yelena Yesha, Naphtali Rishe, Michael A. Grasso, Amanda Niskar
2014 conf
IEEE BigData
Vandana Pursnani Janeja, Ali Azari, Josephine M. Namayanja, Brian Heilig
2014 conf
IEEE BigData
Josephine M. Namayanja, Vandana Pursnani Janeja
2014 J jnl
Intell. Data Anal.
Sandipan Dey, Vandana Pursnani Janeja, Aryya Gangopadhyay
2014 J jnl
Data Min. Knowl. Discov.
Michael P. McGuire, Vandana Pursnani Janeja, Aryya Gangopadhyay
2014 conf
ICHI
Yelena Yesha, Vandana Pursnani Janeja, Naphtali Rishe, Yaacov Yesha
2013 J jnl
Int. J. Data Warehous. Min.
Lei Shi, Vandana Pursnani Janeja
2013 C conf
ISI
Josephine M. Namayanja, Vandana Pursnani Janeja
2013 J jnl
J. Spatial Inf. Sci.
Michael P. McGuire, Vandana Pursnani Janeja, Aryya Gangopadhyay
2013 J jnl
Knowl. Inf. Syst.
Vandana Pursnani Janeja, Revathi Palanisamy
2012 conf
COM.Geo
Michael P. McGuire, Aryya Gangopadhyay, Vandana Pursnani Janeja
2012 J jnl
Int. J. Knowl. Discov. Bioinform.
Ali Azari, Vandana Pursnani Janeja, Alex Mohseni
2012 conf
ICDM Workshops
Ali Azari, Vandana Pursnani Janeja, Alex Mohseni
2012 conf
ICDE Workshops
Yanan Sun, Vandana Pursnani Janeja, Michael P. McGuire, Aryya Gangopadhyay
2011 J jnl
Int. J. Data Warehous. Min.
David M. Lewis, Vandana Pursnani Janeja
2011 J jnl
IEEE Trans. Knowl. Data Eng.
Lei Shi, Vandana Pursnani Janeja
2011 conf
GIS
Michael P. McGuire, Vandana Pursnani Janeja, Aryya Gangopadhyay
2011 J jnl
Stat. Anal. Data Min.
Vandana Pursnani Janeja, Aryya Gangopadhyay, Seyed H. Mohammadi, Revathi Palanisamy
2011 J jnl
Int. J. Comput. Model. Algorithms Medicine
Josephine M. Namayanja, Vandana Pursnani Janeja
2010 J jnl
Data Min. Knowl. Discov.
Vandana Pursnani Janeja, Nabil R. Adam, Vijayalakshmi Atluri, Jaideep Vaidya
2009 A* conf
KDD
Lei Shi, Vandana Pursnani Janeja
2009 A conf
SDM
Seyed H. Mohammadi, Vandana Pursnani Janeja, Aryya Gangopadhyay
2009 Misc conf
SAC
Mikael Lindvall, Raimund L. Feldmann, George Karabatis, Zhiyuan Chen, Vandana Pursnani Janeja
2009 J jnl
Intell. Data Anal.
Vandana Pursnani Janeja, Vijayalakshmi Atluri
2009 A* conf
ICDM
Sandipan Dey, Vandana Pursnani Janeja, Aryya Gangopadhyay
2009 J jnl
J. Data Semant.
George Karabatis, Zhiyuan Chen, Vandana Pursnani Janeja, Tania Lobo, Monish Advani, Mikael Lindvall, Raimund L. Feldmann
2008 ch.
Encyclopedia of GIS
Vandana Pursnani Janeja, Nabil R. Adam
2008 J jnl
IEEE Trans. Knowl. Data Eng.
Vandana Pursnani Janeja, Vijayalakshmi Atluri
2008 conf
KDD Workshop on Knowledge Discovery from Sensor Data
Michael P. McGuire, Vandana Pursnani Janeja, Aryya Gangopadhyay
2007 C conf
ISI
Nabil R. Adam, Vandana Pursnani Janeja, Aabhas V. Paliwal, Basit Shafiq, Cédric Ulmer, Volker Gersabeck, Anne Hardy, Christof Bornhövd, Joachim Schaper
2006 conf
DG.O
Nabil R. Adam, Vijayalakshmi Atluri, Rey Koslowski, Robert Grossman, Vandana Pursnani Janeja, Janice Warner
2006 conf
DG.O
Nabil R. Adam, Vijayalakshmi Atluri, Vandana Pursnani Janeja, Aabhas V. Paliwal, Mahmoud Youssef, Soon Ae Chun, Jim Cooper, John Paczkowski, Christof Bornhövd, Ike Nassi, Joachim Schaper
2005 conf
DG.O
Nabil R. Adam, Vijayalakshmi Atluri, Rey Koslowski, Vandana Pursnani Janeja, Janice Warner, Aabhas V. Paliwal
2005 C conf
ISI
Vandana Pursnani Janeja, Vijayalakshmi Atluri, Jaideep Vaidya, Nabil R. Adam
2005 conf
DG.O
Vandana Pursnani Janeja, Vijayalakshmi Atluri, Ahmed Gomaa, Nabil R. Adam, Christof Bornhövd, Tao Lin
2005 A* conf
ICDM
Vandana Pursnani Janeja, Vijayalakshmi Atluri
2005 Misc conf
SAC
Vandana Pursnani Janeja, Vijayalakshmi Atluri
2004 conf
DG.O
Nabil R. Adam, Vijayalakshmi Atluri, Vandana Pursnani Janeja
2004 conf
DG.O
Vandana Pursnani Janeja, Vijayalakshmi Atluri, Nabil R. Adam
2004 Misc conf
SAC
Nabil R. Adam, Vandana Pursnani Janeja, Vijayalakshmi Atluri
2002 conf
DG.O
Vandana Pursnani Janeja, Vijayalakshmi Atluri, Nabil R. Adam
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()