def test_exit_with_parent_process_died(
    language_server_process: IRobocorpLanguageServerClient,
    language_server_io,
    ws_root_path,
    initialization_options,
):
    """
    :note: Only check with the language_server_io (because that's in another process).
    """
    from robocorp_ls_core.subprocess_wrapper import subprocess
    from robocorp_ls_core.basic import is_process_alive
    from robocorp_ls_core.basic import kill_process_and_subprocesses
    from robocorp_ls_core.unittest_tools.fixtures import wait_for_test_condition

    language_server = language_server_io
    dummy_process = subprocess.Popen(
        [sys.executable, "-c", "import time;time.sleep(10000)"])

    language_server.initialize(
        ws_root_path,
        process_id=dummy_process.pid,
        initialization_options=initialization_options,
    )

    assert is_process_alive(dummy_process.pid)
    assert is_process_alive(language_server_process.pid)

    kill_process_and_subprocesses(dummy_process.pid)

    wait_for_test_condition(lambda: not is_process_alive(dummy_process.pid))
    wait_for_test_condition(
        lambda: not is_process_alive(language_server_process.pid))
    language_server_io.require_exit_messages = False
Пример #2
0
def test_system_mutex_locked_on_subprocess():
    import sys
    from robocorp_ls_core.subprocess_wrapper import subprocess
    from robocorp_ls_core.basic import kill_process_and_subprocesses
    from robocorp_ls_core.system_mutex import SystemMutex
    from robocorp_ls_core.basic import wait_for_condition

    code = '''
import sys
import time
print('initialized')
from robocorp_ls_core.system_mutex import SystemMutex
mutex = SystemMutex('test_system_mutex_locked_on_subprocess')
assert mutex.get_mutex_aquired()
print('acquired mutex')
sys.stdout.flush()
time.sleep(30)
'''
    p = subprocess.Popen([sys.executable, '-c', code], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
    wait_for_condition(lambda: p.stdout.readline().strip() == b'acquired mutex')
    mutex = SystemMutex('test_system_mutex_locked_on_subprocess')
    assert not mutex.get_mutex_aquired()
    
    # i.e.: check that we can acquire the mutex if the related process dies.
    kill_process_and_subprocesses(p.pid)
    
    def acquire_mutex():
        mutex = SystemMutex('test_system_mutex_locked_on_subprocess')
        return mutex.get_mutex_aquired()
    wait_for_condition(acquire_mutex, timeout=5)
Пример #3
0
    def disconnect(self, disconnect_request):
        from robocorp_ls_core.basic import kill_process_and_subprocesses

        if self._popen is not None:
            if self._popen.returncode is None:
                kill_process_and_subprocesses(self._popen.pid)
        else:
            kill_process_and_subprocesses(self._track_process_pid)
def test_restart_when_api_dies(language_server_tcp, ws_root_path,
                               data_regression):
    from robocorp_ls_core.basic import kill_process_and_subprocesses
    from robocorp_ls_core import basic
    from robotframework_ls.server_manager import _ServerApi
    import time

    # Check just with language_server_tcp as it's easier to kill the subprocess.

    server_apis = set()
    server_processes = set()

    def on_get_robotframework_api_client(server_api):
        if (server_api.robot_framework_language_server is
                language_server_tcp.language_server_instance):
            server_apis.add(server_api)
            server_processes.add(server_api._server_process.pid)

    with basic.after(_ServerApi, "get_robotframework_api_client",
                     on_get_robotframework_api_client):
        language_server_tcp.initialize(ws_root_path, process_id=os.getpid())
        import robot

        env = {
            "PYTHONPATH":
            os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__)))
        }
        language_server_tcp.settings({
            "settings": {
                "robot.python.env": env,
                "robot.lint.robocop.enabled": True
            }
        })

        processes_per_api = 3

        check_diagnostics(language_server_tcp, data_regression)
        assert len(server_apis) == processes_per_api
        assert len(server_processes) == processes_per_api

        check_diagnostics(language_server_tcp, data_regression)
        assert len(server_apis) == processes_per_api
        assert len(server_processes) == processes_per_api

        log.info("Killing server api process.")
        for pid in server_processes:
            kill_process_and_subprocesses(pid)

        # Just make sure the connection is properly dropped before re-requesting.
        time.sleep(0.2)

        check_diagnostics(language_server_tcp, data_regression)
        assert len(server_processes) == processes_per_api * 2
        assert len(server_apis) == processes_per_api
Пример #5
0
 def _dispose_server_process(self):
     self._check_in_main_thread()
     try:
         log.debug("Dispose server process.")
         if self._server_process is not None:
             if is_process_alive(self._server_process.pid):
                 kill_process_and_subprocesses(self._server_process.pid)
     finally:
         self._server_process = None
         self._robotframework_api_client = None
         self._used_environ = None
         self._used_python_executable = None
    def _dispose_server_process(self):
        from robocorp_ls_core.basic import kill_process_and_subprocesses

        self._check_thread()
        try:
            log.debug("Dispose server process.")
            if self._server_process is not None:
                if is_process_alive(self._server_process.pid):
                    kill_process_and_subprocesses(self._server_process.pid)
        finally:
            self._server_process = None
            self._locators_api_client = None
Пример #7
0
    def _dispose_server_process(self):
        from robocorp_ls_core.basic import kill_process_and_subprocesses

        with self._lock_api_client:
            try:
                log.debug("Dispose server process.")
                if self._server_process is not None:
                    if is_process_alive(self._server_process.pid):
                        kill_process_and_subprocesses(self._server_process.pid)
            finally:
                self._disposed = True
                self._server_process = None
                self._rf_interpreter_api_client = None
Пример #8
0
def server_process(tmpdir, on_timeout, remote_fs_observer):
    from robocorp_ls_core.basic import kill_process_and_subprocesses
    from robotframework_ls.server_api.server__main__ import start_server_process

    log_file = str(tmpdir.join("robotframework_api_tests.log"))

    import robot

    env = {
        "PYTHONPATH":
        os.path.dirname(os.path.dirname(os.path.abspath(robot.__file__)))
    }

    language_server_api_process = start_server_process(
        args=[
            "-vv",
            "--log-file=%s" % log_file,
            f"--remote-fs-observer-port={remote_fs_observer.port}",
        ],
        env=env,
    )
    returncode = language_server_api_process.poll()
    assert returncode is None

    def write_on_finish():
        import sys

        dirname = os.path.dirname(log_file)
        for f in os.listdir(dirname):
            if f.startswith("robotframework_api_tests") and f.endswith(".log"):
                full = os.path.join(dirname, f)
                sys.stderr.write("\n--- %s contents:\n" % (full, ))
                with open(full, "r") as stream:
                    sys.stderr.write(stream.read())

    on_timeout.add(write_on_finish)

    yield language_server_api_process

    on_timeout.remove(write_on_finish)

    returncode = language_server_api_process.poll()
    if returncode is None:
        kill_process_and_subprocesses(language_server_api_process.pid)

    write_on_finish()
Пример #9
0
def dap_process(dap_log_file, dap_process_stderr_file):
    from robotframework_debug_adapter import __main__
    from robocorp_ls_core.basic import kill_process_and_subprocesses

    env = os.environ.copy()
    env["ROBOTFRAMEWORK_DAP_LOG_LEVEL"] = "3"
    env["ROBOTFRAMEWORK_DAP_LOG_FILENAME"] = dap_log_file

    dap_process = subprocess.Popen(
        [sys.executable, "-u", __main__.__file__],
        stdout=subprocess.PIPE,
        stderr=dap_process_stderr_file,
        stdin=subprocess.PIPE,
        env=env,
    )
    assert dap_process.returncode is None
    yield dap_process
    if dap_process.returncode is None:
        kill_process_and_subprocesses(dap_process.pid)
Пример #10
0
def create_language_server_process(log_file, __main__module):
    from robocorp_ls_core.basic import kill_process_and_subprocesses

    from robocorp_ls_core.subprocess_wrapper import subprocess

    language_server_process = subprocess.Popen(
        [
            sys.executable,
            "-u",
            __main__module.__file__,
            "-vv",
            "--log-file=%s" % log_file,
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        stdin=subprocess.PIPE,
    )
    stderr = language_server_process.stderr
    buf = []
    t = threading.Thread(target=_stderr_reader, args=(stderr, buf))
    t.name = "Stderr reader"
    t.start()

    returncode = language_server_process.poll()
    assert returncode is None
    try:
        yield language_server_process
    finally:
        t.join(1)
        stderr_contents = b"".join(buf).decode("utf-8")
        if stderr_contents:
            sys.stderr.write(
                f"Found stderr contents: >>\n{stderr_contents}\n<<")
        returncode = language_server_process.poll()
        if returncode is None:
            kill_process_and_subprocesses(language_server_process.pid)
Пример #11
0
def main():
    args = sys.argv[1:]

    # If -o is not passed, without logging to any file. All other arguments
    # are passed on to pytest.
    open_stream = _noop_ctx
    pytest_args = []
    for arg in args:
        if arg.startswith("-o"):
            test_output_filename = arg[2:]
            open_stream = lambda: open(test_output_filename, "w")
        else:
            pytest_args.append(arg)

    with open_stream() as stream:

        def write(msg):
            for s in (sys.stderr, stream):
                if s is not None:
                    s.write(msg)
                    s.write("\n")
                    s.flush()

        write("=== Initializing test run ===")
        retcode = 1
        initial_time = time.time()
        try:
            args = [sys.executable, "-m", "pytest"] + pytest_args
            timeout = int(os.environ.get("RUN_TESTS_TIMEOUT", "100"))
            write("Calling:\n  cwd:%s\n  args: %s\n  timeout: %s" %
                  (os.path.abspath(os.getcwd()), args, timeout))
            process = subprocess.Popen(args)
            pid = process.pid
            while (time.time() - initial_time) < timeout:
                time.sleep(1)
                process_retcode = process.poll()
                if process_retcode is not None:
                    retcode = process_retcode
                    process = None
                    break
            else:
                write(
                    "Running tests timed out (pid: %s, timeout: %s seconds)." %
                    (pid, timeout))
                try:
                    import psutil
                except ImportError:
                    pass
                else:
                    pids = []
                    p = psutil.Process()
                    for s in p.children(recursive=True):
                        try:
                            cmdline = s.cmdline()
                        except Exception as e:
                            cmdline = str(e)
                        write("Subprocess leaked: %s (%s)\n" % (s, cmdline))
                        pids.append(s.pid)

                    try:
                        from robocorp_ls_core.basic import kill_process_and_subprocesses
                    except:
                        # Automatically add it to the path if not there.
                        sys.path.append(
                            os.path.join(
                                os.path.dirname(
                                    os.path.dirname(
                                        os.path.abspath(__file__))),
                                "src",
                            ))
                        from robocorp_ls_core.basic import kill_process_and_subprocesses

                    kill_process_and_subprocesses(pid)

                sys.exit(1)

            sys.exit(retcode)

        finally:
            write("=== Finalizing test run. Total time: %.2fs ===" %
                  (time.time() - initial_time))