22
33import static org .assertj .core .api .Assertions .assertThat ;
44import static org .mockito .ArgumentMatchers .any ;
5- import static org .mockito .ArgumentMatchers .anyLong ;
65import static org .mockito .ArgumentMatchers .anyString ;
76import static org .mockito .ArgumentMatchers .eq ;
87import static org .mockito .Mockito .lenient ;
1312import static org .mockito .Mockito .when ;
1413
1514import java .net .URI ;
15+ import java .time .Duration ;
1616import java .util .Map ;
1717import java .util .Optional ;
18- import java .util .concurrent .TimeUnit ;
1918
2019import jakarta .servlet .http .HttpServletRequest ;
2120
3029import org .springframework .security .authentication .AuthenticationManager ;
3130import org .springframework .test .util .ReflectionTestUtils ;
3231
33- import com .hazelcast .core .HazelcastInstance ;
34- import com .hazelcast .map .IMap ;
35-
3632import de .tum .cit .aet .artemis .account .domain .User ;
3733import de .tum .cit .aet .artemis .account .test_repository .UserTestRepository ;
3834import de .tum .cit .aet .artemis .admin .service .RateLimitService ;
3935import de .tum .cit .aet .artemis .core .service .AuthorizationCheckService ;
36+ import de .tum .cit .aet .artemis .core .service .distributed .api .DistributedDataProvider ;
37+ import de .tum .cit .aet .artemis .core .service .distributed .api .map .DistributedMap ;
4038import de .tum .cit .aet .artemis .course .domain .Course ;
4139import de .tum .cit .aet .artemis .exercise .service .ExerciseVersionService ;
4240import de .tum .cit .aet .artemis .localci .service .ci .ContinuousIntegrationTriggerService ;
@@ -112,10 +110,10 @@ class LocalVCServletServiceTest {
112110 private MailSendingService mailSendingService ;
113111
114112 @ Mock
115- private HazelcastInstance hazelcastInstance ;
113+ private DistributedDataProvider distributedDataProvider ;
116114
117115 @ Mock
118- private IMap <Long , Boolean > httpsCloneEmailCache ;
116+ private DistributedMap <Long , Boolean > httpsCloneEmailCache ;
119117
120118 @ InjectMocks
121119 private LocalVCServletService localVCServletService ;
@@ -155,10 +153,9 @@ void setUp() throws Exception {
155153 testRepositoryUri = mock (LocalVCRepositoryUri .class );
156154 // Use lenient() to avoid unnecessary stubbing errors for tests that don't use this mock
157155 lenient ().when (testRepositoryUri .getRelativeRepositoryPath ()).thenReturn (java .nio .file .Path .of ("test/repo" ));
158- lenient ().when (testRepositoryUri .toString ()).thenReturn ("http://localhost/git/TEST/EXERCISE -template.git" );
156+ lenient ().when (testRepositoryUri .toString ()).thenReturn ("http://localhost/git/TEST/test -template.git" );
159157
160- lenient ().when (hazelcastInstance .getMap (anyString ())).thenReturn ((IMap ) httpsCloneEmailCache );
161- // lenient().when(hazelcastInstance.<Long, Boolean>getMap(LocalVCServletService.HTTPS_CLONE_EMAIL_CACHE)).thenReturn(httpsCloneEmailCache);
158+ lenient ().when (distributedDataProvider .<Long , Boolean >getExpiringMap (anyString (), any ())).thenReturn (httpsCloneEmailCache );
162159
163160 // Setup the VcsAccessLogService as an Optional containing the mock
164161 ReflectionTestUtils .setField (localVCServletService , "vcsAccessLogService" , Optional .of (vcsAccessLogService ));
@@ -286,7 +283,7 @@ void testResolveAuthenticationMechanismFromSessionOrRequest_withRepositoryToken(
286283
287284 RepositoryVCSAccessToken repositoryToken = new RepositoryVCSAccessToken ();
288285 repositoryToken .setVcsAccessToken (token );
289- when (repositoryVCSAccessTokenRepository .findByUserIdAndRepositoryUri (testUser .getId (), "http://localhost/git/TEST/EXERCISE -template.git" ))
286+ when (repositoryVCSAccessTokenRepository .findByUserIdAndRepositoryUri (testUser .getId (), "http://localhost/git/TEST/test -template.git" ))
290287 .thenReturn (Optional .of (repositoryToken ));
291288
292289 AuthenticationContext .Request context = new AuthenticationContext .Request (request );
@@ -321,14 +318,14 @@ void testRepositoryActionTypeForFailedOperations() {
321318 void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_sendsEmailOnPasswordCloneWhenNotInCache () {
322319 HttpServletRequest request = mock (HttpServletRequest .class );
323320 when (request .getMethod ()).thenReturn ("POST" );
324- when (request .getRequestURI ()).thenReturn ("/git/TEST/EXERCISE -testuser.git/git-upload-pack" );
321+ when (request .getRequestURI ()).thenReturn ("/git/TEST/test -testuser.git/git-upload-pack" );
325322
326323 String password = "plain-password" ;
327324 String authHeader = "Basic " + java .util .Base64 .getEncoder ().encodeToString (("testuser:" + password ).getBytes ());
328325
329326 when (userRepository .findOneByLogin ("testuser" )).thenReturn (Optional .of (testUser ));
330- // putIfAbsent return null, first clone with HTTPS
331- when (httpsCloneEmailCache .putIfAbsent (eq (testUser .getId ()), eq (Boolean .TRUE ), anyLong (), any (TimeUnit .class ))).thenReturn (null );
327+ // putIfAbsent returns null on first insert
328+ when (httpsCloneEmailCache .putIfAbsent (eq (testUser .getId ()), eq (Boolean .TRUE ), any (Duration .class ))).thenReturn (null );
332329
333330 // clientOffered == 0 means CLONE operation
334331 localVCServletService .updateAndStoreVCSAccessLogForCloneAndPullHTTPS (request , authHeader , 0 );
@@ -340,12 +337,14 @@ void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_sendsEmailOnPasswordClon
340337 void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_doesNotSendEmailWhenAlreadyInCache () {
341338 HttpServletRequest request = mock (HttpServletRequest .class );
342339 when (request .getMethod ()).thenReturn ("POST" );
343- when (request .getRequestURI ()).thenReturn ("/git/TEST/EXERCISE -testuser.git/git-upload-pack" );
340+ when (request .getRequestURI ()).thenReturn ("/git/TEST/test -testuser.git/git-upload-pack" );
344341
345342 String password = "plain-password" ;
346343 String authHeader = "Basic " + java .util .Base64 .getEncoder ().encodeToString (("testuser:" + password ).getBytes ());
347344
348345 when (userRepository .findOneByLogin ("testuser" )).thenReturn (Optional .of (testUser ));
346+ // putIfAbsent returns existing entry (Boolean.TRUE) when already present
347+ when (httpsCloneEmailCache .putIfAbsent (eq (testUser .getId ()), eq (Boolean .TRUE ), any (Duration .class ))).thenReturn (Boolean .TRUE );
349348
350349 localVCServletService .updateAndStoreVCSAccessLogForCloneAndPullHTTPS (request , authHeader , 0 );
351350
@@ -356,7 +355,7 @@ void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_doesNotSendEmailWhenAlre
356355 void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_doesNotSendEmailWhenUsingToken () {
357356 HttpServletRequest request = mock (HttpServletRequest .class );
358357 when (request .getMethod ()).thenReturn ("POST" );
359- when (request .getRequestURI ()).thenReturn ("/git/TEST/EXERCISE -testuser.git/git-upload-pack" );
358+ when (request .getRequestURI ()).thenReturn ("/git/TEST/test -testuser.git/git-upload-pack" );
360359
361360 String token = "vcpat-" + "a" .repeat (44 );
362361 String authHeader = "Basic " + java .util .Base64 .getEncoder ().encodeToString (("testuser:" + token ).getBytes ());
@@ -373,7 +372,7 @@ void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_doesNotSendEmailWhenUsin
373372 void testUpdateAndStoreVCSAccessLogForCloneAndPullHTTPS_doesNotSendEmailOnPullOperation () {
374373 HttpServletRequest request = mock (HttpServletRequest .class );
375374 when (request .getMethod ()).thenReturn ("POST" );
376- when (request .getRequestURI ()).thenReturn ("/git/TEST/EXERCISE -testuser.git/git-upload-pack" );
375+ when (request .getRequestURI ()).thenReturn ("/git/TEST/test -testuser.git/git-upload-pack" );
377376
378377 String password = "plain-password" ;
379378 String authHeader = "Basic " + java .util .Base64 .getEncoder ().encodeToString (("testuser:" + password ).getBytes ());
0 commit comments