from os import listdir, mkdir from os.path import join, exists from shutil import copyfile, rmtree from subprocess import call, TimeoutExpired from Main.models import ExtraFile from Main.models.progress import Progress from Sprint.settings import CONSTS from SprintLib.utils import copy_content from bot import bot class TestException(Exception): pass class BaseTester: working_directory = "app" def before_test(self): files = [ file for file in listdir(self.solution.testing_directory) if file.endswith("." + self.solution.language.file_type) ] code = self.solution.exec_command( f'{self.build_command} {" ".join(files)}', working_directory=self.working_directory, ) if code != 0: raise TestException("CE") def test(self, filename): code = self.solution.exec_command( f"< {filename} {self.command} > output.txt", timeout=self.solution.task.time_limit / 1000, ) if code != 0: raise TestException("RE") result = open(join(self.solution.testing_directory, "output.txt"), "r").read() if result.strip() != self.predicted.strip(): raise TestException("WA") def after_test(self): pass @property def command(self): return "./executable.exe" @property def build_command(self): return "" def __init__(self, solution): self.solution = solution def execute(self): if not exists(self.solution.testing_directory): mkdir(self.solution.testing_directory) copy_content( self.solution.directory, self.solution.testing_directory, ("test_dir",) ) self.solution.result = CONSTS["testing_status"] self.solution.save() docker_command = f"docker run --name solution_{self.solution.id} --volume={self.solution.volume_directory}:/{self.working_directory} -t -d {self.solution.language.image}" print(docker_command) call(docker_command, shell=True) print("Container created") for file in ExtraFile.objects.filter(task=self.solution.task): copyfile(file.path, join(self.solution.testing_directory, file.filename)) print("Files copied") try: self.before_test() print("before test finished") for test in self.solution.task.tests: if not test.filename.endswith(".a"): self.predicted = ExtraFile.objects.get( task=self.solution.task, filename=test.filename + ".a" ).text self.test(test.filename) self.after_test() self.solution.result = CONSTS["ok_status"] progress = Progress.objects.get( user=self.solution.user, task=self.solution.task ) if progress.finished_time is None: progress.finished_time = self.solution.time_sent progress.finished = True progress.save() progress.increment_rating() except TestException as e: self.solution.result = str(e) except TimeoutExpired: self.solution.result = "TL" except Exception as e: self.solution.result = "TE" print(str(e)) self.solution.save() call(f"docker rm --force solution_{self.solution.id}", shell=True) rmtree(self.solution.testing_directory) self.solution.user.userinfo.refresh_from_db() if self.solution.user.userinfo.notification_solution_result: bot.send_message( self.solution.user.userinfo.telegram_chat_id, f"Задача: {self.solution.task.name}\n" f"Результат: {self.solution.result}\n" f"Очки решения: {Progress.by_solution(self.solution).score}\n" f"Текущий рейтинг: {self.solution.user.userinfo.rating}", parse_mode="html", )