def _load_test_case_info(self): try: with open(os.path.join(self._test_case_dir, "info")) as f: return json.load(f) except IOError: raise JudgeClientError("Test case not found") except ValueError: raise JudgeClientError("Bad test case config")
def __init__(self, run_config, exe_path, max_cpu_time, max_memory, test_case_dir, submission_dir, spj_version, spj_config, io_mode, output=False): self._run_config = run_config self._exe_path = exe_path self._max_cpu_time = max_cpu_time self._max_memory = max_memory self._max_real_time = self._max_cpu_time * 3 self._test_case_dir = test_case_dir self._submission_dir = submission_dir self._pool = Pool(processes=psutil.cpu_count()) #创建进程池,进程个数为CPU的个数 self._test_case_info = self._load_test_case_info() self._spj_version = spj_version self._spj_config = spj_config self._output = output self._io_mode = io_mode if self._spj_version and self._spj_config: self._spj_exe = os.path.join( SPJ_EXE_DIR, self._spj_config["exe_name"].format( spj_version=self._spj_version)) if not os.path.exists(self._spj_exe): raise JudgeClientError("spj exe not found")
def __exit__(self, exc_type, exc_val, exc_tb): if not DEBUG: try: shutil.rmtree(self.work_dir) #删除工作目录下的所有文件 except Exception as e: logger.exception(e) raise JudgeClientError("failed to clean runtime dir")
def __enter__(self): try: os.mkdir(self.work_dir) #创建工作目录 if self.init_test_case_dir: os.mkdir(self.test_case_dir) #创建测试样例目录 os.chown(self.work_dir, COMPILER_USER_UID, RUN_GROUP_GID) #修改文件的属主和属组 os.chmod(self.work_dir, 0o711) #dir权限711 except Exception as e: logger.exception(e) raise JudgeClientError("failed to create runtime dir") return self.work_dir, self.test_case_dir
def _judge_one(self, test_case_file_id): test_case_info = self._get_test_case_file_info(test_case_file_id) in_file = os.path.join(self._test_case_dir, test_case_info["input_name"]) if self._io_mode["io_mode"] == ProblemIOMode.file: #如果I/O模式为文件模式 user_output_dir = os.path.join(self._submission_dir, str(test_case_file_id)) os.mkdir(user_output_dir) os.chown(user_output_dir, RUN_USER_UID, RUN_GROUP_GID) os.chmod(user_output_dir, 0o711) os.chdir(user_output_dir) # todo check permission user_output_file = os.path.join(user_output_dir, self._io_mode["output"]) real_user_output_file = os.path.join(user_output_dir, "stdio.txt") shutil.copyfile( in_file, os.path.join(user_output_dir, self._io_mode["input"])) kwargs = { "input_path": in_file, "output_path": real_user_output_file, "error_path": real_user_output_file } else: real_user_output_file = user_output_file = os.path.join( self._submission_dir, test_case_file_id + ".out") #在样例中是1.out kwargs = { "input_path": in_file, "output_path": real_user_output_file, "error_path": real_user_output_file } command = self._run_config["command"].format( exe_path=self._exe_path, exe_dir=os.path.dirname(self._exe_path), max_memory=int(self._max_memory / 1024)).split(" ") env = ["PATH=" + os.environ.get("PATH", "")] + self._run_config.get( "env", []) seccomp_rule = self._run_config["seccomp_rule"] if isinstance(seccomp_rule, dict): seccomp_rule = seccomp_rule[self._io_mode["io_mode"]] run_result = _judger.run(max_cpu_time=self._max_cpu_time, max_real_time=self._max_real_time, max_memory=self._max_memory, max_stack=128 * 1024 * 1024, max_output_size=max( test_case_info.get("output_size", 0) * 2, 1024 * 1024 * 16), max_process_number=_judger.UNLIMITED, exe_path=command[0], args=command[1::], env=env, log_path=JUDGER_RUN_LOG_PATH, seccomp_rule_name=seccomp_rule, uid=RUN_USER_UID, gid=RUN_GROUP_GID, memory_limit_check_only=self._run_config.get( "memory_limit_check_only", 0), **kwargs) run_result["test_case"] = test_case_file_id # if progress exited normally, then we should check output result run_result["output_md5"] = None run_result["output"] = None if run_result["result"] == _judger.RESULT_SUCCESS: if not os.path.exists(user_output_file): run_result["result"] = _judger.RESULT_WRONG_ANSWER else: if self._test_case_info.get("spj"): if not self._spj_config or not self._spj_version: raise JudgeClientError( "spj_config or spj_version not set") spj_result = self._spj(in_file_path=in_file, user_out_file_path=user_output_file) if spj_result == SPJ_WA: run_result["result"] = _judger.RESULT_WRONG_ANSWER elif spj_result == SPJ_ERROR: run_result["result"] = _judger.RESULT_SYSTEM_ERROR run_result["error"] = _judger.ERROR_SPJ_ERROR else: #非 spj run_result["output_md5"], is_ac = self._compare_output( test_case_file_id, user_output_file) # -1 == Wrong Answer if not is_ac: run_result["result"] = _judger.RESULT_WRONG_ANSWER if self._output: try: with open(user_output_file, "rb") as f: run_result["output"] = f.read().decode( "utf-8", errors="backslashreplace") except Exception: pass return run_result
def judge(cls, language_config, src, max_cpu_time, max_memory, test_case_id=None, test_case=None, spj_version=None, spj_config=None, spj_compile_config=None, spj_src=None, output=False, io_mode=None): if not io_mode: io_mode = {"io_mode": ProblemIOMode.standard} #标准I/O if not (test_case or test_case_id) or (test_case and test_case_id): raise JudgeClientError("invalid parameter") # init compile_config = language_config.get("compile") #compile config info run_config = language_config["run"] #run config info submission_id = uuid.uuid4().hex #print("############submission_id = ",submission_id) is_spj = spj_version and spj_config if is_spj: spj_exe_path = os.path.join( SPJ_EXE_DIR, spj_config["exe_name"].format(spj_version=spj_version)) # spj src has not been compiled if not os.path.isfile(spj_exe_path): logger.warning( "%s does not exists, spj src will be recompiled") cls.compile_spj(spj_version=spj_version, src=spj_src, spj_compile_config=spj_compile_config) print("!!!!!test_case =", test_case) init_test_case_dir = bool(test_case) with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=str(submission_id), init_test_case_dir=init_test_case_dir) as dirs: submission_dir, test_case_dir = dirs test_case_dir = test_case_dir or os.path.join( TEST_CASE_DIR, test_case_id) #print("@@@@@test_case_dir = ",test_case_dir) if compile_config: src_path = os.path.join(submission_dir, compile_config["src_name"]) # write source code into file with open(src_path, "w", encoding="utf-8") as f: #创建Main.java文件,并把源代码src写入该文件 f.write(src) os.chown(src_path, COMPILER_USER_UID, 0) #更改属主和属组 os.chmod(src_path, 0o400) #更改权限为只读 # compile source code, return exe file path exe_path = Compiler().compile(compile_config=compile_config, src_path=src_path, output_dir=submission_dir) try: # Java exe_path is SOME_PATH/Main, but the real path is SOME_PATH/Main.class # We ignore it temporarily os.chown(exe_path, RUN_USER_UID, 0) #更改文件的属主和属组 os.chmod(exe_path, 0o500) #更改可执行文件的权限 except Exception: pass else: exe_path = os.path.join( submission_dir, run_config["exe_name"]) #this is for spj with open(exe_path, "w", encoding="utf-8") as f: f.write(src) if init_test_case_dir: #如果test_case参数没有制定的话,需要生成test_case info = { "test_case_number": len(test_case), "spj": is_spj, "test_cases": {} } # write test case for index, item in enumerate(test_case): index += 1 item_info = {} input_name = str(index) + ".in" item_info["input_name"] = input_name input_data = item["input"].encode("utf-8") item_info["input_size"] = len(input_data) with open(os.path.join(test_case_dir, input_name), "wb") as f: f.write(input_data) if not is_spj: output_name = str(index) + ".out" item_info["output_name"] = output_name output_data = item["output"].encode("utf-8") item_info["output_md5"] = hashlib.md5( output_data).hexdigest() item_info["output_size"] = len(output_data) item_info["stripped_output_md5"] = hashlib.md5( output_data.rstrip()).hexdigest() with open(os.path.join(test_case_dir, output_name), "wb") as f: f.write(output_data) info["test_cases"][index] = item_info with open(os.path.join(test_case_dir, "info"), "w") as f: json.dump(info, f) judge_client = JudgeClient(run_config=language_config["run"], exe_path=exe_path, max_cpu_time=max_cpu_time, max_memory=max_memory, test_case_dir=test_case_dir, submission_dir=submission_dir, spj_version=spj_version, spj_config=spj_config, output=output, io_mode=io_mode) run_result = judge_client.run() return run_result
uid=RUN_USER_UID, gid=RUN_GROUP_GID, memory_limit_check_only=self._run_config.get("memory_limit_check_only", 0), **kwargs) run_result["test_case"] = test_case_file_id # if progress exited normally, then we should check output result run_result["output_md5"] = None run_result["output"] = None if run_result["result"] == _judger.RESULT_SUCCESS: if not os.path.exists(user_output_file): run_result["result"] = _judger.RESULT_WRONG_ANSWER else: if self._test_case_info.get("spj"): if not self._spj_config or not self._spj_version: raise JudgeClientError("spj_config or spj_version not set") spj_result = self._spj(in_file_path=in_file, user_out_file_path=user_output_file) if spj_result == SPJ_WA: run_result["result"] = _judger.RESULT_WRONG_ANSWER elif spj_result == SPJ_ERROR: run_result["result"] = _judger.RESULT_SYSTEM_ERROR run_result["error"] = _judger.ERROR_SPJ_ERROR else: #非 spj run_result["output_md5"], is_ac = self._compare_output(test_case_file_id, user_output_file) # -1 == Wrong Answer if not is_ac: run_result["result"] = _judger.RESULT_WRONG_ANSWER if self._output: