use of cn.edu.zjnu.acm.judge.support.RunResult in project judge by zjnu-acm.
the class JudgeRunnerTest method test.
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("data")
public void test(String key, Checker checker, Path path) throws IOException {
Path work = Files.createDirectories(Paths.get("target/work/judgeRunnerTest").resolve(key));
Path[] groovyJars = GroovyHolder.getPaths();
assertThat(groovyJars).isNotEmpty();
for (Path groovyJar : groovyJars) {
Files.copy(groovyJar, work.resolve(groovyJar.getFileName().toString()));
}
String cp = Arrays.stream(groovyJars).map(p -> p.getFileName().toString()).collect(Collectors.joining(File.pathSeparator));
String executeCommand = build("java", "-cp", cp, groovy.ui.GroovyMain.class.getName(), "Main.groovy");
Language groovy = Language.builder().name("groovy").sourceExtension("groovy").executeCommand(executeCommand).executableExtension("groovy").description("").timeFactor(2).build();
log.warn("Language groovy: {}", groovy);
languageMapper.save(groovy);
String extension = getExtension(path);
int languageId = findFirstLanguageByExtension(EXTENSION_MAP.get(extension));
Language language = languageMapper.findOne(languageId);
Objects.requireNonNull(language, "language " + languageId + " not exists");
String source = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
RunRecord runRecord = RunRecord.builder().source(source).timeLimit(timeLimit).memoryLimit(memoryLimit).language(language).build();
RunResult runResult = judgeRunner.run(runRecord, work, judgeData, validator, false);
int expectScore = SPECIAL_SCORE.getOrDefault(key, checker.getScore());
String expectedCaseResult = ResultType.getCaseScoreDescription(checker.getStatus());
Status resultStatus = runResult.getType();
if (resultStatus != null) {
assertThat(resultStatus).describedAs("type will either be null or COMPILATION_ERROR," + " if got other result, please modify this file").isEqualTo(Status.COMPILATION_ERROR);
}
String detail1 = runResult.getDetail();
if (resultStatus == Status.COMPILATION_ERROR) {
assertThat(detail1).describedAs("submission detail").isNull();
} else {
List<SubmissionDetailDTO> details = detail1 != null ? submissionService.parseSubmissionDetail(detail1) : null;
String msg = "%s %s %s";
Object[] param = { key, details, expectedCaseResult };
assertThat(runResult.getScore()).describedAs(msg, param).isEqualTo(expectScore);
assertThat(details).describedAs(msg, param).anyMatch(detail -> expectedCaseResult.equals(detail.getResult()));
}
}
use of cn.edu.zjnu.acm.judge.support.RunResult in project judge by zjnu-acm.
the class JudgeServiceImpl method execute.
@Override
public void execute(long submissionId) {
Submission submission = submissionMapper.findOne(submissionId);
if (submission == null) {
throw new BusinessException(BusinessCode.SUBMISSION_NOT_FOUND, submissionId);
}
long problemId = submission.getProblem();
Problem problem = problemService.findOneNoI18n(problemId);
try {
RunRecord runRecord = RunRecord.builder().language(languageService.getAvailableLanguage(submission.getLanguage())).source(submissionDetailMapper.findSourceById(submissionId)).memoryLimit(problem.getMemoryLimit()).timeLimit(problem.getTimeLimit()).build();
Path dataDirectory = systemService.getDataDirectory(problemId);
JudgeData judgeData = JudgeData.parse(dataDirectory);
Path specialFile = systemService.getSpecialJudgeExecutable(problemId);
boolean isSpecial = systemService.isSpecialJudge(problemId);
// 建立临时文件
Path work = systemService.getWorkDirectory(submissionId);
final Validator validator = isSpecial ? new SpecialValidator(specialFile.toString(), work) : SimpleValidator.PE_AS_AC;
boolean deleteTempFile = systemService.isDeleteTempFile();
RunResult runResult = judgeRunner.run(runRecord, work, judgeData, validator, deleteTempFile);
SubmissionDetail detail = SubmissionDetail.builder().id(submissionId).compileInfo(runResult.getCompileInfo()).detail(runResult.getDetail()).systemInfo(runResult.getSystemInfo()).build();
if (runResult.getType() == Status.COMPILATION_ERROR) {
submissionMapper.updateResult(submissionId, ResultType.COMPILE_ERROR, 0, 0);
} else {
int score = runResult.getScore();
long time = runResult.getTime();
long memory = runResult.getMemory();
submissionMapper.updateResult(submissionId, score, time, memory);
}
// TODO return value not handled, we can do nothing for the record not exists in the table now.
submissionDetailMapper.update(detail);
updateSubmissionStatus(submission.getUser(), problemId);
} catch (ThreadDeath | VirtualMachineError error) {
throw error;
} catch (JudgeException | IOException | Error ex) {
log.error("got an exception when judging submission {}", submissionId, ex);
submissionMapper.updateResult(submissionId, ResultType.SYSTEM_ERROR, 0, 0);
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
ex.printStackTrace(pw);
}
submissionDetailMapper.update(SubmissionDetail.builder().id(submissionId).systemInfo(sw.toString()).build());
}
}
use of cn.edu.zjnu.acm.judge.support.RunResult in project judge by zjnu-acm.
the class JudgeRunnerImpl method run.
@Override
public RunResult run(RunRecord runRecord, Path workDirectory, JudgeData judgeData, Validator validator, boolean cleanDirectory) {
Objects.requireNonNull(runRecord);
Objects.requireNonNull(workDirectory);
try {
RunResult.Builder builder = RunResult.builder();
String source = runRecord.getSource();
if (!StringUtils.hasLength(source)) {
return builder.type(Status.COMPILATION_ERROR).compileInfo("empty source file").build();
}
final String main = "Main";
Files.createDirectories(workDirectory);
Language language = runRecord.getLanguage();
// 源码码文件
Path sourceFile = workDirectory.resolve(main + "." + language.getSourceExtension());
Files.write(sourceFile, source.getBytes(Platform.getCharset()));
String compileCommand = language.getCompileCommand();
log.debug("Compile Command: {}", compileCommand);
if (StringUtils.hasText(compileCommand)) {
// create compiling process
// VC++ will output compiling info to stdout
// G++ will output compiling info to stderr
Path compileInfo = workDirectory.resolve("compileInfo.txt");
@SuppressWarnings("null") Process process = ProcessCreationHelper.execute(new ProcessBuilder(compileCommand.split("\\s+")).directory(workDirectory.toFile()).redirectInput(ProcessBuilder.Redirect.from(NULL_FILE)).redirectOutput(compileInfo.toFile()).redirectErrorStream(true)::start);
try {
process.waitFor(1, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
process.destroy();
throw new InterruptedIOException();
}
// export compiling information
String errorInfo;
if (process.isAlive()) {
process.destroyForcibly();
try {
process.waitFor();
} catch (InterruptedException ex) {
throw new InterruptedIOException();
}
errorInfo = "Compile timeout\nOutput:\n" + collectLines(compileInfo);
} else {
errorInfo = collectLines(compileInfo);
}
builder.compileInfo(errorInfo);
log.debug("errorInfo = {}", errorInfo);
// The executable file after compiling
Path executable = workDirectory.resolve(main + "." + language.getExecutableExtension());
log.debug("executable = {}", executable);
boolean compilePassed = Files.exists(executable);
if (!compilePassed) {
return builder.type(Status.COMPILATION_ERROR).build();
}
}
int caseNum = judgeData.getCaseCount();
ArrayList<String> details = new ArrayList<>(caseNum << 2);
String command = language.getExecuteCommand();
// executable command should be absolute
command = StringUtils.hasText(command) ? command : workDirectory.toAbsolutePath().resolve("Main." + language.getExecutableExtension()).toString();
long extTime = language.getExtTime();
long castTimeLimit = runRecord.getTimeLimit() * language.getTimeFactor() + extTime;
// 内存附加
long extraMemory = language.getExtMemory();
long caseMemoryLimit = (runRecord.getMemoryLimit() + extraMemory) * 1024;
Option[] opts = new Option[caseNum];
for (int cas = 0; cas < caseNum; cas++) {
Path[] entry = judgeData.get(cas);
Path in = entry[0];
Path standard = entry[1];
Path progOutput = workDirectory.resolve(standard.getFileName());
opts[cas] = Option.builder().timeLimit(// time limit
castTimeLimit).memoryLimit(// memory in bytes
caseMemoryLimit).outputLimit(// 16M
16 * 1024 * 1024).command(command).workDirectory(workDirectory).inputFile(in).outputFile(progOutput).standardOutput(standard).errFile(NULL_FILE.toPath()).build();
}
String scorePerCase = new DecimalFormat("0.#").format(100.0 / caseNum);
final ExecuteResult[] ers;
try {
ers = judgeBridge.judge(opts, false, validator);
} catch (NotExecutableException ex) {
// original command
if (!StringUtils.hasText(language.getExecuteCommand())) {
String msg = "fail to execute the binary file";
Win32Exception cause = ex.getCause();
if (cause != null) {
msg = msg + ": " + cause.getMessage();
}
return builder.type(Status.COMPILATION_ERROR).detail(msg).build();
}
throw ex.getCause();
}
long time = 0;
long memory = 0;
// final case whose result is accepted.
int accept = 0;
for (ExecuteResult er : ers) {
long tim1 = Math.max(0, er.getTime() - extTime);
long mem1 = Math.max(0, er.getMemory() / 1024 - extraMemory);
String message = er.getMessage();
boolean success = er.isSuccess();
time = Math.max(time, tim1);
memory = Math.max(memory, mem1);
log.debug("message = {}, time = {}, memory = {}", message, time, memory);
details.add(String.valueOf(er.getCode().getResult()));
details.add(success ? scorePerCase : "0");
details.add(String.valueOf(tim1));
details.add(String.valueOf(mem1));
if (success) {
++accept;
}
}
log.debug("{}", details);
int score = accept >= 0 ? (int) Math.round(accept * 100.0 / caseNum) : accept;
if (score == 0 && accept != 0) {
++score;
} else if (score == 100 && accept != caseNum) {
--score;
}
String msg = details.stream().map(String::valueOf).collect(Collectors.joining(","));
return builder.score(score).time(time).memory(memory).detail(msg).build();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
} finally {
if (cleanDirectory) {
delete(workDirectory);
}
}
}
Aggregations