|
21 | 21 | import java.time.Instant;
|
22 | 22 | import java.time.format.DateTimeFormatter;
|
23 | 23 | 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.*; |
28 | 25 | import java.util.concurrent.CompletableFuture;
|
29 | 26 | import java.util.concurrent.ExecutionException;
|
30 | 27 |
|
@@ -631,6 +628,103 @@ void managedIdentityTest_IMDSRetry() throws Exception {
|
631 | 628 | fail("MsalServiceException is expected but not thrown.");
|
632 | 629 | }
|
633 | 630 |
|
| 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 | + |
634 | 728 | @ParameterizedTest
|
635 | 729 | @MethodSource("com.microsoft.aad.msal4j.ManagedIdentityTestDataProvider#createDataError")
|
636 | 730 | void managedIdentity_RequestFailed_NoPayload(ManagedIdentitySourceType source, String endpoint) throws Exception {
|
|
0 commit comments