def test_seccomp_rule_can_be_none(self): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="/bin/ls", input_path="/dev/null", output_path="/dev/null", error_path="/dev/null", args=["12344"], env=["a=b"], log_path="/dev/null", seccomp_rule_name="c_cpp", uid=0, gid=0) _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="/bin/ls", input_path="/dev/null", output_path="/dev/null", error_path="/dev/null", args=["12344"], env=["a=b"], log_path="/dev/null", seccomp_rule_name=None, uid=0, gid=0)
def test_args_must_be_list(self): with self.assertRaisesRegex(ValueError, "args must be a list"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args="12344", env=["a=b"], log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0) with self.assertRaisesRegex(ValueError, "args must be a list"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args={"k": "v"}, env=["a=b"], log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0)
def test_args_item_must_be_string(self): with self.assertRaisesRegex(ValueError, "arg item must be a string"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args=["1234", 1234], env=["a=b"], log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0) with self.assertRaisesRegex(ValueError, "arg item must be a string"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1000000000, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args=["1234", None], env=["a=b"], log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0)
def run(self): res = None if str(self.lang) == 'C' or str(self.lang) == 'C++': res = _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=128 * 2**20, max_process_number=200, max_output_size=131072, max_stack=128 * 2**20, exe_path=f'{self.DIR}/{self.lang.exe}', input_path=f'{self.DIR}/input', output_path=f'{self.DIR}/output', error_path=f'{self.DIR}/error', seccomp_rule_name='c_cpp', args=[], env=[], log_path=f'{self.DIR}/judger.log', uid=0, gid=0) else: args = [] if str(self.lang) == 'Java': args.append(f'-classpath') args.append(f'{self.DIR}') for arg in shlex.split(str(self.lang.args)): if str(self.lang) == 'Java' or 'Main' not in arg: args.append(arg) else: idx = arg.find('Main') args.append(f'{arg[:idx]}{self.DIR}/{arg[idx:]}') print(args) res = _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=_judger.UNLIMITED if str(self.lang) == 'Java' else self.problem.memory_limit * 2**20, max_process_number=200, max_output_size=131072, max_stack=_judger.UNLIMITED if str(self.lang) == 'Java' else self.problem.memory_limit * 2**20, exe_path=f'/usr/bin/{self.lang.exe}', input_path=f'{self.DIR}/input', output_path=f'{self.DIR}/output', error_path=f'{self.DIR}/error', seccomp_rule_name=None if str(self.lang) == 'Java' else 'general', args=args, env=[], log_path="judger.log", uid=0, gid=0) output = '' with open(f'{self.DIR}/output', 'r') as f: output = ''.join(f.readlines()) return output
def test_stack_size(self): config = self.base_config config["max_memory"] = 256 * 1024 * 1024 config["exe_path"] = self._compile_c("stack.c") config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) config["max_stack"] = 128 * 1024 * 1024 result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual("big stack", self.output_content(config["output_path"]))
def test_exceveat(self): config = self.base_config config["exe_path"] = self._compile_c("execveat.c") config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) if "syscall not found" in self.output_content(config["output_path"]): print("execveat syscall not found, test ignored") return self.assertEqual(result["result"], _judger.RESULT_SUCCESS) # with general seccomp config["seccomp_rule_name"] = "general" result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL)
def test_cpu_time(self): config = self.base_config config["exe_path"] = self._compile_c("while1.c") result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) self.assertEqual(result["signal"], signal.SIGKILL) self.assertTrue(result["cpu_time"] >= config["max_cpu_time"])
def test_normal(self): config = self.base_config config["exe_path"] = self._compile_c("normal.c") config["input_path"] = self.make_input("judger_test") config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) output = "judger_test\nHello world" self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual(output, self.output_content(config["output_path"])) config["exe_path"] = self._compile_c("math.c") config["input_path"] = "/dev/null" config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual("abs 1024", self.output_content(config["output_path"]))
def test_get_time(self): config = self.base_config config["exe_path"] = self._compile_c("time.c") config["seccomp_rule_name"] = "c_cpp" result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_SUCCESS)
def run_judge(not_use, config_data, key, val, count): in_path = os.path.join(config_data["data_dir"], key) out_path = os.path.join(config_data["round_dir"], random_string(32)) ans_path = os.path.join(config_data["data_dir"], val) log_path = os.path.join(config_data["round_dir"], random_string(32)) # Prevent input errors if not os.path.exists(in_path): open(in_path, "w").close() result = _judger.run(**_run_args(config_data, in_path, out_path, log_path)) if ((result["result"] == 0 or result["result"] == RUNTIME_ERROR) and result["memory"] > config_data["max_memory"] * 1024 * 1024): result["result"] = MEMORY_LIMIT_EXCEEDED # A fake time limit / memory limit exceeded elif result['cpu_time'] > config_data["max_time"] or result['result'] == CPU_TIME_LIMIT_EXCEEDED \ or result['result'] == REAL_TIME_LIMIT_EXCEEDED: result['cpu_time'] = config_data["max_time"] result['result'] = CPU_TIME_LIMIT_EXCEEDED elif result['result'] == MEMORY_LIMIT_EXCEEDED: result['memory'] = config_data["max_memory"] elif result['result'] == 0: res_judge = _result_checker(config_data, in_path, out_path, ans_path) # print("res_judge %d" % res_judge) if (res_judge != 0): result['result'] = WRONG_ANSWER verdict = result['result'] return dict(count=count, time=result['cpu_time'], memory=result['memory'] // 1024, result=verdict)
def __call__(self) -> None: os.chdir(self.base_dir) compiler_out = "compiler_output.log" _command = self.command.split(" ") result = _judger.run( max_cpu_time=self._max_cpu_time, max_real_time=self._max_real_time, max_memory=self._max_memory, max_stack=256 * 1024 * 1024, max_output_size=-1, max_process_number=-1, exe_path=_command[0], # /dev/null is best, but in some system, this will call ioctl system call input_path='/dev/null', output_path=compiler_out, error_path=compiler_out, args=_command[1::], env=default_env, log_path='compiler.log', seccomp_rule_name=None, uid=0, gid=0) if result["result"] != _judger.RESULT_SUCCESS: if os.path.exists(compiler_out): with open(compiler_out, encoding="utf-8") as f: error = f.read().strip() if error: raise CompileError(error) logging.warning(f"CE {result}") raise CompileError("Compiler runtime error, info: System Broken")
def test_child_proc_real_time_limit(self): config = self.config config["exe_path"] = self._compile_c("child_proc_real_time_limit.c") result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) self.assertEqual(result["signal"], signal.SIGKILL)
def run_usercode(self): """ 运行用户代码 """ if os.system("g++ " + self.code_path + "/main.cpp" + " -o" + self.code_path + "/main"): return "编译或者运行错误,请检查你的代码" ret = _judger.run( max_cpu_time=1000, max_real_time=2000, max_memory=128 * 1024 * 1024, max_process_number=200, max_output_size=10000, max_stack=32 * 1024 * 1024, # five args above can be _judger.UNLIMITED exe_path=self.code_path + "/main", input_path=self.code_path + "/1.in", output_path=self.code_path + "/1.out", error_path=self.code_path + "/1.out", args=[], # can be empty list env=[], log_path="judger.log", # can be None seccomp_rule_name="c_cpp", uid=0, gid=0) return ret
def judgeJava(timelimit, memorylimit, inputpath, outputpath, errorpath, judgername): return _judger.run( max_cpu_time=timelimit, max_real_time=timelimit * 10, max_memory=memorylimit * 1024 * 1024, max_process_number=10, max_output_size=32 * 1024 * 1024, max_stack=32 * 1024 * 1024, # five args above can be _judger.UNLIMITED exe_path="/usr/bin/java", input_path=inputpath, output_path=outputpath, error_path=errorpath, args=[ "-cp", judgername, "-Djava.security.policy==policy", "-Djava.awt.headless=true", "Main" ], # can be empty list env=[], log_path=judgername + "judger.log", # can be None seccomp_rule_name=None, memory_limit_check_only=1, uid=0, gid=0)
def _spj(self, in_file_path, user_out_file_path): command = self._spj_config["command"].format( exe_path=self._spj_exe, in_file_path=in_file_path, user_out_file_path=user_out_file_path).split(" ") seccomp_rule_name = self._spj_config["seccomp_rule"] result = _judger.run(max_cpu_time=self._max_cpu_time * 3, max_real_time=self._max_cpu_time * 9, max_memory=self._max_memory * 3, max_stack=128 * 1024 * 1024, max_output_size=1024 * 1024 * 1024, max_process_number=_judger.UNLIMITED, exe_path=command[0], input_path=in_file_path, output_path="/tmp/spj.out", error_path="/tmp/spj.out", args=command[1::], env=["PATH=" + os.environ.get("PATH", "")], log_path=JUDGER_RUN_LOG_PATH, seccomp_rule_name=seccomp_rule_name, uid=RUN_USER_UID, gid=RUN_GROUP_GID) if result["result"] == _judger.RESULT_SUCCESS or \ (result["result"] == _judger.RESULT_RUNTIME_ERROR and result["exit_code"] in [SPJ_WA, SPJ_ERROR] and result["signal"] == 0): return result["exit_code"] else: return SPJ_ERROR
def test_real_time(self): config = self.config config["exe_path"] = self._compile_c("sleep.c") result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) self.assertEqual(result["signal"], signal.SIGKILL) self.assertTrue(result["real_time"] >= config["max_real_time"])
def run(file_path_conf='', input_path_conf='', answer_path_conf='', output_path_conf='', error_path_conf='', max_cpu_time_conf=1000, max_memory_conf=128): ret = _judger.run( max_cpu_time=max_cpu_time_conf, max_real_time=max_cpu_time_conf * 2, max_memory=max_memory_conf * 1024 * 1024, max_process_number=200, max_output_size=10000, max_stack=32 * 1024 * 1024, # five args above can be _judger.UNLIMITED exe_path='main', input_path=input_path_conf, output_path=output_path_conf, error_path=error_path_conf, answer_path=answer_path_conf, args=[file_path_conf], # can be empty list env=[], log_path="judger.log", # can be None seccomp_rule_name="c_cpp", uid=0, gid=0) print(ret) return ret
def do_java(): if os.system("/usr/bin/javac jav/Main.java"): print("compile error") exit(1) ret = _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=-1, max_process_number=200, max_output_size=10000, max_stack=32 * 1024 * 1024, memory_limit_check_only=1, exe_path="/usr/bin/java", input_path="1.in", output_path="jav/1.out", error_path="jav/1.error", args=[ "-cp", "jav", "-XX:MaxRAM=131072k", "-Djava.security.manager", "-Dfile.encoding=UTF-8", "-Djava.security.policy==/etc/java_policy", "-Djava.awt.headless=true", "Main" ], env=[], log_path="jav/judger.log", seccomp_rule_name=None, uid=0, gid=0) print(ret)
def test_env_must_be_list(self): with self.assertRaisesRegexp(ValueError, "env must be a list"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args=["1234"], env="1234", log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0) with self.assertRaisesRegexp(ValueError, "env must be a list"): _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, max_process_number=200, max_output_size=10000, exe_path="1.out", input_path="1.in", output_path="1.out", error_path="1.out", args=["1234"], env={"k": "v"}, log_path="1.log", seccomp_rule_name="1.so", uid=0, gid=0)
def test_memory3(self): config = self.config config["max_memory"] = 512 * 1024 * 1024 config["exe_path"] = self._compile_c("memory3.c") result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertTrue(result["memory"] >= 102400000 * 4)
def _run_one(self, answer_in_path, answer_out_path): # 用户程序输出路径 user_out_file_path = os.path.join(self.user_dir_path, 'out') rst = _judger.run(max_cpu_time=1000, max_real_time=2000, max_memory=128 * 1024 * 1024, max_process_number=200, max_output_size=10000, max_stack=32 * 1024 * 1024, # five args above can be _judger.UNLIMITED exe_path=self.user_program_path, input_path=answer_in_path, output_path=user_out_file_path, error_path=self.user_err_file_path, args=[], # can be empty list env=[], log_path="judger.log", # can be None seccomp_rule_name="c_cpp", uid=0, gid=0) print(rst) # 运行成功才评测 if rst['result'] == 0: after_judge = self._judge(user_out_file_path, answer_out_path) # 删除用户答案(因为可能存在多个测试用例) os.remove(user_out_file_path) # 答案不对 if after_judge != 0: return {'result': after_judge} return rst
def compile(self, compile_config, src_path, output_dir): #通过编译配置获取编译命令 command = compile_config["compile_command"] #拼接配置执行文件路径,output_dir就是submission_dir exe_path = os.path.join(output_dir, compile_config["exe_name"]) #编译命令格式化,格式化路径在配置文件里面 command = command.format(src_path=src_path, exe_dir=output_dir, exe_path=exe_path) #编译完成文件输出路径 compiler_out = os.path.join(output_dir, "compiler.out") #按照空格将编译命令分割成块 _command = command.split(" ") #转到编译输出文件路径 os.chdir(output_dir) #调用评判机Judger模块进行编译,也就是说编译也是要经过评判机的,因为编译本身就是一个执行文件的过程, #用户的可执行代码在另外一个文件judge-client中处理。 result = _judger.run( max_cpu_time=compile_config["max_cpu_time"], max_real_time=compile_config["max_real_time"], max_memory=compile_config["max_memory"], max_stack=128 * 1024 * 1024, max_output_size=1024 * 1024, max_process_number=_judger.UNLIMITED, #-1 #编译命令空格分割的第一个文件,这里的exe_path已经更改成编译器的路径,不是上面的exe_path了 exe_path=_command[0], # 使用为文件/dev/null是最好的,但在某些系统中,这将调用ioctl system call input_path=src_path, output_path=compiler_out, error_path=compiler_out, #从第一个开始读取参数 args=_command[1::], #设置运行环境 env=["PATH=" + os.getenv("PATH")], log_path=COMPILER_LOG_PATH, #这里不设置安全计算规则是因为编译的执行文件第一个都是系统的编译器,本身运行就对系统无害 #唯一出现的可能就是编译错误 seccomp_rule_name=None, uid=COMPILER_USER_UID, gid=COMPILER_GROUP_GID) # 如果编译异常,结果不相等,并且编译输出文件存在,那么打开文件并设置编译错误信息,最后删除此文件 # 只会出现编译错误,不可能出现其他错误。 if result["result"] != _judger.RESULT_SUCCESS: if os.path.exists(compiler_out): with open(compiler_out, encoding="utf-8") as f: error = f.read().strip() os.remove(compiler_out) # 错误不空,抛出错误 if error: raise CompileError(error) #抛出编译错误信息 raise CompileError("Compiler runtime error, info: %s" % json.dumps(result)) else: #编译通过,删除编译输出文件,返回编译用户的代码后执行文件路径 os.remove(compiler_out) return exe_path
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"]) user_output_file = os.path.join(self._submission_dir, test_case_file_id + ".out") 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", []) 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], input_path=in_file, output_path=user_output_file, error_path=user_output_file, args=command[1::], env=env, log_path=JUDGER_RUN_LOG_PATH, seccomp_rule_name=self._run_config["seccomp_rule"], uid=RUN_USER_UID, gid=RUN_GROUP_GID, memory_limit_check_only=self._run_config.get("memory_limit_check_only", 0)) 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 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: run_result["output_md5"], is_ac, is_pe = self._compare_output(test_case_file_id) # -1 == Wrong Answer if not is_ac: run_result["result"] = _judger.RESULT_WRONG_ANSWER if not is_ac and is_pe: run_result["result"] = _judger.RESULT_PRESENTATION_ERROR if self._output: try: with open(user_output_file, "r", encoding="utf-8") as f: run_result["output"] = f.read() except Exception: pass return run_result
def runCode(self, language, **kwargs): if (language.getComplication() == True): compileErrorResult = self.checkRunnable( language.getCompileCommand()) if compileErrorResult != '': return {'result': 'CE', 'error_message': compileErrorResult} ret = _judger.run( max_cpu_time=1000, max_real_time=kwargs['time_limit'], max_memory=language.getMax_memory(), max_process_number=200, max_output_size=10000, max_stack=32 * 1024 * 1024, # five args above can be _judger.UNLIMITED exe_path=language.getExe_path(), input_path=kwargs['stdin'], output_path=kwargs['factout'], error_path=kwargs['stderr'], args=language.getRun_args(), # args=[], # can be empty list env=[], log_path=sys_config['logfile'], # can be None seccomp_rule_name=language.getRun_rule(), uid=sys_config['uid'], gid=sys_config['gid']) if ret['result'] == CodeResult.SYSTEM_ERROR: return {'result': 'SE', 'error_message': 'System Error'} if ret['result'] == CodeResult.RUNTIME_ERROR or ret[ 'result'] == CodeResult.MEMORY_LIMIT_EXCEEDED: with open(kwargs['stderr'], 'r', encoding='utf-8') as file: error_message = '' for line in file: error_message = error_message + line return {'result': 'RTE', 'error_message': error_message} if ret['result'] == CodeResult.CPU_TIME_ERROR or ret[ 'result'] == CodeResult.REAL_TIME_ERROR: return { 'result': 'TLE', 'error_message': 'TimeLimitExceed', 'time': kwargs['time_limit'] / 1000.00, 'memory': ret['memory'] / (1000 * 1000) } else: if not self.checkFile(kwargs['stdout'], kwargs['factout']): return { 'result': 'WA', 'error_message': None, 'time': ret['real_time'] / 1000.00, 'memory': ret['memory'] / (1000 * 1000) } return { 'result': 'AC', 'error_message': None, 'time': ret['real_time'] / 1000, 'memory': ret['memory'] / (1000 * 1000) }
def test_memory1(self): config = self.base_config config["max_memory"] = 64 * 1024 * 1024 config["exe_path"] = self._compile_c("memory1.c") result = _judger.run(**config) # malloc succeeded self.assertTrue(result["memory"] > 80 * 1024 * 1024) self.assertEqual(result["result"], _judger.RESULT_MEMORY_LIMIT_EXCEEDED)
def test_output_size(self): config = self.base_config config["exe_path"] = self._compile_c("output_size.c") config["max_output_size"] = 1000 * 10 result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) with open("/tmp/fsize_test", "r") as f: self.assertEqual(len(f.read()), 10000)
def test_gcc_random(self): config = self.base_config config["max_memory"] = _judger.UNLIMITED config["exe_path"] = "/usr/bin/gcc" config["args"] = ["../test_src/integration/gcc_random.c", "-o", os.path.join(self.workspace, "gcc_random")] result = _judger.run(**config) self.assertTrue(result["real_time"] >= 2000)
def test_stdout_and_stderr(self): config = self.config config["exe_path"] = self._compile_c("stdout_stderr.c") config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) self.assertEqual(result["result"], _judger.RESULT_SUCCESS) output = "stderr\n+++++++++++++++\n--------------\nstdout\n" self.assertEqual(output, self.output_content(config["output_path"]))
def test_env(self): config = self.config config["exe_path"] = self._compile_c("env.c") config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) output = "judger_test\njudger\n" self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual(output, self.output_content(config["output_path"]))
def test_args(self): config = self.config config["exe_path"] = self._compile_c("args.c") config["args"] = ["test", "hehe", "000"] config["output_path"] = config["error_path"] = self.output_path() result = _judger.run(**config) output = "argv[0]: /tmp/integration/args\nargv[1]: test\nargv[2]: hehe\nargv[3]: 000\n" self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual(output, self.output_content(config["output_path"]))