Chandan Saha

85 papers A* 15A 9B 2Journal 54Unranked 5
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Abhiram Aravind, Abhranil Chatterjee, Sumanta Ghosh, Rohit Gurjar, Roshan Raj, Chandan Saha
2026 J jnl
Electron. Colloquium Comput. Complex.
Abhiram Aravind, Abhranil Chatterjee, Sumanta Ghosh, Rohit Gurjar, Roshan Raj, Chandan Saha
2024 J jnl
ACM Trans. Comput. Theory
Chandan Saha, Bhargav Thankey
2024 A* conf
ICALP
Omkar Baraskar, Agrim Dewan, Chandan Saha, Pulkit Sinha
2024 J jnl
CoRR
Omkar Baraskar, Agrim Dewan, Chandan Saha, Pulkit Sinha
2024 J jnl
Electron. Colloquium Comput. Complex.
Omkar Baraskar, Agrim Dewan, Chandan Saha, Pulkit Sinha
2024 A conf
STACS
Omkar Baraskar, Agrim Dewan, Chandan Saha
2024 J jnl
Electron. Colloquium Comput. Complex.
Omkar Baraskar, Agrim Dewan, Chandan Saha
2023 A* conf
SODA
Nikhil Gupta, Chandan Saha, Bhargav Thankey
2023 A* conf
ICALP
Prashanth Amireddy, Ankit Garg, Neeraj Kayal, Chandan Saha, Bhargav Thankey
2022 J jnl
Electron. Colloquium Comput. Complex.
Nikhil Gupta, Chandan Saha, Bhargav Thankey
2022 A conf
APPROX/RANDOM
Vishwas Bhargava, Ankit Garg, Neeraj Kayal, Chandan Saha
2022 J jnl
CoRR
Prashanth Amireddy, Ankit Garg, Neeraj Kayal, Chandan Saha, Bhargav Thankey
2022 J jnl
Electron. Colloquium Comput. Complex.
Prashanth Amireddy, Ankit Garg, Neeraj Kayal, Chandan Saha, Bhargav Thankey
2021 conf
APPROX-RANDOM
Chandan Saha, Bhargav Thankey
2021 J jnl
Electron. Colloquium Comput. Complex.
Chandan Saha, Bhargav Thankey
2021 J jnl
Electron. Colloquium Comput. Complex.
Vishwas Bhargava, Ankit Garg, Neeraj Kayal, Chandan Saha
2020 A conf
CCC
Nikhil Gupta, Chandan Saha, Bhargav Thankey
2020 J jnl
Electron. Colloquium Comput. Complex.
Nikhil Gupta, Chandan Saha, Bhargav Thankey
2020 A* conf
FOCS
Ankit Garg, Neeraj Kayal, Chandan Saha
2020 J jnl
CoRR
Ankit Garg, Neeraj Kayal, Chandan Saha
2020 J jnl
Electron. Colloquium Comput. Complex.
Ankit Garg, Neeraj Kayal, Chandan Saha
2020 B conf
MFCS
Janaky Murthy, Vineet Nair, Chandan Saha
2020 J jnl
CoRR
Janaky Murthy, Vineet Nair, Chandan Saha
2020 J jnl
Electron. Colloquium Comput. Complex.
Janaky Murthy, Vineet Nair, Chandan Saha
2020 J jnl
ACM Trans. Comput. Theory
Neeraj Kayal, Vineet Nair, Chandan Saha
2019 J jnl
Comput. Complex.
Neeraj Kayal, Vineet Nair, Chandan Saha
2019 A* conf
ICALP
Ankit Garg, Nikhil Gupta, Neeraj Kayal, Chandan Saha
2019 J jnl
Electron. Colloquium Comput. Complex.
Ankit Garg, Nikhil Gupta, Neeraj Kayal, Chandan Saha
2019 B conf
MFCS
Nikhil Gupta, Chandan Saha
2019 J jnl
ACM Trans. Comput. Theory
Neeraj Kayal, Vineet Nair, Chandan Saha, Sébastien Tavenas
2019 A* conf
STOC
Neeraj Kayal, Chandan Saha
2018 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Vineet Nair, Chandan Saha
2018 J jnl
SIGACT News
Neeraj Kayal, Chandan Saha
2018 J jnl
Theory Comput.
Neeraj Kayal, Chandan Saha, Sébastien Tavenas
2018 J jnl
Electron. Colloquium Comput. Complex.
Nikhil Gupta, Chandan Saha
2018 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha
2017 J jnl
SIAM J. Comput.
Neeraj Kayal, Nutan Limaye, Chandan Saha, Srikanth Srinivasan
2017 J jnl
Theory Comput. Syst.
Neeraj Kayal, Chandan Saha
2017 A conf
CCC
Neeraj Kayal, Vineet Nair, Chandan Saha, Sébastien Tavenas
2017 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Vineet Nair, Chandan Saha, Sébastien Tavenas
2016 A* conf
ICALP
Neeraj Kayal, Chandan Saha, Sébastien Tavenas
2016 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha, Sébastien Tavenas
2016 J jnl
SIAM J. Comput.
Manindra Agrawal, Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2016 J jnl
Comput. Complex.
Neeraj Kayal, Chandan Saha
2016 A* conf
STOC
Neeraj Kayal, Chandan Saha, Sébastien Tavenas
2016 A conf
STACS
Neeraj Kayal, Vineet Nair, Chandan Saha
2015 A conf
CCC
Neeraj Kayal, Chandan Saha
2015 conf
ICALP (1)
Neeraj Kayal, Pascal Koiran, Timothée Pecatte, Chandan Saha
2015 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha
2015 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha
2015 A conf
STACS
Neeraj Kayal, Chandan Saha
2015 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha, Sébastien Tavenas
2015 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Vineet Nair, Chandan Saha
2014 A* conf
STOC
Neeraj Kayal, Chandan Saha, Ramprasad Saptharishi
2014 A* conf
FOCS
Neeraj Kayal, Nutan Limaye, Chandan Saha, Srikanth Srinivasan
2014 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Nutan Limaye, Chandan Saha, Srikanth Srinivasan
2014 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha
2014 A* conf
STOC
Neeraj Kayal, Nutan Limaye, Chandan Saha, Srikanth Srinivasan
2013 J jnl
Comput. Complex.
Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2013 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha, Ramprasad Saptharishi
2013 J jnl
SIAM J. Comput.
Anindya De, Piyush P. Kurur, Chandan Saha, Ramprasad Saptharishi
2013 A* conf
STOC
Manindra Agrawal, Chandan Saha, Nitin Saxena
2012 A* conf
STOC
Manindra Agrawal, Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2012 J jnl
ACM Trans. Comput. Theory
Neeraj Kayal, Chandan Saha
2012 J jnl
Electron. Colloquium Comput. Complex.
Manindra Agrawal, Chandan Saha, Nitin Saxena
2012 J jnl
CoRR
Manindra Agrawal, Chandan Saha, Nitin Saxena
2011 J jnl
Electron. Colloquium Comput. Complex.
Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2011 J jnl
CoRR
Manindra Agrawal, Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2011 J jnl
Electron. Colloquium Comput. Complex.
Manindra Agrawal, Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2011 A conf
CCC
Neeraj Kayal, Chandan Saha
2011 J jnl
CoRR
Michael Forbes, Neeraj Kayal, Rajat Mittal, Chandan Saha
2010 J jnl
Electron. Colloquium Comput. Complex.
Neeraj Kayal, Chandan Saha
2009 J jnl
Inf. Process. Lett.
Chandan Saha, Sandip Das
2009 J jnl
CoRR
Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2009 conf
FSTTCS
Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2009 J jnl
Electron. Colloquium Comput. Complex.
Chandan Saha, Ramprasad Saptharishi, Nitin Saxena
2008 J jnl
CoRR
Chandan Saha
2008 A conf
STACS
Chandan Saha
2008 J jnl
CoRR
Anindya De, Piyush P. Kurur, Chandan Saha, Ramprasad Saptharishi
2008 J jnl
Electron. Colloquium Comput. Complex.
Anindya De, Piyush P. Kurur, Chandan Saha, Ramprasad Saptharishi
2008 A* conf
STOC
Anindya De, Piyush P. Kurur, Chandan Saha, Ramprasad Saptharishi
2007 conf
ICCTA
Chandan Saha, Sandip Das
2006 A* conf
SODA
Lakshminath Bhuvanagiri, Sumit Ganguly, Deepanjan Kesh, Chandan Saha
2005 conf
FSTTCS
Sumit Ganguly, Deepanjan Kesh, Chandan Saha
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"