Jamie Twycross

46 papers A* 1A 1B 7Journal 29Unranked 8
YearRankTypeTitle / Venue / Authors
2023 B conf
DocEng
Hamza Abdi, Steven R. Bagley, Steven Furnell, Jamie Twycross
2022 J jnl
PLoS Comput. Biol.
Nicole Pearcy, Marco Garavaglia, Thomas Millat, James P. Gilbert, Yoseb Song, Hassan Hartman, Craig Woods, Claudio Tomi-Andrino, Rajesh Reddy Bommareddy, Byung-Kwan Cho, David A. Fell, Mark Poolman, John R. King, Klaus Winzer, Jamie Twycross, Nigel P. Minton
2021 J jnl
IEEE Trans. Fuzzy Syst.
Chao Chen, Dongrui Wu, Jonathan M. Garibaldi, Robert I. John, Jamie Twycross, Jerry M. Mendel
2020 conf
LOD (1)
Alexandre Maciel-Guerra, Grazziela P. Figueredo, Jamie Twycross
2020 B conf
IJCNN
Alexandre Maciel-Guerra, Grazziela P. Figueredo, Eliane Marti, Marcos J. C. Alcocer, Jamie Twycross
2019 J jnl
Bioinform.
James P. Gilbert, Nicole Pearcy, Rupert Norman, Thomas Millat, Klaus Winzer, John R. King, Charlie Hodgman, Nigel P. Minton, Jamie Twycross
2019 B conf
CEC
Alexandre Maciel-Guerra, Grazziela P. Figueredo, Fernando J. Von Zuben, Eliane Marti, Jamie Twycross, Marcos J. C. Alcocer
2019 J jnl
Comput. Chem. Eng.
Edward Acheampong, Ian L. Dryden, Jonathan A. D. Wattis, Jamie Twycross, Mark D. Scrimshaw, Rachel L. Gomes
2018 J jnl
IEEE Trans. Fuzzy Syst.
Chao Chen, Dongrui Wu, Jonathan M. Garibaldi, Robert I. John, Jamie Twycross, Jerry M. Mendel
2018 J jnl
IEEE Trans. Fuzzy Syst.
Chao Chen, Robert I. John, Jamie Twycross, Jonathan M. Garibaldi
2018 J jnl
CoRR
James P. Gilbert, Jamie Twycross
2017 B conf
FUZZ-IEEE
Chao Chen, Robert I. John, Jamie Twycross, Jonathan M. Garibaldi
2016 B conf
FUZZ-IEEE
Chao Chen, Robert I. John, Jamie Twycross, Jonathan M. Garibaldi
2013 J jnl
CoRR
Uwe Aickelin, Julie Greensmith, Jamie Twycross
2011 J jnl
Bioinform.
Jonathan Blakes, Jamie Twycross, Francisco José Romero-Campero, Natalio Krasnogor
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2010 J jnl
CoRR
Julie Greensmith, Jamie Twycross, Uwe Aickelin
2010 J jnl
Int. J. Unconv. Comput.
Jamie Twycross, Uwe Aickelin, Amanda M. Whitbrook
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin, Amanda M. Whitbrook
2010 J jnl
CoRR
Julie Greensmith, Uwe Aickelin, Jamie Twycross
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2010 J jnl
Inf. Fusion
Jamie Twycross, Uwe Aickelin
2010 J jnl
CoRR
Gianni Tedesco, Jamie Twycross, Uwe Aickelin
2010 J jnl
CoRR
Jungwon Kim, Julie Greensmith, Jamie Twycross, Uwe Aickelin
2010 A conf
GECCO
Carlos García-Martínez, Claudio Lima, Jamie Twycross, Natalio Krasnogor, Manuel Lozano
2010 J jnl
BMC Syst. Biol.
Jamie Twycross, Leah R. Band, Malcolm Bennett, John R. King, Natalio Krasnogor
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2010 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2009 J jnl
CoRR
Jamie Twycross, Uwe Aickelin
2009 J jnl
CoRR
Julie Greensmith, Uwe Aickelin, Jamie Twycross
2009 J jnl
Int. J. Found. Comput. Sci.
Francisco José Romero-Campero, Jamie Twycross, Miguel Cámara, Malcolm Bennett, Marian Gheorghe, Natalio Krasnogor
2008 conf
Workshop on Membrane Computing
Francisco José Romero-Campero, Jamie Twycross, Hongqing Cao, Jonathan Blakes, Natalio Krasnogor
2008 J jnl
CoRR
Jungwon Kim, Peter J. Bentley, Uwe Aickelin, Julie Greensmith, Gianni Tedesco, Jamie Twycross
2008 J jnl
CoRR
Uwe Aickelin, Jamie Twycross, Thomas Hesketh-Roberts
2007 conf
ICARIS
Jamie Twycross, Uwe Aickelin
2007 J jnl
Nat. Comput.
Jungwon Kim, Peter J. Bentley, Uwe Aickelin, Julie Greensmith, Gianni Tedesco, Jamie Twycross
2007 J jnl
Int. J. Electron. Secur. Digit. Forensics
Uwe Aickelin, Jamie Twycross, Thomas Hesketh-Roberts
2006 conf
ICARIS
Julie Greensmith, Uwe Aickelin, Jamie Twycross
2006 B conf
IEEE Congress on Evolutionary Computation
Julie Greensmith, Jamie Twycross, Uwe Aickelin
2006 conf
ICARIS
Gianni Tedesco, Jamie Twycross, Uwe Aickelin
2006 B conf
IEEE Congress on Evolutionary Computation
Jamie Twycross, Uwe Aickelin
2005 conf
ICARIS
Jamie Twycross, Uwe Aickelin
2004 conf
ICARIS
Uwe Aickelin, Julie Greensmith, Jamie Twycross
2003 conf
IIS
Jamie Twycross, Steve Cayzer
2003 A* conf
USENIX Security Symposium
Jamie Twycross, Matthew M. Williamson
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"