Add real-world large-file test (multi-GB from phone via external URL, chunked)
Build & Release APK / build (push) Successful in 12m58s

Opt-in (-e bigFileMB=<size>): streams a multi-GB file from the device through
the app's chunked-upload path to the external nextcloud.khodak.me and verifies
the full size lands. Verified live: 1.5 GB and 5 GB both succeed end-to-end.
This commit is contained in:
2026-06-05 16:14:13 +00:00
parent abec5276f9
commit 15b94a0407
@@ -22,6 +22,9 @@ import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.time.Instant import java.time.Instant
/** /**
@@ -37,6 +40,7 @@ import java.time.Instant
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class NextcloudIntegrationTest { class NextcloudIntegrationTest {
private val ctx = InstrumentationRegistry.getInstrumentation().targetContext
private val args = InstrumentationRegistry.getArguments() private val args = InstrumentationRegistry.getArguments()
private val url = args.getString("ncUrl") private val url = args.getString("ncUrl")
private val user = args.getString("ncUser") private val user = args.getString("ncUser")
@@ -138,4 +142,44 @@ class NextcloudIntegrationTest {
runCatching { p.deleteFile(dir) } runCatching { p.deleteFile(dir) }
} }
} }
/**
* Real-world large-file test: streams a multi-GB file FROM THE PHONE through the app's
* chunked-upload path to the external URL, verifies the full size landed, then cleans up.
* Opt-in (slow): pass -e bigFileMB=<size>, e.g. 1536 for 1.5 GB.
*/
@Test
fun realWorld_largeFileChunkedUpload() = runBlocking {
assumeTrue("ncUrl/ncUser/ncPass required", url != null && user != null && pass != null)
val mb = args.getString("bigFileMB")?.toIntOrNull() ?: 0
assumeTrue("pass -e bigFileMB=<size> to run the big-file test", mb > 0)
val account = CloudAccount(
id = 1, displayName = "IT", email = user, providerType = ProviderType.NEXTCLOUD,
credentialJson = """{"username":"$user","password":"$pass"}""", serverUrl = url, port = null,
)
val p = NextcloudProvider(account) // default 100 MB chunks -> chunked path for >100 MB
val dir = "SyncFlowBig_${System.currentTimeMillis()}"
val tmp = File(ctx.cacheDir, "bigfile_${System.currentTimeMillis()}.bin")
try {
val total = mb.toLong() * 1024 * 1024
FileOutputStream(tmp).use { os ->
val buf = ByteArray(8 * 1024 * 1024)
var written = 0L
while (written < total) {
val n = minOf(buf.size.toLong(), total - written).toInt()
os.write(buf, 0, n); written += n
}
}
assertEquals(total, tmp.length())
p.createDirectory(dir).getOrThrow()
val up = p.uploadFile(FileInputStream(tmp), "$dir/big.bin", tmp.length())
assertTrue("large chunked upload failed: ${up.exceptionOrNull()}", up.isSuccess)
assertEquals("full file size must land on the server", total,
p.listFiles(dir).getOrThrow().first { it.name == "big.bin" }.sizeBytes)
} finally {
tmp.delete()
runCatching { p.deleteFile(dir) }
}
}
} }