diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCIIntegrationTest.java index 139755d056d5..1ccdaed26a7f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCIIntegrationTest.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.concurrent.TimeUnit; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; @@ -32,6 +31,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.slf4j.Logger; @@ -41,6 +41,11 @@ import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; +import com.hazelcast.collection.IQueue; +import com.hazelcast.core.HazelcastInstance; + +import de.tum.cit.aet.artemis.buildagent.dto.BuildJobQueueItem; +import de.tum.cit.aet.artemis.buildagent.service.SharedQueueProcessingService; import de.tum.cit.aet.artemis.core.service.ldap.LdapUserDto; import de.tum.cit.aet.artemis.exam.domain.Exam; import de.tum.cit.aet.artemis.exam.domain.ExerciseGroup; @@ -55,6 +60,8 @@ import de.tum.cit.aet.artemis.programming.domain.build.BuildJob; import de.tum.cit.aet.artemis.programming.domain.submissionpolicy.LockRepositoryPolicy; import de.tum.cit.aet.artemis.programming.domain.submissionpolicy.SubmissionPolicy; +import de.tum.cit.aet.artemis.programming.service.localci.LocalCITriggerService; +import de.tum.cit.aet.artemis.programming.test_repository.BuildJobTestRepository; import de.tum.cit.aet.artemis.programming.util.LocalRepository; /** @@ -69,6 +76,18 @@ class LocalVCLocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTes @Autowired private ExamUtilService examUtilService; + @Autowired + private BuildJobTestRepository buildJobRepository; + + @Autowired + protected LocalCITriggerService localCITriggerService; + + @Autowired + private SharedQueueProcessingService sharedQueueProcessingService; + + @Autowired + private HazelcastInstance hazelcastInstance; + @Value("${artemis.user-management.internal-admin.username}") private String localVCUsername; @@ -88,6 +107,8 @@ class LocalVCLocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTes private String teamRepositorySlug; + protected IQueue queuedJobs; + @BeforeAll void setupAll() { CredentialsProvider.setDefault(new UsernamePasswordCredentialsProvider(localVCUsername, localVCPassword)); @@ -137,6 +158,8 @@ void initRepositories() throws GitAPIException, IOException, URISyntaxException, doReturn(true).when(ldapTemplate).compare(anyString(), anyString(), any()); localVCLocalCITestService.mockInspectImage(dockerClient); + + queuedJobs = hazelcastInstance.getQueue("buildJobQueue"); } @AfterEach @@ -925,75 +948,93 @@ void testFetchPush_instructorPracticeRepository() throws Exception { practiceRepository.resetLocalRepo(); } - @Test - @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void testBuildPriorityAfterDueDate() throws Exception { - // Set dueDate before now - programmingExercise.setDueDate(ZonedDateTime.now().minusMinutes(1)); - programmingExerciseRepository.save(programmingExercise); - - testPriority(instructor1Login, PRIORITY_OPTIONAL_EXERCISE); - } - - @Test - @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void testBuildPriorityBeforeDueDate() throws Exception { - testPriority(student1Login, PRIORITY_NORMAL); - } - - @Test - @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void testPriorityRunningExam() throws Exception { - Exam exam = examUtilService.addExamWithExerciseGroup(course, true); - ExerciseGroup exerciseGroup = exam.getExerciseGroups().getFirst(); - - programmingExercise.setCourse(null); - programmingExercise.setExerciseGroup(exerciseGroup); - programmingExercise = programmingExerciseRepository.save(programmingExercise); - - // Exam is running - var now = ZonedDateTime.now(); - exam.setStartDate(now.minusHours(1)); - exam.setEndDate(now.plusHours(1)); - exam.setWorkingTime(2 * 60 * 60); - exam = examRepository.save(exam); - - // Create StudentExam. - StudentExam studentExam = examUtilService.addStudentExamWithUser(exam, student1); - studentExam.setExercises(List.of(programmingExercise)); - studentExam.setWorkingTime(exam.getWorkingTime()); - studentExam.setStartedAndStartDate(now.minusHours(1)); - studentExamRepository.save(studentExam); - - testPriority(student1Login, PRIORITY_EXAM_CONDUCTION); - } - - private void testPriority(String login, int expectedPriority) throws Exception { - ProgrammingExerciseStudentParticipation studentParticipation = localVCLocalCITestService.createParticipation(programmingExercise, student1Login); - - localVCLocalCITestService.testFetchSuccessful(assignmentRepository.localGit, login, projectKey1, assignmentRepositorySlug); - String commitHash = localVCLocalCITestService.commitFile(assignmentRepository.localRepoFile.toPath(), assignmentRepository.localGit); - localVCLocalCITestService.mockInputStreamReturnedFromContainer(dockerClient, LOCALCI_WORKING_DIRECTORY + "/testing-dir/assignment/.git/refs/heads/[^/]+", - Map.of("commitHash", commitHash), Map.of("commitHash", commitHash)); - localVCLocalCITestService.mockTestResults(dockerClient, PARTLY_SUCCESSFUL_TEST_RESULTS_PATH, LOCALCI_WORKING_DIRECTORY + LOCALCI_RESULTS_DIRECTORY); - localVCLocalCITestService.testPushSuccessful(assignmentRepository.localGit, login, projectKey1, assignmentRepositorySlug); - - log.info("Push done"); - - await().atMost(15, TimeUnit.SECONDS).until(() -> { - log.info("Search for a build job for participation id: {}", studentParticipation.getId()); - Optional buildJobOptional = buildJobRepository.findFirstByParticipationIdOrderByBuildStartDateDesc(studentParticipation.getId()); - if (buildJobOptional.isPresent()) { - return true; - } - else { - var allBuildJobs = buildJobRepository.findAll(); - log.info("All found build jobs: {}", allBuildJobs); - return false; - } - }); - - BuildJob buildJob = buildJobRepository.findFirstByParticipationIdOrderByBuildStartDateDesc(studentParticipation.getId()).orElseThrow(); - assertThat(buildJob.getPriority()).isEqualTo(expectedPriority); + @Nested + class BuildJobPriorityTest { + + @BeforeEach + void setUp() { + sharedQueueProcessingService.removeListener(); + } + + @AfterEach + void tearDown() { + queuedJobs.clear(); + log.info("Clear queued jobs done"); + + sharedQueueProcessingService.init(); + log.info("Cleanup queue processing service done"); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void testBuildPriorityBeforeDueDate() throws Exception { + testPriority(student1Login, PRIORITY_NORMAL); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void testBuildPriorityAfterDueDate() throws Exception { + // Set dueDate before now + programmingExercise.setDueDate(ZonedDateTime.now().minusMinutes(1)); + programmingExerciseRepository.save(programmingExercise); + + testPriority(instructor1Login, PRIORITY_OPTIONAL_EXERCISE); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") + void testPriorityRunningExam() throws Exception { + Exam exam = examUtilService.addExamWithExerciseGroup(course, true); + ExerciseGroup exerciseGroup = exam.getExerciseGroups().getFirst(); + + programmingExercise.setCourse(null); + programmingExercise.setExerciseGroup(exerciseGroup); + programmingExercise = programmingExerciseRepository.save(programmingExercise); + + // Exam is running + var now = ZonedDateTime.now(); + exam.setStartDate(now.minusHours(1)); + exam.setEndDate(now.plusHours(1)); + exam.setWorkingTime(2 * 60 * 60); + exam = examRepository.save(exam); + + // Create StudentExam. + StudentExam studentExam = examUtilService.addStudentExamWithUser(exam, student1); + studentExam.setExercises(List.of(programmingExercise)); + studentExam.setWorkingTime(exam.getWorkingTime()); + studentExam.setStartedAndStartDate(now.minusHours(1)); + studentExamRepository.save(studentExam); + + testPriority(student1Login, PRIORITY_EXAM_CONDUCTION); + } + + private void testPriority(String login, int expectedPriority) throws Exception { + log.info("Creating participation"); + ProgrammingExerciseStudentParticipation studentParticipation = localVCLocalCITestService.createParticipation(programmingExercise, student1Login); + + localVCLocalCITestService.testFetchSuccessful(assignmentRepository.localGit, login, projectKey1, assignmentRepositorySlug); + String commitHash = localVCLocalCITestService.commitFile(assignmentRepository.localRepoFile.toPath(), assignmentRepository.localGit); + localVCLocalCITestService.mockInputStreamReturnedFromContainer(dockerClient, LOCALCI_WORKING_DIRECTORY + "/testing-dir/assignment/.git/refs/heads/[^/]+", + Map.of("commitHash", commitHash), Map.of("commitHash", commitHash)); + localVCLocalCITestService.mockTestResults(dockerClient, PARTLY_SUCCESSFUL_TEST_RESULTS_PATH, LOCALCI_WORKING_DIRECTORY + LOCALCI_RESULTS_DIRECTORY); + + localCITriggerService.triggerBuild(studentParticipation, false); + log.info("Trigger build done"); + + await().until(() -> { + BuildJobQueueItem buildJobQueueItem = queuedJobs.peek(); + log.info("Poll queue jobs: is null %s".formatted(buildJobQueueItem == null ? "true" : "false")); + if (buildJobQueueItem == null) { + queuedJobs.forEach(item -> log.info("Item in Queue: %s".formatted(item.toString()))); + } + return buildJobQueueItem != null && buildJobQueueItem.participationId() == studentParticipation.getId(); + }); + BuildJobQueueItem buildJobQueueItem = queuedJobs.poll(); + log.info("Polled queue item"); + + assertThat(buildJobQueueItem).isNotNull(); + assertThat(buildJobQueueItem.priority()).isEqualTo(expectedPriority); + log.info("Assertions done"); + } } }