Search in sources :

Example 1 with RunResult

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()));
    }
}
Also used : Path(java.nio.file.Path) Arrays(java.util.Arrays) URISyntaxException(java.net.URISyntaxException) PlatformAssuming.assumingWindows(cn.edu.zjnu.acm.judge.test.PlatformAssuming.assumingWindows) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) RunWith(org.junit.runner.RunWith) Status(cn.edu.zjnu.acm.judge.core.Status) Autowired(org.springframework.beans.factory.annotation.Autowired) ArrayList(java.util.ArrayList) Language(cn.edu.zjnu.acm.judge.domain.Language) Validator(cn.edu.zjnu.acm.judge.core.Validator) SubmissionDetailDTO(cn.edu.zjnu.acm.judge.data.dto.SubmissionDetailDTO) StringTokenizer(java.util.StringTokenizer) Map(java.util.Map) Arguments.arguments(org.junit.jupiter.params.provider.Arguments.arguments) Path(java.nio.file.Path) Application(cn.edu.zjnu.acm.judge.Application) MethodSource(org.junit.jupiter.params.provider.MethodSource) WebAppConfiguration(org.springframework.test.context.web.WebAppConfiguration) ImmutableMap(com.google.common.collect.ImmutableMap) Files(java.nio.file.Files) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) GroovyHolder(cn.edu.zjnu.acm.judge.core.GroovyHolder) IOException(java.io.IOException) RunRecord(cn.edu.zjnu.acm.judge.support.RunRecord) Arguments(org.junit.jupiter.params.provider.Arguments) Collectors(java.util.stream.Collectors) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) Objects(java.util.Objects) List(java.util.List) Slf4j(lombok.extern.slf4j.Slf4j) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Stream(java.util.stream.Stream) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) Paths(java.nio.file.Paths) ResultType(cn.edu.zjnu.acm.judge.util.ResultType) SimpleValidator(cn.edu.zjnu.acm.judge.core.SimpleValidator) LanguageMapper(cn.edu.zjnu.acm.judge.mapper.LanguageMapper) JUnitPlatform(org.junit.platform.runner.JUnitPlatform) JudgeData(cn.edu.zjnu.acm.judge.support.JudgeData) Transactional(org.springframework.transaction.annotation.Transactional) Status(cn.edu.zjnu.acm.judge.core.Status) RunRecord(cn.edu.zjnu.acm.judge.support.RunRecord) Language(cn.edu.zjnu.acm.judge.domain.Language) SubmissionDetailDTO(cn.edu.zjnu.acm.judge.data.dto.SubmissionDetailDTO) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) MethodSource(org.junit.jupiter.params.provider.MethodSource)

Example 2 with RunResult

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());
    }
}
Also used : Path(java.nio.file.Path) Submission(cn.edu.zjnu.acm.judge.domain.Submission) IOException(java.io.IOException) RunRecord(cn.edu.zjnu.acm.judge.support.RunRecord) BusinessException(cn.edu.zjnu.acm.judge.exception.BusinessException) JudgeData(cn.edu.zjnu.acm.judge.support.JudgeData) StringWriter(java.io.StringWriter) SubmissionDetail(cn.edu.zjnu.acm.judge.domain.SubmissionDetail) SpecialValidator(cn.edu.zjnu.acm.judge.sandbox.win32.SpecialValidator) Problem(cn.edu.zjnu.acm.judge.domain.Problem) JudgeException(cn.edu.zjnu.acm.judge.core.JudgeException) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) Validator(cn.edu.zjnu.acm.judge.core.Validator) SpecialValidator(cn.edu.zjnu.acm.judge.sandbox.win32.SpecialValidator) SimpleValidator(cn.edu.zjnu.acm.judge.core.SimpleValidator) PrintWriter(java.io.PrintWriter)

Example 3 with RunResult

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);
        }
    }
}
Also used : InterruptedIOException(java.io.InterruptedIOException) DecimalFormat(java.text.DecimalFormat) ArrayList(java.util.ArrayList) UncheckedIOException(java.io.UncheckedIOException) Language(cn.edu.zjnu.acm.judge.domain.Language) ExecuteResult(cn.edu.zjnu.acm.judge.core.ExecuteResult) RunResult(cn.edu.zjnu.acm.judge.support.RunResult) Path(java.nio.file.Path) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) Win32Exception(jnc.platform.win32.Win32Exception) NotExecutableException(cn.edu.zjnu.acm.judge.core.NotExecutableException) Option(cn.edu.zjnu.acm.judge.core.Option)

Aggregations

RunResult (cn.edu.zjnu.acm.judge.support.RunResult)3 IOException (java.io.IOException)3 Path (java.nio.file.Path)3 SimpleValidator (cn.edu.zjnu.acm.judge.core.SimpleValidator)2 Validator (cn.edu.zjnu.acm.judge.core.Validator)2 Language (cn.edu.zjnu.acm.judge.domain.Language)2 JudgeData (cn.edu.zjnu.acm.judge.support.JudgeData)2 RunRecord (cn.edu.zjnu.acm.judge.support.RunRecord)2 ArrayList (java.util.ArrayList)2 Application (cn.edu.zjnu.acm.judge.Application)1 ExecuteResult (cn.edu.zjnu.acm.judge.core.ExecuteResult)1 GroovyHolder (cn.edu.zjnu.acm.judge.core.GroovyHolder)1 JudgeException (cn.edu.zjnu.acm.judge.core.JudgeException)1 NotExecutableException (cn.edu.zjnu.acm.judge.core.NotExecutableException)1 Option (cn.edu.zjnu.acm.judge.core.Option)1 Status (cn.edu.zjnu.acm.judge.core.Status)1 SubmissionDetailDTO (cn.edu.zjnu.acm.judge.data.dto.SubmissionDetailDTO)1 Problem (cn.edu.zjnu.acm.judge.domain.Problem)1 Submission (cn.edu.zjnu.acm.judge.domain.Submission)1 SubmissionDetail (cn.edu.zjnu.acm.judge.domain.SubmissionDetail)1