From f6cf0d5681a0c60f003dc9ad00c07736e34a0f8c Mon Sep 17 00:00:00 2001 From: Frantisek Nagy Date: Mon, 5 Oct 2020 15:46:34 +0200 Subject: [PATCH] Make HttpException implement CopyableThrowable + add test --- .../main/java/retrofit2/KotlinExtensions.kt | 16 +++++- .../test/java/retrofit2/KotlinSuspendTest.kt | 56 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/retrofit/src/main/java/retrofit2/KotlinExtensions.kt b/retrofit/src/main/java/retrofit2/KotlinExtensions.kt index 6202abef76..202a061093 100644 --- a/retrofit/src/main/java/retrofit2/KotlinExtensions.kt +++ b/retrofit/src/main/java/retrofit2/KotlinExtensions.kt @@ -18,6 +18,7 @@ package retrofit2 +import kotlinx.coroutines.CopyableThrowable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED @@ -50,7 +51,7 @@ suspend fun Call.await(): T { continuation.resume(body) } } else { - continuation.resumeWithException(HttpException(response)) + continuation.resumeWithException(KotlinHttpException(response)) } } @@ -72,7 +73,7 @@ suspend fun Call.await(): T? { if (response.isSuccessful) { continuation.resume(response.body()) } else { - continuation.resumeWithException(HttpException(response)) + continuation.resumeWithException(KotlinHttpException(response)) } } @@ -117,3 +118,14 @@ internal suspend fun Exception.suspendAndThrow(): Nothing { COROUTINE_SUSPENDED } } + +private class KotlinHttpException( + private val response: Response<*> +) : HttpException(response), CopyableThrowable { + + override fun createCopy(): KotlinHttpException { + val result = KotlinHttpException(response) + result.initCause(this) + return result + } +} diff --git a/retrofit/src/test/java/retrofit2/KotlinSuspendTest.kt b/retrofit/src/test/java/retrofit2/KotlinSuspendTest.kt index 8c797cbb83..17b40cda04 100644 --- a/retrofit/src/test/java/retrofit2/KotlinSuspendTest.kt +++ b/retrofit/src/test/java/retrofit2/KotlinSuspendTest.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async +import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import okhttp3.OkHttpClient @@ -36,6 +37,9 @@ import retrofit2.helpers.ToStringConverterFactory import retrofit2.http.GET import retrofit2.http.Path import java.io.IOException +import java.io.PrintWriter +import java.io.StringWriter +import java.lang.Runnable import java.lang.reflect.ParameterizedType import java.lang.reflect.Type import kotlin.coroutines.CoroutineContext @@ -179,6 +183,58 @@ class KotlinSuspendTest { } } + @Test fun await404() { + val retrofit = Retrofit.Builder() + .baseUrl(server.url("/")) + .addConverterFactory(ToStringConverterFactory()) + .build() + val example = retrofit.create(Service::class.java) + + server.enqueue(MockResponse().setResponseCode(404)) + + try { + runBlocking { + val deferred = async { example.body() } + + deferred.await() + } + fail() + } catch (e: HttpException) { + val writer = StringWriter() + e.printStackTrace(PrintWriter(writer)) + val trace = writer.toString() + + assertThat(trace).contains("KotlinSuspendTest") + assertThat(trace).contains("await404") + } + } + + @Test fun launch404() { + val retrofit = Retrofit.Builder() + .baseUrl(server.url("/")) + .addConverterFactory(ToStringConverterFactory()) + .build() + val example = retrofit.create(Service::class.java) + + server.enqueue(MockResponse().setResponseCode(404)) + + try { + runBlocking { + val job = launch { example.body() } + + job.join() + } + fail() + } catch (e: HttpException) { + val writer = StringWriter() + e.printStackTrace(PrintWriter(writer)) + val trace = writer.toString() + + assertThat(trace).contains("KotlinSuspendTest") + assertThat(trace).contains("launch404") + } + } + @Test fun params() { val retrofit = Retrofit.Builder() .baseUrl(server.url("/"))