diff options
| author | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
| commit | 7e04941bccb2683f8a6e3ee38a99c50129234dd1 (patch) | |
| tree | 471227fa437291e7a6b499e3de6c106c54eaf311 /app/src/test/java/invalid/lena | |
| download | rsend-7e04941bccb2683f8a6e3ee38a99c50129234dd1.tar.gz | |
rsend: push phone folders to a home SSH host over rsync
A small Android app for one-way folder backup, a KISS alternative to
Syncthing. It bundles rsync (built from pinned source via the NDK) and
a pure-Go SSH transport, both shipped in the APK as lib*.so and run from
the native library directory.
rsend pins the host key, stores the ed25519 identity Keystore-encrypted,
pushes each folder additively or as a mirror, and runs on demand or on a
WiFi-only schedule. The build is self-contained and reproducible: make
setup provisions the toolchain, make builds rsync, rsh, and the APK.
Diffstat (limited to 'app/src/test/java/invalid/lena')
| -rw-r--r-- | app/src/test/java/invalid/lena/rsend/ConfigTest.kt | 26 | ||||
| -rw-r--r-- | app/src/test/java/invalid/lena/rsend/RsyncRunnerTest.kt | 49 |
2 files changed, 75 insertions, 0 deletions
diff --git a/app/src/test/java/invalid/lena/rsend/ConfigTest.kt b/app/src/test/java/invalid/lena/rsend/ConfigTest.kt new file mode 100644 index 0000000..51796ba --- /dev/null +++ b/app/src/test/java/invalid/lena/rsend/ConfigTest.kt @@ -0,0 +1,26 @@ +package invalid.lena.rsend + +import org.json.JSONObject +import org.junit.Assert.assertEquals +import org.junit.Test + +class ConfigTest { + + @Test + fun roundTrip() { + val c = Config( + remote = Remote("home", 2222, "backup"), + schedule = Schedule(enabled = true, intervalMinutes = 30, wifiOnly = false, requireCharging = true), + folders = listOf( + Folder("DCIM", "/storage/emulated/0/DCIM", "/b/DCIM", false, listOf(".thumbnails/")), + Folder("W", "/w", "/b/w", true, emptyList()), + ), + ) + assertEquals(c, Config.fromJson(c.toJson())) + } + + @Test + fun defaultsForEmptyObject() { + assertEquals(Config(), Config.fromJson(JSONObject("{}"))) + } +} diff --git a/app/src/test/java/invalid/lena/rsend/RsyncRunnerTest.kt b/app/src/test/java/invalid/lena/rsend/RsyncRunnerTest.kt new file mode 100644 index 0000000..ef7958f --- /dev/null +++ b/app/src/test/java/invalid/lena/rsend/RsyncRunnerTest.kt @@ -0,0 +1,49 @@ +package invalid.lena.rsend + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class RsyncRunnerTest { + + private val remote = Remote("host", 22, "user") + + @Test + fun basicArgs() { + val a = RsyncRunner.args("RSH", remote, Folder(name = "n", local = "/a", remote = "/b")) + assertEquals( + listOf( + "-rt", "--partial", "--timeout=300", "--mkpath", + "--no-perms", "--no-owner", "--no-group", "--omit-dir-times", + "-e", "RSH", "/a/", "user@host:/b/", + ), + a, + ) + } + + @Test + fun mirrorAddsDelete() { + val a = RsyncRunner.args("RSH", remote, Folder(local = "/a", remote = "/b", delete = true)) + assertTrue(a.contains("--delete")) + } + + @Test + fun additiveOmitsDelete() { + val a = RsyncRunner.args("RSH", remote, Folder(local = "/a", remote = "/b", delete = false)) + assertTrue(!a.contains("--delete")) + } + + @Test + fun excludesBecomeFlags() { + val a = RsyncRunner.args("RSH", remote, Folder(local = "/a", remote = "/b", excludes = listOf(".x/", ".y"))) + assertTrue(a.contains("--exclude=.x/")) + assertTrue(a.contains("--exclude=.y")) + } + + @Test + fun trailingSlashIdempotent() { + val a = RsyncRunner.args("RSH", remote, Folder(local = "/a/", remote = "/b/")) + assertTrue(a.contains("/a/")) + assertTrue(a.contains("user@host:/b/")) + } +} |