Skip to content

Commit 496f20c

Browse files
authored
refactor(server): do not leak cache in tests (#1933)
Thanks to this, the test aren't aware of an implementation detail of the server: the cache. We wrap the whole server config in an `appModule`, and inject a piece of logic exposed by `maven-binding-builder` Gradle module. This piece is the only thing we need to mock right now in the test. It makes the test less brittle and couple with the implementation (although some necessary coupling is still there).
1 parent e7ea040 commit 496f20c

File tree

3 files changed

+41
-46
lines changed

3 files changed

+41
-46
lines changed

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/ArtifactRoutes.kt

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
package io.github.typesafegithub.workflows.jitbindingserver
22

3-
import com.github.benmanes.caffeine.cache.Caffeine
43
import com.sksamuel.aedile.core.LoadingCache
5-
import com.sksamuel.aedile.core.asLoadingCache
6-
import com.sksamuel.aedile.core.refreshAfterWrite
74
import io.github.oshai.kotlinlogging.KotlinLogging.logger
85
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
96
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.prettyPrint
107
import io.github.typesafegithub.workflows.mavenbinding.Artifact
118
import io.github.typesafegithub.workflows.mavenbinding.JarArtifact
129
import io.github.typesafegithub.workflows.mavenbinding.TextArtifact
13-
import io.github.typesafegithub.workflows.mavenbinding.buildVersionArtifacts
1410
import io.ktor.http.ContentType
1511
import io.ktor.http.HttpStatusCode
1612
import io.ktor.server.application.ApplicationCall
@@ -28,23 +24,13 @@ import io.micrometer.prometheusmetrics.PrometheusMeterRegistry
2824
import kotlinx.coroutines.CoroutineScope
2925
import kotlinx.coroutines.Dispatchers
3026
import kotlinx.coroutines.launch
31-
import kotlin.time.Duration.Companion.hours
3227

3328
private val logger = logger { }
3429

3530
typealias ArtifactResult = Result<Map<String, Artifact>?>
3631

3732
private val prefetchScope = CoroutineScope(Dispatchers.IO)
3833

39-
internal fun buildBindingsCache(
40-
buildVersionArtifacts: (ActionCoords) -> Map<String, Artifact>? = ::buildVersionArtifacts,
41-
): LoadingCache<ActionCoords, ArtifactResult> =
42-
Caffeine
43-
.newBuilder()
44-
.refreshAfterWrite(1.hours)
45-
.recordStats()
46-
.asLoadingCache<ActionCoords, ArtifactResult> { runCatching { buildVersionArtifacts(it) } }
47-
4834
fun Routing.artifactRoutes(
4935
bindingsCache: LoadingCache<ActionCoords, ArtifactResult>,
5036
prometheusRegistry: PrometheusMeterRegistry? = null,

jit-binding-server/src/main/kotlin/io/github/typesafegithub/workflows/jitbindingserver/Main.kt

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package io.github.typesafegithub.workflows.jitbindingserver
22

3+
import com.github.benmanes.caffeine.cache.Caffeine
4+
import com.sksamuel.aedile.core.LoadingCache
5+
import com.sksamuel.aedile.core.asLoadingCache
6+
import com.sksamuel.aedile.core.refreshAfterWrite
37
import io.github.oshai.kotlinlogging.KotlinLogging.logger
8+
import io.github.typesafegithub.workflows.actionbindinggenerator.domain.ActionCoords
9+
import io.github.typesafegithub.workflows.mavenbinding.Artifact
10+
import io.github.typesafegithub.workflows.mavenbinding.buildVersionArtifacts
411
import io.ktor.http.HttpStatusCode
12+
import io.ktor.server.application.Application
513
import io.ktor.server.application.ApplicationCall
614
import io.ktor.server.engine.embeddedServer
715
import io.ktor.server.netty.Netty
@@ -10,6 +18,7 @@ import io.ktor.server.routing.routing
1018
import io.micrometer.prometheusmetrics.PrometheusConfig
1119
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry
1220
import java.time.Duration
21+
import kotlin.time.Duration.Companion.hours
1322

1423
private val prometheusRegistry =
1524
PrometheusMeterRegistry(
@@ -38,19 +47,32 @@ fun main() {
3847
Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
3948
logger.error(throwable) { "Uncaught exception in thread $thread" }
4049
}
41-
val bindingsCache = buildBindingsCache()
4250
embeddedServer(Netty, port = 8080) {
43-
installPlugins(prometheusRegistry)
51+
appModule(buildVersionArtifacts = ::buildVersionArtifacts)
52+
}.start(wait = true)
53+
}
4454

45-
routing {
46-
internalRoutes(prometheusRegistry)
55+
fun Application.appModule(buildVersionArtifacts: (ActionCoords) -> Map<String, Artifact>?) {
56+
val bindingsCache = buildBindingsCache(buildVersionArtifacts)
57+
installPlugins(prometheusRegistry)
4758

48-
artifactRoutes(bindingsCache, prometheusRegistry)
49-
metadataRoutes(bindingsCache, prometheusRegistry)
50-
}
51-
}.start(wait = true)
59+
routing {
60+
internalRoutes(prometheusRegistry)
61+
62+
artifactRoutes(bindingsCache, prometheusRegistry)
63+
metadataRoutes(bindingsCache, prometheusRegistry)
64+
}
5265
}
5366

67+
private fun buildBindingsCache(
68+
buildVersionArtifacts: (ActionCoords) -> Map<String, Artifact>?,
69+
): LoadingCache<ActionCoords, ArtifactResult> =
70+
Caffeine
71+
.newBuilder()
72+
.refreshAfterWrite(1.hours)
73+
.recordStats()
74+
.asLoadingCache<ActionCoords, ArtifactResult> { runCatching { buildVersionArtifacts(it) } }
75+
5476
val deliverOnRefreshRoute = System.getenv("GWKT_DELIVER_ON_REFRESH").toBoolean()
5577

5678
suspend fun ApplicationCall.respondNotFound() = respondText(text = "Not found", status = HttpStatusCode.NotFound)

jit-binding-server/src/test/kotlin/io/github/typesafegithub/workflows/jitbindingserver/ArtifactRoutesTest.kt

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import io.kotest.matchers.shouldBe
66
import io.ktor.client.request.get
77
import io.ktor.client.statement.bodyAsText
88
import io.ktor.http.HttpStatusCode
9-
import io.ktor.server.routing.routing
109
import io.ktor.server.testing.testApplication
1110

1211
class ArtifactRoutesTest :
@@ -16,15 +15,11 @@ class ArtifactRoutesTest :
1615
testApplication {
1716
// Given
1817
application {
19-
routing {
20-
artifactRoutes(
21-
buildBindingsCache(
22-
buildVersionArtifacts = {
23-
mapOf("some-action-v4.pom" to TextArtifact { "Some POM contents" })
24-
},
25-
),
26-
)
27-
}
18+
appModule(
19+
buildVersionArtifacts = {
20+
mapOf("some-action-v4.pom" to TextArtifact { "Some POM contents" })
21+
},
22+
)
2823
}
2924

3025
// When
@@ -40,13 +35,9 @@ class ArtifactRoutesTest :
4035
testApplication {
4136
// Given
4237
application {
43-
routing {
44-
artifactRoutes(
45-
buildBindingsCache(
46-
buildVersionArtifacts = { null },
47-
),
48-
)
49-
}
38+
appModule(
39+
buildVersionArtifacts = { null },
40+
)
5041
}
5142

5243
// When
@@ -61,13 +52,9 @@ class ArtifactRoutesTest :
6152
testApplication {
6253
// Given
6354
application {
64-
routing {
65-
artifactRoutes(
66-
buildBindingsCache(
67-
buildVersionArtifacts = { error("An internal error occurred!") },
68-
),
69-
)
70-
}
55+
appModule(
56+
buildVersionArtifacts = { error("An internal error occurred!") },
57+
)
7158
}
7259

7360
// When

0 commit comments

Comments
 (0)