Skip to content

Commit

Permalink
restructured testfeedback responses
Browse files Browse the repository at this point in the history
  • Loading branch information
Aqua-sc committed May 9, 2024
1 parent b0377a9 commit d669531
Show file tree
Hide file tree
Showing 20 changed files with 123 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@
import com.ugent.pidgeon.model.json.SubmissionJson;
import com.ugent.pidgeon.model.submissionTesting.DockerOutput;
import com.ugent.pidgeon.model.submissionTesting.DockerSubmissionTestModel;
import com.ugent.pidgeon.model.submissionTesting.DockerTestOutput;
import com.ugent.pidgeon.model.submissionTesting.SubmissionTemplateModel;
import com.ugent.pidgeon.postgre.models.*;
import com.ugent.pidgeon.postgre.models.types.DockerTestState;
import com.ugent.pidgeon.postgre.models.types.DockerTestType;
import com.ugent.pidgeon.postgre.models.types.UserRole;
import com.ugent.pidgeon.postgre.repository.*;
import com.ugent.pidgeon.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.zip.ZipException;
import java.util.logging.Level;
import java.util.concurrent.CompletableFuture;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
Expand All @@ -33,7 +31,6 @@
import java.nio.file.Path;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.function.Function;
import java.util.logging.Logger;
import java.util.zip.ZipFile;

Expand Down Expand Up @@ -63,9 +60,11 @@ public class SubmissionController {
private EntityToJsonConverter entityToJsonConverter;
@Autowired
private CommonDatabaseActions commonDatabaseActions;
@Autowired
private TestUtil testUtil;


private SubmissionTemplateModel.SubmissionResult runStructureTest(ZipFile file, TestEntity testEntity) throws IOException {
private SubmissionTemplateModel.SubmissionResult runStructureTest(ZipFile file, TestEntity testEntity) throws IOException {
// There is no structure test for this project
if(testEntity.getStructureTemplate() == null){
return null;
Expand Down Expand Up @@ -261,13 +260,21 @@ public ResponseEntity<?> submitFile(@RequestParam("file") MultipartFile file, @P
submission.setStructureAccepted(structureTestResult.passed);
submission.setStructureFeedback(structureTestResult.feedback);
}
// Define docker test as running
submission.setDockerTestState(DockerTestState.running);

if (testEntity.getDockerTestTemplate() != null) {
submission.setDockerType(DockerTestType.TEMPLATE);
} else if (testEntity.getDockerTestScript() != null) {
submission.setDockerType(DockerTestType.SIMPLE);
} else {
submission.setDockerType(DockerTestType.NONE);
}

// save the first feedback, without docker feedback
submissionRepository.save(submission);

if (testEntity.getDockerTestScript() != null) {
// Define docker test as running
submission.setDockerTestState(DockerTestState.running);
// run docker tests in background
File finalSavedFile = savedFile;
CompletableFuture.runAsync(() -> {
Expand Down Expand Up @@ -351,56 +358,7 @@ public ResponseEntity<?> getSubmissionFile(@PathVariable("submissionid") long su
}
}


public ResponseEntity<?> getFeedbackReponseEntity(long submissionid, Auth auth, Function<SubmissionEntity, String> feedbackGetter) {

CheckResult<SubmissionEntity> checkResult = submissionUtil.canGetSubmission(submissionid, auth.getUserEntity());
if (!checkResult.getStatus().equals(HttpStatus.OK)) {
return ResponseEntity.status(checkResult.getStatus()).body(checkResult.getMessage());
}
SubmissionEntity submission = checkResult.getData();

HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, String.valueOf(MediaType.TEXT_PLAIN));
return ResponseEntity.ok().headers(headers).body(feedbackGetter.apply(submission));
}

/**
* Function to get the structure feedback of a submission
*
* @param submissionid ID of the submission to get the feedback from
* @param auth authentication object of the requesting user
* @return ResponseEntity with the feedback
* @ApiDog <a href="https://apidog.com/apidoc/project-467959/api-6195994">apiDog documentation</a>
* @HttpMethod GET
* @AllowedRoles teacher, student
* @ApiPath /api/submissions/{submissionid}/structurefeedback
*/
@GetMapping(ApiRoutes.SUBMISSION_BASE_PATH + "/{submissionid}/structurefeedback")
//Route to get the structure feedback
@Roles({UserRole.teacher, UserRole.student})
public ResponseEntity<?> getStructureFeedback(@PathVariable("submissionid") long submissionid, Auth auth) {
return getFeedbackReponseEntity(submissionid, auth, SubmissionEntity::getStructureFeedback);
}

/**
* Function to get the docker feedback of a submission
*
* @param submissionid ID of the submission to get the feedback from
* @param auth authentication object of the requesting user
* @return ResponseEntity with the feedback
* @ApiDog <a href="https://apidog.com/apidoc/project-467959/api-6195996">apiDog documentation</a>
* @HttpMethod GET
* @AllowedRoles teacher, student
* @ApiPath /api/submissions/{submissionid}/dockerfeedback
*/
@GetMapping(ApiRoutes.SUBMISSION_BASE_PATH + "/{submissionid}/dockerfeedback") //Route to get the docker feedback
@Roles({UserRole.teacher, UserRole.student})
public ResponseEntity<?> getDockerFeedback(@PathVariable("submissionid") long submissionid, Auth auth) {
return getFeedbackReponseEntity(submissionid, auth, SubmissionEntity::getDockerFeedback);
}



/**
* Function to delete a submission
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ugent.pidgeon.model.json;


import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.ugent.pidgeon.postgre.models.types.DockerTestType;

@JsonSerialize(using = DockerTestFeedbackJsonSerializer.class)
public record DockerTestFeedbackJson(
DockerTestType type,
String feedback,
boolean allowed
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ugent.pidgeon.model.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.ugent.pidgeon.postgre.models.types.DockerTestType;
import java.io.IOException;

public class DockerTestFeedbackJsonSerializer extends JsonSerializer<DockerTestFeedbackJson> {

@Override
public void serialize(DockerTestFeedbackJson value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("type", value.type().toString());
if (value.type() == DockerTestType.TEMPLATE) {
gen.writeFieldName("feedback");
gen.writeRawValue(value.feedback().replace("\n", "\\n"));
} else {
gen.writeStringField("feedback", value.feedback());
}
gen.writeBooleanField("allowed", value.allowed());
gen.writeEndObject();
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,24 @@ public class SubmissionJson {
private String fileUrl;

private Boolean structureAccepted;
private Boolean dockerAccepted;
private String dockerStatus;

@JsonSerialize(using = OffsetDateTimeSerializer.class)
private OffsetDateTime submissionTime;

private String structureFeedbackUrl;
private String structureFeedback;

public String getDockerFeedbackUrl() {
return dockerFeedbackUrl;
}

public void setDockerFeedbackUrl(String dockerFeedbackUrl) {
this.dockerFeedbackUrl = dockerFeedbackUrl;
}
private DockerTestFeedbackJson dockerFeedback;


private String dockerFeedbackUrl;

public SubmissionJson() {
}

public SubmissionJson(
long id, String projectUrl, String groupUrl, Long projectId, Long groupId, String fileUrl,
Boolean structureAccepted, OffsetDateTime submissionTime, Boolean dockerAccepted, String structureFeedbackUrl, String dockerFeedbackUrl, String dockerStatus) {
Boolean structureAccepted, OffsetDateTime submissionTime, String structureFeedbackUrl, DockerTestFeedbackJson dockerFeedback, String dockerStatus) {
this.submissionId = id;
this.projectUrl = projectUrl;
this.groupUrl = groupUrl;
Expand All @@ -46,9 +40,8 @@ public SubmissionJson(
this.fileUrl = fileUrl;
this.structureAccepted = structureAccepted;
this.submissionTime = submissionTime;
this.dockerAccepted = dockerAccepted;
this.structureFeedbackUrl = structureFeedbackUrl;
this.dockerFeedbackUrl = dockerFeedbackUrl;
this.dockerFeedback = dockerFeedback;
this.structureFeedback = structureFeedbackUrl;
this.dockerStatus = dockerStatus;
}

Expand Down Expand Up @@ -100,20 +93,14 @@ public void setSubmissionTime(OffsetDateTime submissionTime) {
this.submissionTime = submissionTime;
}

public Boolean getDockerAccepted() {
return dockerAccepted;
}

public void setDockerAccepted(Boolean dockerAccepted) {
this.dockerAccepted = dockerAccepted;
}

public String getStructureFeedbackUrl() {
return structureFeedbackUrl;
public String getStructureFeedback() {
return structureFeedback;
}

public void setStructureFeedbackUrl(String structureFeedbackUrl) {
this.structureFeedbackUrl = structureFeedbackUrl;
public void setStructureFeedback(String structureFeedback) {
this.structureFeedback = structureFeedback;
}

public Long getProjectId() {
Expand All @@ -139,4 +126,12 @@ public String getDockerStatus() {
public void setDockerStatus(String dockerStatus) {
this.dockerStatus = dockerStatus;
}

public DockerTestFeedbackJson getDockerFeedback() {
return dockerFeedback;
}

public void setDockerFeedback(DockerTestFeedbackJson dockerFeedback) {
this.dockerFeedback = dockerFeedback;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public boolean isAllowed() {
@Override
public String getFeedbackAsString() {
// Display feedback as a json, only display testName and testDescription if they are not empty
String testDescription = this.testDescription.isEmpty() ? "" : ",\"testDescription\":\"" + this.testDescription + "\"";
String testDescription = this.testDescription.isEmpty() ? "" : "\",\"testDescription\":\"" + this.testDescription;
return "{\"testName\":\"" + testName + testDescription + "\",\"correct\":\"" + correct + "\",\"output\":\"" + output + "\"}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public String getFeedbackAsString(){
for (DockerSubtestResult subtestResult : subtestResults) {
feedback.append(subtestResult.getFeedbackAsString()).append(",");
}
return feedback + "\"allowed\": \"" + allowed + "\"}";
feedback.append("]");
return feedback.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.ugent.pidgeon.postgre.models;

import com.ugent.pidgeon.model.submissionTesting.DockerTestOutput;
import com.ugent.pidgeon.postgre.models.types.DockerTestType;
import com.ugent.pidgeon.postgre.models.types.DockerTestState;
import jakarta.persistence.*;

Expand Down Expand Up @@ -41,6 +41,9 @@ public class SubmissionEntity {
@Column(name="docker_test_state")
private String dockerTestState;

@Column(name="docker_type")
private String dockerType;

public SubmissionEntity() {
}

Expand Down Expand Up @@ -136,4 +139,20 @@ public DockerTestState getDockerTestState() {
public void setDockerTestState(DockerTestState dockerTestState) {
this.dockerTestState = dockerTestState.toString();
}

public DockerTestType getDockerTestType() {
if (dockerType == null) {
return DockerTestType.NONE;
}
return switch (dockerType) {
case "SIMPLE" -> DockerTestType.SIMPLE;
case "TEMPLATE" -> DockerTestType.TEMPLATE;
case "NONE" -> DockerTestType.NONE;
default -> null;
};
}

public void setDockerType(DockerTestType dockerType) {
this.dockerType = dockerType.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.ugent.pidgeon.postgre.models.types;

public enum DockerTestType {
SIMPLE,
TEMPLATE,
NONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.ugent.pidgeon.model.json.*;
import com.ugent.pidgeon.postgre.models.*;
import com.ugent.pidgeon.postgre.models.types.CourseRelation;
import com.ugent.pidgeon.postgre.models.types.DockerTestState;
import com.ugent.pidgeon.postgre.models.types.DockerTestType;
import com.ugent.pidgeon.postgre.repository.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
Expand Down Expand Up @@ -33,9 +35,13 @@ public class EntityToJsonConverter {
private SubmissionRepository submissionRepository;
@Autowired
private ClusterUtil clusterUtil;
@Autowired
private TestUtil testUtil;
@Autowired
private TestRepository testRepository;


public GroupJson groupEntityToJson(GroupEntity groupEntity) {
public GroupJson groupEntityToJson(GroupEntity groupEntity) {
GroupClusterEntity cluster = groupClusterRepository.findById(groupEntity.getClusterId()).orElse(null);
GroupJson group = new GroupJson(cluster.getMaxSize(), groupEntity.getId(), groupEntity.getName(), ApiRoutes.CLUSTER_BASE_PATH + "/" + groupEntity.getClusterId());
if (cluster != null && cluster.getGroupAmount() > 1){
Expand Down Expand Up @@ -222,6 +228,18 @@ public CourseReferenceJson courseEntityToCourseReference(CourseEntity course) {


public SubmissionJson getSubmissionJson(SubmissionEntity submission) {
DockerTestFeedbackJson feedback;
TestEntity test = testRepository.findByProjectId(submission.getProjectId()).orElse(null);
if (submission.getDockerTestState().equals(DockerTestState.running)) {
feedback = null;
} else if (submission.getDockerTestType().equals(DockerTestType.NONE)) {
feedback = new DockerTestFeedbackJson(DockerTestType.NONE, "", true);
}
else if (submission.getDockerTestType().equals(DockerTestType.SIMPLE)) {
feedback = new DockerTestFeedbackJson(DockerTestType.SIMPLE, submission.getDockerFeedback(), submission.getDockerAccepted());
} else {
feedback = new DockerTestFeedbackJson(DockerTestType.TEMPLATE, submission.getDockerFeedback(), submission.getDockerAccepted());
}
return new SubmissionJson(
submission.getId(),
ApiRoutes.PROJECT_BASE_PATH + "/" + submission.getProjectId(),
Expand All @@ -231,9 +249,8 @@ public SubmissionJson getSubmissionJson(SubmissionEntity submission) {
ApiRoutes.SUBMISSION_BASE_PATH + "/" + submission.getId() + "/file",
submission.getStructureAccepted(),
submission.getSubmissionTime(),
submission.getDockerAccepted(),
ApiRoutes.SUBMISSION_BASE_PATH + "/" + submission.getId() + "/structurefeedback",
ApiRoutes.SUBMISSION_BASE_PATH + "/" + submission.getId() + "/dockerfeedback",
submission.getStructureFeedback(),
feedback,
submission.getDockerTestState().toString()
);
}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

2 changes: 0 additions & 2 deletions backend/app/tmp/test/HelloWorld.sh

This file was deleted.

2 changes: 0 additions & 2 deletions backend/app/tmp/test/HelloWorld2.sh

This file was deleted.

1 change: 0 additions & 1 deletion backend/app/tmp/test/testInput

This file was deleted.

Loading

0 comments on commit d669531

Please sign in to comment.