d05b98b443d5

test: Add H-09 snapshot wire-guardrail tests from T2 verify pass (v2.9.1)

T2 (remote-input cluster H-08/H-09/M-01/M-02) verify-and-harden pass with a fresh Qwen3.7-Max worker. H-08 (updater independent signer-set + blake3/sha256 checksum + bounded download), M-01 (bounded atomic import), and M-02 (PeachScript caps + Long arithmetic) verified SOLID with no code change needed. H-09 had a coverage thin spot: the inline-snapshot wire guardrails lacked direct negative tests. Added two (VaultAdoptSnapshotTest): - rejects raw frame exceeding SNAPSHOT_FRAME_WIRE_CEILING (768 KiB) before deserialization - rejects chunk_count mismatch on a subsequent frame Orchestrator gate after the worker hit an API rate limit: 822 tests, 0 failures/errors/skips.

time
2026-07-30 06:19 UTC · 2 months ago
machine
koh2
parent
85d691ffdf4a
2 files VERSION+1 −1app/src/test/java/com/peachpasswords/sync/VaultAdoptSnapshotTest.kt+39 −0
VERSION+1 −1
@@ -1 +1 @@1-2.9.01+2.9.1

view file

app/src/test/java/com/peachpasswords/sync/VaultAdoptSnapshotTest.kt+39 −0
@@ -126,4 +126,43 @@126126         val jsonNoFlag = AdoptJson.encodeToString(AdoptionFrame.serializer(), noFlag)127127         assertTrue(!jsonNoFlag.contains("snapshot_capable"))128128     }129+130+    @Test131+    fun `rejects raw frame exceeding wire ceiling`() = runBlocking {132+        // H-09: a hostile source could send an arbitrarily large frame to exhaust133+        // receiver memory before JSON parsing. receiveVaultSnapshot checks the raw134+        // byte length against SNAPSHOT_FRAME_WIRE_CEILING (512 KiB + 256 KiB = 768 KiB)135+        // and throws before attempting deserialization.136+        val ceiling = MAX_SNAPSHOT_CHUNK_BYTES + 256 * 1024137+        val oversized = ByteArray(ceiling + 1)138+        val channel = object : PairingTransport {139+            override suspend fun send(msg: ByteArray) {}140+            override suspend fun receive(): ByteArray = oversized141+            override suspend fun close() {}142+        }143+        val error = runCatching { receiveVaultSnapshot(channel) }.exceptionOrNull()144+        assertTrue(error is IllegalStateException)145+        assertTrue(error!!.message!!.contains("CHUNK_TOO_LARGE"))146+    }147+148+    @Test149+    fun `rejects chunk_count mismatch on subsequent frame`() = runBlocking {150+        val (source, receiver) = memoryPair()151+        sendFrame(source, AdoptionFrame.Snapshot(152+            chunkIndex = 0,153+            chunkCount = 2,154+            entries = mapOf("a" to "x"),155+            tombstones = emptyMap(),156+        ))157+        sendFrame(source, AdoptionFrame.Snapshot(158+            chunkIndex = 1,159+            chunkCount = 3,160+            entries = mapOf("b" to "y"),161+            tombstones = emptyMap(),162+        ))163+        val error = runCatching { receiveVaultSnapshot(receiver) }.exceptionOrNull()164+        assertTrue(error is IllegalStateException)165+        assertTrue(error!!.message!!.contains("CHUNK_COUNT_MISMATCH"))166+    }167+129168 }

view file