package com.peachpasswords.sync import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test class SyncPaddingTest { @Test fun round_trips_payloads_of_every_shape() { for (size in listOf(0, 1, 5, 251, 252, 253, 1000, 70_000)) { val payload = ByteArray(size) { ((it * 31) and 0xFF).toByte() } assertArrayEquals(payload, SyncPadding.unpad(SyncPadding.pad(payload))) } } @Test fun small_control_frames_collapse_to_one_indistinguishable_size() { // A relay must not be able to tell a HELLO from a DONE by frame size. val hello = ("{\"type\":\"SYNC_HELLO\",\"vaultId\":\"" + "a".repeat(64) + "\"}") .toByteArray(Charsets.UTF_8) val done = "{\"type\":\"SYNC_DONE\"}".toByteArray(Charsets.UTF_8) assertEquals(SyncPadding.pad(hello).size, SyncPadding.pad(done).size) assertEquals(256, SyncPadding.pad(done).size) } @Test fun bucket_ladder_matches_the_browser_kat() { // Pinned against peach-browser sync-padding.test.ts. A mismatch here // means the two platforms cannot read each other's frames at all. val cases = listOf( 0 to 256, 252 to 256, 253 to 512, 1024 to 2048, 65_532 to 65_536, 65_533 to 131_072, 200_000 to 262_144, ) for ((payload, expected) in cases) { assertEquals(expected, SyncPadding.bucket(4 + payload)) assertEquals(expected, SyncPadding.pad(ByteArray(payload)).size) } } @Test fun large_frame_overhead_stays_bounded() { val twelveMiB = 12 * 1024 * 1024 val padded = SyncPadding.bucket(twelveMiB) assertTrue(padded >= twelveMiB) assertTrue(padded - twelveMiB < 64 * 1024) } @Test fun rejects_a_frame_declaring_more_payload_than_it_carries() { val forged = ByteArray(256) forged[0] = 0; forged[1] = 0; forged[2] = 0x27; forged[3] = 0x0F.toByte() // 9999 var threw = false try { SyncPadding.unpad(forged) } catch (_: IllegalArgumentException) { threw = true } assertTrue(threw) } @Test fun rejects_a_frame_shorter_than_its_length_header() { var threw = false try { SyncPadding.unpad(ByteArray(3)) } catch (_: IllegalArgumentException) { threw = true } assertTrue(threw) } }