Improve DocumentsProvider tests against Nextcloud

This commit is contained in:
Torsten Grote 2020-08-26 14:17:50 -03:00 committed by Chirayu Desai
parent 897fd8473e
commit 740fe53a52
6 changed files with 71 additions and 11 deletions

View file

@ -126,7 +126,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-rc03'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
lintChecks 'com.github.thirdegg:lint-rules:0.0.4-alpha'
lintChecks 'com.github.thirdegg:lint-rules:0.0.5-alpha'
def junit_version = "5.5.2" // careful, upgrading this can change a Cipher's IV size in tests!?
def mockk_version = "1.10.0"

View file

@ -141,11 +141,18 @@ class PluginTest : KoinComponent {
initStorage(token)
// write random bytes as APK
val apk = getRandomByteArray(1337)
backupPlugin.getApkOutputStream(packageInfo).writeAndClose(apk)
val apk1 = getRandomByteArray(1337 * 1024)
backupPlugin.getApkOutputStream(packageInfo).writeAndClose(apk1)
// assert that read APK bytes match what was written
assertReadEquals(apk, restorePlugin.getApkInputStream(token, packageInfo.packageName))
assertReadEquals(apk1, restorePlugin.getApkInputStream(token, packageInfo.packageName))
// write random bytes as another APK
val apk2 = getRandomByteArray(23 * 1024 * 1024)
backupPlugin.getApkOutputStream(packageInfo2).writeAndClose(apk2)
// assert that read APK bytes match what was written
assertReadEquals(apk2, restorePlugin.getApkInputStream(token, packageInfo2.packageName))
}
@Test
@ -226,11 +233,14 @@ class PluginTest : KoinComponent {
initStorage(token)
// FIXME get Nextcloud to have the same limit
// Since Nextcloud is using WebDAV and that seems to have undefined lower file name limits
// we might have to lower our maximum to accommodate for that.
val max = if (isNextcloud()) MAX_KEY_LENGTH_NEXTCLOUD else MAX_KEY_LENGTH
val maxOver = if (isNextcloud()) max + 10 else max + 1
// define record with maximum key length and one above the maximum
val recordMax = Pair(getRandomBase64(max), getRandomByteArray(1024))
val recordOver = Pair(getRandomBase64(max + 1), getRandomByteArray(1024))
val recordOver = Pair(getRandomBase64(maxOver), getRandomByteArray(1024))
// write max record
kvBackup.ensureRecordStorageForPackage(packageInfo)
@ -306,7 +316,7 @@ class PluginTest : KoinComponent {
}
private fun isNextcloud(): Boolean {
return backupPlugin.providerPackageName == "com.nextcloud.client"
return backupPlugin.providerPackageName?.startsWith("com.nextcloud") ?: false
}
}

View file

@ -118,6 +118,49 @@ class DocumentsStorageTest : KoinComponent {
assertFalse(createdFile.exists())
}
@Test
fun testCreateTwoFiles() = runBlocking {
val mimeType = "application/octet-stream"
val dir = storage.rootBackupDir!!
// create test file
val name1 = getRandomBase64(Random.nextInt(1, 10))
val file1 = requireNotNull(dir.createFile(mimeType, name1))
assertTrue(file1.exists())
assertEquals(name1, file1.name)
assertEquals(0L, file1.length())
assertReadEquals(getRandomByteArray(0), context.contentResolver.openInputStream(file1.uri))
// write some data into it
val data1 = getRandomByteArray(5 * 1024 * 1024)
context.contentResolver.openOutputStream(file1.uri)!!.writeAndClose(data1)
assertEquals(data1.size.toLong(), file1.length())
// data should still be there
assertReadEquals(data1, context.contentResolver.openInputStream(file1.uri))
// create test file
val name2 = getRandomBase64(Random.nextInt(1, 10))
val file2 = requireNotNull(dir.createFile(mimeType, name2))
assertTrue(file2.exists())
assertEquals(name2, file2.name)
// write some data into it
val data2 = getRandomByteArray(12 * 1024 * 1024)
context.contentResolver.openOutputStream(file2.uri)!!.writeAndClose(data2)
assertEquals(data2.size.toLong(), file2.length())
// data should still be there
assertReadEquals(data2, context.contentResolver.openInputStream(file2.uri))
// delete files again
file1.delete()
file2.delete()
assertFalse(file1.exists())
assertFalse(file2.exists())
}
@Test
fun testGetLoadedCursor() = runBlocking {
// empty cursor extras are like not loading, returns same cursor right away

View file

@ -10,7 +10,7 @@ import java.io.IOException
import java.io.OutputStream
const val MAX_KEY_LENGTH = 255
const val MAX_KEY_LENGTH_NEXTCLOUD = 228
const val MAX_KEY_LENGTH_NEXTCLOUD = 225
@Suppress("BlockingMethodInNonBlockingContext")
internal class DocumentsProviderKVBackup(
@ -59,7 +59,7 @@ internal class DocumentsProviderKVBackup(
packageInfo: PackageInfo,
key: String
): OutputStream {
check(key.length < MAX_KEY_LENGTH) {
check(key.length <= MAX_KEY_LENGTH) {
"Key $key for ${packageInfo.packageName} is too long: ${key.length} chars."
}
if (key.length > MAX_KEY_LENGTH_NEXTCLOUD) {

View file

@ -204,7 +204,9 @@ fun DocumentFile.deleteContents() {
}
fun DocumentFile.assertRightFile(packageInfo: PackageInfo) {
if (name != packageInfo.packageName) throw AssertionError()
if (name != packageInfo.packageName) {
throw AssertionError("Expected ${packageInfo.packageName}, but got $name")
}
}
/**

View file

@ -1,5 +1,6 @@
package com.stevesoltys.seedvault
import com.stevesoltys.seedvault.plugins.saf.MAX_KEY_LENGTH_NEXTCLOUD
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
@ -12,12 +13,14 @@ fun assertContains(stack: String?, needle: String) {
if (stack?.contains(needle) != true) throw AssertionError()
}
@Suppress("MagicNumber")
fun getRandomByteArray(size: Int = Random.nextInt(1337)) = ByteArray(size).apply {
Random.nextBytes(this)
}
private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9') + '_' + '.'
@Suppress("MagicNumber")
fun getRandomString(size: Int = Random.nextInt(1, 255)): String {
return (1..size)
.map { Random.nextInt(0, charPool.size) }
@ -26,9 +29,10 @@ fun getRandomString(size: Int = Random.nextInt(1, 255)): String {
}
// URL-save version (RFC 4648)
private val base64CharPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9') + '+' + '_' + '='
private val base64CharPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9') // + '+' + '_' + '='
fun getRandomBase64(size: Int = Random.nextInt(1, 255)): String {
@Suppress("MagicNumber")
fun getRandomBase64(size: Int = Random.nextInt(1, MAX_KEY_LENGTH_NEXTCLOUD)): String {
return (1..size)
.map { Random.nextInt(0, base64CharPool.size) }
.map(base64CharPool::get)
@ -61,6 +65,7 @@ fun assertReadEquals(data: ByteArray, inputStream: InputStream?) = inputStream?.
fun <T : Throwable> coAssertThrows(clazz: Class<T>, block: suspend () -> Unit) {
var thrown = false
@Suppress("TooGenericExceptionCaught")
try {
runBlocking {
block()