ExecuteTestUtil.java 5.87 KB
Newer Older
1
2
3
4
5
6
package de.hftstuttgart.dtabackend.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.Volume;
import de.hftstuttgart.dtabackend.models.ResultSummary;
7
8
import de.hftstuttgart.dtabackend.models.TestCompetencyProfile;

9
10
11
12
13
14
15
16
17
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
18
import java.util.List;
19
import java.util.regex.Matcher;
20
21
import java.util.stream.Collectors;
import java.util.stream.IntStream;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

@Component
public class ExecuteTestUtil  {
    private static final Logger LOG = LogManager.getLogger(ExecuteTestUtil.class);

    private final JGitUtil jGitUtil;
    private final DockerUtil dockerUtil;
    private final String assignmentBasePath;
    private final Path testTmpPathHost;
    private final Path testTmpPath;

    public ExecuteTestUtil(
        Environment env,
        JGitUtil jGitUtil,
        DockerUtil dockerUtil
    ) {
        this.jGitUtil = jGitUtil;
        this.dockerUtil = dockerUtil;

        // set base path for assignments to be stored
        Path p = Paths.get(
            env.getProperty("data.dir"),
            env.getProperty("data.dir.test.folder.name"));
        this.assignmentBasePath = p.toAbsolutePath().toString();

        // set path of temporary directory on host and inside our container
        this.testTmpPathHost = Paths.get(env.getProperty("host.tests.tmp.dir"));
        this.testTmpPath = Paths.get(env.getProperty("tests.tmp.dir"));
    }

    public ResultSummary runTests(String assignmentId, Path workDirectory) throws IOException, InterruptedException {

        // define paths for the test, the submission and where the result is to be expected afterwards
        Path testPath   = Paths.get(workDirectory.toAbsolutePath().toString(), "/test");
        Path srcPath    = Paths.get(workDirectory.toAbsolutePath().toString(), "/src");
        Path resultPath = Paths.get(workDirectory.toAbsolutePath().toString(), "/result");

        // clone stored test to tmpdir
        LOG.debug("copying pre-downloaded unitttest repo");
        FileUtil.copyFolder(
            Paths.get(
                assignmentBasePath,
                assignmentId
            ),
            testPath
        );

        LOG.debug("copy test config");
        Files.copy(
            Paths.get(
                assignmentBasePath,
                assignmentId + ".txt"
            ),
            Paths.get(
                workDirectory.toAbsolutePath().toString(),
                "config.txt"
            )
        );

        Files.createDirectory(resultPath);

        LOG.info("reading test config");
        Matcher config = RegexUtil.findProfessorConfig(
            new FileInputStream(Paths.get(workDirectory.toAbsolutePath().toString(), "config.txt").toFile()));

        // define the paths to mount as Binds from Host to the test-container
        Path testPathHost = Paths.get(
            testTmpPathHost.toAbsolutePath().toString(),
            workDirectory.getName(workDirectory.getNameCount()-1).toString(),
            testPath.getName(testPath.getNameCount()-1).toString()
        );
        Path srcPathHost = Paths.get(
            testTmpPathHost.toAbsolutePath().toString(),
            workDirectory.getName(workDirectory.getNameCount()-1).toString(),
            srcPath.getName(srcPath.getNameCount()-1).toString()
        );
        Path resultPathHost = Paths.get(
            testTmpPathHost.toAbsolutePath().toString(),
            workDirectory.getName(workDirectory.getNameCount()-1).toString(),
            resultPath.getName(resultPath.getNameCount()-1).toString()
        );

        // start test-container with professor given image and bind mounts for test, submission and result
        dockerUtil.runContainer(
            config.group(4),
            new Bind(testPathHost.toAbsolutePath().toString(), new Volume("/data/test")),
            new Bind(srcPathHost.toAbsolutePath().toString(), new Volume("/data/src")),
            new Bind(resultPathHost.toAbsolutePath().toString(), new Volume("/data/result"))
        );

        // define expected result file
        File resultFile = Paths.get(resultPath.toAbsolutePath().toString(), "result.json").toFile();

        // check if result file is there
        if (!resultFile.exists() || !resultFile.isFile()) {
117
            LOG.error(String.format("Could not find result file in %s", resultFile.getAbsolutePath()));
118
119
120
121
122
123
124
125
            throw new RuntimeException("no resultfile found");
        }

        LOG.debug("parse results json");
        ObjectMapper objectMapper = new ObjectMapper();
        ResultSummary resultSummary = objectMapper.readValue(
            resultFile.toURI().toURL(),
            ResultSummary.class);
126
127
128
129
130
131
132
133
134
        
        LOG.info("Checking for optional test competency profile information for paedagogical agent functionality...");
        List<TestCompetencyProfile> testCompetencyProfiles=CompetencyAssessmentUtil.readTestCompetencyProfiles(testPathHost, CompetencyAssessmentUtil.TEST_COMPETENCY_MANIFEST_FILE_NAME);
        if(testCompetencyProfiles!=null) {
        	LOG.info("Found optional test competency profiles, generating agent profile data...");
        	resultSummary.overallTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumTestCompetencyProfiles(testCompetencyProfiles));
        	resultSummary.successfulTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary));
        }
        
135
136
        return resultSummary;
    }
137
138
139
140
141
142
    
    private static String packFloats(float[] array) {
    	return IntStream.range(0, array.length)
                .mapToObj(i -> String.valueOf(array[i]))
                .collect(Collectors.joining(";"));
    }
143
}