|
| 1 | +"""A test generator using UTBotPython.""" |
| 2 | +import pathlib |
| 3 | +import site |
| 4 | +import subprocess |
| 5 | +import sys |
| 6 | +import tempfile |
| 7 | +import time |
| 8 | + |
| 9 | +import rich |
| 10 | +from python_tool_competition_2024.config import get_config, GeneratorName |
| 11 | +from python_tool_competition_2024.generation_results import ( |
| 12 | + TestGenerationFailure, |
| 13 | + TestGenerationResult, |
| 14 | + TestGenerationSuccess, |
| 15 | + FailureReason, |
| 16 | +) |
| 17 | +from python_tool_competition_2024.generators import FileInfo, TestGenerator |
| 18 | + |
| 19 | +from python_tool_competition_2024_utbot_python.config import UTBotPythonConfig |
| 20 | + |
| 21 | +GENERATION_TIMES: list[float] = [] |
| 22 | + |
| 23 | + |
| 24 | +class UTBotPythonTestGenerator(TestGenerator): |
| 25 | + """A test generator using UTBotPython.""" |
| 26 | + |
| 27 | + def build_test(self, target_file_info: FileInfo) -> TestGenerationResult: |
| 28 | + """ |
| 29 | + Generate a test for the specific target file. |
| 30 | +
|
| 31 | + Args: |
| 32 | + target_file_info: The `FileInfo` of the file to generate a test for. |
| 33 | +
|
| 34 | + Returns: |
| 35 | + Either a `TestGenerationSuccess` if it was successful, or a |
| 36 | + `TestGenerationFailure` otherwise. |
| 37 | + """ |
| 38 | + return _build_test(target_file_info) |
| 39 | + |
| 40 | + @staticmethod |
| 41 | + def check_run() -> None: |
| 42 | + """ |
| 43 | + Try to run UTBotPython and shows error message. |
| 44 | + """ |
| 45 | + target_file_info = FileInfo( |
| 46 | + pathlib.Path("./targets/example1.py").resolve().absolute(), |
| 47 | + "example1", |
| 48 | + get_config( |
| 49 | + GeneratorName("UTBotPython"), |
| 50 | + pathlib.Path("./targets/").resolve().absolute(), |
| 51 | + pathlib.Path("").absolute(), |
| 52 | + rich.console.Console(), |
| 53 | + show_commands=True, |
| 54 | + show_failures=True, |
| 55 | + ), |
| 56 | + ) |
| 57 | + _build_test(target_file_info, check_usvm=True) |
| 58 | + |
| 59 | + |
| 60 | +def _build_test( |
| 61 | + target_file_info: FileInfo, check_usvm: bool = False |
| 62 | +) -> TestGenerationResult: |
| 63 | + if not sys.platform.startswith("linux"): |
| 64 | + sys.stderr.write("ERROR: This script works only on Linux\n") |
| 65 | + exit(1) |
| 66 | + |
| 67 | + sys_paths = [target_file_info.config.targets_dir] |
| 68 | + |
| 69 | + with tempfile.TemporaryDirectory() as tempdir: |
| 70 | + output_dir = pathlib.Path(tempdir) |
| 71 | + module_name = target_file_info.module_name.replace(".", "_") |
| 72 | + output_file = output_dir / f"test_{module_name}.py" |
| 73 | + _run_utbot( |
| 74 | + target_file_info.absolute_path, |
| 75 | + sys_paths, |
| 76 | + output_file, |
| 77 | + UTBotPythonConfig.JAR_FILE, |
| 78 | + UTBotPythonConfig.USVM_PATH, |
| 79 | + UTBotPythonConfig.TIMEOUT, |
| 80 | + UTBotPythonConfig.PYTHON_PATH, |
| 81 | + UTBotPythonConfig.JAVA_PATH, |
| 82 | + check_usvm=check_usvm, |
| 83 | + ) |
| 84 | + |
| 85 | + utbot_tests = _read_generated_tests(str(output_file)) |
| 86 | + if utbot_tests == "": |
| 87 | + return TestGenerationFailure(tuple(), FailureReason.NOTHING_GENERATED) |
| 88 | + |
| 89 | + return TestGenerationSuccess(utbot_tests) |
| 90 | + |
| 91 | + |
| 92 | +def _run_utbot( |
| 93 | + source_file: pathlib.Path, |
| 94 | + sys_paths: list[pathlib.Path], |
| 95 | + output_file: pathlib.Path, |
| 96 | + jar_path: pathlib.Path, |
| 97 | + usvm_dir: pathlib.Path, |
| 98 | + timeout: int, |
| 99 | + python_path: str, |
| 100 | + java_cmd: str, |
| 101 | + check_usvm: bool = False, |
| 102 | +): |
| 103 | + command = ( |
| 104 | + f"{java_cmd} -jar {jar_path}" |
| 105 | + f" generate_python {source_file}" |
| 106 | + f" -p {python_path}" |
| 107 | + f" -o {output_file}" |
| 108 | + f" -s {','.join(map(str, sys_paths))}" |
| 109 | + f" -t {timeout}" |
| 110 | + f" --java-cmd {java_cmd}" |
| 111 | + f" --usvm-dir {usvm_dir}" |
| 112 | + f" --runtime-exception-behaviour PASS" |
| 113 | + f" --prohibited-exceptions -" |
| 114 | + ) |
| 115 | + if check_usvm: |
| 116 | + command += " --check-usvm" |
| 117 | + |
| 118 | + print(command) |
| 119 | + start = time.time() |
| 120 | + |
| 121 | + p = subprocess.Popen(command.split(), close_fds=True) |
| 122 | + while p.poll() is None: |
| 123 | + time.sleep(1) |
| 124 | + |
| 125 | + cur_time = time.time() - start |
| 126 | + GENERATION_TIMES.append(cur_time) |
| 127 | + print("Process finished in", cur_time) |
| 128 | + print("Mean time:", sum(GENERATION_TIMES) / len(GENERATION_TIMES)) |
| 129 | + print("Max time:", max(GENERATION_TIMES)) |
| 130 | + |
| 131 | + |
| 132 | +def _read_generated_tests(output_file: str) -> str: |
| 133 | + try: |
| 134 | + with open(output_file, "r") as f: |
| 135 | + return f.read() |
| 136 | + except: |
| 137 | + return "" |
0 commit comments