Files
flamenet-messenger-android/engine/src/test/kotlin/io/flamenet/e2e/ControlFlagInteropTest.kt
T
Paul HittandClaude Fable 5.1 4dd544083c Remove machine-writing tells from comments and docs
Emoji markers, markdown bold inside code comments, and em-dashes are
gone from source comments, string literals, scripts, Gradle files and
the markdown docs. Counted before and after:

  emoji markers   2680 -> 1 (the emoji picker's own list, which is the feature)
  em-dashes       2490 -> 9 (table placeholders and fenced code)

Two warning glyphs in user-facing strings in ChatScreens.kt are removed
as well; the sentences say the same thing without them. Two backtick
test names carried an em-dash and now carry a comma.

Nothing else changed. 1208 tests pass, counted from the result XML.
The three obfs4 interop tests are opted out with OBFS4_INTEROP_OPTOUT=1
for this run, as their own message instructs when no bridge is set up.

CONTRIBUTING gets a four-line rule so it does not grow back.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 18:52:12 -04:00

74 lines
3.0 KiB
Kotlin

package io.flamenet.e2e
import org.json.JSONObject
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
/**
* The `ctl` flag, as all three engines actually write it.
*
* This engine wrote `"ctl":true` and the specification says `"ctl":1`.
* That was not a cosmetic disagreement. iOS decodes the field as a number
* through a synthesised `Codable`, so a boolean did not fail to set the flag,
* it failed the whole envelope's decode and dropped the message onto the
* plain-text path. An Android user turning on disappearing messages therefore
* sent an iPhone a bubble containing raw JSON, and the timer was never applied
* at that end. Nothing caught it because each engine parsed what it had written
* itself, and the piece-level tests on both sides passed.
*/
class ControlFlagInteropTest {
@Test
fun `a disappearing envelope carries the number the spec asks for`() {
val envelope = JSONObject(Content.disappearing(3600))
assertEquals(1, envelope.get("ctl"),
"the spec says {\"fnc\":1,\"kind\":\"…\",\"ctl\":1}")
assertEquals(3600, envelope.getInt("secs"))
assertEquals(1, envelope.getInt("fnc"))
}
/** And it still parses here, which is the half that already worked. */
@Test
fun `our own disappearing envelope round trips`() {
val content = Content.parse(Content.disappearing(900))
assertEquals(900, Content.disappearSeconds(content))
assertTrue(content.isControl)
}
/**
* Both shapes are accepted on the way IN. `org.json`'s `optBoolean` does
* not coerce a number, so reading only that missed every `"ctl":1` the
* other two engines send, and reading only the number would miss the
* `true` this engine itself wrote, which is on phones now and cannot be
* recalled.
*/
@Test
fun `both spellings of the flag are understood`() {
for (spelling in listOf("1", "true")) {
val raw = """{"fnc":1,"kind":"some_future_thing","ctl":$spelling}"""
assertTrue(Content.parse(raw).isControl,
"a control envelope written as ctl:$spelling was shown to the user")
}
}
/**
* The point of the flag: a control kind from a NEWER peer must be
* swallowed, not rendered. Without it, every control kind added after a
* given release shows in that release as a bubble the person cannot act on.
*/
@Test
fun `an unknown control kind is swallowed rather than shown`() {
val content = Content.parse("""{"fnc":1,"kind":"invented_next_year","ctl":1}""")
assertTrue(content.isControl)
assertTrue(!content.isRenderable, "control traffic must not reach the thread")
}
/** An ordinary message is untouched by any of it. */
@Test
fun `a plain message is not control traffic`() {
assertTrue(!Content.parse("just a message").isControl)
assertTrue(!Content.parse(Content.text("hello")).isControl)
}
}