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>
74 lines
3.0 KiB
Kotlin
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)
|
|
}
|
|
}
|