Ioannis Seimenis

18 papers A 1C 5Misc 1Journal 9Unranked 2
YearRankTypeTitle / Venue / Authors
2025 J jnl
J. Imaging
Eleni Bekou, Ioannis Seimenis, Athanasios Tsochatzis, Karafyllia Tziagkana, Nikolaos Kelekis, Savas Deftereos, Nikolaos Courcoutsakis, Michael I. Koukourakis, Efstratios Karavasilis
2023 J jnl
J. Imaging
Dimitris Kalatzis, Ellas Spyratou, Maria Karnachoriti, Maria Anthi Kouri, Ioannis Stathopoulos, Nikolaos Danias, Nikolaos Arkadopoulos, Spyros Orfanoudakis, Ioannis Seimenis, Athanassios G. Kontos, Efstathios P. Efstathopoulos
2021 J jnl
J. Digit. Imaging
Cristina Marie Morales Mojica, Jose D. Velazco-Garcia, Eleftherios P. Pappas, Theodosios Birbilis, Aaron T. Becker, Ernst L. Leiss, Andrew G. Webb, Ioannis Seimenis, Nikolaos V. Tsekos
2019 conf
MIPR
Mahmut Unan, Junmo An, Ioannis Seimenis, Dipan J. Shah, Nikolaos V. Tsekos
2019 J jnl
J. Digit. Imaging
Jose D. Velazco-Garcia, Nikhil V. Navkar, Dawei Gui, Cristina Marie Morales Mojica, Eftychios G. Christoforou, Alpay Özcan, Julien Abinahed, Abdulla Al-Ansari, Andrew G. Webb, Ioannis Seimenis, Nikolaos V. Tsekos
2019 C conf
BIBE
Giovanni Molina, Jose D. Velazco-Garcia, Dipan J. Shah, Aaron T. Becker, Ioannis Seimenis, Panagiotis Tsiamyrtzis, Nikolaos V. Tsekos
2019 C conf
BIBE
Cristina Marie Morales Mojica, Nikolaos V. Tsekos, Jose Daniel Velazco-Garcia, Haoran Zhao, Ioannis Seimenis, Ernst L. Leiss, Dipan J. Shah, Andrew G. Webb, Aaron T. Becker, Panagiotis Tsiamyrtzis
2018 conf
VCBM@MICCAI
Cristina Marie Morales Mojica, Jose D. Velazco-Garcia, Nikhil V. Navkar, Shidin Balakrishnan, Julien Abinahed, Walid El Ansari, Khalid Al-Rumaihi, Adham Darweesh, Abdulla Al-Ansari, Mohamed Gharib, Mansour A. Karkoub, Ernst L. Leiss, Ioannis Seimenis, Nikolaos V. Tsekos
2017 C conf
BIBE
Cristina Marie Morales Mojica, Nikhil V. Navkar, Nikolaos V. Tsekos, Dimitrios Tsagkaris, Andrew G. Webb, Theodosios Birbilis, Ioannis Seimenis
2017 A conf
IROS
Thibault Kensicher, Julien Leclerc, Daniel Biediger, Dipan J. Shah, Ioannis Seimenis, Aaron T. Becker, Nikolaos V. Tsekos
2014 J jnl
IEEE J. Biomed. Health Informatics
Nicolas Aristokleous, Ioannis Seimenis, Georgios C. Georgiou, Yannis Papaharilaou, Brigitta C. Brott, Andrew Nicolaides, Andreas S. Anayiotos
2013 J jnl
Intell. Decis. Technol.
Christos P. Loizou, Efthyvoulos C. Kyriacou, Ioannis Seimenis, Marios Pantziaris, Styliani Petroudi, Minas A. Karaolis, Constantinos S. Pattichis
2013 J jnl
Medical Biol. Eng. Comput.
Yannis Papaharilaou, Nicolas Aristokleous, Ioannis Seimenis, Mohammad Iman Khozeymeh, Georgios C. Georgiou, Brigitta C. Brott, Elena Eracleous, Andreas S. Anayiotos
2012 C conf
BIBE
Costas Sophocleous, Eftychios G. Christoforou, Panayiotis S. Shiakolas, Ioannis Seimenis, Nikolaos V. Tsekos, Charalambos C. Doumanidis
2012 C conf
BIBE
Nicolas Aristokleous, Ioannis Seimenis, Yannis Papaharilaou, Mohammad Iman Khozeymeh, Georgios C. Georgiou, Brigitta C. Brott, Andreas S. Anayiotos
2011 Misc conf
AIAI
Christos P. Loizou, Efthyvoulos C. Kyriacou, Ioannis Seimenis, Marios Pantziaris, Christodoulos S. Christodoulou, Constantinos S. Pattichis
2011 J jnl
IEEE Trans. Inf. Technol. Biomed.
Nicolas Aristokleous, Ioannis Seimenis, Yannis Papaharilaou, Georgios C. Georgiou, Brigitta C. Brott, Elena Eracleous, Andreas S. Anayiotos
2011 J jnl
IEEE Trans. Inf. Technol. Biomed.
Christos P. Loizou, Víctor Murray, Marios S. Pattichis, Ioannis Seimenis, Marios Pantziaris, Constantinos S. Pattichis
tests/unit/test_apk_jadx_wrapper.py
← Index tests/unit/test_apk_jadx_wrapper.py python
"""
Unit tests for JADX wrapper subprocess management and output parsing.

All subprocess calls are mocked — no JADX/Java installation required.
"""
import os
import tempfile
import textwrap

import pytest
from unittest.mock import MagicMock, patch, call

pytestmark = [pytest.mark.unit, pytest.mark.apk, pytest.mark.decompile]


class TestJADXDecompiler:
    """Tests for JADXDecompiler subprocess wrapper."""

    @patch.dict(os.environ, {}, clear=False)
    def test_init_defaults(self):
        os.environ.pop("JADX_PATH", None)
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler()
        assert j.jadx_path == "jadx"
        assert j.timeout == 300

    def test_init_custom_path(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler(jadx_path="/usr/local/bin/jadx", timeout=300)
        assert j.jadx_path == "/usr/local/bin/jadx"
        assert j.timeout == 300

    def test_init_from_env(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        with patch.dict(os.environ, {"JADX_PATH": "/opt/jadx/bin/jadx", "JADX_TIMEOUT": "120"}):
            j = JADXDecompiler()
            assert j.jadx_path == "/opt/jadx/bin/jadx"
            assert j.timeout == 120

    @patch("subprocess.Popen")
    def test_decompile_success(self, mock_popen):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        mock_proc = MagicMock()
        mock_proc.communicate.return_value = ("output", "")
        mock_proc.returncode = 0
        mock_popen.return_value = mock_proc

        j = JADXDecompiler()
        result = j.decompile("/test.apk", "/output")
        assert result is True

    @patch("subprocess.Popen")
    def test_decompile_nonzero_exit_no_sources(self, mock_popen):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        mock_proc = MagicMock()
        mock_proc.communicate.return_value = ("", "error msg")
        mock_proc.returncode = 1
        mock_popen.return_value = mock_proc

        j = JADXDecompiler(log=MagicMock())
        result = j.decompile("/test.apk", "/nonexistent_output")
        assert result is False

    @patch("subprocess.Popen")
    def test_decompile_timeout(self, mock_popen):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        import subprocess
        mock_proc = MagicMock()
        mock_proc.communicate.side_effect = subprocess.TimeoutExpired(cmd="jadx", timeout=10)
        mock_proc.pid = 12345
        mock_popen.return_value = mock_proc

        with patch("os.getpgid", return_value=12345), \
             patch("os.killpg"):
            j = JADXDecompiler(timeout=10, log=MagicMock())
            result = j.decompile("/test.apk", "/output")
            assert result is False

    @patch("subprocess.Popen", side_effect=FileNotFoundError)
    def test_decompile_not_found(self, mock_popen):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler(log=MagicMock())
        result = j.decompile("/test.apk", "/output")
        assert result is False

    @patch("subprocess.Popen")
    def test_decompile_command_args(self, mock_popen):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        mock_proc = MagicMock()
        mock_proc.communicate.return_value = ("", "")
        mock_proc.returncode = 0
        mock_popen.return_value = mock_proc

        j = JADXDecompiler(jadx_path="/opt/jadx")
        j.decompile("/test.apk", "/output")

        cmd = mock_popen.call_args[0][0]
        assert cmd[0] == "/opt/jadx"
        assert "--no-res" in cmd
        assert "--no-imports" in cmd
        assert "--threads-count" in cmd
        assert "/test.apk" in cmd

    def test_parse_java_methods_empty_dir(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler()
        result = j.parse_java_methods("/nonexistent")
        assert result == {}

    def test_parse_java_methods_with_files(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        with tempfile.TemporaryDirectory() as tmpdir:
            sources_dir = os.path.join(tmpdir, "sources", "com", "example")
            os.makedirs(sources_dir)

            java_content = textwrap.dedent("""\
                package com.example;

                public class MyClass {
                    public void doStuff(int x) {
                        System.out.println(x);
                    }

                    private String getName() {
                        return "test";
                    }
                }
            """)
            with open(os.path.join(sources_dir, "MyClass.java"), "w") as f:
                f.write(java_content)

            j = JADXDecompiler()
            methods = j.parse_java_methods(tmpdir)
            assert len(methods) >= 1

    def test_extract_methods_from_java(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        source = textwrap.dedent("""\
            public void foo(int x) {
                if (x > 0) {
                    System.out.println(x);
                }
            }
        """)
        j = JADXDecompiler()
        methods = j._extract_methods_from_java(source, "com.example.Test")
        assert len(methods) == 1
        key = list(methods.keys())[0]
        assert "foo" in key

    def test_is_method_declaration_valid(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler()
        result = j._is_method_declaration("    public void foo(int x) {")
        assert result is not None
        assert result[0] == "foo"

    def test_is_method_declaration_control_flow(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler()
        # 'if', 'for', etc. should not be recognized as methods
        assert j._is_method_declaration("        if (x > 0) {") is None
        assert j._is_method_declaration("        for (int i = 0; i < 10; i++) {") is None

    def test_is_method_declaration_static(self):
        from redb.extractors.decompiler.apk.jadx_wrapper import JADXDecompiler
        j = JADXDecompiler()
        result = j._is_method_declaration("    public static void main(String[] args) {")
        assert result is not None
        assert result[0] == "main"