diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-02 18:21:26 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-03 14:24:54 +0200 |
| commit | d8f5005ba2c9a249ce5ce8976d9c3754a3a7458e (patch) | |
| tree | 960ece9a79c58fbe60033b91f6ec685795eff8a1 /packages/meshbay-android/app/src/test/kotlin/org/meshbay | |
| parent | ede70b0fcc006d3ced8ef0d1d7115593f6627aef (diff) | |
| download | meshbay-d8f5005ba2c9a249ce5ce8976d9c3754a3a7458e.tar.gz | |
feat(android): downloads to disk and uploads through the system picker
Native save over the Storage Access Framework and MediaStore, chunks sent as
binary bridge messages, a chosen folder that has gone asks rather than
redirects, unfinished files removed on abort and after a killed process.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-android/app/src/test/kotlin/org/meshbay')
| -rw-r--r-- | packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/SaveNamesTest.kt | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/SaveNamesTest.kt b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/SaveNamesTest.kt new file mode 100644 index 0000000..d3b8450 --- /dev/null +++ b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/SaveNamesTest.kt @@ -0,0 +1,45 @@ +package org.meshbay.client + +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.meshbay.client.save.BinaryFrame +import org.meshbay.client.save.SaveNames + +class SaveNamesTest { + @Test fun `a suggested name is a basename with no bidirectional tricks`() { + assertEquals("invoice_fdp.exe", SaveNames.sanitize("invoice\u202efdp.exe")) + assertEquals("passwd", SaveNames.sanitize("../../etc/passwd")) + assertEquals("x.txt", SaveNames.sanitize("C:\\Users\\x.txt")) + assertEquals("download", SaveNames.sanitize("")) + assertEquals("download", SaveNames.sanitize("..")) + assertEquals("a_b", SaveNames.sanitize("a\u0000b")) + } + + @Test fun `only what runs nothing is opened, under a type from the name`() { + assertEquals("application/pdf", SaveNames.openableType("Report.PDF")) + assertEquals("video/mp4", SaveNames.openableType("clip.mp4")) + for (n in listOf("page.html", "image.svg", "run.apk", "script.js", "noext", "x.pdf.exe")) { + assertNull(n, SaveNames.openableType(n)) + } + assertEquals("application/octet-stream", SaveNames.storedType("page.html")) + } + + @Test fun `a taken name becomes name (n), never an overwrite`() { + assertEquals("film (2).mkv", SaveNames.numbered("film.mkv", 2)) + assertEquals("README (3)", SaveNames.numbered("README", 3)) + } + + @Test fun `a binary frame is read as the shim writes it`() { + val payload = byteArrayOf(1, 2, 3, 4, 5) + val b = byteArrayOf(0x4d, 0x42, 0x42, 0x31, 0, 0, 1, 2, 0, 1, 0, 0, 0, 0, 0, 7) + payload + val f = BinaryFrame.parse(b)!! + assertEquals(258L, f.id) + assertEquals(BinaryFrame.SAVE_WRITE, f.channel) + assertEquals(7L, f.handle) + assertArrayEquals(payload, f.bytes.copyOfRange(f.offset, f.bytes.size)) + assertNull(BinaryFrame.parse(byteArrayOf(0x4d, 0x42, 0x42, 0x32) + ByteArray(12))) + assertNull(BinaryFrame.parse(ByteArray(10))) + } +} |