mirror of
https://github.com/okhsunrog/vpnhide.git
synced 2026-08-20 05:53:51 +00:00
refactor(lsposed): parse KPM status into typed model
This commit is contained in:
parent
1b3f3d8f02
commit
f0dcf80ef2
7 changed files with 183 additions and 67 deletions
|
|
@ -134,15 +134,9 @@ internal fun classifyMultiNative(
|
|||
* redundant state worth warning about so the user removes one.
|
||||
*/
|
||||
internal fun kpmDeferredForConflict(
|
||||
loadStatusSection: String,
|
||||
status: KpmLoadStatus,
|
||||
currentBootId: String,
|
||||
): Boolean {
|
||||
val load = parseKeyValueLines(loadStatusSection)
|
||||
val bootId = load["boot_id"]?.trim()
|
||||
return load["runtime"]?.trim() == "conflict" &&
|
||||
!bootId.isNullOrEmpty() &&
|
||||
bootId == currentBootId.trim()
|
||||
}
|
||||
): Boolean = status.runtime == KpmRuntime.Conflict && status.isFreshFor(currentBootId)
|
||||
|
||||
/**
|
||||
* True when the KPM boot script stood down this boot because it runs under
|
||||
|
|
@ -156,17 +150,13 @@ internal fun kpmDeferredForConflict(
|
|||
* would just show KPM as inactive with no explanation.
|
||||
*/
|
||||
internal fun kpmAwaitingSuperkey(
|
||||
loadStatusSection: String,
|
||||
status: KpmLoadStatus,
|
||||
currentBootId: String,
|
||||
): Boolean {
|
||||
val load = parseKeyValueLines(loadStatusSection)
|
||||
val bootId = load["boot_id"]?.trim()
|
||||
return load["runtime"]?.trim() == "apatch" &&
|
||||
load["loaded"]?.trim() == "0" &&
|
||||
load["detail"]?.trim() == "awaiting_superkey" &&
|
||||
!bootId.isNullOrEmpty() &&
|
||||
bootId == currentBootId.trim()
|
||||
}
|
||||
): Boolean =
|
||||
status.runtime == KpmRuntime.Apatch &&
|
||||
status.loaded == false &&
|
||||
status.reason == KpmFailureReason.AwaitingSuperkey &&
|
||||
status.isFreshFor(currentBootId)
|
||||
|
||||
internal fun kpatchRuntimeAvailable(kpatchRuntimeSection: String): Boolean {
|
||||
val props = parseKeyValueLines(kpatchRuntimeSection)
|
||||
|
|
@ -918,6 +908,7 @@ internal fun detectZygiskModule(
|
|||
|
||||
internal fun detectKpmModule(
|
||||
sections: Map<String, String>,
|
||||
loadStatus: KpmLoadStatus,
|
||||
currentBootId: String,
|
||||
): ModuleState {
|
||||
val prop = parseModuleProp(sections["kpm_prop"].orEmpty())
|
||||
|
|
@ -926,9 +917,7 @@ internal fun detectKpmModule(
|
|||
// supercall). The boot script writes load_status with loaded=1 and the
|
||||
// boot_id it loaded under, so "active" = loaded for the current boot —
|
||||
// the same freshness check the zygisk heartbeat uses.
|
||||
val load = parseKeyValueLines(sections["kpm_load_status"].orEmpty())
|
||||
val bootId = load["boot_id"]?.trim()
|
||||
val active = load["loaded"]?.trim() == "1" && bootId != null && bootId == currentBootId.trim()
|
||||
val active = loadStatus.loaded == true && loadStatus.isFreshFor(currentBootId)
|
||||
return ModuleState.Installed(
|
||||
version = prop.version,
|
||||
active = active,
|
||||
|
|
@ -1191,8 +1180,14 @@ internal suspend fun loadDashboardState(
|
|||
// brokenReason is layered on below, once the kernel recommendation and
|
||||
// load status are known (classifyKmodProblem).
|
||||
val currentBootId = shellSnapshot["current_boot_id"].orEmpty()
|
||||
val kpmLoadStatus = parseKpmLoadStatus(shellSnapshot["kpm_load_status"].orEmpty())
|
||||
val nativeTargetCount = countPackages(targetsSnapshot.nativeTargets)
|
||||
val rawNativeBackends = detectNativeBackendStates(shellSnapshot, currentBootId = currentBootId)
|
||||
val rawNativeBackends =
|
||||
detectNativeBackendStates(
|
||||
shellSnapshot,
|
||||
currentBootId = currentBootId,
|
||||
kpmLoadStatus = kpmLoadStatus,
|
||||
)
|
||||
val kmodRaw = rawNativeBackends.kmod
|
||||
val zygiskStatusRaw = shellSnapshot["zygisk_status"].orEmpty()
|
||||
val zygisk = rawNativeBackends.zygisk
|
||||
|
|
@ -1241,7 +1236,7 @@ internal suspend fun loadDashboardState(
|
|||
// runtime=activator failure cases classifyKpmProblem diagnoses (the
|
||||
// conflict / awaiting-superkey cases stay separate warnings below).
|
||||
val kpmProblem: ModuleProblem? =
|
||||
classifyKpmProblem(kpmRaw, shellSnapshot["kpm_load_status"].orEmpty(), currentBootId)
|
||||
classifyKpmProblem(kpmRaw, kpmLoadStatus, currentBootId)
|
||||
?.let { renderKpmProblem(it, res) }
|
||||
val kpm: ModuleState =
|
||||
if (kpmRaw is ModuleState.Installed && kpmProblem?.reason != null) {
|
||||
|
|
@ -1545,7 +1540,7 @@ internal suspend fun loadDashboardState(
|
|||
// kernel hookers freeze the device). The KPM standing down for a
|
||||
// co-installed .ko is the real state to surface — warn so the user
|
||||
// removes one of the two kernel backends.
|
||||
if (kpmDeferredForConflict(shellSnapshot["kpm_load_status"].orEmpty(), currentBootId)) {
|
||||
if (kpmDeferredForConflict(kpmLoadStatus, currentBootId)) {
|
||||
warn(res.getString(R.string.dashboard_issue_native_conflict_deferred))
|
||||
}
|
||||
}
|
||||
|
|
@ -1555,7 +1550,7 @@ internal suspend fun loadDashboardState(
|
|||
// trusted `su` token nor a saved SuperKey was usable. Without this the module
|
||||
// just reads as inactive with no reason.
|
||||
if (kpm is ModuleState.Installed &&
|
||||
kpmAwaitingSuperkey(shellSnapshot["kpm_load_status"].orEmpty(), currentBootId)
|
||||
kpmAwaitingSuperkey(kpmLoadStatus, currentBootId)
|
||||
) {
|
||||
warn(res.getString(R.string.dashboard_issue_kpm_awaiting_superkey))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,27 +30,22 @@ internal sealed interface KpmProblemKind {
|
|||
/** Diagnose a complete KPM installation that failed in either boot path. */
|
||||
internal fun classifyKpmProblem(
|
||||
kpm: ModuleState,
|
||||
loadStatusSection: String,
|
||||
status: KpmLoadStatus,
|
||||
currentBootId: String,
|
||||
): KpmProblemKind? {
|
||||
if (kpm !is ModuleState.Installed || kpm.active) return null
|
||||
val load = parseKeyValueLines(loadStatusSection)
|
||||
val bootId = load["boot_id"]?.trim()
|
||||
val runtime = load["runtime"]?.trim()
|
||||
if (runtime !in setOf("activator", "kpatch-next") ||
|
||||
load["loaded"]?.trim() != "0" ||
|
||||
bootId.isNullOrEmpty() ||
|
||||
bootId != currentBootId.trim()
|
||||
if (status.runtime !in setOf(KpmRuntime.Activator, KpmRuntime.KpatchNext) ||
|
||||
status.loaded != false ||
|
||||
!status.isFreshFor(currentBootId)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
val reason = load["reason"]?.trim()
|
||||
if (reason == "unsupported_kernel") {
|
||||
return KpmProblemKind.UnsupportedKernel(load["uname_r"]?.trim().orEmpty().ifBlank { "?" })
|
||||
if (status.reason == KpmFailureReason.UnsupportedKernel) {
|
||||
return KpmProblemKind.UnsupportedKernel(status.unameR ?: "?")
|
||||
}
|
||||
val detail = load["detail"]?.trim().orEmpty()
|
||||
val detail = status.detail.orEmpty()
|
||||
val missingPrefix = "activator missing at "
|
||||
return if (reason == "missing_activator" || detail.startsWith(missingPrefix)) {
|
||||
return if (status.reason == KpmFailureReason.MissingActivator || detail.startsWith(missingPrefix)) {
|
||||
KpmProblemKind.ActivatorMissing(detail.removePrefix(missingPrefix))
|
||||
} else {
|
||||
KpmProblemKind.LoadFailed(detail)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
package dev.okhsunrog.vpnhide
|
||||
|
||||
internal enum class KpmRuntime {
|
||||
Activator,
|
||||
KpatchNext,
|
||||
Apatch,
|
||||
Conflict,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
internal enum class KpmFailureReason {
|
||||
Ok,
|
||||
ConflictingBackend,
|
||||
MissingKpm,
|
||||
MissingActivator,
|
||||
AwaitingSuperkey,
|
||||
UnsupportedKernel,
|
||||
ActivationFailed,
|
||||
LoadFailed,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
internal data class KpmLoadStatus(
|
||||
val timestamp: Long?,
|
||||
val bootId: String?,
|
||||
val unameR: String?,
|
||||
val runtime: KpmRuntime,
|
||||
val loaded: Boolean?,
|
||||
val reason: KpmFailureReason,
|
||||
val detail: String?,
|
||||
) {
|
||||
fun isFreshFor(currentBootId: String): Boolean = !bootId.isNullOrEmpty() && bootId == currentBootId.trim()
|
||||
}
|
||||
|
||||
internal fun parseKpmLoadStatus(raw: String): KpmLoadStatus {
|
||||
val values = parseKeyValueLines(raw)
|
||||
return KpmLoadStatus(
|
||||
timestamp = values["timestamp"]?.trim()?.toLongOrNull(),
|
||||
bootId = values["boot_id"]?.trim()?.ifEmpty { null },
|
||||
unameR = values["uname_r"]?.trim()?.ifEmpty { null },
|
||||
runtime =
|
||||
when (values["runtime"]?.trim()) {
|
||||
"activator" -> KpmRuntime.Activator
|
||||
"kpatch-next" -> KpmRuntime.KpatchNext
|
||||
"apatch" -> KpmRuntime.Apatch
|
||||
"conflict" -> KpmRuntime.Conflict
|
||||
else -> KpmRuntime.Unknown
|
||||
},
|
||||
loaded =
|
||||
when (values["loaded"]?.trim()) {
|
||||
"1" -> true
|
||||
"0" -> false
|
||||
else -> null
|
||||
},
|
||||
reason =
|
||||
when (values["reason"]?.trim()) {
|
||||
"ok" -> KpmFailureReason.Ok
|
||||
"conflicting_backend" -> KpmFailureReason.ConflictingBackend
|
||||
"missing_kpm" -> KpmFailureReason.MissingKpm
|
||||
"missing_activator" -> KpmFailureReason.MissingActivator
|
||||
"awaiting_superkey" -> KpmFailureReason.AwaitingSuperkey
|
||||
"unsupported_kernel" -> KpmFailureReason.UnsupportedKernel
|
||||
"activation_failed" -> KpmFailureReason.ActivationFailed
|
||||
"load_failed" -> KpmFailureReason.LoadFailed
|
||||
else -> KpmFailureReason.Unknown
|
||||
},
|
||||
detail = values["detail"]?.trim()?.ifEmpty { null },
|
||||
)
|
||||
}
|
||||
|
|
@ -43,10 +43,11 @@ private val NATIVE_BACKEND_PRIORITY =
|
|||
internal fun detectNativeBackendStates(
|
||||
sections: Map<String, String>,
|
||||
currentBootId: String = sections["current_boot_id"].orEmpty(),
|
||||
kpmLoadStatus: KpmLoadStatus = parseKpmLoadStatus(sections["kpm_load_status"].orEmpty()),
|
||||
): NativeBackendStates =
|
||||
NativeBackendStates(
|
||||
kmod = detectKmodModule(sections),
|
||||
kpm = detectKpmModule(sections, currentBootId),
|
||||
kpm = detectKpmModule(sections, kpmLoadStatus, currentBootId),
|
||||
zygisk =
|
||||
detectZygiskModule(
|
||||
sections = sections,
|
||||
|
|
|
|||
|
|
@ -7,32 +7,38 @@ import org.junit.Test
|
|||
class ClassifyKpmProblemTest {
|
||||
private fun installed(active: Boolean) = ModuleState.Installed(version = "1.0", active = active)
|
||||
|
||||
private fun classify(
|
||||
kpm: ModuleState,
|
||||
rawStatus: String,
|
||||
currentBootId: String,
|
||||
): KpmProblemKind? = classifyKpmProblem(kpm, parseKpmLoadStatus(rawStatus), currentBootId)
|
||||
|
||||
@Test
|
||||
fun `not installed produces no problem`() {
|
||||
assertNull(classifyKpmProblem(ModuleState.NotInstalled, "runtime=activator\nloaded=0\nboot_id=boot-1\n", "boot-1"))
|
||||
assertNull(classify(ModuleState.NotInstalled, "runtime=activator\nloaded=0\nboot_id=boot-1\n", "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `active kpm is fine regardless of load status`() {
|
||||
assertNull(classifyKpmProblem(installed(active = true), "runtime=activator\nloaded=1\nboot_id=boot-1\n", "boot-1"))
|
||||
assertNull(classify(installed(active = true), "runtime=activator\nloaded=1\nboot_id=boot-1\n", "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `conflict runtime is not diagnosed here — handled by kpmDeferredForConflict`() {
|
||||
val status = "runtime=conflict\nloaded=0\nboot_id=boot-1\ndetail=vpnhide_kmod present\n"
|
||||
assertNull(classifyKpmProblem(installed(active = false), status, "boot-1"))
|
||||
assertNull(classify(installed(active = false), status, "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `apatch awaiting-superkey runtime is not diagnosed here — handled by kpmAwaitingSuperkey`() {
|
||||
val status = "runtime=apatch\nloaded=0\nboot_id=boot-1\ndetail=awaiting_superkey\n"
|
||||
assertNull(classifyKpmProblem(installed(active = false), status, "boot-1"))
|
||||
assertNull(classify(installed(active = false), status, "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `missing activator binary is a named diagnosis with a red card`() {
|
||||
val status = "runtime=activator\nloaded=0\nboot_id=boot-1\ndetail=activator missing at /data/adb/modules/vpnhide_kpm/activator\n"
|
||||
val kind = classifyKpmProblem(installed(active = false), status, "boot-1")
|
||||
val kind = classify(installed(active = false), status, "boot-1")
|
||||
assertEquals(KpmProblemKind.ActivatorMissing("/data/adb/modules/vpnhide_kpm/activator"), kind)
|
||||
assertEquals(ModuleBrokenReason.KpmActivatorMissing, kind?.reason)
|
||||
}
|
||||
|
|
@ -40,7 +46,7 @@ class ClassifyKpmProblemTest {
|
|||
@Test
|
||||
fun `generic activator failure surfaces the raw detail with no card color`() {
|
||||
val status = "runtime=activator\nloaded=0\nboot_id=boot-1\ndetail=rc=1 supercall failed: ENOENT\n"
|
||||
val kind = classifyKpmProblem(installed(active = false), status, "boot-1")
|
||||
val kind = classify(installed(active = false), status, "boot-1")
|
||||
assertEquals(KpmProblemKind.LoadFailed("rc=1 supercall failed: ENOENT"), kind)
|
||||
assertNull(kind?.reason)
|
||||
}
|
||||
|
|
@ -50,7 +56,7 @@ class ClassifyKpmProblemTest {
|
|||
val status =
|
||||
"runtime=activator\nloaded=0\nboot_id=boot-1\nuname_r=4.4.302-vendor\n" +
|
||||
"reason=unsupported_kernel\ndetail=unsupported kernel 4.4.302-vendor\n"
|
||||
val kind = classifyKpmProblem(installed(active = false), status, "boot-1")
|
||||
val kind = classify(installed(active = false), status, "boot-1")
|
||||
assertEquals(KpmProblemKind.UnsupportedKernel("4.4.302-vendor"), kind)
|
||||
assertEquals(ModuleBrokenReason.UnsupportedKernel, kind?.reason)
|
||||
}
|
||||
|
|
@ -60,31 +66,31 @@ class ClassifyKpmProblemTest {
|
|||
val status =
|
||||
"runtime=kpatch-next\nloaded=0\nboot_id=boot-1\nreason=load_failed\n" +
|
||||
"detail=rc=1 kpatch CLI not found\n"
|
||||
val kind = classifyKpmProblem(installed(active = false), status, "boot-1")
|
||||
val kind = classify(installed(active = false), status, "boot-1")
|
||||
assertEquals(KpmProblemKind.LoadFailed("rc=1 kpatch CLI not found"), kind)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `stale boot id is ignored`() {
|
||||
val status = "runtime=activator\nloaded=0\nboot_id=boot-0\ndetail=rc=1 boom\n"
|
||||
assertNull(classifyKpmProblem(installed(active = false), status, "boot-1"))
|
||||
assertNull(classify(installed(active = false), status, "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `missing boot id is ignored`() {
|
||||
val status = "runtime=activator\nloaded=0\ndetail=rc=1 boom\n"
|
||||
assertNull(classifyKpmProblem(installed(active = false), status, "boot-1"))
|
||||
assertNull(classify(installed(active = false), status, "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `empty load status is ignored`() {
|
||||
assertNull(classifyKpmProblem(installed(active = false), "", "boot-1"))
|
||||
assertNull(classify(installed(active = false), "", "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `inactive with fresh configured status but stale active flag is not diagnosed`() {
|
||||
// loaded=1 on runtime=activator means "configured" per service.sh, not a failure.
|
||||
val status = "runtime=activator\nloaded=1\nboot_id=boot-1\ndetail=configured\n"
|
||||
assertNull(classifyKpmProblem(installed(active = false), status, "boot-1"))
|
||||
assertNull(classify(installed(active = false), status, "boot-1"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package dev.okhsunrog.vpnhide
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class KpmLoadStatusTest {
|
||||
@Test
|
||||
fun `parser maps known wire values to typed status`() {
|
||||
val status =
|
||||
parseKpmLoadStatus(
|
||||
"""
|
||||
timestamp=42
|
||||
boot_id=boot-1
|
||||
uname_r=6.1.0-android
|
||||
runtime=kpatch-next
|
||||
loaded=0
|
||||
reason=unsupported_kernel
|
||||
detail=unsupported kernel
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
assertEquals(42L, status.timestamp)
|
||||
assertEquals("boot-1", status.bootId)
|
||||
assertEquals("6.1.0-android", status.unameR)
|
||||
assertEquals(KpmRuntime.KpatchNext, status.runtime)
|
||||
assertEquals(false, status.loaded)
|
||||
assertEquals(KpmFailureReason.UnsupportedKernel, status.reason)
|
||||
assertEquals("unsupported kernel", status.detail)
|
||||
assertTrue(status.isFreshFor("boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parser keeps unknown and missing wire values non-actionable`() {
|
||||
val status = parseKpmLoadStatus("runtime=future-runtime\nloaded=maybe\nreason=future-reason\n")
|
||||
|
||||
assertEquals(KpmRuntime.Unknown, status.runtime)
|
||||
assertEquals(null, status.loaded)
|
||||
assertEquals(KpmFailureReason.Unknown, status.reason)
|
||||
assertFalse(status.isFreshFor("boot-1"))
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,13 @@ import org.junit.Test
|
|||
class NativeBackendTest {
|
||||
private fun installed(active: Boolean) = ModuleState.Installed(version = "1.0", active = active)
|
||||
|
||||
private fun parseStatus(raw: String): KpmLoadStatus = parseKpmLoadStatus(raw)
|
||||
|
||||
private fun detectKpm(
|
||||
sections: Map<String, String>,
|
||||
currentBootId: String,
|
||||
): ModuleState = detectKpmModule(sections, parseStatus(sections["kpm_load_status"].orEmpty()), currentBootId)
|
||||
|
||||
private fun states(
|
||||
kmod: ModuleState,
|
||||
kpm: ModuleState,
|
||||
|
|
@ -158,43 +165,43 @@ class NativeBackendTest {
|
|||
@Test
|
||||
fun `kpm deferred-conflict detected for current boot`() {
|
||||
val status = "runtime=conflict\nloaded=0\nboot_id=boot-1\ndetail=vpnhide_kmod present\n"
|
||||
assertEquals(true, kpmDeferredForConflict(status, currentBootId = "boot-1"))
|
||||
assertEquals(true, kpmDeferredForConflict(parseStatus(status), currentBootId = "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `kpm deferred-conflict ignored for a stale boot`() {
|
||||
val status = "runtime=conflict\nloaded=0\nboot_id=boot-0\n"
|
||||
assertEquals(false, kpmDeferredForConflict(status, currentBootId = "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict(parseStatus(status), currentBootId = "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `kpm deferred-conflict false for non-conflict runtimes and empty status`() {
|
||||
assertEquals(false, kpmDeferredForConflict("runtime=activator\nloaded=1\nboot_id=boot-1\n", "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict("runtime=conflict\nloaded=0\n", "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict("", "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict(parseStatus("runtime=activator\nloaded=1\nboot_id=boot-1\n"), "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict(parseStatus("runtime=conflict\nloaded=0\n"), "boot-1"))
|
||||
assertEquals(false, kpmDeferredForConflict(parseStatus(""), "boot-1"))
|
||||
}
|
||||
|
||||
// ── kpmAwaitingSuperkey ──────────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
fun `kpm awaiting-superkey detected for current boot`() {
|
||||
val status = "runtime=apatch\nloaded=0\nboot_id=boot-1\ndetail=awaiting_superkey\n"
|
||||
assertEquals(true, kpmAwaitingSuperkey(status, currentBootId = "boot-1"))
|
||||
val status = "runtime=apatch\nloaded=0\nboot_id=boot-1\nreason=awaiting_superkey\ndetail=awaiting_superkey\n"
|
||||
assertEquals(true, kpmAwaitingSuperkey(parseStatus(status), currentBootId = "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `kpm awaiting-superkey ignored for a stale boot`() {
|
||||
val status = "runtime=apatch\nloaded=0\nboot_id=boot-0\ndetail=awaiting_superkey\n"
|
||||
assertEquals(false, kpmAwaitingSuperkey(status, currentBootId = "boot-1"))
|
||||
val status = "runtime=apatch\nloaded=0\nboot_id=boot-0\nreason=awaiting_superkey\ndetail=awaiting_superkey\n"
|
||||
assertEquals(false, kpmAwaitingSuperkey(parseStatus(status), currentBootId = "boot-1"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `kpm awaiting-superkey false once loaded or for other states`() {
|
||||
// Superkey saved and module loaded this boot.
|
||||
assertEquals(false, kpmAwaitingSuperkey("runtime=kpatch-next\nloaded=1\nboot_id=boot-1\n", "boot-1"))
|
||||
assertEquals(false, kpmAwaitingSuperkey(parseStatus("runtime=kpatch-next\nloaded=1\nboot_id=boot-1\n"), "boot-1"))
|
||||
// Conflict deferral is a different status, not awaiting-superkey.
|
||||
assertEquals(false, kpmAwaitingSuperkey("runtime=conflict\nloaded=0\nboot_id=boot-1\n", "boot-1"))
|
||||
assertEquals(false, kpmAwaitingSuperkey("", "boot-1"))
|
||||
assertEquals(false, kpmAwaitingSuperkey(parseStatus("runtime=conflict\nloaded=0\nboot_id=boot-1\n"), "boot-1"))
|
||||
assertEquals(false, kpmAwaitingSuperkey(parseStatus(""), "boot-1"))
|
||||
}
|
||||
|
||||
// ── kpatchRuntimeAvailable ───────────────────────────────────────────
|
||||
|
|
@ -238,7 +245,7 @@ class NativeBackendTest {
|
|||
|
||||
@Test
|
||||
fun `kpm not installed when no module prop`() {
|
||||
val state = detectKpmModule(emptyMap(), currentBootId = "boot-1")
|
||||
val state = detectKpm(emptyMap(), currentBootId = "boot-1")
|
||||
assertEquals(ModuleState.NotInstalled, state)
|
||||
}
|
||||
|
||||
|
|
@ -249,7 +256,7 @@ class NativeBackendTest {
|
|||
"kpm_prop" to "id=vpnhide_kpm\nversion=v1.0\n",
|
||||
"kpm_load_status" to "loaded=1\nboot_id=boot-1\n",
|
||||
)
|
||||
val state = detectKpmModule(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
val state = detectKpm(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
assertEquals(true, state.active)
|
||||
assertEquals("1.0", state.version)
|
||||
}
|
||||
|
|
@ -261,7 +268,7 @@ class NativeBackendTest {
|
|||
"kpm_prop" to "id=vpnhide_kpm\nversion=v1.0\n",
|
||||
"kpm_load_status" to "loaded=1\nboot_id=old-boot\n",
|
||||
)
|
||||
val state = detectKpmModule(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
val state = detectKpm(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
assertEquals(false, state.active)
|
||||
}
|
||||
|
||||
|
|
@ -272,7 +279,7 @@ class NativeBackendTest {
|
|||
"kpm_prop" to "id=vpnhide_kpm\nversion=v1.0\n",
|
||||
"kpm_load_status" to "loaded=1\ndetail=configured\n",
|
||||
)
|
||||
val state = detectKpmModule(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
val state = detectKpm(sections, currentBootId = "boot-1") as ModuleState.Installed
|
||||
assertEquals(false, state.active)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue