aboutsummaryrefslogtreecommitdiff
path: root/app/src/test/java/invalid/lena
diff options
context:
space:
mode:
authorLena <lena@omega>2026-01-01 00:00:00 +0000
committerLena <lena@omega>2026-01-01 00:00:00 +0000
commit7e04941bccb2683f8a6e3ee38a99c50129234dd1 (patch)
tree471227fa437291e7a6b499e3de6c106c54eaf311 /app/src/test/java/invalid/lena
downloadrsend-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.kt26
-rw-r--r--app/src/test/java/invalid/lena/rsend/RsyncRunnerTest.kt49
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/"))
+ }
+}