Mahdi Motagh

50 papers C 9Journal 39Unranked 2
YearRankTypeTitle / Venue / Authors
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Chao Zhou, Lulu Gan, Ying Cao, Yue Wang, Samuele Segoni, Xuguo Shi, Mahdi Motagh, Ramesh P. Singhc
2025 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Chen Chen, Mimi Peng, Mahdi Motagh, Xinxin Guo, Mengdao Xing, Yinghui Quan
2025 J jnl
Earth Sci. Informatics
Somayeh Ebrahimzadeh, Seyed Kazem Alavipanah, Sara Attarchi, Vahid Mahboub, Mahdi Motagh
2025 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yufang He, Bo Chen, Mahdi Motagh, Yuyan Zhu, Songdong Shao, Jiaye Li, Bing Zhang, Hermann Kaufmann
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Wandi Wang, Mahdi Motagh, Zhuge Xia, Simon Plank, Zhe Li, Aiym Orynbaikyzy, Chao Zhou, Sigrid Roessner
2024 J jnl
IEEE Geosci. Remote. Sens. Lett.
Sijie Ma, Tao Li, Mahdi Motagh, Stefan Auer, Yan Liu, Jie Liu
2024 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Yufang He, Mahdi Motagh, Xiaohang Wang, Xiaojie Liu, Hermann Kaufmann, Guochang Xu, Bo Chen
2024 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Marc Wieland, Florian W. Fichtner, Sandro Martinis, Sandro Groth, Christian Krullikowski, Simon Plank, Mahdi Motagh
2024 C conf
IGARSS
Henrik J. Persson, Ritwika Mukhopadhyay, Rubén Valbuena, Alina V. Shevchenko, Linda Lück, Martin Herold, Mahdi Motagh, Gian Oré, Eduardo Freitas, Christian Wimmer, Hugo E. Hernández-Figueroa
2023 J jnl
Remote. Sens.
Juanjuan Yu, Xiufeng He, Peng Yang, Mahdi Motagh, Jia Xu, Jiacheng Xiong
2023 conf
EnvirVis@EuroVis
Mike Sips, Magdalena Vassileva, Daniel Eggert, Mahdi Motagh
2022 J jnl
Remote. Sens.
Zohreh Erfani Jazi, Mahdi Motagh, Volker Klemann
2022 J jnl
IEEE Geosci. Remote. Sens. Lett.
Zhuge Xia, Mahdi Motagh, Tao Li
2022 J jnl
Remote. Sens.
Deying Ma, Mahdi Motagh, Guoxiang Liu, Rui Zhang, Xiaowen Wang, Bo Zhang, Wei Xiang, Bing Yu
2021 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Binayak Ghosh, Mahdi Motagh, Mahmud Haghshenas-Haghighi, Magdalena Vassileva, Thomas R. Walter, Setareh Maghsudi
2021 J jnl
Remote. Sens.
Jiyuan Hu, Mahdi Motagh, Jiayao Wang, Fen Qin, Jianchen Zhang, Wenhao Wu, Yakun Han
2021 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Vamshi Karanam, Mahdi Motagh, Shagun Garg, Kamal Jain
2021 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Wei Tang, Wei Zhan, Bowen Jin, Mahdi Motagh, Yubin Xu
2020 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Wei Tang, Mahdi Motagh, Wei Zhan
2020 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Chuanguang Zhu, Zhengshuai Wang, Peixian Li, Mahdi Motagh, Liya Zhang, Zongli Jiang, Sichun Long
2019 J jnl
Remote. Sens.
Tao Li, Mahdi Motagh, Mingzhou Wang, Wei Zhang, Chunlong Gong, Xunan Xiong, JinPing He, Lulu Chen, Jingnan Liu
2019 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Christin Lubitz, Thomas Kempka, Mahdi Motagh
2018 C conf
IGARSS
Fariba Mohammadimanesh, Bahram Salehi, Masoud MahdianPari, Mahdi Motagh
2018 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Fariba Mohammadimanesh, Bahram Salehi, Masoud MahdianPari, Mahdi Motagh, Brian Brisco
2018 J jnl
Remote. Sens.
Sanaz Vajedian, Mahdi Motagh, Zahra Mousavi, Khalil Motaghi, Eric J. Fielding, Bahman Akbari, Hans-Ulrich Wetzel, Aliakbar Darabi
2018 J jnl
Remote. Sens.
Roghayeh Shamshiri, Hossein Nahavandchi, Mahdi Motagh, Andy Hooper
2018 J jnl
Remote. Sens.
Julia Neelmeijer, Tilo Schöne, Robert Dill, Volker Klemann, Mahdi Motagh
2018 J jnl
IEEE J. Sel. Top. Appl. Earth Obs. Remote. Sens.
Roghayeh Shamshiri, Hossein Nahavandchi, Mahdi Motagh
2018 C conf
IGARSS
Sanaz Vajedian, Mahdi Motagh, Sergey V. Samsonov
2017 J jnl
IEEE Geosci. Remote. Sens. Lett.
Mostafa Esmaeili, Mahdi Motagh, Andy Hooper
2017 C conf
IGARSS
Fariba Mohammadimanesh, Bahram Salehi, Masoud MahdianPari, Mahdi Motagh
2016 J jnl
Remote. Sens.
Mi Chen, Roberto Tomás, Zhenhong Li, Mahdi Motagh, Tao Li, Leyin Hu, Huili Gong, Xiaojuan Li, Jun Yu, Xulong Gong
2015 J jnl
Remote. Sens.
Kanayim Teshebaeva, Sigrid Roessner, Helmut Echtler, Mahdi Motagh, Hans-Ulrich Wetzel, Bolot Moldobekov
2015 J jnl
Remote. Sens.
Sanaz Vajedian, Mahdi Motagh, Faramarz Nilfouroushan
2015 J jnl
Remote. Sens.
Sanaz Vajedian, Mahdi Motagh, Faramarz Nilfouroushan
2014 J jnl
Int. J. Appl. Earth Obs. Geoinformation
Masoome Amighpey, Behzad Vosooghi, Mahdi Motagh
2014 J jnl
Remote. Sens.
Julia Neelmeijer, Mahdi Motagh, Hans-Ulrich Wetzel
2014 J jnl
Remote. Sens.
Christin Lubitz, Mahdi Motagh, Hermann Kaufmann
2014 C conf
IGARSS
Nestor Yague-Martinez, Eric J. Fielding, Mahmud Haghshenas-Haghighi, Xiaoying Cong, Mahdi Motagh, Ulrich Steinbrecher, Michael Eineder, Thomas Fritz
2014 J jnl
IEEE Geosci. Remote. Sens. Lett.
Mahdi Motagh, John Beavan, Eric J. Fielding, Mahmud Haghshenas
2014 J jnl
Remote. Sens.
Mohamad Nobakht, Mahdi Motagh, Hans-Ulrich Wetzel, Sigrid Roessner, Hermann Kaufmann
2013 J jnl
Sensors
Akram Eftekhari, Mohammad Saadatseresht, Mahdi Motagh
2013 C conf
IGARSS
Mohammad Alioghli Fazel, Valentin Poncos, Saeid Homayouni, Mahdi Motagh
2013 J jnl
Remote. Sens.
Christin Lubitz, Mahdi Motagh, Hans-Ulrich Wetzel, Hermann Kaufmann
2013 J jnl
Remote. Sens.
Mehrdad Akbarimehr, Mahdi Motagh, Mahmud Haghshenas-Haghighi
2012 J jnl
IEEE Geosci. Remote. Sens. Lett.
Vahid Akbari, Mahdi Motagh
2012 conf
CIDU
Mozhdeh Shahbazi, Mahdi Motagh
2012 C conf
IGARSS
Masoud MahdianPari, Mahdi Motagh, Vahid Akbari
2012 C conf
IGARSS
Christin Lubitz, Mahdi Motagh, Hans-Ulrich Wetzel, Jan Anderssohn
2012 C conf
IGARSS
Michael Eineder, Jörn Hoffmann, Christian Minet, Mahdi Motagh, Achim Roth
tests/conftest.py
← Index tests/conftest.py python
"""
Pytest configuration and shared fixtures for REDB unit tests.
"""
import os
import sys
import pytest
import logging
import tempfile
import hashlib
from unittest.mock import Mock, MagicMock, patch
from pathlib import Path

# Add the project root to the path
sys.path.insert(0, str(Path(__file__).parent.parent))

# Test files directory
TEST_FILES_DIR = Path(__file__).parent.parent / "test_files"


# ============================================================================
# Logger Fixtures
# ============================================================================

@pytest.fixture
def mock_logger():
    """Create a mock logger for testing."""
    logger = Mock()
    logger.debug = Mock()
    logger.info = Mock()
    logger.warning = Mock()
    logger.error = Mock()
    return logger


@pytest.fixture
def real_logger():
    """Create a real logger for testing with debug output."""
    logger = logging.getLogger("test_logger")
    logger.setLevel(logging.DEBUG)
    if not logger.handlers:
        handler = logging.StreamHandler()
        handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    return logger


# ============================================================================
# Test Binary Files Fixtures
# ============================================================================

@pytest.fixture
def elf_binary_path():
    """Path to the ELF test binary."""
    path = TEST_FILES_DIR / "hello"
    if not path.exists():
        pytest.skip(f"Test file not found: {path}")
    return str(path)


@pytest.fixture
def elf_advanced_binary_path():
    """Path to the advanced ELF test binary."""
    path = TEST_FILES_DIR / "hello_advanced"
    if not path.exists():
        pytest.skip(f"Test file not found: {path}")
    return str(path)


@pytest.fixture
def pe_binary_path():
    """Path to the PE test binary (.NET PE)."""
    path = TEST_FILES_DIR / "d8637bdbcfc9112fcb1f0167b398e771"
    if not path.exists():
        pytest.skip(f"Test file not found: {path}")
    return str(path)


@pytest.fixture
def elf_binary_content(elf_binary_path):
    """Read the ELF test binary content."""
    with open(elf_binary_path, "rb") as f:
        return f.read()


@pytest.fixture
def pe_binary_content(pe_binary_path):
    """Read the PE test binary content."""
    with open(pe_binary_path, "rb") as f:
        return f.read()


# ============================================================================
# Temporary Files Fixtures
# ============================================================================

@pytest.fixture
def temp_binary_file():
    """Create a temporary binary file for testing."""
    with tempfile.NamedTemporaryFile(delete=False, suffix=".bin") as f:
        # Write some test data
        f.write(b"\x7fELF" + b"\x00" * 100 + b"test data")
        temp_path = f.name

    yield temp_path

    # Cleanup
    if os.path.exists(temp_path):
        os.unlink(temp_path)


@pytest.fixture
def temp_text_file():
    """Create a temporary text file for testing."""
    with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w") as f:
        f.write("This is a test file with some text content.")
        temp_path = f.name

    yield temp_path

    # Cleanup
    if os.path.exists(temp_path):
        os.unlink(temp_path)


@pytest.fixture
def temp_pe_like_file():
    """Create a temporary file with PE-like header for testing."""
    with tempfile.NamedTemporaryFile(delete=False, suffix=".exe") as f:
        # MZ header
        f.write(b"MZ" + b"\x00" * 58)
        # e_lfanew pointing to PE header at offset 64
        f.write(b"\x40\x00\x00\x00")
        # PE signature at offset 64
        f.write(b"PE\x00\x00")
        # Minimal COFF header (20 bytes)
        f.write(b"\x4c\x01")  # Machine (i386)
        f.write(b"\x01\x00")  # NumberOfSections
        f.write(b"\x00" * 16)  # Rest of COFF header
        temp_path = f.name

    yield temp_path

    # Cleanup
    if os.path.exists(temp_path):
        os.unlink(temp_path)


# ============================================================================
# Mock Exporter Fixtures
# ============================================================================

@pytest.fixture
def mock_print_exporter(mock_logger):
    """Create a mock PrintExporter."""
    from redb.extractors.database_exporters import PrintExporter
    exporter = PrintExporter(mock_logger, "test_index")
    return exporter


@pytest.fixture
def mock_elasticsearch_exporter(mock_logger):
    """Create a mock ElasticsearchExporter with mocked client."""
    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")
        return exporter


@pytest.fixture
def mock_clickhouse_exporter(mock_logger):
    """Create a mock ClickHouseExporter with mocked client."""
    with patch('redb.settings.create_clickhouse_client') as mock_client:
        mock_client.return_value = Mock()
        from redb.extractors.database_exporters import ClickHouseExporter
        exporter = ClickHouseExporter(mock_logger, "test_index", client=Mock())
        return exporter


# ============================================================================
# Mock Settings Fixtures
# ============================================================================

@pytest.fixture
def mock_settings():
    """Mock the redb.settings module."""
    with patch.multiple(
        'redb.settings',
        ELASTIC_BINARIES_COLLECTION="test_collection",
        get_elasticsearch_client=Mock(return_value=Mock()),
        create_clickhouse_client=Mock(return_value=Mock()),
    ):
        yield


# ============================================================================
# Hash Fixtures
# ============================================================================

@pytest.fixture
def known_hashes(elf_binary_content):
    """Compute known hashes for the ELF test binary."""
    return {
        'md5': hashlib.md5(elf_binary_content).hexdigest(),
        'sha1': hashlib.sha1(elf_binary_content).hexdigest(),
        'sha256': hashlib.sha256(elf_binary_content).hexdigest(),
    }


@pytest.fixture
def pe_known_hashes(pe_binary_content):
    """Compute known hashes for the PE test binary."""
    return {
        'md5': hashlib.md5(pe_binary_content).hexdigest(),
        'sha1': hashlib.sha1(pe_binary_content).hexdigest(),
        'sha256': hashlib.sha256(pe_binary_content).hexdigest(),
    }


# ============================================================================
# Sample Data Fixtures
# ============================================================================

@pytest.fixture
def sample_binary_data():
    """Sample binary data for entropy and hash testing."""
    return b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" * 16


@pytest.fixture
def high_entropy_data():
    """High entropy random-like data for testing."""
    import random
    random.seed(42)  # Reproducible
    return bytes(random.randint(0, 255) for _ in range(256))


@pytest.fixture
def low_entropy_data():
    """Low entropy repetitive data for testing."""
    return b"\x00" * 256


# ============================================================================
# PE Object Fixtures
# ============================================================================

@pytest.fixture
def pe_object(pe_binary_path):
    """Create a pefile PE object for testing."""
    import pefile
    try:
        pe = pefile.PE(pe_binary_path)
        yield pe
        pe.close()
    except Exception as e:
        pytest.skip(f"Failed to parse PE file: {e}")


# ============================================================================
# ELF Object Fixtures
# ============================================================================

@pytest.fixture
def elf_object(elf_binary_path):
    """Create an ELFFile object for testing."""
    from elftools.elf.elffile import ELFFile
    try:
        with open(elf_binary_path, 'rb') as f:
            elf = ELFFile(f)
            # We need to keep the file open for ELFFile to work
            yield elf
    except Exception as e:
        pytest.skip(f"Failed to parse ELF file: {e}")


# ============================================================================
# Dataclass Fixtures
# ============================================================================

@pytest.fixture
def sample_hash_dataclass():
    """Create a sample Hash dataclass."""
    from redb.models.dataclasses import Hash
    return Hash(
        md5="d41d8cd98f00b204e9800998ecf8427e",
        sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709",
        sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
    )


@pytest.fixture
def sample_hashes_dataclass():
    """Create a sample Hashes dataclass."""
    from redb.models.dataclasses import Hashes
    return Hashes(
        md5="d41d8cd98f00b204e9800998ecf8427e",
        sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709",
        sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        ssdeep_hash="3::",
        tlsh_hash=""
    )


@pytest.fixture
def sample_basic_properties():
    """Create a sample BasicProperties dataclass."""
    from redb.models.dataclasses import BasicProperties
    return BasicProperties(
        filename="test.exe",
        sample_name="test.exe",
        filesize=1024,
        filetype="PE32 executable",
        filetype_mime="application/x-dosexec",
        filetype_magika="pebin",
        file_entropy=6.5
    )


# ============================================================================
# Utility Functions for Tests
# ============================================================================

def compute_entropy(data):
    """Compute entropy of data for verification in tests."""
    import math
    from collections import Counter

    if not data:
        return 0.0

    if isinstance(data, str):
        counts = Counter(data)
        frequencies = (i / len(data) for i in counts.values())
        return -sum(f * math.log(f, 2) for f in frequencies)
    else:
        occurrences = Counter(bytearray(data))
        entropy = 0
        for x in occurrences.values():
            p_x = float(x) / len(data)
            entropy -= p_x * math.log(p_x, 2)
        return entropy


# Make the function available as a fixture
@pytest.fixture
def entropy_calculator():
    """Return the entropy calculation function."""
    return compute_entropy


# ============================================================================
# Skip Markers
# ============================================================================

# Mark tests that require external tools
requires_die = pytest.mark.skipif(
    not os.path.exists("/usr/bin/diec") and not os.path.exists("/usr/local/bin/diec"),
    reason="Detect It Easy (diec) not installed"
)

requires_capa = pytest.mark.skipif(
    not os.path.exists("/usr/bin/capa") and not os.path.exists("/usr/local/bin/capa"),
    reason="capa not installed"
)

requires_floss = pytest.mark.skipif(
    not os.path.exists("/usr/bin/floss") and not os.path.exists("/usr/local/bin/floss"),
    reason="floss not installed"
)