Commit b294c18e authored by Lückemeyer's avatar Lückemeyer
Browse files

refactor & extend url listener

No related merge requests found
Showing with 391 additions and 379 deletions
+391 -379
# base image to build a JRE # base image to build a JRE
FROM amazoncorretto:17.0.3-alpine as corretto-jdk FROM amazoncorretto:17.0.3-alpine as corretto-jdk
# required for strip-debug to work # required for strip-debug to work
RUN apk add --no-cache binutils RUN apk add --no-cache binutils
# Build small JRE image # Build small JRE image
RUN $JAVA_HOME/bin/jlink \ RUN $JAVA_HOME/bin/jlink \
--verbose \ --verbose \
--add-modules ALL-MODULE-PATH \ --add-modules ALL-MODULE-PATH \
--strip-debug \ --strip-debug \
--no-man-pages \ --no-man-pages \
--no-header-files \ --no-header-files \
--compress=2 \ --compress=2 \
--output /customjre --output /customjre
# main app image # main app image
FROM alpine:latest FROM alpine:latest
ENV JAVA_HOME=/jre ENV JAVA_HOME=/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}" ENV PATH="${JAVA_HOME}/bin:${PATH}"
ENV SPRING_CONFIG_ADDITIONAL_LOCATION "file:/data/config/" ENV SPRING_CONFIG_ADDITIONAL_LOCATION "file:/data/config/"
# copy JRE from the base image # copy JRE from the base image
COPY --from=corretto-jdk /customjre $JAVA_HOME COPY --from=corretto-jdk /customjre $JAVA_HOME
# Add app user # Add app user
ARG AUSER=appuser ARG AUSER=appuser
ARG AGID=137 ARG AGID=137
ENV USER=$AUSER ENV USER=$AUSER
ENV GID=$AGID ENV GID=$AGID
ARG BUILD_NUMBER= ARG BUILD_NUMBER=
RUN addgroup -g $GID -S docker
RUN adduser --no-create-home -u 1000 -G docker -D $USER # Create docker group identical to host
RUN addgroup -g $GID -S docker
# Prepare environment. RUN adduser --no-create-home -u 1000 -G docker -D $USER
# Create needed folders
RUN mkdir /data && \ # Prepare environment.
mkdir /data/config && \ # Create needed folders
chown -R $USER /data RUN mkdir /data && \
mkdir /data/config && \
VOLUME /data chown -R $USER /data
COPY --chown=1000:$GID target/dta-backend-$BUILD_NUMBER.jar app.jar VOLUME /data
USER 1000:$GID COPY --chown=1000:$GID target/dta-backend-$BUILD_NUMBER.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] USER 1000:$GID
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
package de.hftstuttgart.dtabackend.rest.v1.task; package de.hftstuttgart.dtabackend.rest.v1.task;
import de.hftstuttgart.dtabackend.utils.*; import de.hftstuttgart.dtabackend.utils.*;
import de.hftstuttgart.dtabackend.models.ResultSummary; import de.hftstuttgart.dtabackend.models.ResultSummary;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.tika.Tika; import org.apache.tika.Tika;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.annotation.MultipartConfig;
/** /**
* Rest controller for everything related to the TASK files * Rest controller for everything related to the TASK files
*/ */
@RestController @RestController
@RequestMapping("/v1/task") @RequestMapping("/v1/task/*")
@MultipartConfig @MultipartConfig
public class TaskUpload { public class TaskUpload {
private static final Logger LOG = LogManager.getLogger(TaskUpload.class); private static final Logger LOG = LogManager.getLogger(TaskUpload.class);
private final JGitUtil jGitUtil; private final JGitUtil jGitUtil;
private final Path testTmpPath; private final Path testTmpPath;
private final ExecuteTestUtil executeTestUtil; private final ExecuteTestUtil executeTestUtil;
public TaskUpload( public TaskUpload(
Environment env, Environment env,
JGitUtil jGitUtil, JGitUtil jGitUtil,
ExecuteTestUtil executeTestUtil ExecuteTestUtil executeTestUtil
) { ) {
this.jGitUtil = jGitUtil; this.jGitUtil = jGitUtil;
this.executeTestUtil = executeTestUtil; this.executeTestUtil = executeTestUtil;
// set path of temporary directory on host and inside our container // set path of temporary directory on host and inside our container
this.testTmpPath = Paths.get(env.getProperty("tests.tmp.dir")); this.testTmpPath = Paths.get(env.getProperty("tests.tmp.dir"));
} }
@RequestMapping(method = RequestMethod.POST) @RequestMapping(method = RequestMethod.POST)
public ResultSummary uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef, public ResultSummary uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef,
@RequestParam("assignmentId") String assignmentId @RequestParam("assignmentId") String assignmentId
) throws IOException, InterruptedException { ) throws IOException, InterruptedException {
LOG.info("submission for testing received"); LOG.info("submission for testing received");
LOG.debug("creating new temporary directory"); LOG.debug("creating new temporary directory");
Path workDirectory = Files.createTempDirectory(testTmpPath, "dtt"); Path workDirectory = Files.createTempDirectory(testTmpPath, "dtt");
LOG.debug(String.format("working dir for test is: %s", workDirectory.toAbsolutePath().toString())); LOG.debug(String.format("working dir for test is: %s", workDirectory.toAbsolutePath().toString()));
// define paths for the test, the submission and where the result is to be expected afterwards // define paths for the test, the submission and where the result is to be expected afterwards
Path srcPath = Paths.get(workDirectory.toAbsolutePath().toString(), "src"); Path srcPath = Paths.get(workDirectory.toAbsolutePath().toString(), "src");
String mimeInfo = new Tika().detect(taskFileRef.getInputStream()); String mimeInfo = new Tika().detect(taskFileRef.getInputStream());
switch (mimeInfo) { switch (mimeInfo) {
case "text/plain": case "text/plain":
LOG.debug("textfile uploaded, searching for dtt config"); LOG.debug("textfile uploaded, searching for dtt config");
// find URI in config file // find URI in config file
Matcher config = RegexUtil.findStudentConfig(taskFileRef.getInputStream()); Matcher config = RegexUtil.findStudentConfig(taskFileRef.getInputStream());
LOG.debug("calling repo clone"); LOG.debug("calling repo clone");
jGitUtil.cloneRepository(config, srcPath.toAbsolutePath().toString()); jGitUtil.cloneRepository(config, srcPath.toAbsolutePath().toString());
break; break;
case "application/zip": case "application/zip":
LOG.debug("zip archive uploaded, extracting content as student submission"); LOG.debug("zip archive uploaded, extracting content as student submission");
ArchiveUtil.extractProjectFromZip(taskFileRef.getInputStream(), srcPath.toAbsolutePath()); ArchiveUtil.extractProjectFromZip(taskFileRef.getInputStream(), srcPath.toAbsolutePath());
break; break;
default: default:
String msg = String.format("couldn't process uploaded file with mime type %s", mimeInfo); String msg = String.format("couldn't process uploaded file with mime type %s", mimeInfo);
LOG.error(msg); LOG.error(msg);
throw new RuntimeException(msg); throw new RuntimeException(msg);
} }
// run test // run test
LOG.debug("calling test execution"); LOG.debug("calling test execution");
ResultSummary resultSummary = executeTestUtil.runTests(assignmentId, workDirectory); ResultSummary resultSummary = executeTestUtil.runTests(assignmentId, workDirectory);
if (mimeInfo.equals("text/plain")) { if (mimeInfo.equals("text/plain")) {
LOG.info("check for provided Ticketsystem information"); LOG.info("check for provided Ticketsystem information");
UnifiedTicketingUtil.reportResults(taskFileRef.getInputStream(), resultSummary); UnifiedTicketingUtil.reportResults(taskFileRef.getInputStream(), resultSummary);
} }
taskFileRef.getInputStream().close(); taskFileRef.getInputStream().close();
LOG.info("submission tested successfully"); LOG.info("submission tested successfully");
return resultSummary; return resultSummary;
} }
} }
package de.hftstuttgart.dtabackend.utils; package de.hftstuttgart.dtabackend.utils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.net.MalformedURLException;
import java.io.File; import java.nio.file.Path;
import java.util.ArrayList; import java.io.File;
import java.util.List; import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager; import java.util.stream.Collectors;
import org.apache.logging.log4j.Logger; import java.util.stream.IntStream;
import de.hftstuttgart.dtabackend.models.Result; import org.apache.logging.log4j.LogManager;
import de.hftstuttgart.dtabackend.models.ResultSummary; import org.apache.logging.log4j.Logger;
import de.hftstuttgart.dtabackend.models.TestCompetencyProfile;
import com.fasterxml.jackson.core.exc.StreamReadException;
import java.io.FileNotFoundException; import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CompetencyAssessmentUtil {
private static final Logger LOG = LogManager.getLogger(CompetencyAssessmentUtil.class); import de.hftstuttgart.dtabackend.models.Result;
import de.hftstuttgart.dtabackend.models.ResultSummary;
public static String TEST_COMPETENCY_MANIFEST_FILE_NAME="competency-tests.mft"; import de.hftstuttgart.dtabackend.models.TestCompetencyProfile;
/* public static void main(String[] args) throws StreamReadException, DatabindException, MalformedURLException, IOException { import java.io.FileNotFoundException;
List<TestCompetencyProfile> testCompetencyProfiles=readTestCompetencyProfiles(Path.of(args[0]), args[1]);
sumTestCompetencyProfiles(testCompetencyProfiles); public class CompetencyAssessmentUtil {
ObjectMapper objectMapper = new ObjectMapper(); private static final Logger LOG = LogManager.getLogger(CompetencyAssessmentUtil.class);
ResultSummary resultSummary = objectMapper.readValue(
new File(Path.of(args[0]).toFile(), args[2]).toURI().toURL(), public static String TEST_COMPETENCY_MANIFEST_FILE_NAME="competency-tests.mft";
ResultSummary.class);
sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary); public static void main(String[] args) throws StreamReadException, DatabindException, MalformedURLException, IOException {
} ResultSummary summary=ExecuteTestUtil.generateResult(Path.of(args[0]), Path.of(args[1]));
*/ System.out.println(summary.successfulTestCompetencyProfile);
public static float[] sumTestCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles) { }
float[] tcpTotalProfile=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
for(TestCompetencyProfile currentProfile: testCompetencyProfiles) { public static float[] sumTestCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles) {
tcpTotalProfile=TestCompetencyProfile.competencySum(tcpTotalProfile, currentProfile.competencyAssessments); float[] tcpTotalProfile=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
} for(TestCompetencyProfile currentProfile: testCompetencyProfiles) {
return tcpTotalProfile; tcpTotalProfile=TestCompetencyProfile.competencySum(tcpTotalProfile, currentProfile.competencyAssessments);
} }
return tcpTotalProfile;
public static float[] sumSuccessfulCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary) { }
float[] sumSuccessful=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
for(Result currentResult: resultSummary.results) { public static float[] sumSuccessfulCompetencyProfiles(List<TestCompetencyProfile> testCompetencyProfiles, ResultSummary resultSummary) {
if(currentResult.state==Result.State.SUCCESS.ordinal()) { float[] sumSuccessful=new float[TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS];
TestCompetencyProfile currentProfile=new TestCompetencyProfile(); for(Result currentResult: resultSummary.results) {
currentProfile.testPackageName=(currentResult.packageName!=null)?currentResult.packageName:""; if(currentResult.state==Result.State.SUCCESS.ordinal()) {
currentProfile.testClassName=(currentResult.className!=null)?currentResult.className:""; TestCompetencyProfile currentProfile=new TestCompetencyProfile();
currentProfile.testName=(currentResult.name!=null)?currentResult.name:""; currentProfile.testPackageName=(currentResult.packageName!=null)?currentResult.packageName:"";
int testIndex=testCompetencyProfiles.indexOf(currentProfile); currentProfile.testClassName=(currentResult.className!=null)?currentResult.className:"";
if(testIndex!=-1) { currentProfile.testName=(currentResult.name!=null)?currentResult.name:"";
sumSuccessful=TestCompetencyProfile.competencySum(sumSuccessful, testCompetencyProfiles.get(testIndex).competencyAssessments); int testIndex=testCompetencyProfiles.indexOf(currentProfile);
} if(testIndex!=-1) {
} sumSuccessful=TestCompetencyProfile.competencySum(sumSuccessful, testCompetencyProfiles.get(testIndex).competencyAssessments);
} }
return sumSuccessful; }
} }
return sumSuccessful;
public static List<TestCompetencyProfile> readTestCompetencyProfiles(Path testPath, String fileName) { }
List<TestCompetencyProfile> testCompetencyProfiles=new ArrayList<TestCompetencyProfile>();
try { public static List<TestCompetencyProfile> readTestCompetencyProfiles(Path testPath, String fileName) {
BufferedReader testCompetencyManifest=new BufferedReader(new FileReader(new File(testPath.toFile(), fileName))); List<TestCompetencyProfile> testCompetencyProfiles=new ArrayList<TestCompetencyProfile>();
String testEntry=testCompetencyManifest.readLine(); try {
while(testEntry!=null) BufferedReader testCompetencyManifest=new BufferedReader(new FileReader(new File(testPath.toFile(), fileName)));
{ String testEntry=testCompetencyManifest.readLine();
String[] testEntyComponents=testEntry.split(TestCompetencyProfile.COMPETENCY_SEPARATOR); while(testEntry!=null)
TestCompetencyProfile currentProfile=new TestCompetencyProfile(); {
currentProfile.testPackageName=testEntyComponents[0]; String[] testEntyComponents=testEntry.split(TestCompetencyProfile.COMPETENCY_SEPARATOR);
currentProfile.testClassName=testEntyComponents[1]; TestCompetencyProfile currentProfile=new TestCompetencyProfile();
currentProfile.testName=testEntyComponents[2]; currentProfile.testPackageName=testEntyComponents[0];
for(int competencyIndex=0; competencyIndex<TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) { currentProfile.testClassName=testEntyComponents[1];
currentProfile.competencyAssessments[competencyIndex]=Float.valueOf(testEntyComponents[competencyIndex+3]); currentProfile.testName=testEntyComponents[2];
} for(int competencyIndex=0; competencyIndex<TestCompetencyProfile.MAX_COMPETENCY_DIMENSIONS; competencyIndex++) {
testCompetencyProfiles.add(currentProfile); currentProfile.competencyAssessments[competencyIndex]=Float.valueOf(testEntyComponents[competencyIndex+3]);
testEntry=testCompetencyManifest.readLine(); }
} testCompetencyProfiles.add(currentProfile);
testCompetencyManifest.close(); testEntry=testCompetencyManifest.readLine();
LOG.info("Added "+testCompetencyProfiles.size()+" test competency profiles from test competency manifest. Optional agent functionality enabled."); }
} catch (FileNotFoundException e) { testCompetencyManifest.close();
LOG.info("Test competency manifest file for agent feedback not found. Skipping optional functionality."); LOG.info("Added "+testCompetencyProfiles.size()+" test competency profiles from test competency manifest. Optional agent functionality enabled.");
testCompetencyProfiles=null; } catch (FileNotFoundException e) {
} catch (IOException e) { LOG.info("Test competency manifest file for agent feedback not found. Skipping optional functionality.");
LOG.info("Test competency manifest file for agent feedback unreadable. Skipping optional functionality."); testCompetencyProfiles=null;
testCompetencyProfiles=null; } catch (IOException e) {
} LOG.info("Test competency manifest file for agent feedback unreadable. Skipping optional functionality.");
return testCompetencyProfiles; testCompetencyProfiles=null;
} }
return testCompetencyProfiles;
} }
public static String packFloats(float[] array) {
return IntStream.range(0, array.length)
.mapToObj(i -> String.valueOf(array[i]))
.collect(Collectors.joining(";"));
}
}
package de.hftstuttgart.dtabackend.utils; package de.hftstuttgart.dtabackend.utils;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.exc.StreamReadException;
import com.github.dockerjava.api.model.Bind; import com.fasterxml.jackson.databind.DatabindException;
import com.github.dockerjava.api.model.Volume; import com.fasterxml.jackson.databind.ObjectMapper;
import de.hftstuttgart.dtabackend.models.ResultSummary; import com.github.dockerjava.api.model.Bind;
import de.hftstuttgart.dtabackend.models.TestCompetencyProfile; import com.github.dockerjava.api.model.Volume;
import de.hftstuttgart.dtabackend.models.ResultSummary;
import org.apache.logging.log4j.LogManager; import de.hftstuttgart.dtabackend.models.TestCompetencyProfile;
import org.apache.logging.log4j.Logger;
import org.springframework.core.env.Environment; import org.apache.logging.log4j.LogManager;
import org.springframework.stereotype.Component; import org.apache.logging.log4j.Logger;
import org.springframework.core.env.Environment;
import java.io.*; import org.springframework.stereotype.Component;
import java.nio.file.Files;
import java.nio.file.Path; import java.io.*;
import java.nio.file.Paths; import java.net.MalformedURLException;
import java.util.List; import java.nio.file.Files;
import java.util.regex.Matcher; import java.nio.file.Path;
import java.util.stream.Collectors; import java.nio.file.Paths;
import java.util.stream.IntStream; import java.util.List;
import java.util.regex.Matcher;
@Component
public class ExecuteTestUtil { @Component
private static final Logger LOG = LogManager.getLogger(ExecuteTestUtil.class); public class ExecuteTestUtil {
private static final Logger LOG = LogManager.getLogger(ExecuteTestUtil.class);
private final JGitUtil jGitUtil;
private final DockerUtil dockerUtil; private final JGitUtil jGitUtil;
private final String assignmentBasePath; private final DockerUtil dockerUtil;
private final Path testTmpPathHost; private final String assignmentBasePath;
private final Path testTmpPath; private final Path testTmpPathHost;
private final Path testTmpPath;
public ExecuteTestUtil(
Environment env, public ExecuteTestUtil(
JGitUtil jGitUtil, Environment env,
DockerUtil dockerUtil JGitUtil jGitUtil,
) { DockerUtil dockerUtil
this.jGitUtil = jGitUtil; ) {
this.dockerUtil = dockerUtil; this.jGitUtil = jGitUtil;
this.dockerUtil = dockerUtil;
// set base path for assignments to be stored
Path p = Paths.get( // set base path for assignments to be stored
env.getProperty("data.dir"), Path p = Paths.get(
env.getProperty("data.dir.test.folder.name")); env.getProperty("data.dir"),
this.assignmentBasePath = p.toAbsolutePath().toString(); 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")); // set path of temporary directory on host and inside our container
this.testTmpPath = Paths.get(env.getProperty("tests.tmp.dir")); 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 {
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"); // define paths for the test, the submission and where the result is to be expected afterwards
Path srcPath = Paths.get(workDirectory.toAbsolutePath().toString(), "/src"); Path testPath = Paths.get(workDirectory.toAbsolutePath().toString(), "/test");
Path resultPath = Paths.get(workDirectory.toAbsolutePath().toString(), "/result"); 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"); // clone stored test to tmpdir
FileUtil.copyFolder( LOG.debug("copying pre-downloaded unitttest repo");
Paths.get( FileUtil.copyFolder(
assignmentBasePath, Paths.get(
assignmentId assignmentBasePath,
), assignmentId
testPath ),
); testPath
);
LOG.debug("copy test config");
Files.copy( LOG.debug("copy test config");
Paths.get( Files.copy(
assignmentBasePath, Paths.get(
assignmentId + ".txt" assignmentBasePath,
), assignmentId + ".txt"
Paths.get( ),
workDirectory.toAbsolutePath().toString(), Paths.get(
"config.txt" workDirectory.toAbsolutePath().toString(),
) "config.txt"
); )
);
Files.createDirectory(resultPath);
Files.createDirectory(resultPath);
LOG.info("reading test config");
Matcher config = RegexUtil.findProfessorConfig( LOG.info("reading test config");
new FileInputStream(Paths.get(workDirectory.toAbsolutePath().toString(), "config.txt").toFile())); 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( // define the paths to mount as Binds from Host to the test-container
testTmpPathHost.toAbsolutePath().toString(), Path testPathHost = Paths.get(
workDirectory.getName(workDirectory.getNameCount()-1).toString(), testTmpPathHost.toAbsolutePath().toString(),
testPath.getName(testPath.getNameCount()-1).toString() workDirectory.getName(workDirectory.getNameCount()-1).toString(),
); testPath.getName(testPath.getNameCount()-1).toString()
Path srcPathHost = Paths.get( );
testTmpPathHost.toAbsolutePath().toString(), Path srcPathHost = Paths.get(
workDirectory.getName(workDirectory.getNameCount()-1).toString(), testTmpPathHost.toAbsolutePath().toString(),
srcPath.getName(srcPath.getNameCount()-1).toString() workDirectory.getName(workDirectory.getNameCount()-1).toString(),
); srcPath.getName(srcPath.getNameCount()-1).toString()
Path resultPathHost = Paths.get( );
testTmpPathHost.toAbsolutePath().toString(), Path resultPathHost = Paths.get(
workDirectory.getName(workDirectory.getNameCount()-1).toString(), testTmpPathHost.toAbsolutePath().toString(),
resultPath.getName(resultPath.getNameCount()-1).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( // start test-container with professor given image and bind mounts for test, submission and result
config.group(4), dockerUtil.runContainer(
new Bind(testPathHost.toAbsolutePath().toString(), new Volume("/data/test")), config.group(4),
new Bind(srcPathHost.toAbsolutePath().toString(), new Volume("/data/src")), new Bind(testPathHost.toAbsolutePath().toString(), new Volume("/data/test")),
new Bind(resultPathHost.toAbsolutePath().toString(), new Volume("/data/result")) 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(); ResultSummary resultSummary = generateResult(resultPath, testPathHost);
// check if result file is there return resultSummary;
if (!resultFile.exists() || !resultFile.isFile()) { }
LOG.error(String.format("Could not find result file in %s", resultFile.getAbsolutePath()));
throw new RuntimeException("no resultfile found"); static ResultSummary generateResult(Path resultPath, Path testPathHost)
} throws IOException, StreamReadException, DatabindException, MalformedURLException {
// define expected result file
LOG.debug("parse results json"); File resultFile = Paths.get(resultPath.toAbsolutePath().toString(), "result.json").toFile();
ObjectMapper objectMapper = new ObjectMapper();
ResultSummary resultSummary = objectMapper.readValue( // check if result file is there
resultFile.toURI().toURL(), if (!resultFile.exists() || !resultFile.isFile()) {
ResultSummary.class); LOG.error(String.format("Could not find result file in %s", resultFile.getAbsolutePath()));
throw new RuntimeException("no resultfile found");
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.debug("parse results json");
LOG.info("Found optional test competency profiles, generating agent profile data..."); ObjectMapper objectMapper = new ObjectMapper();
resultSummary.overallTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumTestCompetencyProfiles(testCompetencyProfiles)); ResultSummary resultSummary = objectMapper.readValue(
resultSummary.successfulTestCompetencyProfile=packFloats(CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary)); resultFile.toURI().toURL(),
} ResultSummary.class);
LOG.debug("result json returned time "+ resultSummary.timestamp + " with "+resultSummary.results.size()+ " test results.");
return resultSummary;
} 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);
private static String packFloats(float[] array) { if(testCompetencyProfiles!=null) {
return IntStream.range(0, array.length) LOG.info("Found optional test competency profiles, generating agent profile data...");
.mapToObj(i -> String.valueOf(array[i])) resultSummary.overallTestCompetencyProfile=CompetencyAssessmentUtil.packFloats(CompetencyAssessmentUtil.sumTestCompetencyProfiles(testCompetencyProfiles));
.collect(Collectors.joining(";")); resultSummary.successfulTestCompetencyProfile=CompetencyAssessmentUtil.packFloats(CompetencyAssessmentUtil.sumSuccessfulCompetencyProfiles(testCompetencyProfiles, resultSummary));
} }
} return resultSummary;
}
}
...@@ -7,7 +7,7 @@ spring.http.multipart.max-file-size=5Mb ...@@ -7,7 +7,7 @@ spring.http.multipart.max-file-size=5Mb
############################################### ###############################################
# Holds the uploaded Zip-Files # Holds the uploaded Zip-Files
tests.tmp.dir=/tmp/dtt-tests tests.tmp.dir=~/dta-tests
host.tests.tmp.dir=${tests.tmp.dir} host.tests.tmp.dir=${tests.tmp.dir}
data.dir=/data data.dir=/data
data.dir.test.folder.name=UnitTests data.dir.test.folder.name=UnitTests
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment