Exemplo n.º 1
0
def test_debugger_core_hit_condition_breakpoint(debugger_api,
                                                robot_thread) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    debugger_impl = install_robot_debugger()
    target = debugger_api.get_dap_case_file("case_condition.robot")
    line = debugger_api.get_line_index_with_content("Log    ${counter}",
                                                    target)

    debugger_impl.set_breakpoints(target, RobotBreakpoint(line,
                                                          hit_condition=2))

    robot_thread.run_target(target)

    # It should only stop once (when counter == 2).
    dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 1)

    thread_id = debugger_impl.get_current_thread_id(robot_thread)
    frame_ids = list(debugger_impl.iter_frame_ids(thread_id))
    eval_info = debugger_impl.evaluate(frame_ids[0], "${counter}")
    assert eval_info.future.result() == 2

    debugger_impl.step_continue()

    dbg_wait_for(lambda: robot_thread.result_code == 0)
    def check_waited(expected):
        def msg():
            return "Expected waited to be: %s. Found: %s" % (
                expected,
                debugger_impl.busy_wait.waited,
            )

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == expected, msg=msg)
Exemplo n.º 3
0
def test_debugger_core_evaluate(debugger_api_core, robot_thread,
                                tmpdir) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    from robotframework_debug_adapter.constants import MAIN_THREAD_ID
    from robotframework_debug_adapter.debugger_impl import InvalidFrameIdError
    from robotframework_debug_adapter.debugger_impl import InvalidFrameTypeError

    debugger_impl = install_robot_debugger()
    target = debugger_api_core.get_dap_case_file("case_evaluate.robot")
    debugger_api_core.target = target
    line = debugger_api_core.get_line_index_with_content("Break 1")
    debugger_impl.set_breakpoints(target, RobotBreakpoint(line))

    robot_thread.run_target(target)
    dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 1)

    try:
        invalid_frame_id = -11
        filename = str(tmpdir.join("file.txt"))
        filename = filename.replace("\\", "/")
        content = "file.txt"
        frame_ids = list(debugger_impl.iter_frame_ids(MAIN_THREAD_ID))

        # Fail due to invalid frame id
        eval_info = debugger_impl.evaluate(
            invalid_frame_id,
            "Create File    %s    content=%s" % (filename, content))
        with pytest.raises(InvalidFrameIdError):
            eval_info.future.result()

        # Fail because the stack selected is not a keyword stack.
        eval_info = debugger_impl.evaluate(
            frame_ids[-1],
            "Create File    %s    content=%s" % (filename, content))
        with pytest.raises(InvalidFrameTypeError):
            eval_info.future.result()

        # Keyword evaluation works
        eval_info = debugger_impl.evaluate(
            frame_ids[0],
            "Create File    %s    content=%s" % (filename, content))

        assert eval_info.future.result() is None
        with open(filename, "r") as stream:
            contents = stream.read()

        assert contents == content

        # Get variable in evaluation works
        eval_info = debugger_impl.evaluate(frame_ids[0], "${arg1}")
        assert eval_info.future.result() == "2"

        eval_info = debugger_impl.evaluate(frame_ids[0], "${ARG1}")
        assert eval_info.future.result() == "2"
    finally:
        debugger_impl.step_continue()
Exemplo n.º 4
0
def test_debugger_core_if(debugger_api, robot_thread, data_regression) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    from robotframework_debug_adapter.constants import MAIN_THREAD_ID

    debugger_impl = install_robot_debugger()
    target = debugger_api.get_dap_case_file(
        "case_control_flow/case_control_flow_if.robot")
    line = debugger_api.get_line_index_with_content("Break 1", target)
    debugger_impl.set_breakpoints(target, RobotBreakpoint(line))

    robot_thread.run_target(target)

    stack_lst: List[Optional[List[StackFrame]]] = []

    try:
        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 1)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 2)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
    finally:
        debugger_impl.step_in()  # Will actually finish the program now.

    dbg_wait_for(lambda: debugger_impl.busy_wait.proceeded == 2)

    data_regression.check(stack_frames_repr(stack_lst))
    dbg_wait_for(lambda: robot_thread.result_code == 0)
Exemplo n.º 5
0
def test_debugger_core_keyword_if(debugger_api, robot_thread,
                                  data_regression) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    from robotframework_debug_adapter.constants import MAIN_THREAD_ID

    debugger_impl = install_robot_debugger()
    target = debugger_api.get_dap_case_file(
        "case_control_flow/case_control_flow_for.robot")
    line = debugger_api.get_line_index_with_content("Break 2", target)
    debugger_impl.set_breakpoints(target, RobotBreakpoint(line))

    robot_thread.run_target(target)

    stack_lst = []

    def check_waited(expected):
        def msg():
            return "Expected waited to be: %s. Found: %s" % (
                expected,
                debugger_impl.busy_wait.waited,
            )

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == expected,
                     msg=msg)

    try:
        check_waited(1)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        check_waited(2)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        check_waited(3)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        check_waited(4)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
    finally:
        debugger_impl.step_continue()

    dbg_wait_for(lambda: debugger_impl.busy_wait.proceeded == 4)

    data_regression.check(stack_frames_repr(stack_lst))
    dbg_wait_for(lambda: robot_thread.result_code == 0)
Exemplo n.º 6
0
def test_debugger_core(debugger_api_core, robot_thread) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    debugger_impl = install_robot_debugger()
    target = debugger_api_core.get_dap_case_file("case_log.robot")
    debugger_api_core.target = target
    line = debugger_api_core.get_line_index_with_content(
        "check that log works")
    debugger_impl.set_breakpoints(target, RobotBreakpoint(line))

    robot_thread.run_target(target)
    thread_id = debugger_impl.get_current_thread_id(robot_thread)
    try:
        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 1)

        stack = debugger_impl.get_frames(thread_id)
    finally:
        debugger_impl.step_continue()

    dbg_wait_for(lambda: debugger_impl.busy_wait.proceeded == 1)
    assert stack and len(stack) == 3
    dbg_wait_for(lambda: robot_thread.result_code == 0)
def test_debug_adapter_threaded(
    debugger_api_core, dap_log_file, robot_thread, dap_logs_dir
):
    """
    This is an example on how to setup the debugger structure in-memory but
    still talking through the DAP instead of using the core APIs.
    
    debugger_api_core: helper to get file to run / compute breakpoint position.
    dap_log_file: a place to store logs.
    robot_thread: helper run robot in a thread. 
    dap_logs_dir: another api to store the logs needed. 
    """
    import robotframework_ls
    from robotframework_debug_adapter_tests.fixtures import dbg_wait_for
    from robocorp_ls_core.debug_adapter_core.debug_adapter_threads import (
        STOP_WRITER_THREAD,
    )

    robotframework_ls.import_robocorp_ls_core()

    # Configure the logger
    from robocorp_ls_core.robotframework_log import configure_logger

    reader, writer = None, None

    with configure_logger("robot", 3, dap_log_file):

        # i.e: create the server socket which will wait for the debugger connection.
        client_thread = _ClientThread()
        try:
            client_thread.start()
            address = client_thread.get_address()

            from robotframework_debug_adapter.run_robot__main__ import (
                connect,
                _RobotTargetComm,
            )

            # Note: _RobotTargetComm takes care of initializing the debugger.
            processor = _RobotTargetComm(connect(address[1]), debug=True)
            reader, writer = processor.start_communication_threads(
                mark_as_pydevd_threads=False
            )
            assert client_thread.started.wait(2)

            # Ok, at this point the setup should be done, let's set a breakpoint
            # then ask to run and see if it stops there.
            target = debugger_api_core.get_dap_case_file("case_log.robot")
            debugger_api_core.target = target
            line = debugger_api_core.get_line_index_with_content("check that log works")

            client_thread.debugger_api.set_breakpoints(target, line)

            # Actually run it (do it in a thread so that we can verify
            # things on this thread).
            robot_thread.run_target(target)

            json_hit = client_thread.debugger_api.wait_for_thread_stopped(
                file=target, line=line
            )
            client_thread.debugger_api.continue_event(json_hit.thread_id)
            dbg_wait_for(
                lambda: robot_thread.result_code is not None,
                msg="Robot execution did not finish properly.",
            )

            # Run it once more to check that the communication is still in place
            # -- i.e.: we don't actually terminate it if the connection was done
            # in memory.
            from robotframework_debug_adapter_tests.fixtures import RunRobotThread

            robot_thread2 = RunRobotThread(dap_logs_dir)
            robot_thread2.run_target(target)
            json_hit = client_thread.debugger_api.wait_for_thread_stopped(
                file=target, line=line
            )
            client_thread.debugger_api.continue_event(json_hit.thread_id)
            dbg_wait_for(
                lambda: robot_thread2.result_code is not None,
                msg="Robot execution did not finish properly.",
            )
        finally:
            # Upon finish the client should close the sockets to finish the readers.
            client_thread.finish.set()
            # Upon finish ask the writer thread to exit too (it won't automatically finish
            # even if sockets are closed).
            processor.write_message(STOP_WRITER_THREAD)

        assert client_thread.sockets_closed.wait(1)

    if reader is not None:
        reader.join(2)
        assert not reader.is_alive(), "Expected reader to have exited already."
    if writer is not None:
        writer.join(2)
        assert not writer.is_alive(), "Expected writer to have exited already."
Exemplo n.º 8
0
def test_debugger_core_for(debugger_api, robot_thread,
                           data_regression) -> None:
    from robotframework_debug_adapter.debugger_impl import install_robot_debugger
    from robotframework_debug_adapter.debugger_impl import RobotBreakpoint

    from robotframework_debug_adapter.constants import MAIN_THREAD_ID

    debugger_impl = install_robot_debugger()
    target = debugger_api.get_dap_case_file(
        "case_control_flow/case_control_flow_for.robot")
    line = debugger_api.get_line_index_with_content("Break 1", target)
    debugger_impl.set_breakpoints(target, RobotBreakpoint(line))

    robot_thread.run_target(target)

    stack_lst: List[Optional[List[StackFrame]]] = []

    try:
        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 1)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 2)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 3)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
        debugger_impl.step_in()

        dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 4)
        stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))

        n_proceeded = 4
        if IS_ROBOT_4_ONWARDS:
            # We have additional steps as we get one step with the creation
            # of the ${counter} variable when stepping into the for.
            debugger_impl.step_in()

            dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 5)
            stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
            debugger_impl.step_in()

            dbg_wait_for(lambda: debugger_impl.busy_wait.waited == 6)
            stack_lst.append(debugger_impl.get_frames(MAIN_THREAD_ID))
            n_proceeded = 6
    finally:
        debugger_impl.step_continue()

    dbg_wait_for(lambda: debugger_impl.busy_wait.proceeded == n_proceeded)

    if IS_ROBOT_4_ONWARDS:
        basename = "test_debugger_core_for.v4"
    else:
        basename = "test_debugger_core_for.v3"
    data_regression.check(stack_frames_repr(stack_lst), basename=basename)
    dbg_wait_for(lambda: robot_thread.result_code == 0)