1package soy.iko.opencode.data.network
3import io.ktor.client.HttpClient
4import io.ktor.client.engine.mock.MockEngine
5import io.ktor.client.engine.mock.respond
6import io.ktor.client.plugins.ClientRequestException
7import io.ktor.client.plugins.ServerResponseException
8import io.ktor.client.request.get
9import io.ktor.http.HttpStatusCode
10import io.ktor.http.headersOf
11import kotlinx.coroutines.CancellationException
12import kotlinx.coroutines.test.runTest
13import org.junit.Assert.assertEquals
14import org.junit.Assert.assertTrue
16import java.io.IOException
20 /** Produce the real exception Ktor throws for a status when expectSuccess = true. */
21 private suspend fun httpError(status: HttpStatusCode): Throwable {
22 val client = HttpClient(MockEngine { respond("", status, headersOf("Content-Length", "0")) }) {
25 return client.use { runCatching { it.get("test") }.exceptionOrNull()!! }
29 fun returnsValueOnFirstAttempt() = runTest {
31 val result = withRetryInternal { calls++; "ok" }
32 assertEquals("ok", result)
33 assertEquals(1, calls)
37 fun retriesTransientFailureThenSucceeds() = runTest {
39 val result = withRetryInternal(initialDelayMs = 0) {
41 if (calls < 3) throw IOException("boom")
44 assertEquals("ok", result)
45 assertEquals(3, calls)
49 fun throwsAfterExhaustingAttempts() = runTest {
51 val error = runCatching {
52 withRetryInternal(maxAttempts = 3, initialDelayMs = 0) {
54 throw IOException("always")
57 assertTrue("expected IOException, got $error", error is IOException)
58 assertEquals(3, calls)
62 fun clientErrorIsNotRetried() = runTest {
63 val notFound = httpError(HttpStatusCode.NotFound)
64 assertTrue("expected ClientRequestException, got $notFound", notFound is ClientRequestException)
66 val error = runCatching {
67 withRetryInternal(initialDelayMs = 0) {
72 assertEquals("4xx must not be retried", 1, calls)
73 assertTrue(error is ClientRequestException)
77 fun serverErrorIsRetried() = runTest {
78 val serverError = httpError(HttpStatusCode.InternalServerError)
79 assertTrue("expected ServerResponseException, got $serverError", serverError is ServerResponseException)
82 withRetryInternal(maxAttempts = 3, initialDelayMs = 0) {
87 assertEquals("5xx must be retried", 3, calls)
91 fun cancellationIsRethrownImmediately() = runTest {
93 val error = runCatching {
94 withRetryInternal(initialDelayMs = 0) {
96 throw CancellationException("cancel")
99 assertEquals("cancellation must not be retried", 1, calls)
100 assertTrue("expected CancellationException, got $error", error is CancellationException)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list