Skip to content

Commit 2dc552a

Browse files
committed
Cover more edge cases
1 parent a2b3eae commit 2dc552a

File tree

1 file changed

+98
-4
lines changed

1 file changed

+98
-4
lines changed

msal4j-sdk/src/test/java/com/microsoft/aad/msal4j/ManagedIdentityTests.java

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@
2121
import java.time.Instant;
2222
import java.time.format.DateTimeFormatter;
2323
import java.time.temporal.ChronoUnit;
24-
import java.util.Collections;
25-
import java.util.HashMap;
26-
import java.util.List;
27-
import java.util.Map;
24+
import java.util.*;
2825
import java.util.concurrent.CompletableFuture;
2926
import java.util.concurrent.ExecutionException;
3027

@@ -631,6 +628,103 @@ void managedIdentityTest_IMDSRetry() throws Exception {
631628
fail("MsalServiceException is expected but not thrown.");
632629
}
633630

631+
@Test
632+
void managedIdentityTest_RetrySucceedsAfterFailure() throws Exception {
633+
IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper(IMDS, ManagedIdentityTestConstants.IMDS_ENDPOINT);
634+
ManagedIdentityApplication.setEnvironmentVariables(environmentVariables);
635+
636+
DefaultHttpClientManagedIdentity httpClientMock = mock(DefaultHttpClientManagedIdentity.class);
637+
638+
miApp = ManagedIdentityApplication
639+
.builder(ManagedIdentityId.systemAssigned())
640+
.httpClient(httpClientMock)
641+
.build();
642+
643+
// First call returns 500, subsequent calls return 200
644+
when(httpClientMock.send(expectedRequest(IMDS, ManagedIdentityTestConstants.RESOURCE)))
645+
.thenReturn(expectedResponse(500, ManagedIdentityTestConstants.MSI_ERROR_RESPONSE_500))
646+
.thenReturn(expectedResponse(200, getSuccessfulResponse(ManagedIdentityTestConstants.RESOURCE)));
647+
648+
IAuthenticationResult result = acquireTokenCommon(ManagedIdentityTestConstants.RESOURCE).get();
649+
650+
assertTokenFromIdentityProvider(result);
651+
assertNotNull(result.accessToken());
652+
653+
// Verify that the client was called exactly twice (first attempt + one retry)
654+
verify(httpClientMock, times(2)).send(any());
655+
}
656+
657+
@Test
658+
void managedIdentityTest_NonRetryableError() throws Exception {
659+
IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper(IMDS, ManagedIdentityTestConstants.IMDS_ENDPOINT);
660+
ManagedIdentityApplication.setEnvironmentVariables(environmentVariables);
661+
662+
DefaultHttpClientManagedIdentity httpClientMock = mock(DefaultHttpClientManagedIdentity.class);
663+
664+
miApp = ManagedIdentityApplication
665+
.builder(ManagedIdentityId.systemAssigned())
666+
.httpClient(httpClientMock)
667+
.build();
668+
669+
// Use a status code that doesn't trigger retries (499)
670+
when(httpClientMock.send(expectedRequest(IMDS, ManagedIdentityTestConstants.RESOURCE)))
671+
.thenReturn(expectedResponse(499, ManagedIdentityTestConstants.MSI_ERROR_RESPONSE_NORETRY));
672+
673+
CompletableFuture<IAuthenticationResult> future = acquireTokenCommon(ManagedIdentityTestConstants.RESOURCE);
674+
675+
// Verify that an exception is thrown
676+
ExecutionException ex = assertThrows(ExecutionException.class, future::get);
677+
assertInstanceOf(MsalServiceException.class, ex.getCause());
678+
679+
MsalServiceException msalException = (MsalServiceException) ex.getCause();
680+
assertEquals(MsalError.MANAGED_IDENTITY_REQUEST_FAILED, msalException.errorCode());
681+
682+
// Verify the client was called exactly once (no retries attempted)
683+
verify(httpClientMock, times(1)).send(any());
684+
}
685+
686+
@Test
687+
void managedIdentityTest_RetriesARePerRequest() throws Exception {
688+
IEnvironmentVariables environmentVariables = new EnvironmentVariablesHelper(IMDS, ManagedIdentityTestConstants.IMDS_ENDPOINT);
689+
ManagedIdentityApplication.setEnvironmentVariables(environmentVariables);
690+
691+
DefaultHttpClientManagedIdentity httpClientMock = mock(DefaultHttpClientManagedIdentity.class);
692+
693+
miApp = ManagedIdentityApplication
694+
.builder(ManagedIdentityId.systemAssigned())
695+
.httpClient(httpClientMock)
696+
.build();
697+
698+
// First call returns 500, subsequent calls return 200
699+
when(httpClientMock.send(expectedRequest(IMDS, ManagedIdentityTestConstants.RESOURCE)))
700+
.thenReturn(expectedResponse(500, ManagedIdentityTestConstants.MSI_ERROR_RESPONSE_500))
701+
.thenReturn(expectedResponse(200, getSuccessfulResponse(ManagedIdentityTestConstants.RESOURCE)));
702+
703+
IAuthenticationResult result = acquireTokenCommon(ManagedIdentityTestConstants.RESOURCE).get();
704+
705+
assertTokenFromIdentityProvider(result);
706+
assertNotNull(result.accessToken());
707+
708+
// Verify that the client was called exactly twice (first attempt + one retry)
709+
verify(httpClientMock, times(2)).send(any());
710+
711+
//All calls return 500
712+
when(httpClientMock.send(expectedRequest(IMDS, "otherResource")))
713+
.thenReturn(expectedResponse(500, ManagedIdentityTestConstants.MSI_ERROR_RESPONSE_500));
714+
715+
CompletableFuture<IAuthenticationResult> future = acquireTokenCommon("otherResource");
716+
717+
// Verify that an exception is thrown
718+
ExecutionException ex = assertThrows(ExecutionException.class, future::get);
719+
assertInstanceOf(MsalServiceException.class, ex.getCause());
720+
721+
MsalServiceException msalException = (MsalServiceException) ex.getCause();
722+
assertEquals(MsalError.MANAGED_IDENTITY_REQUEST_FAILED, msalException.errorCode());
723+
724+
// Verify that the client was called four more times (new first attempt + three new retries)
725+
verify(httpClientMock, times(6)).send(any());
726+
}
727+
634728
@ParameterizedTest
635729
@MethodSource("com.microsoft.aad.msal4j.ManagedIdentityTestDataProvider#createDataError")
636730
void managedIdentity_RequestFailed_NoPayload(ManagedIdentitySourceType source, String endpoint) throws Exception {

0 commit comments

Comments
 (0)