mirror of
https://github.com/QingdaoU/JudgeServer.git
synced 2024-12-28 21:31:43 +00:00
完善SpecialJudge的逻辑
This commit is contained in:
parent
d27e1e9fa8
commit
b03e9e3b30
@ -31,18 +31,20 @@ class JudgeServerClient(object):
|
||||
def ping(self):
|
||||
return self._request(self.server_base_url + "/ping")
|
||||
|
||||
def judge(self, src, language_config, submission_id, max_cpu_time, max_memory, test_case_id):
|
||||
def judge(self, src, language_config, submission_id, max_cpu_time, max_memory, test_case_id, spj_version=None, spj_config=None):
|
||||
data = {"language_config": language_config,
|
||||
"submission_id": submission_id,
|
||||
"src": src,
|
||||
"max_cpu_time": max_cpu_time,
|
||||
"max_memory": max_memory,
|
||||
"test_case_id": test_case_id}
|
||||
"test_case_id": test_case_id,
|
||||
"spj_version": spj_version,
|
||||
"spj_config": spj_config}
|
||||
return self._request(self.server_base_url + "/judge", data=data)
|
||||
|
||||
def compile_spj(self, src, spj_version, spj_config, test_case_id):
|
||||
def compile_spj(self, src, spj_version, spj_compile_config, test_case_id):
|
||||
data = {"src": src, "spj_version": spj_version,
|
||||
"spj_compile_config": spj_config, "test_case_id": test_case_id}
|
||||
"spj_compile_config": spj_compile_config, "test_case_id": test_case_id}
|
||||
return self._request(self.server_base_url + "/compile_spj", data=data)
|
||||
|
||||
|
||||
@ -59,6 +61,13 @@ if __name__ == "__main__":
|
||||
}
|
||||
"""
|
||||
|
||||
c_spj_src = r"""
|
||||
#include <stdio.h>
|
||||
int main(){
|
||||
return 1;
|
||||
}
|
||||
"""
|
||||
|
||||
cpp_src = r"""
|
||||
#include <iostream>
|
||||
|
||||
@ -87,14 +96,22 @@ if __name__ == "__main__":
|
||||
|
||||
client = JudgeServerClient(token="token", server_base_url="http://123.57.151.42:11235")
|
||||
print client.ping(), "\n\n"
|
||||
print client.compile_spj(src=c_src, spj_version="4", spj_config=c_lang_config["spj"],
|
||||
test_case_id="d8c460de943189a83bad166ec96d975d"), "\n\n"
|
||||
print client.compile_spj(src=c_spj_src, spj_version="1", spj_compile_config=c_lang_config["spj_compile"],
|
||||
test_case_id="spj"), "\n\n"
|
||||
|
||||
print client.judge(src=cpp_src, language_config=cpp_lang_config, submission_id=str(int(time.time())),
|
||||
print client.judge(src=c_src, language_config=c_lang_config, submission_id=str(int(time.time())),
|
||||
max_cpu_time=1000, max_memory=1024 * 1024 * 128,
|
||||
test_case_id="d8c460de943189a83bad166ec96d975d"), "\n\n"
|
||||
time.sleep(2)
|
||||
print client.judge(src=java_src, language_config=java_lang_config, submission_id=str(int(time.time())),
|
||||
test_case_id="normal"), "\n\n"
|
||||
|
||||
print client.judge(src=cpp_src, language_config=cpp_lang_config, submission_id="1",
|
||||
max_cpu_time=1000, max_memory=1024 * 1024 * 128,
|
||||
test_case_id="d8c460de943189a83bad166ec96d975d"), "\n\n"
|
||||
time.sleep(2)
|
||||
test_case_id="normal"), "\n\n"
|
||||
|
||||
print client.judge(src=java_src, language_config=java_lang_config, submission_id="2",
|
||||
max_cpu_time=1000, max_memory=1024 * 1024 * 1024,
|
||||
test_case_id="normal"), "\n\n"
|
||||
|
||||
print client.judge(src=c_src, language_config=c_lang_config, submission_id="3",
|
||||
max_cpu_time=1000, max_memory=1024 * 1024 * 128,
|
||||
test_case_id="spj",
|
||||
spj_version="1", spj_config=c_lang_config["spj_config"]), "\n\n"
|
||||
|
@ -15,13 +15,18 @@ c_lang_config = {
|
||||
"seccomp_rule": None,
|
||||
"max_process_number": -1
|
||||
},
|
||||
"spj": {
|
||||
"spj_compile": {
|
||||
"src_name": "spj-{spj_version}.c",
|
||||
"exe_name": "spj-{spj_version}",
|
||||
"max_cpu_time": 10000,
|
||||
"max_real_time": 20000,
|
||||
"max_memory": 1024 * 1024 * 1024,
|
||||
"compile_command": "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {src_path} -lm -o {exe_path}"
|
||||
},
|
||||
"spj_config": {
|
||||
"exe_name": "spj-{spj_version}",
|
||||
"command": "{exe_path} {in_file_path} {user_out_file_path}",
|
||||
"seccomp_rule": "c_cpp"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,12 +38,9 @@ class Compiler(object):
|
||||
if result["result"] != _judger.RESULT_SUCCESS:
|
||||
with open(compiler_out) as f:
|
||||
error = f.read().strip()
|
||||
os.remove(compiler_out)
|
||||
if error:
|
||||
raise CompileError(error)
|
||||
|
||||
# 如果是spj的话, 不要在test_case文件夹中留下这个文件
|
||||
os.remove(compiler_out)
|
||||
|
||||
raise CompileError("Compiler runtime error, info: %s" % json.dumps(result).decode("utf-8"))
|
||||
|
||||
return exe_path
|
||||
|
@ -8,8 +8,8 @@ import pwd
|
||||
JUDGER_WORKSPACE_BASE = "/judger_run"
|
||||
LOG_BASE = "/log"
|
||||
|
||||
COMPILER_LOG_PATH = os.path.join(LOG_BASE, "compile.log")
|
||||
JUDGER_RUN_LOG_PATH = os.path.join(LOG_BASE, "judger.log")
|
||||
COMPILER_LOG_PATH = os.path.join(LOG_BASE, "compile.log").encode("utf-8")
|
||||
JUDGER_RUN_LOG_PATH = os.path.join(LOG_BASE, "judger.log").encode("utf-8")
|
||||
|
||||
LOW_PRIVILEDGE_UID = pwd.getpwnam("nobody").pw_uid
|
||||
LOW_PRIVILEDGE_GID = grp.getgrnam("nogroup").gr_gid
|
||||
|
@ -1,7 +1,7 @@
|
||||
judge_server:
|
||||
image: judge_server
|
||||
volumes:
|
||||
- /data/test_case:/test_case
|
||||
- /data/JudgeServer/test/test_case:/test_case
|
||||
- /data/log:/log
|
||||
- /data/JudgeServer:/code
|
||||
environment:
|
||||
|
@ -12,12 +12,18 @@ from config import TEST_CASE_DIR, JUDGER_RUN_LOG_PATH, LOW_PRIVILEDGE_GID, LOW_P
|
||||
from exception import JudgeClientError
|
||||
|
||||
|
||||
WA = -1
|
||||
SPJ_WA = 1
|
||||
SPJ_AC = 0
|
||||
SPJ_ERROR = -1
|
||||
|
||||
|
||||
def _run(instance, test_case_file_id):
|
||||
return instance._judge_one(test_case_file_id)
|
||||
|
||||
|
||||
class JudgeClient(object):
|
||||
def __init__(self, run_config, exe_path, max_cpu_time, max_memory, test_case_id, submission_dir):
|
||||
def __init__(self, run_config, exe_path, max_cpu_time, max_memory, test_case_id, submission_dir, spj_version, spj_config):
|
||||
self._run_config = run_config
|
||||
self._exe_path = exe_path
|
||||
self._max_cpu_time = max_cpu_time
|
||||
@ -30,6 +36,9 @@ class JudgeClient(object):
|
||||
self._pool = Pool(processes=psutil.cpu_count())
|
||||
self._test_case_info = self._load_test_case_info()
|
||||
|
||||
self._spj_version = spj_version
|
||||
self._spj_config = spj_config
|
||||
|
||||
def _load_test_case_info(self):
|
||||
try:
|
||||
with open(os.path.join(self._test_case_dir, "info")) as f:
|
||||
@ -52,9 +61,36 @@ class JudgeClient(object):
|
||||
output_md5 = hashlib.md5(f.read().rstrip()).hexdigest()
|
||||
return output_md5, output_md5 == self._test_case_info["test_cases"][str(test_case_file_id)]["striped_output_md5"]
|
||||
|
||||
def _spj(self, in_file_path, user_out_file_path):
|
||||
command = self._spj_config["command"].format(exe_path=os.path.join(self._test_case_dir,
|
||||
self._spj_config["exe_name"].format(spj_version=self._spj_version)),
|
||||
in_file_path=in_file_path, user_out_file_path=user_out_file_path).split(" ")
|
||||
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_output_size=1024 * 1024 * 1024,
|
||||
max_process_number=self._run_config["max_process_number"],
|
||||
exe_path=command[0].encode("utf-8"),
|
||||
input_path=in_file_path.encode("utf-8"),
|
||||
output_path="/tmp/spj.out".encode("utf-8"),
|
||||
error_path="/tmp/spj.out".encode("utf-8"),
|
||||
args=[item.encode("utf-8") for item in command[1::]],
|
||||
env=[("PATH=" + os.environ.get("PATH", "")).encode("utf-8")],
|
||||
log_path=JUDGER_RUN_LOG_PATH,
|
||||
seccomp_rule_so_path=self._seccomp_rule_path(self._spj_config["seccomp_rule"]),
|
||||
uid=LOW_PRIVILEDGE_UID,
|
||||
gid=LOW_PRIVILEDGE_GID)
|
||||
print result
|
||||
|
||||
if result["result"] == _judger.RESULT_SUCCESS or \
|
||||
(result["result"] == _judger.RESULT_RUNTIME_ERROR and result["exit_code"] in [SPJ_WA, SPJ_ERROR]):
|
||||
return result["exit_code"]
|
||||
else:
|
||||
return SPJ_ERROR
|
||||
|
||||
def _judge_one(self, test_case_file_id):
|
||||
in_file = os.path.join(self._test_case_dir, str(test_case_file_id) + ".in")
|
||||
out_file = os.path.join(self._submission_dir, str(test_case_file_id) + ".out")
|
||||
in_file = os.path.join(self._test_case_dir, str(test_case_file_id) + ".in").encode("utf-8")
|
||||
out_file = os.path.join(self._submission_dir, str(test_case_file_id) + ".out").encode("utf-8")
|
||||
|
||||
command = self._run_config["command"].format(exe_path=self._exe_path, exe_dir=os.path.dirname(self._exe_path),
|
||||
max_memory=self._max_memory / 1024).split(" ")
|
||||
@ -69,7 +105,7 @@ class JudgeClient(object):
|
||||
output_path=out_file,
|
||||
error_path=out_file,
|
||||
args=[item.encode("utf-8") for item in command[1::]],
|
||||
env=[("PATH=" + os.getenv("PATH")).encode("utf-8")],
|
||||
env=[("PATH=" + os.getenv("PATH", "")).encode("utf-8")],
|
||||
log_path=JUDGER_RUN_LOG_PATH,
|
||||
seccomp_rule_so_path=self._seccomp_rule_path(self._run_config["seccomp_rule"]),
|
||||
uid=LOW_PRIVILEDGE_UID,
|
||||
@ -78,11 +114,23 @@ class JudgeClient(object):
|
||||
|
||||
# if progress exited normally, then we should check output result
|
||||
run_result["output_md5"] = None
|
||||
if run_result["result"] == 0:
|
||||
run_result["output_md5"], is_ac = self._compare_output(test_case_file_id)
|
||||
# -1 == Wrong Answer
|
||||
if not is_ac:
|
||||
run_result["result"] = -1
|
||||
if run_result["result"] == _judger.RESULT_SUCCESS:
|
||||
if self._test_case_info["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=out_file)
|
||||
|
||||
print "spj_result", spj_result
|
||||
|
||||
if spj_result == SPJ_WA:
|
||||
run_result["result"] = WA
|
||||
elif spj_result == SPJ_ERROR:
|
||||
run_result["result"] = _judger.RESULT_SYSTEM_ERROR
|
||||
else:
|
||||
run_result["output_md5"], is_ac = self._compare_output(test_case_file_id)
|
||||
# -1 == Wrong Answer
|
||||
if not is_ac:
|
||||
run_result["result"] = WA
|
||||
|
||||
return run_result
|
||||
|
||||
|
13
server.py
13
server.py
@ -6,6 +6,7 @@ import json
|
||||
import os
|
||||
import shutil
|
||||
import socket
|
||||
import logging
|
||||
|
||||
import _judger
|
||||
import psutil
|
||||
@ -52,11 +53,12 @@ class JudgeServer(object):
|
||||
raise TokenVerificationFailed("token not set")
|
||||
return hashlib.sha256(t).hexdigest()
|
||||
|
||||
def judge(self, language_config, submission_id, src, max_cpu_time, max_memory, test_case_id):
|
||||
def judge(self, language_config, submission_id, src, max_cpu_time, max_memory, test_case_id,
|
||||
spj_version=None, spj_config=None):
|
||||
# init
|
||||
compile_config = language_config["compile"]
|
||||
|
||||
with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=submission_id) as submission_dir:
|
||||
with InitSubmissionEnv(JUDGER_WORKSPACE_BASE, submission_id=str(submission_id)) as submission_dir:
|
||||
src_path = os.path.join(submission_dir, compile_config["src_name"])
|
||||
|
||||
# write source code into file
|
||||
@ -72,8 +74,10 @@ class JudgeServer(object):
|
||||
exe_path=exe_path,
|
||||
max_cpu_time=max_cpu_time,
|
||||
max_memory=max_memory,
|
||||
test_case_id=test_case_id,
|
||||
submission_dir=submission_dir)
|
||||
test_case_id=str(test_case_id),
|
||||
submission_dir=submission_dir,
|
||||
spj_version=str(spj_version),
|
||||
spj_config=spj_config)
|
||||
run_result = judge_client.run()
|
||||
return run_result
|
||||
|
||||
@ -116,6 +120,7 @@ class JudgeServer(object):
|
||||
return json.dumps({"err": "invalid-method", "data": None})
|
||||
return json.dumps({"err": None, "data": callback(**data)})
|
||||
except Exception as e:
|
||||
logging.exception(e)
|
||||
ret = dict()
|
||||
ret["err"] = e.__class__.__name__
|
||||
ret["data"] = e.message
|
||||
|
Loading…
Reference in New Issue
Block a user