Files
flamenet-messenger-android/engine/src/test/kotlin/io/flamenet/e2e/DisappearingTest.kt
T
Paul HittandClaude Fable 5.1 2fa430f21c API-style comments and ktlint formatting
Every comment is reduced to its first sentence plus @param, @return
and @throws tags. Comment lines: 20040 to 8526. ktlint 1.8 applied
with its default (official Kotlin) style across all modules; 262 files
reformatted. The 264 remaining ktlint findings are naming and filename
rules, which are code changes, and are left alone.

Comments and formatting only. 1208 tests pass, counted from the XML.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 20:02:07 -04:00

114 lines
3.3 KiB
Kotlin

package io.flamenet.e2e
import org.json.JSONObject
import javax.crypto.KeyGenerator
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
/**
* Disappearing messages (§6.11), at the vault.
*/
class DisappearingTest {
private class MapStorage : Vault.Storage {
private val records = mutableMapOf<String, ByteArray>()
override fun read(name: String) = records[name]
override fun write(
name: String,
bytes: ByteArray,
) {
records[name] = bytes
}
override fun delete(name: String) {
records.remove(name)
}
override fun names() = records.keys.toList()
}
private fun vault() = Vault(MapStorage(), KeyGenerator.getInstance("AES").apply { init(256) }.generateKey())
private fun line(
text: String,
at: Long,
) = JSONObject().put("text", text).put("mine", true).put("at", at)
private val now = 1_700_000_000_000L
@Test
fun `with no timer nothing is removed`() {
val v = vault()
v.append("t", line("ancient", 1L))
assertEquals(1, v.history("t", now).length())
}
@Test
fun `messages older than the timer are gone on the next read`() {
val v = vault()
v.saveDisappearSeconds("t", 60)
v.append("t", line("old", now - 120_000))
v.append("t", line("fresh", now - 10_000))
val kept = v.history("t", now)
assertEquals(1, kept.length())
assertEquals("fresh", kept.getJSONObject(0).optString("text"))
}
/** Gone from disk, not merely filtered out of the answer. */
@Test
fun `expiry is a deletion, not a filter`() {
val v = vault()
v.saveDisappearSeconds("t", 60)
v.append("t", line("old", now - 120_000))
v.history("t", now)
// Read again with the timer switched off: an expired message must not
// come back, which it would if the first read had only hidden it.
v.saveDisappearSeconds("t", 0)
assertEquals(0, v.history("t", now).length())
}
/**
* A message with no timestamp predates the field.
*/
@Test
fun `a message with no timestamp is kept`() {
val v = vault()
v.saveDisappearSeconds("t", 60)
v.append("t", JSONObject().put("text", "from before").put("mine", true))
assertEquals(1, v.history("t", now).length())
}
@Test
fun `the timer is per conversation`() {
val v = vault()
v.saveDisappearSeconds("timed", 60)
v.append("timed", line("old", now - 120_000))
v.append("untimed", line("old", now - 120_000))
assertEquals(0, v.history("timed", now).length())
assertEquals(1, v.history("untimed", now).length())
}
@Test
fun `turning the timer off forgets it`() {
val v = vault()
v.saveDisappearSeconds("t", 3600)
assertEquals(3600, v.disappearSeconds("t"))
v.saveDisappearSeconds("t", 0)
assertEquals(0, v.disappearSeconds("t"))
}
/** Exactly at the boundary the message survives, off-by-one deletes data. */
@Test
fun `a message exactly at the cutoff survives`() {
val v = vault()
v.saveDisappearSeconds("t", 60)
v.append("t", line("edge", now - 60_000))
assertTrue(v.history("t", now).length() == 1)
}
}