diff options
Diffstat (limited to 'packages/meshbay-android/app/src/test')
| -rw-r--r-- | packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/DriveTest.kt | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/DriveTest.kt b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/DriveTest.kt new file mode 100644 index 0000000..e661bd1 --- /dev/null +++ b/packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/DriveTest.kt @@ -0,0 +1,90 @@ +package org.meshbay.client + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.meshbay.client.drive.DriveFile +import org.meshbay.client.drive.DriveLedger +import org.meshbay.client.drive.DrivePlan +import org.meshbay.client.photos.PhotoPlan +import org.meshbay.client.photos.PhotoSource +import java.util.TimeZone + +class DriveTest { + @get:Rule val tmp = TemporaryFolder() + + private val utc = TimeZone.getTimeZone("UTC") + private val tree = "content://tree/primary%3ADocuments" + private val names = mapOf(tree to "Documents") + + private fun file(id: String, sub: String = "", size: Long = 10, modified: Long = 1000) = + DriveFile(tree, "primary:Documents/" + (if (sub.isEmpty()) "" else "$sub/") + id, sub, id, size, modified, + "application/pdf") + + private fun plan(files: List<DriveFile>, sent: Map<String, DriveLedger.Entry> = emptyMap(), + skip: Set<String> = emptySet(), same: Boolean = false) = + DrivePlan.plan(files, "Backups/bob-drive", names, { sent[it] }, skip, utc) { _, _ -> same } + + private fun entry(f: DriveFile) = DriveLedger.Entry(f.docId, f.modified, f.size, "h", "d", f.name, 1) + + @Test fun `media folders and a whole volume cannot be chosen`() { + assertEquals("whole_storage", DrivePlan.refusal("primary:")) + assertEquals("whole_storage", DrivePlan.refusal("1234-ABCD:")) + assertEquals("media_folder", DrivePlan.refusal("primary:DCIM")) + assertEquals("media_folder", DrivePlan.refusal("primary:DCIM/Camera")) + assertEquals("media_folder", DrivePlan.refusal("primary:Pictures/Screenshots")) + assertEquals("media_folder", DrivePlan.refusal("1234-ABCD:movies")) + assertNull(DrivePlan.refusal("primary:Documents")) + assertNull(DrivePlan.refusal("primary:Download/Invoices")) + assertNull(DrivePlan.refusal("primary:Documents/Pictures")) + } + + @Test fun `files go under the chosen folder's name, sub-folders kept`() { + val out = plan(listOf(file("a.pdf"), file("b.pdf", sub = "Tax/2026"))) + assertEquals(setOf("Backups/bob-drive/Documents", "Backups/bob-drive/Documents/Tax/2026"), + out.map { it.dir }.toSet()) + } + + @Test fun `smallest first, hidden files and photo-backed files left out`() { + val out = plan(listOf(file("big.pdf", size = 900), file("small.pdf", size = 5), file(".secret"), + file("scan.jpg", sub = "Scans")), + skip = setOf("documents/scans/scan.jpg")) + assertEquals(listOf("small.pdf", "big.pdf"), out.map { it.name }) + } + + @Test fun `a file already sent is not sent again, a changed one goes beside it`() { + val f = file("a.pdf") + assertTrue(plan(listOf(f), sent = mapOf(f.docId to entry(f))).isEmpty()) + val changed = f.copy(size = 20, modified = 86_400_000) + val out = plan(listOf(changed), sent = mapOf(f.docId to entry(f))) + assertEquals("a-modified-19700102-000000.pdf", out.single().name) + assertTrue(out.single().edited) + val touched = f.copy(modified = 5000) + assertTrue(plan(listOf(touched), sent = mapOf(f.docId to entry(f)), same = true).isEmpty()) + } + + @Test fun `names the node would refuse are mended, not dropped`() { + assertEquals("report.pdf", DrivePlan.safeName("report.pdf")) + assertEquals("a_b_c.txt", DrivePlan.safeName("a:b?c.txt")) + assertEquals("file-.env", DrivePlan.safeName(".env")) + assertEquals("file-_draft", DrivePlan.safeName("_draft")) + assertTrue(PhotoPlan.UPLOAD_NAME.matches(DrivePlan.safeName("x".repeat(300) + ".pdf"))) + assertTrue(PhotoPlan.UPLOAD_NAME.matches(DrivePlan.safeName("end. "))) + } + + @Test fun `the ledger remembers across a restart`() { + val path = tmp.newFile("d.jsonl") + DriveLedger(path).apply { record(entry(file("a.pdf"))); record(entry(file("a.pdf")).copy(sha256 = "z")) } + val again = DriveLedger(path) + assertEquals(1, again.size) + assertEquals("z", again["primary:Documents/a.pdf"]!!.sha256) + } + + @Test fun `a path from before Android 10 is read from the top of its volume`() { + assertEquals("Documents/Scans/a.jpg", PhotoSource.volumeRelative("/storage/emulated/0/Documents/Scans/a.jpg")) + assertEquals("x/a.jpg", PhotoSource.volumeRelative("/storage/1234-ABCD/x/a.jpg")) + } +} |