diff --git a/openai-java-core/src/main/kotlin/com/openai/core/http/WorkloadIdentityHttpClient.kt b/openai-java-core/src/main/kotlin/com/openai/core/http/WorkloadIdentityHttpClient.kt index 33ed86940..2107a4198 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/http/WorkloadIdentityHttpClient.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/http/WorkloadIdentityHttpClient.kt @@ -55,7 +55,18 @@ internal class WorkloadIdentityHttpClient( } override fun close() { - workloadIdentityAuth?.close() + try { + workloadIdentityAuth?.close() + } catch (authFailure: Throwable) { + try { + delegate.close() + } catch (delegateFailure: Throwable) { + if (delegateFailure !== authFailure) { + authFailure.addSuppressed(delegateFailure) + } + } + throw authFailure + } delegate.close() } } diff --git a/openai-java-core/src/test/kotlin/com/openai/core/http/WorkloadIdentityHttpClientTest.kt b/openai-java-core/src/test/kotlin/com/openai/core/http/WorkloadIdentityHttpClientTest.kt index 2efd06e13..d0de79f9d 100644 --- a/openai-java-core/src/test/kotlin/com/openai/core/http/WorkloadIdentityHttpClientTest.kt +++ b/openai-java-core/src/test/kotlin/com/openai/core/http/WorkloadIdentityHttpClientTest.kt @@ -10,10 +10,12 @@ import java.util.concurrent.ExecutionException import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.any import org.mockito.kotlin.argThat +import org.mockito.kotlin.doThrow import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @@ -134,6 +136,51 @@ internal class WorkloadIdentityHttpClientTest { ) } + @Test + fun close_closesAuthAndDelegate() { + val workloadIdentityAuth = mock() + val delegateHttpClient = mock() + val client = WorkloadIdentityHttpClient(delegateHttpClient, workloadIdentityAuth) + + client.close() + + verify(workloadIdentityAuth).close() + verify(delegateHttpClient).close() + } + + @Test + fun close_whenAuthCloseFails_stillClosesDelegate() { + val authFailure = IllegalStateException("auth close failed") + val workloadIdentityAuth = mock() + val delegateHttpClient = mock() + doThrow(authFailure).whenever(workloadIdentityAuth).close() + val client = WorkloadIdentityHttpClient(delegateHttpClient, workloadIdentityAuth) + + val thrown = assertThrows { client.close() } + + assertThat(thrown).isSameAs(authFailure) + verify(workloadIdentityAuth).close() + verify(delegateHttpClient).close() + } + + @Test + fun close_whenAuthAndDelegateCloseFail_suppressesDelegateFailure() { + val authFailure = IllegalStateException("auth close failed") + val delegateFailure = IllegalArgumentException("delegate close failed") + val workloadIdentityAuth = mock() + val delegateHttpClient = mock() + doThrow(authFailure).whenever(workloadIdentityAuth).close() + doThrow(delegateFailure).whenever(delegateHttpClient).close() + val client = WorkloadIdentityHttpClient(delegateHttpClient, workloadIdentityAuth) + + val thrown = assertThrows { client.close() } + + assertThat(thrown).isSameAs(authFailure) + assertThat(thrown.suppressed).containsExactly(delegateFailure) + verify(workloadIdentityAuth).close() + verify(delegateHttpClient).close() + } + private fun mockResponse(statusCode: Int, body: String): HttpResponse { return object : HttpResponse { override fun statusCode() = statusCode