refactor(debug): Use Instant for createdAt, extract scanSessions helpers, add pendingAutoZips guard

This commit is contained in:
darken
2026-03-09 04:53:01 +00:00
committed by Matthias Urhahn
parent b2f8586dc9
commit 58bd0f91f5
7 changed files with 171 additions and 145 deletions
@@ -10,6 +10,7 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import testhelpers.BaseTest
import java.io.File
import java.time.Instant
class DebugSessionManagerSessionLogicTest : BaseTest() {
@@ -30,33 +31,19 @@ class DebugSessionManagerSessionLogicTest : BaseTest() {
@Nested
inner class ParseCreatedAt {
@Test
fun `standard format extracts timestamp`() {
DebugSessionManager.parseCreatedAt("capod_1.2.3_1709810400000_abcd1234", 99L) shouldBe 1709810400000L
fun `returns creation time from file attributes`() {
val file = File(externalLogsDir, "capod_1.2.3_1709810400000_abcd1234").also { it.mkdirs() }
val result = DebugSessionManager.parseCreatedAt(file)
// Should return a valid Instant (either from file attributes or lastModified fallback)
result.shouldBeInstanceOf<Instant>()
}
@Test
fun `zip suffix is stripped before parsing`() {
DebugSessionManager.parseCreatedAt("capod_1.2.3_1709810400000_abcd1234.zip", 99L) shouldBe 1709810400000L
}
@Test
fun `too few parts returns fallback`() {
DebugSessionManager.parseCreatedAt("capod_1.2.3", 99L) shouldBe 99L
}
@Test
fun `non-numeric timestamp returns fallback`() {
DebugSessionManager.parseCreatedAt("capod_1.2.3_notanumber_abcd1234", 99L) shouldBe 99L
}
@Test
fun `timestamp in seconds returns fallback`() {
DebugSessionManager.parseCreatedAt("capod_1.2.3_1709810400_abcd1234", 99L) shouldBe 99L
}
@Test
fun `empty string returns fallback`() {
DebugSessionManager.parseCreatedAt("", 42L) shouldBe 42L
fun `non-existent file returns epoch fallback`() {
val file = File(externalLogsDir, "nonexistent")
val result = DebugSessionManager.parseCreatedAt(file)
// Falls back to lastModified (0 for non-existent) → Instant.ofEpochMilli(0)
result shouldBe Instant.EPOCH
}
}
@@ -283,17 +270,20 @@ class DebugSessionManagerSessionLogicTest : BaseTest() {
@Test
fun `multiple sessions sorted by createdAt descending then id ascending`() {
// Create dirs with a time gap so filesystem timestamps differ
val oldDir = File(externalLogsDir, "capod_1.0_1600000000000_abcd1234").also { it.mkdirs() }
File(oldDir, "core.log").writeText("old log")
oldDir.setLastModified(1600000000000L)
val newDir = File(externalLogsDir, "capod_1.0_1700000000000_abcd1234").also { it.mkdirs() }
File(newDir, "core.log").writeText("new log")
newDir.setLastModified(1700000000000L)
val result = DebugSessionManager.scanSessions(logDirectories = logDirs())
result shouldHaveSize 2
result[0].createdAt shouldBe 1700000000000L
result[1].createdAt shouldBe 1600000000000L
// Newer session should come first (descending)
result[0].createdAt.isAfter(result[1].createdAt) shouldBe true
}
}
}
@@ -10,13 +10,14 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import testhelpers.BaseTest
import java.io.File
import java.time.Instant
/**
* Tests for [DebugSessionManager] overlay and reconciliation logic.
*
* These tests exercise the instance-level behaviors (zippingIds overlay, failedZipIds overlay,
* orphan detection) by calling the companion [scanSessions] and then manually applying overlays,
* mirroring what [DebugSessionManager.applyOverlays] and [DebugSessionManager.reconcileOrphans] do.
* mirroring what [DebugSessionManager.applyOverlays] and [DebugSessionManager.findOrphans] do.
*
* Full integration tests with mocked RecorderModule are deferred until MockK/Java 21 compat is resolved.
*/
@@ -8,13 +8,16 @@ import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import testhelpers.BaseTest
import java.io.File
import java.time.Instant
class SupportViewModelStateTest : BaseTest() {
private val testInstant = Instant.ofEpochMilli(1700000000000L)
private fun readySession(id: String = "ext:s1", diskSize: Long = 100L) = DebugSession.Ready(
id = id,
displayName = "s1",
createdAt = 1700000000000L,
createdAt = testInstant,
diskSize = diskSize,
logDir = File("/tmp/s1"),
zipFile = null,
@@ -24,7 +27,7 @@ class SupportViewModelStateTest : BaseTest() {
private fun recordingSession(id: String = "ext:rec") = DebugSession.Recording(
id = id,
displayName = "rec",
createdAt = 1700000000000L,
createdAt = testInstant,
diskSize = 50L,
path = File("/tmp/rec"),
startedAt = 1700000000000L,
@@ -33,7 +36,7 @@ class SupportViewModelStateTest : BaseTest() {
private fun failedSession(id: String = "ext:fail", diskSize: Long = 10L) = DebugSession.Failed(
id = id,
displayName = "fail",
createdAt = 1700000000000L,
createdAt = testInstant,
diskSize = diskSize,
path = File("/tmp/fail"),
reason = DebugSession.Failed.Reason.EMPTY_LOG,
@@ -42,7 +45,7 @@ class SupportViewModelStateTest : BaseTest() {
private fun compressingSession(id: String = "ext:comp", diskSize: Long = 75L) = DebugSession.Compressing(
id = id,
displayName = "comp",
createdAt = 1700000000000L,
createdAt = testInstant,
diskSize = diskSize,
path = File("/tmp/comp"),
)