Merge pull request 'Use Forgejo releases for Wolfskin updates and match installed versions consistently' (#20) from fm/wolfskin-5-updater-gpt into main

This commit is contained in:
justinzeus 2026-10-22 16:13:20 +02:00
commit 761a5a6145
7 changed files with 314 additions and 70 deletions

View file

@ -1,11 +1,16 @@
package com.github.damontecres.wholphin.test
import com.github.damontecres.wholphin.services.UpdateChecker
import com.github.damontecres.wholphin.services.getDownloadUrl
import com.github.damontecres.wholphin.util.Version
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -19,71 +24,151 @@ class TestUpdateChecker {
lateinit var releaseV108Json: JsonObject
val assetsV108Json: JsonArray by lazy { releaseV108Json["assets"]!!.jsonArray }
private fun read(filename: String): JsonObject {
private val forgejoLatest: JsonObject by lazy { read("forgejo_release_latest.json") }
private val forgejoAssets: JsonArray by lazy { forgejoLatest["assets"]!!.jsonArray }
private val forgejoReleases: JsonArray by lazy { readElement("forgejo_releases.json").jsonArray }
private val suffixedAssets: JsonArray by lazy { read("forgejo_release_suffixed.json")["assets"]!!.jsonArray }
private fun readElement(filename: String): JsonElement {
val resource = javaClass.classLoader?.getResource(filename)
Assert.assertNotNull(resource)
val fileContents = Paths.get(resource!!.toURI()).readText()
return Json.parseToJsonElement(fileContents).jsonObject
return Json.parseToJsonElement(fileContents)
}
private fun read(filename: String): JsonObject = readElement(filename).jsonObject
private fun forgejoDownload(name: String) =
"https://git.justinvisser.org/justinzeus/wolfskin/releases/download/pwolfskin-v1.0.9-2-g3094fc8c/$name"
@Before
fun setup() {
releaseJson = read("release_develop.json")
}
// The GitHub fixtures are upstream Wholphin releases: their assets are named Wholphin*.apk, which
// the Wolfskin updater must not select.
@Test
fun `Release chooses release`() {
fun `Release does not choose upstream Wholphin assets`() {
val url = getDownloadUrl(assetsJson, false, listOf())
Assert.assertEquals("https://github.com/damontecres/Wholphin/releases/download/develop/Wholphin-release.apk", url)
Assert.assertNull(url)
}
@Test
fun `Choose abi`() {
fun `Choose abi does not choose upstream Wholphin assets`() {
val url = getDownloadUrl(assetsJson, false, listOf("arm64-v8a"))
Assert.assertEquals("https://github.com/damontecres/Wholphin/releases/download/develop/Wholphin-release-arm64-v8a.apk", url)
Assert.assertNull(url)
}
@Test
fun `Choose unknown abi`() {
fun `Choose unknown abi does not choose upstream Wholphin assets`() {
val url = getDownloadUrl(assetsJson, false, listOf("unknown"))
Assert.assertEquals("https://github.com/damontecres/Wholphin/releases/download/develop/Wholphin-release.apk", url)
Assert.assertNull(url)
}
@Test
fun `Debug chooses debug`() {
fun `Debug does not choose upstream Wholphin assets`() {
val url = getDownloadUrl(assetsJson, true, listOf())
Assert.assertEquals("https://github.com/damontecres/Wholphin/releases/download/develop/Wholphin-debug.apk", url)
Assert.assertNull(url)
}
@Test
fun `Choose debug abi`() {
fun `Choose debug abi does not choose upstream Wholphin assets`() {
val url = getDownloadUrl(assetsJson, true, listOf("arm64-v8a"))
Assert.assertEquals("https://github.com/damontecres/Wholphin/releases/download/develop/Wholphin-debug-arm64-v8a.apk", url)
Assert.assertNull(url)
}
@Test
fun `Test regular release`() {
fun `Test regular release does not choose upstream Wholphin assets`() {
releaseV108Json = read("release_v108.json")
getDownloadUrl(assetsV108Json, false, listOf("arm64-v8a")).let { url ->
Assert.assertEquals(
"https://github.com/damontecres/Wholphin/releases/download/v1.0.8/Wholphin-arm64-v8a.apk",
url,
)
Assert.assertNull(getDownloadUrl(assetsV108Json, false, listOf("arm64-v8a")))
Assert.assertNull(getDownloadUrl(assetsV108Json, false, listOf("armeabi-v7a")))
Assert.assertNull(getDownloadUrl(assetsV108Json, false, emptyList()))
Assert.assertNull(getDownloadUrl(assetsV108Json, true, listOf("arm64-v8a")))
}
@Test
fun `Parse Forgejo latest release`() {
val release = UpdateChecker.parseRelease(forgejoLatest, debug = false, supportedABIs = listOf("arm64-v8a"))
checkNotNull(release)
Assert.assertEquals(Version.fromString("v1.0.9-2-g3094fc8c"), release.version)
Assert.assertEquals(forgejoDownload("Wolfskin-arm64-v8a.apk"), release.downloadUrl)
Assert.assertEquals("2026-10-20T09:05:00Z", release.publishedAt)
Assert.assertEquals(listOf("Subtitle preference fix"), release.notes)
}
@Test
fun `Choose Wolfskin asset for abi`() {
Assert.assertEquals(forgejoDownload("Wolfskin-arm64-v8a.apk"), getDownloadUrl(forgejoAssets, false, listOf("arm64-v8a")))
Assert.assertEquals(forgejoDownload("Wolfskin-armeabi-v7a.apk"), getDownloadUrl(forgejoAssets, false, listOf("armeabi-v7a")))
}
@Test
fun `Choose universal Wolfskin asset for unknown abi`() {
Assert.assertEquals(forgejoDownload("Wolfskin.apk"), getDownloadUrl(forgejoAssets, false, listOf("unknown")))
Assert.assertEquals(forgejoDownload("Wolfskin.apk"), getDownloadUrl(forgejoAssets, false, emptyList()))
}
@Test
fun `Debug asset is not offered when release has none`() {
Assert.assertNull(getDownloadUrl(forgejoAssets, true, listOf("arm64-v8a")))
}
@Test
fun `Choose debug ABI before universal and fall back for missing ABI`() {
for ((abis, name) in listOf(
listOf("arm64-v8a") to "Wolfskin-debug-arm64-v8a.apk",
listOf("unknown") to "Wolfskin-debug.apk",
emptyList<String>() to "Wolfskin-debug.apk",
)) {
Assert.assertEquals(forgejoDownload(name), getDownloadUrl(suffixedAssets, true, abis))
}
getDownloadUrl(assetsV108Json, false, listOf("armeabi-v7a")).let { url ->
Assert.assertEquals(
"https://github.com/damontecres/Wholphin/releases/download/v1.0.8/Wholphin-armeabi-v7a.apk",
url,
)
}
getDownloadUrl(assetsV108Json, false, emptyList()).let { url ->
Assert.assertEquals(
"https://github.com/damontecres/Wholphin/releases/download/v1.0.8/Wholphin.apk",
url,
)
}
getDownloadUrl(assetsV108Json, true, listOf("arm64-v8a")).let { url ->
Assert.assertNull(url)
}
@Test
fun `Choose release suffixed ABI before universal and unsuffixed assets`() {
val assets = JsonArray(forgejoAssets + suffixedAssets)
for ((abis, name) in listOf(
listOf("arm64-v8a") to "Wolfskin-release-arm64-v8a.apk",
listOf("armeabi-v7a") to "Wolfskin-release.apk",
emptyList<String>() to "Wolfskin-release.apk",
)) {
Assert.assertEquals(forgejoDownload(name), getDownloadUrl(assets, false, abis))
}
}
@Test
fun `Release and debug assets do not cross build types`() {
val debugAssets = JsonArray(suffixedAssets.filter { it.jsonObject["name"]!!.jsonPrimitive.content.contains("-debug") })
val releaseAssets = JsonArray(suffixedAssets.filter { it.jsonObject["name"]!!.jsonPrimitive.content.contains("-release") })
Assert.assertNull(getDownloadUrl(debugAssets, false, listOf("arm64-v8a")))
Assert.assertNull(getDownloadUrl(releaseAssets, true, listOf("arm64-v8a")))
}
@Test
fun `Find installed version in release list`() {
val release = UpdateChecker.findReleaseByVersion(forgejoReleases, Version.fromString("1.0.9-2-g3094fc8c"))
Assert.assertEquals("v1.0.9-2-g3094fc8c", release?.get("name")?.jsonPrimitive?.content)
}
@Test
fun `Find release with different hash abbreviation length`() {
val release = UpdateChecker.findReleaseByVersion(forgejoReleases, Version.fromString("1.0.9-2-g3094fc8"))
Assert.assertEquals("v1.0.9-2-g3094fc8c", release?.get("name")?.jsonPrimitive?.content)
}
@Test
fun `Find release with absent or zero commit count`() {
val release = UpdateChecker.findReleaseByVersion(forgejoReleases, Version.fromString("1.0.10"))
Assert.assertEquals("v1.0.10-0-gfeedbee", release?.get("name")?.jsonPrimitive?.content)
val plainRelease = JsonObject(forgejoReleases.first().jsonObject + ("name" to JsonPrimitive("v1.0.10")))
val plainReleases = JsonArray(listOf(plainRelease))
Assert.assertEquals(plainReleases.first(), UpdateChecker.findReleaseByVersion(plainReleases, Version.fromString("1.0.10-0-gfeedbee")))
}
@Test
fun `Find no release for version missing from list`() {
Assert.assertNull(UpdateChecker.findReleaseByVersion(forgejoReleases, Version.fromString("1.0.9-3-gffffff")))
}
}