def _launch(self, *args: str):
        from hstest.stage_test import StageTest
        test_num = StageTest.curr_test_run.test_num

        InputHandler.set_dynamic_input_func(lambda: self._request_input())
        self.__executor = DaemonThreadPoolExecutor(
            name=f"MainModuleExecutor test #{test_num}")
        self.__task = self.__executor.submit(
            lambda: self._invoke_method(*args))
    def _run_file(self, test_run: TestRun) -> Optional[CheckResult]:
        test_case = test_run.test_case
        time_limit = test_case.time_limit

        executor = DaemonThreadPoolExecutor(
            name=f"AsyncMainFileRunner test #{test_run.test_num}")
        try:
            future: Future = executor.submit(
                lambda: self._run_dynamic_test(test_run))
            if time_limit <= 0 or debug_mode:
                return future.result()
            else:
                return future.result(timeout=time_limit / 1000)
        except TimeoutError:
            test_run.set_error_in_test(TimeLimitException(time_limit))
        except BaseException as ex:
            test_run.set_error_in_test(ex)
        finally:
            executor.shutdown(wait=False)

        return None
class MainModuleExecutor(ProgramExecutor):
    def __init__(self, source_name: str = None):
        super().__init__()

        if source_name is None:
            from hstest.stage_test import StageTest
            source_name = StageTest.curr_test_run.test_case.source_name

        if source_name is None:
            self._init_by_nothing()
        else:
            self._init_by_source_name(source_name)

        self.__module_name: str = source_name
        self.__run_module = None
        self.__executor: Optional[DaemonThreadPoolExecutor] = None
        self.__task: Optional[Future] = None

    def _init_by_source_name(self, source: str):
        path_to_test = source.replace('.', os.sep) + '.py'
        if not os.path.exists(path_to_test):
            self._init_by_nothing()
            return

        path, sep, module = source.rpartition('.')
        module_abs_path = os.path.abspath(path.replace('.', os.sep))
        self._init_by_module(module_abs_path, module)

    def _init_by_module(self, module_abs_path: str, module_name: str):
        self.module_to_test = module_name
        self.file_to_test = module_name + '.py'
        self.folder_to_test = module_abs_path

    def _init_by_nothing(self):
        folder, file = runnable_searcher(os.getcwd())
        without_py = file[:-3]
        self._init_by_module(os.path.abspath(folder), without_py)

    def _invoke_method(self, *args: str):
        modules_before = [k for k in sys.modules.keys()]

        from hstest.stage_test import StageTest
        try:
            self._machine.set_state(ProgramState.RUNNING)

            sys.argv = [self.file_to_test] + list(args)
            sys.path.append(self.folder_to_test)

            runpy.run_module(self.module_to_test, run_name="__main__")

            self._machine.set_state(ProgramState.FINISHED)

        except BaseException as ex:
            if StageTest.curr_test_run.error_in_test is None:
                # ExitException is thrown in case of exit() or quit()
                # consider them like normal exit
                if isinstance(ex, ExitException):
                    self._machine.set_state(ProgramState.FINISHED)
                    return

                StageTest.curr_test_run.set_error_in_test(
                    ExceptionWithFeedback('', ex))

            self._machine.set_state(ProgramState.EXCEPTION_THROWN)

        finally:
            modules_to_delete = []
            for m in sys.modules:
                if m not in modules_before:
                    modules_to_delete += [m]
            for m in modules_to_delete:
                del sys.modules[m]
            sys.path.remove(self.folder_to_test)

    def _launch(self, *args: str):
        from hstest.stage_test import StageTest
        test_num = StageTest.curr_test_run.test_num

        InputHandler.set_dynamic_input_func(lambda: self._request_input())
        self.__executor = DaemonThreadPoolExecutor(
            name=f"MainModuleExecutor test #{test_num}")
        self.__task = self.__executor.submit(
            lambda: self._invoke_method(*args))

    def _terminate(self):
        self.__executor.shutdown(wait=False)
        self.__task.cancel()
        with self._machine.cv:
            while not self.is_finished():
                self._input = None
                self._machine.wait_not_state(ProgramState.RUNNING)
                if self.is_waiting_input():
                    self._machine.set_state(ProgramState.RUNNING)

    def get_output(self) -> str:
        return OutputHandler.get_partial_output()

    def __str__(self) -> str:
        return self.file_to_test
示例#4
0
class MainModuleExecutor(ProgramExecutor):
    def __init__(self, source_name: str = None):
        super().__init__()
        self.runnable = PythonRunnableFile.find(source_name)
        self.__executor: Optional[DaemonThreadPoolExecutor] = None
        self.__task: Optional[Future] = None

    def _invoke_method(self, *args: str):
        modules_before = [k for k in sys.modules.keys()]
        working_directory_before = os.path.abspath(os.getcwd())

        from hstest.stage_test import StageTest
        try:
            self._machine.set_state(ProgramState.RUNNING)

            sys.argv = [self.runnable.file] + list(args)
            sys.path.insert(0, self.runnable.folder)

            runpy.run_module(self.runnable.module, run_name="__main__")

            self._machine.set_state(ProgramState.FINISHED)

        except BaseException as ex:
            if StageTest.curr_test_run.error_in_test is None:
                # ExitException is thrown in case of exit() or quit()
                # consider them like normal exit
                if isinstance(ex, ExitException):
                    self._machine.set_state(ProgramState.FINISHED)
                    return

                StageTest.curr_test_run.set_error_in_test(
                    ExceptionWithFeedback('', ex))

            self._machine.set_state(ProgramState.EXCEPTION_THROWN)

        finally:
            modules_to_delete = []
            for m in sys.modules:
                if m not in modules_before:
                    modules_to_delete += [m]
            for m in modules_to_delete:
                del sys.modules[m]
            sys.path.remove(self.runnable.folder)
            os.chdir(working_directory_before)

    def _launch(self, *args: str):
        from hstest.stage_test import StageTest
        test_num = StageTest.curr_test_run.test_num

        InputHandler.set_dynamic_input_func(lambda: self._request_input())
        self.__executor = DaemonThreadPoolExecutor(
            name=f"MainModuleExecutor test #{test_num}")
        self.__task = self.__executor.submit(
            lambda: self._invoke_method(*args))

    def _terminate(self):
        self.__executor.shutdown(wait=False)
        self.__task.cancel()
        with self._machine.cv:
            while not self.is_finished():
                self._input = None
                self._machine.wait_not_state(ProgramState.RUNNING)
                if self.is_waiting_input():
                    self._machine.set_state(ProgramState.RUNNING)

    def __str__(self) -> str:
        return self.runnable.file