diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java b/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java index c6bfd3384110..b9a911ce6194 100644 --- a/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java +++ b/src/main/java/de/tum/cit/aet/artemis/communication/domain/push_notification/PushNotificationDeviceConfiguration.java @@ -106,7 +106,9 @@ public boolean equals(Object object) { return false; } PushNotificationDeviceConfiguration that = (PushNotificationDeviceConfiguration) object; - return token.equals(that.token) && deviceType == that.deviceType && expirationDate.equals(that.expirationDate) && Arrays.equals(secretKey, that.secretKey) + // Use compareTo rather than equals for dates to ensure timestamps and dates with the same time are considered equal + // This is caused by Java internal design having different classes for Date (java.util) and Timestamp (java.sql) + return token.equals(that.token) && deviceType == that.deviceType && expirationDate.compareTo(that.expirationDate) == 0 && Arrays.equals(secretKey, that.secretKey) && owner.equals(that.owner); } diff --git a/src/main/java/de/tum/cit/aet/artemis/core/service/ZipFileService.java b/src/main/java/de/tum/cit/aet/artemis/core/service/ZipFileService.java index 4d40473c4eb9..5871cd7ed7d4 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/service/ZipFileService.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/service/ZipFileService.java @@ -6,6 +6,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.zip.ZipEntry; @@ -33,6 +34,12 @@ public class ZipFileService { private final FileService fileService; + /** + * Set of file names that should be ignored when zipping. + * This currently only includes the gc.log.lock (garbage collector) file created by JGit in programming repositories. + */ + private static final Set IGNORED_ZIP_FILE_NAMES = Set.of(Path.of("gc.log.lock")); + public ZipFileService(FileService fileService) { this.fileService = fileService; } @@ -113,7 +120,7 @@ private void createZipFileFromPathStream(Path zipFilePath, Stream paths, P if (extraFilter != null) { filteredPaths = filteredPaths.filter(extraFilter); } - filteredPaths.forEach(path -> { + filteredPaths.filter(path -> !IGNORED_ZIP_FILE_NAMES.contains(path)).forEach(path -> { ZipEntry zipEntry = new ZipEntry(pathsRoot.relativize(path).toString()); copyToZipFile(zipOutputStream, path, zipEntry); }); diff --git a/src/test/java/de/tum/cit/aet/artemis/assessment/ExerciseScoresChartIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/assessment/ExerciseScoresChartIntegrationTest.java index fd48d4a5ace5..8782f11f8593 100644 --- a/src/test/java/de/tum/cit/aet/artemis/assessment/ExerciseScoresChartIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/assessment/ExerciseScoresChartIntegrationTest.java @@ -3,10 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import java.time.Instant; import java.time.ZonedDateTime; import java.util.List; -import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.AfterEach; @@ -15,7 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.util.ReflectionTestUtils; import de.tum.cit.aet.artemis.assessment.repository.ParticipantScoreRepository; import de.tum.cit.aet.artemis.assessment.service.ParticipantScoreScheduleService; @@ -60,11 +57,7 @@ class ExerciseScoresChartIntegrationTest extends AbstractSpringIntegrationIndepe @BeforeEach void setupTestScenario() { - // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results - ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); - ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 50; - participantScoreScheduleService.activate(); ZonedDateTime pastTimestamp = ZonedDateTime.now().minusDays(5); userUtilService.addUsers(TEST_PREFIX, 3, 2, 0, 0); Course course = courseUtilService.createCourse(); diff --git a/src/test/java/de/tum/cit/aet/artemis/assessment/ParticipantScoreIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/assessment/ParticipantScoreIntegrationTest.java index 85f521f00be5..1313f5147150 100644 --- a/src/test/java/de/tum/cit/aet/artemis/assessment/ParticipantScoreIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/assessment/ParticipantScoreIntegrationTest.java @@ -3,10 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import java.time.Instant; import java.time.ZonedDateTime; import java.util.List; -import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.AfterEach; @@ -15,7 +13,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.util.ReflectionTestUtils; import de.tum.cit.aet.artemis.assessment.domain.GradingScale; import de.tum.cit.aet.artemis.assessment.dto.score.ScoreDTO; @@ -98,11 +95,7 @@ class ParticipantScoreIntegrationTest extends AbstractSpringIntegrationLocalCILo @BeforeEach void setupTestScenario() { - // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results - ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); - ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); ZonedDateTime pastTimestamp = ZonedDateTime.now().minusDays(5); // creating the users student1, tutor1 and instructors1 userUtilService.addUsers(TEST_PREFIX, 1, 1, 0, 1); diff --git a/src/test/java/de/tum/cit/aet/artemis/assessment/ResultListenerIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/assessment/ResultListenerIntegrationTest.java index 4877e18e8c99..dffe1451edf7 100644 --- a/src/test/java/de/tum/cit/aet/artemis/assessment/ResultListenerIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/assessment/ResultListenerIntegrationTest.java @@ -4,10 +4,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; -import java.time.Instant; import java.time.ZonedDateTime; import java.util.List; -import java.util.Optional; import java.util.Set; import org.junit.jupiter.api.AfterEach; @@ -17,7 +15,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.util.ReflectionTestUtils; import de.tum.cit.aet.artemis.assessment.domain.ParticipantScore; import de.tum.cit.aet.artemis.assessment.domain.Result; @@ -84,11 +81,7 @@ void cleanup() { @BeforeEach void setupTestScenario() { - // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results - ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); - ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 100; - participantScoreScheduleService.activate(); ZonedDateTime pastReleaseDate = ZonedDateTime.now().minusDays(5); ZonedDateTime pastDueDate = ZonedDateTime.now().minusDays(3); ZonedDateTime pastAssessmentDueDate = ZonedDateTime.now().minusDays(2); diff --git a/src/test/java/de/tum/cit/aet/artemis/atlas/competency/CourseCompetencyIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/atlas/competency/CourseCompetencyIntegrationTest.java index 748a1f4d5b0f..df2c561bda7e 100644 --- a/src/test/java/de/tum/cit/aet/artemis/atlas/competency/CourseCompetencyIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/atlas/competency/CourseCompetencyIntegrationTest.java @@ -50,8 +50,6 @@ class CourseCompetencyIntegrationTest extends AbstractCompetencyPrerequisiteInte @BeforeEach void setupTestScenario() { super.setupTestScenario(TEST_PREFIX, course -> competencyUtilService.createCompetency(course, "penguin")); - - participantScoreScheduleService.activate(); } private Result createExerciseParticipationSubmissionAndResult(Exercise exercise, StudentParticipation studentParticipation, double pointsOfExercise, diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java index 21b6a8abdaed..c49163742ba4 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java @@ -6,7 +6,6 @@ import static org.awaitility.Awaitility.await; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anySet; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; @@ -81,7 +80,6 @@ void init() { exercise.setMaxPoints(5.0); exerciseRepository.saveAndFlush(exercise); - doNothing().when(javaMailSender).send(any(MimeMessage.class)); sizeBefore = notificationRepository.count(); } diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java index 9a3f7db09aff..347438c89a97 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java @@ -22,12 +22,14 @@ import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.MESSAGE_REPLY_IN_CONVERSATION_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.NEW_PLAGIARISM_CASE_STUDENT_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.PLAGIARISM_CASE_VERDICT_STUDENT_TITLE; +import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_ASSIGNED_TEXT; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_ASSIGNED_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_DEREGISTRATION_STUDENT_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_DEREGISTRATION_TUTOR_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_REGISTRATION_MULTIPLE_TUTOR_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_REGISTRATION_STUDENT_TITLE; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_REGISTRATION_TUTOR_TITLE; +import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_UNASSIGNED_TEXT; import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_UNASSIGNED_TITLE; import static de.tum.cit.aet.artemis.communication.service.notifications.NotificationSettingsService.NOTIFICATION_USER_NOTIFICATION_DATA_EXPORT_CREATED; import static de.tum.cit.aet.artemis.communication.service.notifications.NotificationSettingsService.NOTIFICATION_USER_NOTIFICATION_DATA_EXPORT_FAILED; @@ -40,7 +42,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anySet; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.timeout; @@ -63,6 +64,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.springframework.beans.factory.annotation.Autowired; import de.tum.cit.aet.artemis.assessment.domain.AssessmentType; @@ -132,6 +134,12 @@ class SingleUserNotificationServiceTest extends AbstractSpringIntegrationIndepen @Autowired private ParticipationUtilService participationUtilService; + @Captor + private ArgumentCaptor appleNotificationCaptor; + + @Captor + private ArgumentCaptor firebaseNotificationCaptor; + private User user; private User userTwo; @@ -263,8 +271,6 @@ void setUp() { dataExport = new DataExport(); dataExport.setUser(user); - - doNothing().when(javaMailSender).send(any(MimeMessage.class)); } /** @@ -273,8 +279,10 @@ void setUp() { * @param expectedNotificationTitle is the title (NotificationTitleTypeConstants) of the expected notification */ private void verifyRepositoryCallWithCorrectNotification(String expectedNotificationTitle) { - Notification capturedNotification = notificationRepository.findAll().getFirst(); - assertThat(capturedNotification.getTitle()).as("Title of the captured notification should be equal to the expected one").isEqualTo(expectedNotificationTitle); + List capturedNotifications = notificationRepository.findAll(); + assertThat(capturedNotifications).isNotEmpty(); + List relevantNotifications = capturedNotifications.stream().filter(e -> e.getTitle().equals(expectedNotificationTitle)).toList(); + assertThat(relevantNotifications).as("Title of the captured notification should be equal to the expected one").hasSize(1); } /// General notify Tests @@ -531,24 +539,24 @@ void testTutorialGroupNotifications_tutorDeregistration() { @Test void testTutorialGroupNotifications_groupAssigned() { notificationSettingRepository.deleteAll(); - notificationSettingRepository - .save(new NotificationSetting(tutorialGroup.getTeachingAssistant(), true, true, true, NOTIFICATION__TUTOR_NOTIFICATION__TUTORIAL_GROUP_ASSIGN_UNASSIGN)); + User teachingAssistant = tutorialGroup.getTeachingAssistant(); + notificationSettingRepository.save(new NotificationSetting(teachingAssistant, true, true, true, NOTIFICATION__TUTOR_NOTIFICATION__TUTORIAL_GROUP_ASSIGN_UNASSIGN)); singleUserNotificationService.notifyTutorAboutAssignmentToTutorialGroup(tutorialGroup, tutorialGroup.getTeachingAssistant(), userThree); verifyRepositoryCallWithCorrectNotification(TUTORIAL_GROUP_ASSIGNED_TITLE); verifyEmail(); - verifyPush(1); + verifyPush(1, TUTORIAL_GROUP_ASSIGNED_TEXT, teachingAssistant); } @Test void testTutorialGroupNotifications_groupUnassigned() { notificationSettingRepository.deleteAll(); - notificationSettingRepository - .save(new NotificationSetting(tutorialGroup.getTeachingAssistant(), true, true, true, NOTIFICATION__TUTOR_NOTIFICATION__TUTORIAL_GROUP_ASSIGN_UNASSIGN)); + User teachingAssistant = tutorialGroup.getTeachingAssistant(); + notificationSettingRepository.save(new NotificationSetting(teachingAssistant, true, true, true, NOTIFICATION__TUTOR_NOTIFICATION__TUTORIAL_GROUP_ASSIGN_UNASSIGN)); singleUserNotificationService.notifyTutorAboutUnassignmentFromTutorialGroup(tutorialGroup, tutorialGroup.getTeachingAssistant(), userThree); verifyRepositoryCallWithCorrectNotification(TUTORIAL_GROUP_UNASSIGNED_TITLE); verifyEmail(); - verifyPush(1); + verifyPush(1, TUTORIAL_GROUP_UNASSIGNED_TEXT, teachingAssistant); } @Test @@ -579,9 +587,20 @@ private void verifyEmail() { * * @param times how often the email should have been sent */ - private void verifyPush(int times) { - verify(applePushNotificationService, timeout(1500).times(times)).sendNotification(any(Notification.class), anySet(), any(Object.class)); - verify(firebasePushNotificationService, timeout(1500).times(times)).sendNotification(any(Notification.class), anySet(), any(Object.class)); + private void verifyPush(int times, String text, User recipient) { + verify(applePushNotificationService, timeout(1500).atLeast(times)).sendNotification(appleNotificationCaptor.capture(), anySet(), any(Object.class)); + verify(firebasePushNotificationService, timeout(1500).atLeast(times)).sendNotification(firebaseNotificationCaptor.capture(), anySet(), any(Object.class)); + + List appleNotifications = filterRelevantNotifications(appleNotificationCaptor.getAllValues(), text, recipient); + assertThat(appleNotifications).as(times + " Apple notifications should have been sent").hasSize(times); + + List firebaseNotifications = filterRelevantNotifications(firebaseNotificationCaptor.getAllValues(), text, recipient); + assertThat(firebaseNotifications).as(times + " Firebase notifications should have been sent").hasSize(times); + } + + private List filterRelevantNotifications(List notifications, String title, User recipient) { + return notifications.stream().filter(notification -> notification instanceof SingleUserNotification).map(notification -> (SingleUserNotification) notification) + .filter(notification -> title.equals(notification.getText()) && recipient.getId().equals(notification.getRecipient().getId())).toList(); } private static Stream getNotificationTypesAndTitlesParametersForGroupChat() { diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/TutorialGroupNotificationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/TutorialGroupNotificationServiceTest.java index 23ad94f5a00f..26816a87c239 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/TutorialGroupNotificationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/TutorialGroupNotificationServiceTest.java @@ -4,8 +4,6 @@ import static de.tum.cit.aet.artemis.communication.domain.notification.NotificationConstants.TUTORIAL_GROUP_UPDATED_TITLE; import static de.tum.cit.aet.artemis.communication.service.notifications.NotificationSettingsService.NOTIFICATION__TUTORIAL_GROUP_NOTIFICATION__TUTORIAL_GROUP_DELETE_UPDATE; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; @@ -15,8 +13,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import jakarta.mail.internet.MimeMessage; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -86,7 +82,6 @@ void setUp() { userRepository.findOneByLogin(TEST_PREFIX + "tutor1").orElseThrow(), IntStream.range(1, STUDENT_COUNT + 1) .mapToObj((studentId) -> userRepository.findOneByLogin(TEST_PREFIX + "student" + studentId).orElseThrow()).collect(Collectors.toSet())); - doNothing().when(javaMailSender).send(any(MimeMessage.class)); tutorialGroupNotificationRepository.deleteAll(); notificationSettingRepository.deleteAll(); } diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java index 4a42a5a826a5..a54be369017e 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java @@ -3,7 +3,6 @@ import static de.tum.cit.aet.artemis.communication.service.notifications.NotificationSettingsService.NOTIFICATION__WEEKLY_SUMMARY__BASIC_WEEKLY_SUMMARY; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; @@ -118,8 +117,6 @@ void setUp() { exerciseRepository.saveAll(allTestExercises); weeklyEmailSummaryService.setScheduleInterval(Duration.ofDays(7)); - - doNothing().when(javaMailSender).send(any(MimeMessage.class)); } /** diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java index dc59407ff76b..c8b142c4dc59 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/service/PushNotificationDeviceConfigurationCleanupServiceTest.java @@ -1,10 +1,9 @@ package de.tum.cit.aet.artemis.communication.service; -import static org.springframework.test.util.AssertionErrors.assertEquals; +import static org.assertj.core.api.Assertions.assertThat; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Set; @@ -54,6 +53,7 @@ void cleanupTest() { List result = deviceConfigurationRepository.findByUserIn(Set.of(user), PushNotificationDeviceType.FIREBASE); - assertEquals("The result is not correct", Collections.singletonList(valid), result); + assertThat(result).contains(valid); + assertThat(result).doesNotContain(expired); } } diff --git a/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java index 2b1b73492764..4aefa856aef2 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java @@ -4,7 +4,6 @@ import static de.tum.cit.aet.artemis.core.util.TimeUtil.toRelativeTime; import static org.assertj.core.api.Assertions.assertThat; -import java.time.Instant; import java.util.Comparator; import java.util.HashSet; import java.util.List; @@ -20,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.util.ReflectionTestUtils; import de.tum.cit.aet.artemis.assessment.domain.ParticipantScore; import de.tum.cit.aet.artemis.assessment.repository.StudentScoreRepository; @@ -84,10 +82,7 @@ class MetricsIntegrationTest extends AbstractSpringIntegrationIndependentTest { @BeforeEach void setupTestScenario() throws Exception { - // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results - ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 100; - participantScoreScheduleService.activate(); userUtilService.addUsers(TEST_PREFIX, 3, 1, 1, 1); diff --git a/src/test/java/de/tum/cit/aet/artemis/core/StatisticsIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/StatisticsIntegrationTest.java index bcd5a8d5c8ae..3a483ba5b736 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/StatisticsIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/StatisticsIntegrationTest.java @@ -95,7 +95,6 @@ class StatisticsIntegrationTest extends AbstractSpringIntegrationIndependentTest @BeforeEach void initTestCase() { - participantScoreScheduleService.activate(); userUtilService.addUsers(TEST_PREFIX, NUMBER_OF_STUDENTS, 1, 0, 1); course = modelingExerciseUtilService.addCourseWithOneModelingExercise(); diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java index 99e6b153def6..52f93e2d6741 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java @@ -203,7 +203,6 @@ void setup() { userTestRepository.save(instructor10); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); } @BeforeEach diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java index 0483663734ad..ec49d8ec78a7 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamParticipationIntegrationTest.java @@ -185,7 +185,6 @@ void initTestCase() { gitlabRequestMockProvider.enableMockingOfRequests(); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamRegistrationIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamRegistrationIntegrationTest.java index 016803accf6b..8402a7e431f3 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamRegistrationIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamRegistrationIntegrationTest.java @@ -88,7 +88,6 @@ void initTestCase() { examUtilService.addStudentExamForTestExam(testExam1, student1); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java index 399cb4306f6d..ea6ca670ad01 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java @@ -112,7 +112,6 @@ void initTestCase() throws GitAPIException { exam = examUtilService.addExamWithExerciseGroup(course1, true); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); doNothing().when(gitService).combineAllCommitsOfRepositoryIntoOne(any()); diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ProgrammingExamIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ProgrammingExamIntegrationTest.java index ef813745a412..a598f6ddbb79 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ProgrammingExamIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ProgrammingExamIntegrationTest.java @@ -100,7 +100,6 @@ void initTestCase() { gitlabRequestMockProvider.enableMockingOfRequests(); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); } @AfterEach diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/TestExamIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/TestExamIntegrationTest.java index 159866350e68..0853bed96f6c 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/TestExamIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/TestExamIntegrationTest.java @@ -74,7 +74,6 @@ void initTestCase() { examUtilService.addStudentExamForTestExam(testExam1, student1); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 200; - participantScoreScheduleService.activate(); } @Test diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java index 50e46b7e57db..f23887c80d43 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java @@ -46,7 +46,6 @@ class CourseGitlabJenkinsIntegrationTest extends AbstractSpringIntegrationJenkin @BeforeEach void setup() { - participantScoreScheduleService.activate(); courseTestService.setup(TEST_PREFIX, this); gitlabRequestMockProvider.enableMockingOfRequests(); jenkinsRequestMockProvider.enableMockingOfRequests(jenkinsServer); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseTestCaseServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseTestCaseServiceTest.java index 2d985741a637..cf293bf0740c 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseTestCaseServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseTestCaseServiceTest.java @@ -4,7 +4,6 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; @@ -95,7 +94,7 @@ void shouldResetExamExerciseTestCases() { private void testResetTestCases(ProgrammingExercise programmingExercise, Visibility expectedVisibility) { String dummyHash = "9b3a9bd71a0d80e5bbc42204c319ed3d1d4f0d6d"; - when(gitService.getLastCommitHash(any())).thenReturn(ObjectId.fromString(dummyHash)); + doReturn(ObjectId.fromString(dummyHash)).when(gitService).getLastCommitHash(any()); participationUtilService.addProgrammingParticipationWithResultForExercise(programmingExercise, TEST_PREFIX + "student1"); new ArrayList<>(testCaseRepository.findByExerciseId(programmingExercise.getId())).getFirst().weight(50.0); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportIntegrationTest.java index d0144595c37b..6d5bf267139a 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportIntegrationTest.java @@ -53,6 +53,11 @@ void initTestCase() throws Exception { exercise = ProgrammingExerciseFactory.generateProgrammingExercise(ZonedDateTime.now().minusDays(1), ZonedDateTime.now().plusDays(7), course); } + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @AfterEach void cleanup() throws Exception { solutionRepo.resetLocalRepo(); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportServiceTest.java index fefa75a3cf8a..70e3c6fb8301 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/ProgrammingExerciseGitDiffReportServiceTest.java @@ -58,6 +58,11 @@ class ProgrammingExerciseGitDiffReportServiceTest extends AbstractLocalCILocalVC @Autowired private ProgrammingExerciseGitDiffReportRepository reportRepository; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeEach void initTestCase() { userUtilService.addUsers(TEST_PREFIX, 1, 1, 1, 1); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/StructuralTestCaseServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/StructuralTestCaseServiceTest.java index 21e976498ece..08d6f5994ac7 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/StructuralTestCaseServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/StructuralTestCaseServiceTest.java @@ -56,6 +56,11 @@ class StructuralTestCaseServiceTest extends AbstractLocalCILocalVCIntegrationTes private ProgrammingExercise exercise; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeEach void initTestCase() { Course course = courseUtilService.addEmptyCourse(); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/TestwiseCoverageReportServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/TestwiseCoverageReportServiceTest.java index fc7b8542022a..ba89b52dc804 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/TestwiseCoverageReportServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/TestwiseCoverageReportServiceTest.java @@ -69,6 +69,11 @@ class TestwiseCoverageReportServiceTest extends AbstractLocalCILocalVCIntegratio private final LocalRepository solutionRepo = new LocalRepository("main"); + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeEach void setup() throws Exception { userUtilService.addUsers(TEST_PREFIX, 1, 0, 0, 1); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/behavioral/BehavioralTestCaseServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/behavioral/BehavioralTestCaseServiceTest.java index 802284ffd99f..f646dd652ded 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/hestia/behavioral/BehavioralTestCaseServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/hestia/behavioral/BehavioralTestCaseServiceTest.java @@ -78,6 +78,11 @@ class BehavioralTestCaseServiceTest extends AbstractLocalCILocalVCIntegrationTes private ProgrammingExercise exercise; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeEach void initTestCase() { userUtilService.addUsers(TEST_PREFIX, 0, 0, 0, 1); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/AbstractLocalCILocalVCIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/AbstractLocalCILocalVCIntegrationTest.java index 08fe3a292db2..0f559f0c3a50 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/AbstractLocalCILocalVCIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/AbstractLocalCILocalVCIntegrationTest.java @@ -30,9 +30,7 @@ import de.tum.cit.aet.artemis.programming.util.ProgrammingExerciseUtilService; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; -public class AbstractLocalCILocalVCIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { - - protected static final String TEST_PREFIX = "localvclocalciintegration"; +public abstract class AbstractLocalCILocalVCIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { @Autowired protected TeamRepository teamRepository; @@ -112,20 +110,23 @@ public class AbstractLocalCILocalVCIntegrationTest extends AbstractSpringIntegra protected String auxiliaryRepositorySlug; + protected abstract String getTestPrefix(); + @BeforeEach void initUsersAndExercise() throws JsonProcessingException { // The port cannot be injected into the LocalVCLocalCITestService because {local.server.port} is not available when the class is instantiated. // Thus, "inject" the port from here. localVCLocalCITestService.setPort(port); - List users = userUtilService.addUsers(TEST_PREFIX, 2, 1, 0, 2); - student1Login = TEST_PREFIX + "student1"; + String testPrefix = getTestPrefix(); + List users = userUtilService.addUsers(testPrefix, 2, 1, 0, 2); + student1Login = testPrefix + "student1"; student1 = users.stream().filter(user -> student1Login.equals(user.getLogin())).findFirst().orElseThrow(); - student2Login = TEST_PREFIX + "student2"; - tutor1Login = TEST_PREFIX + "tutor1"; - instructor1Login = TEST_PREFIX + "instructor1"; + student2Login = testPrefix + "student2"; + tutor1Login = testPrefix + "tutor1"; + instructor1Login = testPrefix + "instructor1"; instructor1 = users.stream().filter(user -> instructor1Login.equals(user.getLogin())).findFirst().orElseThrow(); - instructor2Login = TEST_PREFIX + "instructor2"; + instructor2Login = testPrefix + "instructor2"; instructor2 = users.stream().filter(user -> instructor2Login.equals(user.getLogin())).findFirst().orElseThrow(); // Remove instructor2 from the instructor group of the course. instructor2.setGroups(Set.of()); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java index b48bd518766e..46fcf73bdfb3 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIIntegrationTest.java @@ -81,6 +81,8 @@ @Execution(ExecutionMode.SAME_THREAD) class LocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTest { + private static final String TEST_PREFIX = "localciint"; + @Autowired private LocalVCServletService localVCServletService; @@ -99,6 +101,11 @@ class LocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTest { @Value("${artemis.user-management.internal-admin.password}") private String localVCPassword; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + private LocalRepository studentAssignmentRepository; private LocalRepository testsRepository; @@ -262,7 +269,8 @@ void testCommitHashNull() { // Should still work because in that case the latest commit should be retrieved from the repository. localVCServletService.processNewPush(null, studentAssignmentRepository.originGit.getRepository()); - localVCLocalCITestService.testLatestSubmission(studentParticipation.getId(), commitHash, 1, false); + // ToDo: Investigate why specifically this test requires so much time (all other << 5s) + localVCLocalCITestService.testLatestSubmission(studentParticipation.getId(), commitHash, 1, false, 120); } @Test @@ -291,7 +299,7 @@ void testProjectTypeIsNull() { @Test @WithMockUser(username = TEST_PREFIX + "student1", roles = "USER") - void testCannotFindResults() { + void testResultsNotFound() { ProgrammingExerciseStudentParticipation studentParticipation = localVCLocalCITestService.createParticipation(programmingExercise, student1Login); // Should return a build result that indicates that the build failed. diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java index b57491c34db5..83f9d9019f27 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResourceIntegrationTest.java @@ -42,6 +42,8 @@ class LocalCIResourceIntegrationTest extends AbstractLocalCILocalVCIntegrationTest { + private static final String TEST_PREFIX = "localciresourceint"; + @Autowired @Qualifier("hazelcastInstance") private HazelcastInstance hazelcastInstance; @@ -75,6 +77,11 @@ class LocalCIResourceIntegrationTest extends AbstractLocalCILocalVCIntegrationTe protected IMap buildAgentInformation; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeEach void createJobs() { // temporarily remove listener to avoid triggering build job processing @@ -136,11 +143,10 @@ void clearDataStructures() { @WithMockUser(username = TEST_PREFIX + "admin", roles = "ADMIN") void testGetQueuedBuildJobs_returnsJobs() throws Exception { var retrievedJobs = request.get("/api/admin/queued-jobs", HttpStatus.OK, List.class); - assertThat(retrievedJobs).isEmpty(); // Adding a lot of jobs as they get processed very quickly due to mocking queuedJobs.addAll(List.of(job1, job2)); var retrievedJobs1 = request.get("/api/admin/queued-jobs", HttpStatus.OK, List.class); - assertThat(retrievedJobs1).hasSize(2); + assertThat(retrievedJobs1).hasSize(retrievedJobs.size() + 2); } @Test diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResultServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResultServiceTest.java index e0947713cf57..a951d065e0cc 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResultServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalCIResultServiceTest.java @@ -14,9 +14,16 @@ class LocalCIResultServiceTest extends AbstractLocalCILocalVCIntegrationTest { + private static final String TEST_PREFIX = "localciresultservice"; + @Autowired private LocalCIResultService localCIResultService; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @Test void testThrowsExceptionWhenResultIsNotLocalCIBuildResult() { var wrongBuildResult = ProgrammingExerciseFactory.generateTestResultDTO("some-name", "some-repository", ZonedDateTime.now().minusSeconds(10), diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java index e57b850240a2..1531a4e2649a 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCIntegrationTest.java @@ -37,6 +37,8 @@ */ class LocalVCIntegrationTest extends AbstractLocalCILocalVCIntegrationTest { + private static final String TEST_PREFIX = "localvcint"; + private LocalRepository assignmentRepository; private LocalRepository templateRepository; @@ -60,6 +62,11 @@ void initRepositories() throws GitAPIException, IOException, URISyntaxException testsRepository = localVCLocalCITestService.createAndConfigureLocalRepository(projectKey1, projectKey1.toLowerCase() + "-tests"); } + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @AfterEach void removeRepositories() throws IOException { assignmentRepository.resetLocalRepo(); @@ -77,7 +84,16 @@ void testFetchPush_repositoryDoesNotExist() throws IOException, GitAPIException, // Delete the remote repository. someRepository.originGit.close(); - FileUtils.deleteDirectory(someRepository.originRepoFile); + try { + FileUtils.deleteDirectory(someRepository.originRepoFile); + } + catch (IOException exception) { + // JGit creates a lock file in each repository that could cause deletion problems. + if (exception.getMessage().contains("gc.log.lock")) { + return; + } + throw exception; + } // Try to fetch from the remote repository. localVCLocalCITestService.testFetchThrowsException(someRepository.localGit, student1Login, USER_PASSWORD, projectKey, repositorySlug, InvalidRemoteException.class, ""); @@ -122,7 +138,7 @@ void testFetchPush_usingVcsAccessToken() { @Test void testFetchPush_wrongCredentials() throws InvalidNameException { - var student1 = new LdapUserDto().login(TEST_PREFIX + "student1"); + var student1 = new LdapUserDto().login(getTestPrefix() + "student1"); student1.setUid(new LdapName("cn=student1,ou=test,o=lab")); var fakeUser = new LdapUserDto().login(localVCBaseUsername); 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 526d5b8a522f..877ccd6493e0 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 @@ -87,6 +87,8 @@ class LocalVCLocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTes private static final Logger log = LoggerFactory.getLogger(LocalVCLocalCIIntegrationTest.class); + private static final String TEST_PREFIX = "localvcciint"; + @Autowired private ExamUtilService examUtilService; @@ -124,6 +126,11 @@ class LocalVCLocalCIIntegrationTest extends AbstractLocalCILocalVCIntegrationTes protected IQueue queuedJobs; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @BeforeAll void setupAll() { CredentialsProvider.setDefault(new UsernamePasswordCredentialsProvider(localVCUsername, localVCPassword)); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java index 08c02eedceed..c6d7556e3766 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCLocalCITestService.java @@ -54,6 +54,7 @@ import de.tum.cit.aet.artemis.assessment.domain.Result; import de.tum.cit.aet.artemis.assessment.domain.Visibility; +import de.tum.cit.aet.artemis.assessment.service.ParticipantScoreScheduleService; import de.tum.cit.aet.artemis.assessment.test_repository.ResultTestRepository; import de.tum.cit.aet.artemis.core.domain.User; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; @@ -91,6 +92,9 @@ public class LocalVCLocalCITestService { @Autowired private ParticipationVcsAccessTokenService participationVcsAccessTokenService; + @Autowired + private ParticipantScoreScheduleService participantScoreScheduleService; + @Autowired private ResultTestRepository resultRepository; @@ -573,7 +577,11 @@ public void testLatestSubmission(Long participationId, String expectedCommitHash int expectedCodeIssueCount, Integer timeoutInSeconds) { // wait for result to be persisted Duration timeoutDuration = timeoutInSeconds != null ? Duration.ofSeconds(timeoutInSeconds) : Duration.ofSeconds(DEFAULT_AWAITILITY_TIMEOUT_IN_SECONDS); - await().atMost(timeoutDuration).until(() -> resultRepository.findFirstWithSubmissionsByParticipationIdOrderByCompletionDateDesc(participationId).isPresent()); + await().atMost(timeoutDuration).until(() -> { + participantScoreScheduleService.executeScheduledTasks(); + await().until(participantScoreScheduleService::isIdle); + return resultRepository.findFirstWithSubmissionsByParticipationIdOrderByCompletionDateDesc(participationId).isPresent(); + }); Authentication auth = SecurityContextHolder.getContext().getAuthentication(); List submissions = programmingSubmissionRepository.findAllByParticipationIdWithResults(participationId); @@ -609,6 +617,10 @@ public void testLatestSubmission(Long participationId, String expectedCommitHash testLatestSubmission(participationId, expectedCommitHash, expectedSuccessfulTestCaseCount, buildFailed, false, 0, null); } + public void testLatestSubmission(Long participationId, String expectedCommitHash, int expectedSuccessfulTestCaseCount, boolean buildFailed, int timeoutInSeconds) { + testLatestSubmission(participationId, expectedCommitHash, expectedSuccessfulTestCaseCount, buildFailed, false, 0, timeoutInSeconds); + } + /** * Perform a push operation and fail if there was no exception. * diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCSshIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCSshIntegrationTest.java index ac20db1c209c..bca0ed60beb9 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCSshIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/LocalVCSshIntegrationTest.java @@ -12,6 +12,7 @@ import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; +import java.util.Objects; import java.util.concurrent.TimeUnit; import org.apache.sshd.client.SshClient; @@ -20,6 +21,7 @@ import org.apache.sshd.common.SshException; import org.apache.sshd.common.config.keys.AuthorizedKeyEntry; import org.apache.sshd.common.config.keys.writer.openssh.OpenSSHKeyPairResourceWriter; +import org.apache.sshd.common.session.helpers.AbstractSession; import org.apache.sshd.server.SshServer; import org.apache.sshd.server.session.ServerSession; import org.junit.jupiter.api.Test; @@ -35,9 +37,16 @@ @Profile(PROFILE_LOCALVC) class LocalVCSshIntegrationTest extends LocalVCIntegrationTest { + private static final String TEST_PREFIX = "localvcsshint"; + @Autowired private SshServer sshServer; + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + private final String hostname = "localhost"; private final int port = 7921; @@ -111,8 +120,8 @@ void testAuthenticationFailure() { void testConnectOverSshAndReceivePack() throws IOException, GeneralSecurityException { try (var client = clientConnectToArtemisSshServer()) { assertThat(client).isNotNull(); - var serverSessions = sshServer.getActiveSessions(); - var serverSession = serverSessions.getFirst(); + var user = userTestRepository.getUser(); + var serverSession = getCurrentServerSession(user); final var uploadCommandString = "git-upload-pack '/git/" + projectKey1 + "/" + templateRepositorySlug + "'"; @@ -144,9 +153,13 @@ private SshGitCommand setupCommand(String commandString, ServerSession serverSes return command; } + /** + * Note: Don't count unattached sessions as a potential result from previous tests. + * See {@link org.apache.sshd.server.SshServer#getActiveSessions} + * and {@link org.apache.sshd.common.session.helpers.AbstractSession#getSession}. + */ private SshClient clientConnectToArtemisSshServer() throws GeneralSecurityException, IOException { var serverSessions = sshServer.getActiveSessions(); - var numberOfSessions = serverSessions.size(); localVCLocalCITestService.createParticipation(programmingExercise, student1Login); KeyPair keyPair = setupKeyPairAndAddToUser(); User user = userTestRepository.getUser(); @@ -155,6 +168,7 @@ private SshClient clientConnectToArtemisSshServer() throws GeneralSecurityExcept client.start(); ClientSession clientSession; + int numberOfSessions = serverSessions.size(); try { ConnectFuture connectFuture = client.connect(user.getName(), hostname, port); connectFuture.await(10, TimeUnit.SECONDS); @@ -169,11 +183,20 @@ private SshClient clientConnectToArtemisSshServer() throws GeneralSecurityExcept } serverSessions = sshServer.getActiveSessions(); + var attachedServerSessions = serverSessions.stream().filter(Objects::nonNull).count(); assertThat(clientSession.isAuthenticated()).isTrue(); - assertThat(serverSessions.size()).isEqualTo(numberOfSessions + 1); + assertThat(attachedServerSessions).as("There are more server sessions activated than expected.").isEqualTo(numberOfSessions + 1); return client; } + private AbstractSession getCurrentServerSession(User user) { + var serverSessions = sshServer.getActiveSessions(); + // parallel tests might create additional sessions, we need to be specific + var serverSession = serverSessions.stream().filter(session -> user.getName().equals(session.getUsername())).findFirst(); + + return serverSession.orElseThrow(() -> new IllegalStateException("No server session found for user " + user.getName())); + } + private KeyPair setupKeyPairAndAddToUser() throws GeneralSecurityException, IOException { User user = userTestRepository.getUser(); diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/icl/MultipleHostKeyProviderTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/icl/MultipleHostKeyProviderTest.java index bf9c4cde79fc..a386ae6ccc2d 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/icl/MultipleHostKeyProviderTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/icl/MultipleHostKeyProviderTest.java @@ -13,6 +13,13 @@ @Profile(PROFILE_LOCALVC) class MultipleHostKeyProviderTest extends AbstractLocalCILocalVCIntegrationTest { + private static final String TEST_PREFIX = "multiplehostkeyprovider"; + + @Override + protected String getTestPrefix() { + return TEST_PREFIX; + } + @Test void testMultipleHostKeyProvider() { MultipleHostKeyProvider multipleHostKeyProvider = new MultipleHostKeyProvider(Path.of("./")); diff --git a/src/test/java/de/tum/cit/aet/artemis/quiz/QuizSubmissionIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/quiz/QuizSubmissionIntegrationTest.java index 5a56c62d5273..41736fa7c6a9 100644 --- a/src/test/java/de/tum/cit/aet/artemis/quiz/QuizSubmissionIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/quiz/QuizSubmissionIntegrationTest.java @@ -1,12 +1,12 @@ package de.tum.cit.aet.artemis.quiz; +import static de.tum.cit.aet.artemis.core.config.Constants.EXERCISE_TOPIC_ROOT; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import java.io.IOException; import java.time.Duration; @@ -414,7 +414,7 @@ void testQuizSubmitPractice_badRequest() throws Exception { Result result = request.postWithResponseBody("/api/exercises/" + quizExerciseServer.getId() + "/submissions/practice", quizSubmission, Result.class, HttpStatus.BAD_REQUEST); assertThat(result).isNull(); - verifyNoInteractions(websocketMessagingService); + verifyNoWebsocketMessageForExercise(quizExerciseServer); } @Test @@ -431,7 +431,7 @@ void testQuizSubmitPractice_badRequest_exam() throws Exception { Result result = request.postWithResponseBody("/api/exercises/" + quizExerciseServer.getId() + "/submissions/practice", quizSubmission, Result.class, HttpStatus.BAD_REQUEST); assertThat(result).isNull(); - verifyNoInteractions(websocketMessagingService); + verifyNoWebsocketMessageForExercise(quizExerciseServer); } @Test @@ -451,7 +451,7 @@ void testQuizSubmitPractice_forbidden() throws Exception { QuizExercise quizExercise = QuizExerciseFactory.createQuiz(course, ZonedDateTime.now().minusSeconds(4), null, QuizMode.SYNCHRONIZED); quizExerciseService.save(quizExercise); request.postWithResponseBody("/api/exercises/" + quizExercise.getId() + "/submissions/practice", new QuizSubmission(), Result.class, HttpStatus.FORBIDDEN); - verifyNoInteractions(websocketMessagingService); + verifyNoWebsocketMessageForExercise(quizExercise); } @Test @@ -757,6 +757,12 @@ private QuizExercise setupQuizExerciseParameters() { return quizExercise; } + private void verifyNoWebsocketMessageForExercise(QuizExercise exercise) { + String topic = EXERCISE_TOPIC_ROOT + exercise.getId() + "/newResults"; + verify(websocketMessagingService, never()).sendMessage(eq(topic), any()); + verify(websocketMessagingService, never()).sendMessageToUser(any(), eq(topic), any()); + } + @Nested @Isolated class QuizSubmitLiveModeIsolatedTest { diff --git a/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java index 4157341a3deb..469e4f117837 100644 --- a/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java @@ -4,7 +4,9 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import java.time.Instant; import java.util.List; +import java.util.Optional; import jakarta.mail.internet.MimeMessage; @@ -23,6 +25,7 @@ import org.springframework.context.annotation.Import; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; import de.tum.cit.aet.artemis.assessment.service.ParticipantScoreScheduleService; import de.tum.cit.aet.artemis.assessment.test_repository.ResultTestRepository; @@ -199,6 +202,14 @@ void mockMailService() { doNothing().when(javaMailSender).send(any(MimeMessage.class)); } + @BeforeEach + void resetParticipantScoreScheduler() { + // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results + ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); + ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 100; + participantScoreScheduleService.activate(); + } + @AfterEach void stopQuizScheduler() { scheduleService.clearAllTasks();