Refactor Storage Plugin API

This commit is contained in:
Torsten Grote 2021-09-23 14:56:01 +02:00 committed by Chirayu Desai
parent 50066f0317
commit 3c5e4120c7
30 changed files with 219 additions and 268 deletions

View file

@ -3,18 +3,14 @@ package com.stevesoltys.seedvault
import androidx.test.core.content.pm.PackageInfoBuilder import androidx.test.core.content.pm.PackageInfoBuilder
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderBackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderFullRestorePlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderKVRestorePlugin import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderStoragePlugin
import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderRestorePlugin import com.stevesoltys.seedvault.plugins.saf.DocumentsProviderLegacyPlugin
import com.stevesoltys.seedvault.plugins.saf.DocumentsStorage import com.stevesoltys.seedvault.plugins.saf.DocumentsStorage
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.plugins.saf.deleteContents import com.stevesoltys.seedvault.plugins.saf.deleteContents
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.restore.FullRestorePlugin
import com.stevesoltys.seedvault.transport.restore.KVRestorePlugin
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -39,14 +35,10 @@ class PluginTest : KoinComponent {
private val mockedSettingsManager: SettingsManager = mockk() private val mockedSettingsManager: SettingsManager = mockk()
private val storage = DocumentsStorage(context, mockedSettingsManager) private val storage = DocumentsStorage(context, mockedSettingsManager)
private val backupPlugin: BackupPlugin = DocumentsProviderBackupPlugin(context, storage) private val storagePlugin: StoragePlugin = DocumentsProviderStoragePlugin(context, storage)
@Suppress("Deprecation")
private val kvRestorePlugin: KVRestorePlugin = private val legacyStoragePlugin: LegacyStoragePlugin =
DocumentsProviderKVRestorePlugin(context, storage) DocumentsProviderLegacyPlugin(context, storage)
private val fullRestorePlugin: FullRestorePlugin =
DocumentsProviderFullRestorePlugin(context, storage)
private val restorePlugin: RestorePlugin =
DocumentsProviderRestorePlugin(context, storage, kvRestorePlugin, fullRestorePlugin)
private val token = System.currentTimeMillis() - 365L * 24L * 60L * 60L * 1000L private val token = System.currentTimeMillis() - 365L * 24L * 60L * 60L * 1000L
private val packageInfo = PackageInfoBuilder.newBuilder().setPackageName("org.example").build() private val packageInfo = PackageInfoBuilder.newBuilder().setPackageName("org.example").build()
@ -67,7 +59,7 @@ class PluginTest : KoinComponent {
@Test @Test
fun testProviderPackageName() { fun testProviderPackageName() {
assertNotNull(backupPlugin.providerPackageName) assertNotNull(storagePlugin.providerPackageName)
} }
/** /**
@ -80,38 +72,38 @@ class PluginTest : KoinComponent {
@Test @Test
fun testInitializationAndRestoreSets() = runBlocking(Dispatchers.IO) { fun testInitializationAndRestoreSets() = runBlocking(Dispatchers.IO) {
// no backups available initially // no backups available initially
assertEquals(0, backupPlugin.getAvailableBackups()?.toList()?.size) assertEquals(0, storagePlugin.getAvailableBackups()?.toList()?.size)
val uri = settingsManager.getStorage()?.getDocumentFile(context)?.uri ?: error("no storage") val uri = settingsManager.getStorage()?.getDocumentFile(context)?.uri ?: error("no storage")
assertFalse(backupPlugin.hasBackup(uri)) assertFalse(storagePlugin.hasBackup(uri))
// prepare returned tokens requested when initializing device // prepare returned tokens requested when initializing device
every { mockedSettingsManager.getToken() } returnsMany listOf(token, token + 1, token + 1) every { mockedSettingsManager.getToken() } returnsMany listOf(token, token + 1, token + 1)
// start new restore set and initialize device afterwards // start new restore set and initialize device afterwards
backupPlugin.startNewRestoreSet(token) storagePlugin.startNewRestoreSet(token)
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
// write metadata (needed for backup to be recognized) // write metadata (needed for backup to be recognized)
backupPlugin.getOutputStream(token, FILE_BACKUP_METADATA) storagePlugin.getOutputStream(token, FILE_BACKUP_METADATA)
.writeAndClose(getRandomByteArray()) .writeAndClose(getRandomByteArray())
// one backup available now // one backup available now
assertEquals(1, backupPlugin.getAvailableBackups()?.toList()?.size) assertEquals(1, storagePlugin.getAvailableBackups()?.toList()?.size)
assertTrue(backupPlugin.hasBackup(uri)) assertTrue(storagePlugin.hasBackup(uri))
// initializing again (with another restore set) does add a restore set // initializing again (with another restore set) does add a restore set
backupPlugin.startNewRestoreSet(token + 1) storagePlugin.startNewRestoreSet(token + 1)
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
backupPlugin.getOutputStream(token + 1, FILE_BACKUP_METADATA) storagePlugin.getOutputStream(token + 1, FILE_BACKUP_METADATA)
.writeAndClose(getRandomByteArray()) .writeAndClose(getRandomByteArray())
assertEquals(2, backupPlugin.getAvailableBackups()?.toList()?.size) assertEquals(2, storagePlugin.getAvailableBackups()?.toList()?.size)
assertTrue(backupPlugin.hasBackup(uri)) assertTrue(storagePlugin.hasBackup(uri))
// initializing again (without new restore set) doesn't change number of restore sets // initializing again (without new restore set) doesn't change number of restore sets
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
backupPlugin.getOutputStream(token + 1, FILE_BACKUP_METADATA) storagePlugin.getOutputStream(token + 1, FILE_BACKUP_METADATA)
.writeAndClose(getRandomByteArray()) .writeAndClose(getRandomByteArray())
assertEquals(2, backupPlugin.getAvailableBackups()?.toList()?.size) assertEquals(2, storagePlugin.getAvailableBackups()?.toList()?.size)
// ensure that the new backup dir exist // ensure that the new backup dir exist
assertTrue(storage.currentSetDir!!.exists()) assertTrue(storage.currentSetDir!!.exists())
@ -121,15 +113,15 @@ class PluginTest : KoinComponent {
fun testMetadataWriteRead() = runBlocking(Dispatchers.IO) { fun testMetadataWriteRead() = runBlocking(Dispatchers.IO) {
every { mockedSettingsManager.getToken() } returns token every { mockedSettingsManager.getToken() } returns token
backupPlugin.startNewRestoreSet(token) storagePlugin.startNewRestoreSet(token)
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
// write metadata // write metadata
val metadata = getRandomByteArray() val metadata = getRandomByteArray()
backupPlugin.getOutputStream(token, FILE_BACKUP_METADATA).writeAndClose(metadata) storagePlugin.getOutputStream(token, FILE_BACKUP_METADATA).writeAndClose(metadata)
// get available backups, expect only one with our token and no error // get available backups, expect only one with our token and no error
var availableBackups = backupPlugin.getAvailableBackups()?.toList() var availableBackups = storagePlugin.getAvailableBackups()?.toList()
check(availableBackups != null) check(availableBackups != null)
assertEquals(1, availableBackups.size) assertEquals(1, availableBackups.size)
assertEquals(token, availableBackups[0].token) assertEquals(token, availableBackups[0].token)
@ -138,9 +130,9 @@ class PluginTest : KoinComponent {
assertReadEquals(metadata, availableBackups[0].inputStreamRetriever()) assertReadEquals(metadata, availableBackups[0].inputStreamRetriever())
// initializing again (without changing storage) keeps restore set with same token // initializing again (without changing storage) keeps restore set with same token
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
backupPlugin.getOutputStream(token, FILE_BACKUP_METADATA).writeAndClose(metadata) storagePlugin.getOutputStream(token, FILE_BACKUP_METADATA).writeAndClose(metadata)
availableBackups = backupPlugin.getAvailableBackups()?.toList() availableBackups = storagePlugin.getAvailableBackups()?.toList()
check(availableBackups != null) check(availableBackups != null)
assertEquals(1, availableBackups.size) assertEquals(1, availableBackups.size)
assertEquals(token, availableBackups[0].token) assertEquals(token, availableBackups[0].token)
@ -157,22 +149,25 @@ class PluginTest : KoinComponent {
// write random bytes as APK // write random bytes as APK
val apk1 = getRandomByteArray(1337 * 1024) val apk1 = getRandomByteArray(1337 * 1024)
backupPlugin.getOutputStream(token, "${packageInfo.packageName}.apk").writeAndClose(apk1) storagePlugin.getOutputStream(token, "${packageInfo.packageName}.apk").writeAndClose(apk1)
// assert that read APK bytes match what was written // assert that read APK bytes match what was written
assertReadEquals(apk1, restorePlugin.getApkInputStream(token, packageInfo.packageName, "")) assertReadEquals(
apk1,
legacyStoragePlugin.getApkInputStream(token, packageInfo.packageName, "")
)
// write random bytes as another APK // write random bytes as another APK
val suffix2 = getRandomBase64(23) val suffix2 = getRandomBase64(23)
val apk2 = getRandomByteArray(23 * 1024 * 1024) val apk2 = getRandomByteArray(23 * 1024 * 1024)
backupPlugin.getOutputStream(token, "${packageInfo2.packageName}$suffix2.apk") storagePlugin.getOutputStream(token, "${packageInfo2.packageName}$suffix2.apk")
.writeAndClose(apk2) .writeAndClose(apk2)
// assert that read APK bytes match what was written // assert that read APK bytes match what was written
assertReadEquals( assertReadEquals(
apk2, apk2,
restorePlugin.getApkInputStream(token, packageInfo2.packageName, suffix2) legacyStoragePlugin.getApkInputStream(token, packageInfo2.packageName, suffix2)
) )
} }
@ -185,41 +180,41 @@ class PluginTest : KoinComponent {
val name2 = getRandomBase64() val name2 = getRandomBase64()
// no data available initially // no data available initially
assertFalse(backupPlugin.hasData(token, name1)) assertFalse(storagePlugin.hasData(token, name1))
assertFalse(backupPlugin.hasData(token, name2)) assertFalse(storagePlugin.hasData(token, name2))
// write full backup data // write full backup data
val data = getRandomByteArray(5 * 1024 * 1024) val data = getRandomByteArray(5 * 1024 * 1024)
backupPlugin.getOutputStream(token, name1).writeAndClose(data) storagePlugin.getOutputStream(token, name1).writeAndClose(data)
// data is available now, but only this token // data is available now, but only this token
assertTrue(backupPlugin.hasData(token, name1)) assertTrue(storagePlugin.hasData(token, name1))
assertFalse(backupPlugin.hasData(token + 1, name1)) assertFalse(storagePlugin.hasData(token + 1, name1))
// restore data matches backed up data // restore data matches backed up data
assertReadEquals(data, backupPlugin.getInputStream(token, name1)) assertReadEquals(data, storagePlugin.getInputStream(token, name1))
// write and check data for second package // write and check data for second package
val data2 = getRandomByteArray(5 * 1024 * 1024) val data2 = getRandomByteArray(5 * 1024 * 1024)
backupPlugin.getOutputStream(token, name2).writeAndClose(data2) storagePlugin.getOutputStream(token, name2).writeAndClose(data2)
assertTrue(backupPlugin.hasData(token, name2)) assertTrue(storagePlugin.hasData(token, name2))
assertReadEquals(data2, backupPlugin.getInputStream(token, name2)) assertReadEquals(data2, storagePlugin.getInputStream(token, name2))
// remove data of first package again and ensure that no more data is found // remove data of first package again and ensure that no more data is found
backupPlugin.removeData(token, name1) storagePlugin.removeData(token, name1)
assertFalse(backupPlugin.hasData(token, name1)) assertFalse(storagePlugin.hasData(token, name1))
// second package is still there // second package is still there
assertTrue(backupPlugin.hasData(token, name2)) assertTrue(storagePlugin.hasData(token, name2))
// ensure that it gets deleted as well // ensure that it gets deleted as well
backupPlugin.removeData(token, name2) storagePlugin.removeData(token, name2)
assertFalse(backupPlugin.hasData(token, name2)) assertFalse(storagePlugin.hasData(token, name2))
} }
private fun initStorage(token: Long) = runBlocking { private fun initStorage(token: Long) = runBlocking {
every { mockedSettingsManager.getToken() } returns token every { mockedSettingsManager.getToken() } returns token
backupPlugin.initializeDevice() storagePlugin.initializeDevice()
} }
} }

View file

@ -1,10 +1,11 @@
package com.stevesoltys.seedvault.transport.restore package com.stevesoltys.seedvault.plugins
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
interface KVRestorePlugin { @Deprecated("Only for old v0 backup format")
interface LegacyStoragePlugin {
/** /**
* Return true if there is data stored for the given package. * Return true if there is data stored for the given package.
@ -36,4 +37,19 @@ interface KVRestorePlugin {
key: String key: String
): InputStream ): InputStream
/**
* Return true if there is data stored for the given package.
*/
@Throws(IOException::class)
suspend fun hasDataForFullPackage(token: Long, packageInfo: PackageInfo): Boolean
@Throws(IOException::class)
suspend fun getInputStreamForPackage(token: Long, packageInfo: PackageInfo): InputStream
/**
* Returns an [InputStream] for the given token, for reading an APK that is to be restored.
*/
@Throws(IOException::class)
suspend fun getApkInputStream(token: Long, packageName: String, suffix: String): InputStream
} }

View file

@ -1,4 +1,4 @@
package com.stevesoltys.seedvault.transport.backup package com.stevesoltys.seedvault.plugins
import android.app.backup.RestoreSet import android.app.backup.RestoreSet
import android.net.Uri import android.net.Uri
@ -7,7 +7,7 @@ import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
interface BackupPlugin { interface StoragePlugin {
/** /**
* Start a new [RestoreSet] with the given token. * Start a new [RestoreSet] with the given token.

View file

@ -1,33 +0,0 @@
package com.stevesoltys.seedvault.plugins.saf
import android.content.Context
import android.content.pm.PackageInfo
import com.stevesoltys.seedvault.transport.restore.FullRestorePlugin
import java.io.IOException
import java.io.InputStream
@Suppress("BlockingMethodInNonBlockingContext", "Deprecation")
@Deprecated("Use only for v0 restore")
internal class DocumentsProviderFullRestorePlugin(
private val context: Context,
private val documentsStorage: DocumentsStorage
) : FullRestorePlugin {
@Throws(IOException::class)
override suspend fun hasDataForPackage(token: Long, packageInfo: PackageInfo): Boolean {
val backupDir = documentsStorage.getFullBackupDir(token) ?: return false
return backupDir.findFileBlocking(context, packageInfo.packageName) != null
}
@Throws(IOException::class)
override suspend fun getInputStreamForPackage(
token: Long,
packageInfo: PackageInfo
): InputStream {
val backupDir = documentsStorage.getFullBackupDir(token) ?: throw IOException()
val packageFile =
backupDir.findFileBlocking(context, packageInfo.packageName) ?: throw IOException()
return documentsStorage.getInputStream(packageFile)
}
}

View file

@ -2,17 +2,19 @@ package com.stevesoltys.seedvault.plugins.saf
import android.content.Context import android.content.Context
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import androidx.annotation.WorkerThread
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import com.stevesoltys.seedvault.transport.restore.KVRestorePlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
@Suppress("BlockingMethodInNonBlockingContext", "Deprecation") @WorkerThread
@Deprecated("Use only for v0 restore") @Suppress("BlockingMethodInNonBlockingContext", "Deprecation") // all methods do I/O
internal class DocumentsProviderKVRestorePlugin( internal class DocumentsProviderLegacyPlugin(
private val context: Context, private val context: Context,
private val storage: DocumentsStorage private val storage: DocumentsStorage
) : KVRestorePlugin { ) : LegacyStoragePlugin {
private var packageDir: DocumentFile? = null private var packageDir: DocumentFile? = null
private var packageChildren: List<DocumentFile>? = null private var packageChildren: List<DocumentFile>? = null
@ -59,4 +61,33 @@ internal class DocumentsProviderKVRestorePlugin(
return storage.getInputStream(keyFile) return storage.getInputStream(keyFile)
} }
@Throws(IOException::class)
override suspend fun hasDataForFullPackage(token: Long, packageInfo: PackageInfo): Boolean {
val backupDir = storage.getFullBackupDir(token) ?: return false
return backupDir.findFileBlocking(context, packageInfo.packageName) != null
}
@Throws(IOException::class)
override suspend fun getInputStreamForPackage(
token: Long,
packageInfo: PackageInfo
): InputStream {
val backupDir = storage.getFullBackupDir(token) ?: throw IOException()
val packageFile =
backupDir.findFileBlocking(context, packageInfo.packageName) ?: throw IOException()
return storage.getInputStream(packageFile)
}
@Throws(IOException::class)
override suspend fun getApkInputStream(
token: Long,
packageName: String,
suffix: String
): InputStream {
val setDir = storage.getSetDir(token) ?: throw IOException()
val file = setDir.findFileBlocking(context, "$packageName$suffix.apk")
?: throw FileNotFoundException()
return storage.getInputStream(file)
}
} }

View file

@ -1,18 +1,14 @@
package com.stevesoltys.seedvault.plugins.saf package com.stevesoltys.seedvault.plugins.saf
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.transport.restore.FullRestorePlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.transport.restore.KVRestorePlugin
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module import org.koin.dsl.module
val documentsProviderModule = module { val documentsProviderModule = module {
single { DocumentsStorage(androidContext(), get()) } single { DocumentsStorage(androidContext(), get()) }
single<BackupPlugin> { DocumentsProviderBackupPlugin(androidContext(), get()) } single<StoragePlugin> { DocumentsProviderStoragePlugin(androidContext(), get()) }
@Suppress("Deprecation")
single<KVRestorePlugin> { DocumentsProviderKVRestorePlugin(androidContext(), get()) } single<LegacyStoragePlugin> { DocumentsProviderLegacyPlugin(androidContext(), get()) }
single<FullRestorePlugin> { DocumentsProviderFullRestorePlugin(androidContext(), get()) }
single<RestorePlugin> { DocumentsProviderRestorePlugin(androidContext(), get(), get(), get()) }
} }

View file

@ -1,33 +0,0 @@
package com.stevesoltys.seedvault.plugins.saf
import android.content.Context
import androidx.annotation.WorkerThread
import com.stevesoltys.seedvault.transport.restore.FullRestorePlugin
import com.stevesoltys.seedvault.transport.restore.KVRestorePlugin
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import java.io.FileNotFoundException
import java.io.IOException
import java.io.InputStream
@WorkerThread
@Suppress("BlockingMethodInNonBlockingContext") // all methods do I/O
internal class DocumentsProviderRestorePlugin(
private val context: Context,
private val storage: DocumentsStorage,
override val kvRestorePlugin: KVRestorePlugin,
override val fullRestorePlugin: FullRestorePlugin
) : RestorePlugin {
@Throws(IOException::class)
override suspend fun getApkInputStream(
token: Long,
packageName: String,
suffix: String
): InputStream {
val setDir = storage.getSetDir(token) ?: throw IOException()
val file = setDir.findFileBlocking(context, "$packageName$suffix.apk")
?: throw FileNotFoundException()
return storage.getInputStream(file)
}
}

View file

@ -5,20 +5,20 @@ import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.EncryptedMetadata
import com.stevesoltys.seedvault.transport.backup.EncryptedMetadata import com.stevesoltys.seedvault.plugins.StoragePlugin
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
private val TAG = DocumentsProviderBackupPlugin::class.java.simpleName private val TAG = DocumentsProviderStoragePlugin::class.java.simpleName
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class DocumentsProviderBackupPlugin( internal class DocumentsProviderStoragePlugin(
private val context: Context, private val context: Context,
private val storage: DocumentsStorage private val storage: DocumentsStorage
) : BackupPlugin { ) : StoragePlugin {
private val packageManager: PackageManager = context.packageManager private val packageManager: PackageManager = context.packageManager

View file

@ -8,16 +8,16 @@ import android.util.Log
import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.crypto.Crypto
import com.stevesoltys.seedvault.metadata.ApkSplit import com.stevesoltys.seedvault.metadata.ApkSplit
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.restore.RestorableBackup import com.stevesoltys.seedvault.restore.RestorableBackup
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP
import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.backup.copyStreamsAndGetHash import com.stevesoltys.seedvault.transport.backup.copyStreamsAndGetHash
import com.stevesoltys.seedvault.transport.backup.getSignatures import com.stevesoltys.seedvault.transport.backup.getSignatures
import com.stevesoltys.seedvault.transport.backup.isSystemApp import com.stevesoltys.seedvault.transport.backup.isSystemApp
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import kotlinx.coroutines.TimeoutCancellationException import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
@ -28,8 +28,9 @@ private val TAG = ApkRestore::class.java.simpleName
internal class ApkRestore( internal class ApkRestore(
private val context: Context, private val context: Context,
private val backupPlugin: BackupPlugin, private val storagePlugin: StoragePlugin,
private val restorePlugin: RestorePlugin, @Suppress("Deprecation")
private val legacyStoragePlugin: LegacyStoragePlugin,
private val crypto: Crypto, private val crypto: Crypto,
private val splitCompatChecker: ApkSplitCompatibilityChecker, private val splitCompatChecker: ApkSplitCompatibilityChecker,
private val apkInstaller: ApkInstaller private val apkInstaller: ApkInstaller
@ -157,7 +158,7 @@ internal class ApkRestore(
} }
/** /**
* Retrieves APK splits from [RestorePlugin] and caches them locally. * Retrieves APK splits from [StoragePlugin] and caches them locally.
* *
* @throws SecurityException if a split has an unexpected SHA-256 hash. * @throws SecurityException if a split has an unexpected SHA-256 hash.
* @return a list of all APKs that need to be installed * @return a list of all APKs that need to be installed
@ -195,7 +196,7 @@ internal class ApkRestore(
} }
/** /**
* Retrieves an APK from the [RestorePlugin] and caches it locally * Retrieves an APK from the [StoragePlugin] and caches it locally
* while calculating its SHA-256 hash. * while calculating its SHA-256 hash.
* *
* @return a [Pair] of the cached [File] and SHA-256 hash. * @return a [Pair] of the cached [File] and SHA-256 hash.
@ -214,10 +215,10 @@ internal class ApkRestore(
// copy APK to cache file and calculate SHA-256 hash while we are at it // copy APK to cache file and calculate SHA-256 hash while we are at it
val inputStream = if (version == 0.toByte()) { val inputStream = if (version == 0.toByte()) {
@Suppress("Deprecation") @Suppress("Deprecation")
restorePlugin.getApkInputStream(token, packageName, suffix) legacyStoragePlugin.getApkInputStream(token, packageName, suffix)
} else { } else {
val name = crypto.getNameForApk(salt, packageName, suffix) val name = crypto.getNameForApk(salt, packageName, suffix)
backupPlugin.getInputStream(token, name) storagePlugin.getInputStream(token, name)
} }
val sha256 = copyStreamsAndGetHash(inputStream, cachedApk.outputStream()) val sha256 = copyStreamsAndGetHash(inputStream, cachedApk.outputStream())
return Pair(cachedApk, sha256) return Pair(cachedApk, sha256)

View file

@ -29,6 +29,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
@ -64,7 +65,7 @@ private class CoordinatorState(
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class BackupCoordinator( internal class BackupCoordinator(
private val context: Context, private val context: Context,
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val kv: KVBackup, private val kv: KVBackup,
private val full: FullBackup, private val full: FullBackup,
private val apkBackup: ApkBackup, private val apkBackup: ApkBackup,
@ -508,7 +509,7 @@ internal class BackupCoordinator(
} }
} }
private suspend fun BackupPlugin.getMetadataOutputStream(token: Long? = null): OutputStream { private suspend fun StoragePlugin.getMetadataOutputStream(token: Long? = null): OutputStream {
val t = token ?: settingsManager.getToken() ?: throw IOException("no current token") val t = token ?: settingsManager.getToken() ?: throw IOException("no current token")
return getOutputStream(t, FILE_BACKUP_METADATA) return getOutputStream(t, FILE_BACKUP_METADATA)
} }

View file

@ -11,6 +11,7 @@ import android.util.Log
import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.crypto.Crypto
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import libcore.io.IoUtils.closeQuietly import libcore.io.IoUtils.closeQuietly
import java.io.EOFException import java.io.EOFException
@ -38,7 +39,7 @@ private val TAG = FullBackup::class.java.simpleName
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class FullBackup( internal class FullBackup(
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val settingsManager: SettingsManager, private val settingsManager: SettingsManager,
private val inputFactory: InputFactory, private val inputFactory: InputFactory,
private val crypto: Crypto private val crypto: Crypto

View file

@ -12,6 +12,7 @@ import android.util.Log
import com.stevesoltys.seedvault.crypto.Crypto import com.stevesoltys.seedvault.crypto.Crypto
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForKV import com.stevesoltys.seedvault.header.getADForKV
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import java.io.IOException import java.io.IOException
import java.util.zip.GZIPOutputStream import java.util.zip.GZIPOutputStream
@ -31,7 +32,7 @@ private val TAG = KVBackup::class.java.simpleName
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class KVBackup( internal class KVBackup(
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val settingsManager: SettingsManager, private val settingsManager: SettingsManager,
private val inputFactory: InputFactory, private val inputFactory: InputFactory,
private val crypto: Crypto, private val crypto: Crypto,

View file

@ -12,7 +12,8 @@ import com.stevesoltys.seedvault.header.HeaderReader
import com.stevesoltys.seedvault.header.MAX_SEGMENT_LENGTH import com.stevesoltys.seedvault.header.MAX_SEGMENT_LENGTH
import com.stevesoltys.seedvault.header.UnsupportedVersionException import com.stevesoltys.seedvault.header.UnsupportedVersionException
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import libcore.io.IoUtils.closeQuietly import libcore.io.IoUtils.closeQuietly
import java.io.EOFException import java.io.EOFException
import java.io.IOException import java.io.IOException
@ -33,8 +34,9 @@ private val TAG = FullRestore::class.java.simpleName
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class FullRestore( internal class FullRestore(
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val legacyPlugin: FullRestorePlugin, @Suppress("Deprecation")
private val legacyPlugin: LegacyStoragePlugin,
private val outputFactory: OutputFactory, private val outputFactory: OutputFactory,
private val headerReader: HeaderReader, private val headerReader: HeaderReader,
private val crypto: Crypto private val crypto: Crypto
@ -52,7 +54,7 @@ internal class FullRestore(
@Throws(IOException::class) @Throws(IOException::class)
@Deprecated("Use BackupPlugin#hasData() instead") @Deprecated("Use BackupPlugin#hasData() instead")
suspend fun hasDataForPackage(token: Long, packageInfo: PackageInfo): Boolean { suspend fun hasDataForPackage(token: Long, packageInfo: PackageInfo): Boolean {
return legacyPlugin.hasDataForPackage(token, packageInfo) return legacyPlugin.hasDataForFullPackage(token, packageInfo)
} }
/** /**

View file

@ -1,18 +0,0 @@
package com.stevesoltys.seedvault.transport.restore
import android.content.pm.PackageInfo
import java.io.IOException
import java.io.InputStream
interface FullRestorePlugin {
/**
* Return true if there is data stored for the given package.
*/
@Throws(IOException::class)
suspend fun hasDataForPackage(token: Long, packageInfo: PackageInfo): Boolean
@Throws(IOException::class)
suspend fun getInputStreamForPackage(token: Long, packageInfo: PackageInfo): InputStream
}

View file

@ -15,7 +15,8 @@ import com.stevesoltys.seedvault.header.HeaderReader
import com.stevesoltys.seedvault.header.UnsupportedVersionException import com.stevesoltys.seedvault.header.UnsupportedVersionException
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForKV import com.stevesoltys.seedvault.header.getADForKV
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.transport.backup.KVDb import com.stevesoltys.seedvault.transport.backup.KVDb
import com.stevesoltys.seedvault.transport.backup.KvDbManager import com.stevesoltys.seedvault.transport.backup.KvDbManager
import libcore.io.IoUtils.closeQuietly import libcore.io.IoUtils.closeQuietly
@ -41,8 +42,9 @@ private val TAG = KVRestore::class.java.simpleName
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class KVRestore( internal class KVRestore(
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val legacyPlugin: KVRestorePlugin, @Suppress("Deprecation")
private val legacyPlugin: LegacyStoragePlugin,
private val outputFactory: OutputFactory, private val outputFactory: OutputFactory,
private val headerReader: HeaderReader, private val headerReader: HeaderReader,
private val crypto: Crypto, private val crypto: Crypto,

View file

@ -21,7 +21,7 @@ import com.stevesoltys.seedvault.metadata.DecryptionFailedException
import com.stevesoltys.seedvault.metadata.MetadataManager import com.stevesoltys.seedvault.metadata.MetadataManager
import com.stevesoltys.seedvault.metadata.MetadataReader import com.stevesoltys.seedvault.metadata.MetadataReader
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import java.io.IOException import java.io.IOException
@ -46,7 +46,7 @@ internal class RestoreCoordinator(
private val settingsManager: SettingsManager, private val settingsManager: SettingsManager,
private val metadataManager: MetadataManager, private val metadataManager: MetadataManager,
private val notificationManager: BackupNotificationManager, private val notificationManager: BackupNotificationManager,
private val plugin: BackupPlugin, private val plugin: StoragePlugin,
private val kv: KVRestore, private val kv: KVRestore,
private val full: FullRestore, private val full: FullRestore,
private val metadataReader: MetadataReader private val metadataReader: MetadataReader

View file

@ -5,8 +5,8 @@ import org.koin.dsl.module
val restoreModule = module { val restoreModule = module {
single { OutputFactory() } single { OutputFactory() }
single { KVRestore(get(), get<RestorePlugin>().kvRestorePlugin, get(), get(), get(), get()) } single { KVRestore(get(), get(), get(), get(), get(), get()) }
single { FullRestore(get(), get<RestorePlugin>().fullRestorePlugin, get(), get(), get()) } single { FullRestore(get(), get(), get(), get(), get()) }
single { single {
RestoreCoordinator(androidContext(), get(), get(), get(), get(), get(), get(), get(), get()) RestoreCoordinator(androidContext(), get(), get(), get(), get(), get(), get(), get(), get())
} }

View file

@ -1,19 +0,0 @@
package com.stevesoltys.seedvault.transport.restore
import java.io.IOException
import java.io.InputStream
interface RestorePlugin {
val kvRestorePlugin: KVRestorePlugin
val fullRestorePlugin: FullRestorePlugin
/**
* Returns an [InputStream] for the given token, for reading an APK that is to be restored.
*/
@Throws(IOException::class)
@Deprecated("Use only for v0 restores")
suspend fun getApkInputStream(token: Long, packageName: String, suffix: String): InputStream
}

View file

@ -7,7 +7,7 @@ import androidx.lifecycle.viewModelScope
import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.R
import com.stevesoltys.seedvault.plugins.saf.DIRECTORY_ROOT import com.stevesoltys.seedvault.plugins.saf.DIRECTORY_ROOT
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.IOException import java.io.IOException
@ -16,7 +16,7 @@ private val TAG = RestoreStorageViewModel::class.java.simpleName
internal class RestoreStorageViewModel( internal class RestoreStorageViewModel(
private val app: Application, private val app: Application,
private val backupPlugin: BackupPlugin, private val storagePlugin: StoragePlugin,
settingsManager: SettingsManager settingsManager: SettingsManager
) : StorageViewModel(app, settingsManager) { ) : StorageViewModel(app, settingsManager) {
@ -25,7 +25,7 @@ internal class RestoreStorageViewModel(
override fun onLocationSet(uri: Uri) { override fun onLocationSet(uri: Uri) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val hasBackup = try { val hasBackup = try {
backupPlugin.hasBackup(uri) storagePlugin.hasBackup(uri)
} catch (e: IOException) { } catch (e: IOException) {
Log.e(TAG, "Error reading URI: $uri", e) Log.e(TAG, "Error reading URI: $uri", e)
false false

View file

@ -12,11 +12,11 @@ import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class BackupPluginTest : BackupTest() { internal class StoragePluginTest : BackupTest() {
private val storage = mockk<DocumentsStorage>() private val storage = mockk<DocumentsStorage>()
private val plugin = DocumentsProviderBackupPlugin(context, storage) private val plugin = DocumentsProviderStoragePlugin(context, storage)
private val setDir: DocumentFile = mockk() private val setDir: DocumentFile = mockk()
private val backupFile: DocumentFile = mockk() private val backupFile: DocumentFile = mockk()

View file

@ -11,11 +11,11 @@ import com.stevesoltys.seedvault.metadata.ApkSplit
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.metadata.PackageMetadataMap import com.stevesoltys.seedvault.metadata.PackageMetadataMap
import com.stevesoltys.seedvault.metadata.PackageState import com.stevesoltys.seedvault.metadata.PackageState
import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.restore.RestorableBackup import com.stevesoltys.seedvault.restore.RestorableBackup
import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.transport.TransportTest
import com.stevesoltys.seedvault.transport.backup.ApkBackup import com.stevesoltys.seedvault.transport.backup.ApkBackup
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
@ -46,16 +46,17 @@ internal class ApkBackupRestoreTest : TransportTest() {
private val strictContext: Context = mockk<Context>().apply { private val strictContext: Context = mockk<Context>().apply {
every { packageManager } returns pm every { packageManager } returns pm
} }
private val backupPlugin: BackupPlugin = mockk() @Suppress("Deprecation")
private val restorePlugin: RestorePlugin = mockk() private val legacyStoragePlugin: LegacyStoragePlugin = mockk()
private val storagePlugin: StoragePlugin = mockk()
private val splitCompatChecker: ApkSplitCompatibilityChecker = mockk() private val splitCompatChecker: ApkSplitCompatibilityChecker = mockk()
private val apkInstaller: ApkInstaller = mockk() private val apkInstaller: ApkInstaller = mockk()
private val apkBackup = ApkBackup(pm, crypto, settingsManager, metadataManager) private val apkBackup = ApkBackup(pm, crypto, settingsManager, metadataManager)
private val apkRestore: ApkRestore = ApkRestore( private val apkRestore: ApkRestore = ApkRestore(
context = strictContext, context = strictContext,
backupPlugin = backupPlugin, storagePlugin = storagePlugin,
restorePlugin = restorePlugin, legacyStoragePlugin = legacyStoragePlugin,
crypto = crypto, crypto = crypto,
splitCompatChecker = splitCompatChecker, splitCompatChecker = splitCompatChecker,
apkInstaller = apkInstaller apkInstaller = apkInstaller
@ -129,7 +130,7 @@ internal class ApkBackupRestoreTest : TransportTest() {
every { strictContext.cacheDir } returns tmpFile every { strictContext.cacheDir } returns tmpFile
every { crypto.getNameForApk(salt, packageName, "") } returns name every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { backupPlugin.getInputStream(token, name) } returns inputStream coEvery { storagePlugin.getInputStream(token, name) } returns inputStream
every { pm.getPackageArchiveInfo(capture(apkPath), any()) } returns packageInfo every { pm.getPackageArchiveInfo(capture(apkPath), any()) } returns packageInfo
every { every {
@Suppress("UNRESOLVED_REFERENCE") @Suppress("UNRESOLVED_REFERENCE")
@ -143,7 +144,7 @@ internal class ApkBackupRestoreTest : TransportTest() {
splitCompatChecker.isCompatible(metadata.deviceName, listOf(splitName)) splitCompatChecker.isCompatible(metadata.deviceName, listOf(splitName))
} returns true } returns true
every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName
coEvery { backupPlugin.getInputStream(token, suffixName) } returns splitInputStream coEvery { storagePlugin.getInputStream(token, suffixName) } returns splitInputStream
coEvery { coEvery {
apkInstaller.install(capture(cacheFiles), packageName, installerName, any()) apkInstaller.install(capture(cacheFiles), packageName, installerName, any())
} returns MutableInstallResult(1).apply { } returns MutableInstallResult(1).apply {

View file

@ -14,6 +14,8 @@ import com.stevesoltys.seedvault.getRandomString
import com.stevesoltys.seedvault.metadata.ApkSplit import com.stevesoltys.seedvault.metadata.ApkSplit
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.metadata.PackageMetadataMap import com.stevesoltys.seedvault.metadata.PackageMetadataMap
import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.restore.RestorableBackup import com.stevesoltys.seedvault.restore.RestorableBackup
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP
@ -21,8 +23,6 @@ import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.transport.TransportTest
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.restore.RestorePlugin
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
@ -50,15 +50,15 @@ internal class ApkRestoreTest : TransportTest() {
private val strictContext: Context = mockk<Context>().apply { private val strictContext: Context = mockk<Context>().apply {
every { packageManager } returns pm every { packageManager } returns pm
} }
private val backupPlugin: BackupPlugin = mockk() private val storagePlugin: StoragePlugin = mockk()
private val restorePlugin: RestorePlugin = mockk() private val legacyStoragePlugin: LegacyStoragePlugin = mockk()
private val splitCompatChecker: ApkSplitCompatibilityChecker = mockk() private val splitCompatChecker: ApkSplitCompatibilityChecker = mockk()
private val apkInstaller: ApkInstaller = mockk() private val apkInstaller: ApkInstaller = mockk()
private val apkRestore: ApkRestore = ApkRestore( private val apkRestore: ApkRestore = ApkRestore(
strictContext, strictContext,
backupPlugin, storagePlugin,
restorePlugin, legacyStoragePlugin,
crypto, crypto,
splitCompatChecker, splitCompatChecker,
apkInstaller apkInstaller
@ -96,7 +96,7 @@ internal class ApkRestoreTest : TransportTest() {
every { strictContext.cacheDir } returns File(tmpDir.toString()) every { strictContext.cacheDir } returns File(tmpDir.toString())
every { crypto.getNameForApk(salt, packageName, "") } returns name every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { backupPlugin.getInputStream(token, name) } returns apkInputStream coEvery { storagePlugin.getInputStream(token, name) } returns apkInputStream
apkRestore.restore(backup).collectIndexed { i, value -> apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedFailFinished(i, value) assertQueuedFailFinished(i, value)
@ -110,7 +110,7 @@ internal class ApkRestoreTest : TransportTest() {
every { strictContext.cacheDir } returns File(tmpDir.toString()) every { strictContext.cacheDir } returns File(tmpDir.toString())
every { crypto.getNameForApk(salt, packageName, "") } returns name every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { backupPlugin.getInputStream(token, name) } returns apkInputStream coEvery { storagePlugin.getInputStream(token, name) } returns apkInputStream
every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo
apkRestore.restore(backup).collectIndexed { i, value -> apkRestore.restore(backup).collectIndexed { i, value ->
@ -169,7 +169,9 @@ internal class ApkRestoreTest : TransportTest() {
every { strictContext.cacheDir } returns File(tmpDir.toString()) every { strictContext.cacheDir } returns File(tmpDir.toString())
@Suppress("Deprecation") @Suppress("Deprecation")
coEvery { restorePlugin.getApkInputStream(token, packageName, "") } returns apkInputStream coEvery {
legacyStoragePlugin.getApkInputStream(token, packageName, "")
} returns apkInputStream
every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo
every { every {
@Suppress("UNRESOLVED_REFERENCE") @Suppress("UNRESOLVED_REFERENCE")
@ -299,7 +301,7 @@ internal class ApkRestoreTest : TransportTest() {
every { splitCompatChecker.isCompatible(deviceName, listOf(splitName)) } returns true every { splitCompatChecker.isCompatible(deviceName, listOf(splitName)) } returns true
every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName
coEvery { coEvery {
backupPlugin.getInputStream(token, suffixName) storagePlugin.getInputStream(token, suffixName)
} returns ByteArrayInputStream(getRandomByteArray()) } returns ByteArrayInputStream(getRandomByteArray())
apkRestore.restore(backup).collectIndexed { i, value -> apkRestore.restore(backup).collectIndexed { i, value ->
@ -322,7 +324,7 @@ internal class ApkRestoreTest : TransportTest() {
every { splitCompatChecker.isCompatible(deviceName, listOf(splitName)) } returns true every { splitCompatChecker.isCompatible(deviceName, listOf(splitName)) } returns true
every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName
coEvery { backupPlugin.getInputStream(token, suffixName) } throws IOException() coEvery { storagePlugin.getInputStream(token, suffixName) } throws IOException()
apkRestore.restore(backup).collectIndexed { i, value -> apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressFailFinished(i, value) assertQueuedProgressFailFinished(i, value)
@ -358,9 +360,9 @@ internal class ApkRestoreTest : TransportTest() {
val suffixName1 = getRandomString() val suffixName1 = getRandomString()
val suffixName2 = getRandomString() val suffixName2 = getRandomString()
every { crypto.getNameForApk(salt, packageName, split1Name) } returns suffixName1 every { crypto.getNameForApk(salt, packageName, split1Name) } returns suffixName1
coEvery { backupPlugin.getInputStream(token, suffixName1) } returns split1InputStream coEvery { storagePlugin.getInputStream(token, suffixName1) } returns split1InputStream
every { crypto.getNameForApk(salt, packageName, split2Name) } returns suffixName2 every { crypto.getNameForApk(salt, packageName, split2Name) } returns suffixName2
coEvery { backupPlugin.getInputStream(token, suffixName2) } returns split2InputStream coEvery { storagePlugin.getInputStream(token, suffixName2) } returns split2InputStream
coEvery { coEvery {
apkInstaller.install(match { it.size == 3 }, packageName, installerName, any()) apkInstaller.install(match { it.size == 3 }, packageName, installerName, any())
@ -387,7 +389,7 @@ internal class ApkRestoreTest : TransportTest() {
private fun cacheBaseApkAndGetInfo(tmpDir: Path) { private fun cacheBaseApkAndGetInfo(tmpDir: Path) {
every { strictContext.cacheDir } returns File(tmpDir.toString()) every { strictContext.cacheDir } returns File(tmpDir.toString())
every { crypto.getNameForApk(salt, packageName, "") } returns name every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { backupPlugin.getInputStream(token, name) } returns apkInputStream coEvery { storagePlugin.getInputStream(token, name) } returns apkInputStream
every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo
every { every {
@Suppress("UNRESOLVED_REFERENCE") @Suppress("UNRESOLVED_REFERENCE")

View file

@ -16,19 +16,18 @@ import com.stevesoltys.seedvault.metadata.BackupType
import com.stevesoltys.seedvault.metadata.MetadataReaderImpl import com.stevesoltys.seedvault.metadata.MetadataReaderImpl
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.transport.backup.ApkBackup import com.stevesoltys.seedvault.transport.backup.ApkBackup
import com.stevesoltys.seedvault.transport.backup.BackupCoordinator import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.backup.FullBackup import com.stevesoltys.seedvault.transport.backup.FullBackup
import com.stevesoltys.seedvault.transport.backup.InputFactory import com.stevesoltys.seedvault.transport.backup.InputFactory
import com.stevesoltys.seedvault.transport.backup.KVBackup import com.stevesoltys.seedvault.transport.backup.KVBackup
import com.stevesoltys.seedvault.transport.backup.PackageService import com.stevesoltys.seedvault.transport.backup.PackageService
import com.stevesoltys.seedvault.transport.backup.TestKvDbManager import com.stevesoltys.seedvault.transport.backup.TestKvDbManager
import com.stevesoltys.seedvault.transport.restore.FullRestore import com.stevesoltys.seedvault.transport.restore.FullRestore
import com.stevesoltys.seedvault.transport.restore.FullRestorePlugin
import com.stevesoltys.seedvault.transport.restore.KVRestore import com.stevesoltys.seedvault.transport.restore.KVRestore
import com.stevesoltys.seedvault.transport.restore.KVRestorePlugin
import com.stevesoltys.seedvault.transport.restore.OutputFactory import com.stevesoltys.seedvault.transport.restore.OutputFactory
import com.stevesoltys.seedvault.transport.restore.RestoreCoordinator import com.stevesoltys.seedvault.transport.restore.RestoreCoordinator
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
@ -61,7 +60,9 @@ internal class CoordinatorIntegrationTest : TransportTest() {
private val notificationManager = mockk<BackupNotificationManager>() private val notificationManager = mockk<BackupNotificationManager>()
private val dbManager = TestKvDbManager() private val dbManager = TestKvDbManager()
private val backupPlugin = mockk<BackupPlugin>() @Suppress("Deprecation")
private val legacyPlugin = mockk<LegacyStoragePlugin>()
private val backupPlugin = mockk<StoragePlugin>()
private val kvBackup = private val kvBackup =
KVBackup(backupPlugin, settingsManager, inputFactory, cryptoImpl, dbManager) KVBackup(backupPlugin, settingsManager, inputFactory, cryptoImpl, dbManager)
private val fullBackup = FullBackup(backupPlugin, settingsManager, inputFactory, cryptoImpl) private val fullBackup = FullBackup(backupPlugin, settingsManager, inputFactory, cryptoImpl)
@ -80,18 +81,16 @@ internal class CoordinatorIntegrationTest : TransportTest() {
notificationManager notificationManager
) )
private val kvRestorePlugin = mockk<KVRestorePlugin>()
private val kvRestore = KVRestore( private val kvRestore = KVRestore(
backupPlugin, backupPlugin,
kvRestorePlugin, legacyPlugin,
outputFactory, outputFactory,
headerReader, headerReader,
cryptoImpl, cryptoImpl,
dbManager dbManager
) )
private val fullRestorePlugin = mockk<FullRestorePlugin>()
private val fullRestore = private val fullRestore =
FullRestore(backupPlugin, fullRestorePlugin, outputFactory, headerReader, cryptoImpl) FullRestore(backupPlugin, legacyPlugin, outputFactory, headerReader, cryptoImpl)
private val restore = RestoreCoordinator( private val restore = RestoreCoordinator(
context, context,
crypto, crypto,

View file

@ -22,6 +22,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.settings.Storage import com.stevesoltys.seedvault.settings.Storage
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
@ -44,7 +45,7 @@ import kotlin.random.Random
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class BackupCoordinatorTest : BackupTest() { internal class BackupCoordinatorTest : BackupTest() {
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val kv = mockk<KVBackup>() private val kv = mockk<KVBackup>()
private val full = mockk<FullBackup>() private val full = mockk<FullBackup>()
private val apkBackup = mockk<ApkBackup>() private val apkBackup = mockk<ApkBackup>()

View file

@ -6,6 +6,7 @@ import android.app.backup.BackupTransport.TRANSPORT_PACKAGE_REJECTED
import android.app.backup.BackupTransport.TRANSPORT_QUOTA_EXCEEDED import android.app.backup.BackupTransport.TRANSPORT_QUOTA_EXCEEDED
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.plugins.StoragePlugin
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
@ -23,7 +24,7 @@ import kotlin.random.Random
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class FullBackupTest : BackupTest() { internal class FullBackupTest : BackupTest() {
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val backup = FullBackup(plugin, settingsManager, inputFactory, crypto) private val backup = FullBackup(plugin, settingsManager, inputFactory, crypto)
private val bytes = ByteArray(23).apply { Random.nextBytes(this) } private val bytes = ByteArray(23).apply { Random.nextBytes(this) }

View file

@ -12,6 +12,7 @@ import com.stevesoltys.seedvault.getRandomString
import com.stevesoltys.seedvault.header.MAX_KEY_LENGTH_SIZE import com.stevesoltys.seedvault.header.MAX_KEY_LENGTH_SIZE
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForKV import com.stevesoltys.seedvault.header.getADForKV
import com.stevesoltys.seedvault.plugins.StoragePlugin
import io.mockk.CapturingSlot import io.mockk.CapturingSlot
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
@ -31,7 +32,7 @@ import kotlin.random.Random
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class KVBackupTest : BackupTest() { internal class KVBackupTest : BackupTest() {
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val dataInput = mockk<BackupDataInput>() private val dataInput = mockk<BackupDataInput>()
private val dbManager = mockk<KvDbManager>() private val dbManager = mockk<KvDbManager>()

View file

@ -11,7 +11,8 @@ import com.stevesoltys.seedvault.header.UnsupportedVersionException
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.VersionHeader import com.stevesoltys.seedvault.header.VersionHeader
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePlugin
import io.mockk.CapturingSlot import io.mockk.CapturingSlot
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
@ -33,8 +34,8 @@ import kotlin.random.Random
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class FullRestoreTest : RestoreTest() { internal class FullRestoreTest : RestoreTest() {
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val legacyPlugin = mockk<FullRestorePlugin>() private val legacyPlugin = mockk<LegacyStoragePlugin>()
private val restore = FullRestore(plugin, legacyPlugin, outputFactory, headerReader, crypto) private val restore = FullRestore(plugin, legacyPlugin, outputFactory, headerReader, crypto)
private val encrypted = getRandomByteArray() private val encrypted = getRandomByteArray()
@ -50,7 +51,7 @@ internal class FullRestoreTest : RestoreTest() {
@Suppress("deprecation") @Suppress("deprecation")
fun `v0 hasDataForPackage() delegates to plugin`() = runBlocking { fun `v0 hasDataForPackage() delegates to plugin`() = runBlocking {
val result = Random.nextBoolean() val result = Random.nextBoolean()
coEvery { legacyPlugin.hasDataForPackage(token, packageInfo) } returns result coEvery { legacyPlugin.hasDataForFullPackage(token, packageInfo) } returns result
assertEquals(result, restore.hasDataForPackage(token, packageInfo)) assertEquals(result, restore.hasDataForPackage(token, packageInfo))
} }

View file

@ -10,9 +10,10 @@ import com.stevesoltys.seedvault.header.UnsupportedVersionException
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.VersionHeader import com.stevesoltys.seedvault.header.VersionHeader
import com.stevesoltys.seedvault.header.getADForKV import com.stevesoltys.seedvault.header.getADForKV
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.transport.backup.KVDb import com.stevesoltys.seedvault.transport.backup.KVDb
import com.stevesoltys.seedvault.transport.backup.KvDbManager import com.stevesoltys.seedvault.transport.backup.KvDbManager
import com.stevesoltys.seedvault.plugins.StoragePlugin
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
@ -35,8 +36,8 @@ import kotlin.random.Random
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
internal class KVRestoreTest : RestoreTest() { internal class KVRestoreTest : RestoreTest() {
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val legacyPlugin = mockk<KVRestorePlugin>() private val legacyPlugin = mockk<LegacyStoragePlugin>()
private val dbManager = mockk<KvDbManager>() private val dbManager = mockk<KvDbManager>()
private val output = mockk<BackupDataOutput>() private val output = mockk<BackupDataOutput>()
private val restore = private val restore =

View file

@ -16,8 +16,8 @@ import com.stevesoltys.seedvault.metadata.MetadataReader
import com.stevesoltys.seedvault.metadata.PackageMetadata import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.settings.Storage import com.stevesoltys.seedvault.settings.Storage
import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.transport.TransportTest
import com.stevesoltys.seedvault.transport.backup.BackupPlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.transport.backup.EncryptedMetadata import com.stevesoltys.seedvault.plugins.EncryptedMetadata
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
@ -39,7 +39,7 @@ import kotlin.random.Random
internal class RestoreCoordinatorTest : TransportTest() { internal class RestoreCoordinatorTest : TransportTest() {
private val notificationManager: BackupNotificationManager = mockk() private val notificationManager: BackupNotificationManager = mockk()
private val plugin = mockk<BackupPlugin>() private val plugin = mockk<StoragePlugin>()
private val kv = mockk<KVRestore>() private val kv = mockk<KVRestore>()
private val full = mockk<FullRestore>() private val full = mockk<FullRestore>()
private val metadataReader = mockk<MetadataReader>() private val metadataReader = mockk<MetadataReader>()

View file

@ -13,10 +13,11 @@ import com.stevesoltys.seedvault.crypto.KeyManagerTestImpl
import com.stevesoltys.seedvault.encodeBase64 import com.stevesoltys.seedvault.encodeBase64
import com.stevesoltys.seedvault.header.HeaderReaderImpl import com.stevesoltys.seedvault.header.HeaderReaderImpl
import com.stevesoltys.seedvault.metadata.MetadataReaderImpl import com.stevesoltys.seedvault.metadata.MetadataReaderImpl
import com.stevesoltys.seedvault.plugins.LegacyStoragePlugin
import com.stevesoltys.seedvault.toByteArrayFromHex import com.stevesoltys.seedvault.toByteArrayFromHex
import com.stevesoltys.seedvault.transport.TransportTest import com.stevesoltys.seedvault.transport.TransportTest
import com.stevesoltys.seedvault.transport.backup.BackupPlugin
import com.stevesoltys.seedvault.transport.backup.KvDbManager import com.stevesoltys.seedvault.transport.backup.KvDbManager
import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
@ -49,19 +50,19 @@ internal class RestoreV0IntegrationTest : TransportTest() {
private val metadataReader = MetadataReaderImpl(cryptoImpl) private val metadataReader = MetadataReaderImpl(cryptoImpl)
private val notificationManager = mockk<BackupNotificationManager>() private val notificationManager = mockk<BackupNotificationManager>()
private val backupPlugin = mockk<BackupPlugin>() @Suppress("Deprecation")
private val kvRestorePlugin = mockk<KVRestorePlugin>() private val legacyPlugin = mockk<LegacyStoragePlugin>()
private val backupPlugin = mockk<StoragePlugin>()
private val kvRestore = KVRestore( private val kvRestore = KVRestore(
backupPlugin, backupPlugin,
kvRestorePlugin, legacyPlugin,
outputFactory, outputFactory,
headerReader, headerReader,
cryptoImpl, cryptoImpl,
dbManager dbManager
) )
private val fullRestorePlugin = mockk<FullRestorePlugin>()
private val fullRestore = private val fullRestore =
FullRestore(backupPlugin, fullRestorePlugin, outputFactory, headerReader, cryptoImpl) FullRestore(backupPlugin, legacyPlugin, outputFactory, headerReader, cryptoImpl)
private val restore = RestoreCoordinator( private val restore = RestoreCoordinator(
context, context,
crypto, crypto,
@ -161,7 +162,7 @@ internal class RestoreV0IntegrationTest : TransportTest() {
assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo))) assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo)))
// find data for K/V backup // find data for K/V backup
coEvery { kvRestorePlugin.hasDataForPackage(token, packageInfo) } returns true coEvery { legacyPlugin.hasDataForPackage(token, packageInfo) } returns true
val restoreDescription = restore.nextRestorePackage() ?: fail() val restoreDescription = restore.nextRestorePackage() ?: fail()
assertEquals(packageInfo.packageName, restoreDescription.packageName) assertEquals(packageInfo.packageName, restoreDescription.packageName)
@ -171,10 +172,10 @@ internal class RestoreV0IntegrationTest : TransportTest() {
val backupDataOutput = mockk<BackupDataOutput>() val backupDataOutput = mockk<BackupDataOutput>()
val rInputStream = ByteArrayInputStream(encryptedAppData) val rInputStream = ByteArrayInputStream(encryptedAppData)
val rInputStream2 = ByteArrayInputStream(encryptedAppData2) val rInputStream2 = ByteArrayInputStream(encryptedAppData2)
coEvery { kvRestorePlugin.listRecords(token, packageInfo) } returns listOf(key64, key264) coEvery { legacyPlugin.listRecords(token, packageInfo) } returns listOf(key64, key264)
every { outputFactory.getBackupDataOutput(fileDescriptor) } returns backupDataOutput every { outputFactory.getBackupDataOutput(fileDescriptor) } returns backupDataOutput
coEvery { coEvery {
kvRestorePlugin.getInputStreamForRecord( legacyPlugin.getInputStreamForRecord(
token, token,
packageInfo, packageInfo,
key64 key64
@ -183,7 +184,7 @@ internal class RestoreV0IntegrationTest : TransportTest() {
every { backupDataOutput.writeEntityHeader(key, appData.size) } returns 1137 every { backupDataOutput.writeEntityHeader(key, appData.size) } returns 1137
every { backupDataOutput.writeEntityData(appData, appData.size) } returns appData.size every { backupDataOutput.writeEntityData(appData, appData.size) } returns appData.size
coEvery { coEvery {
kvRestorePlugin.getInputStreamForRecord( legacyPlugin.getInputStreamForRecord(
token, token,
packageInfo, packageInfo,
key264 key264
@ -212,8 +213,8 @@ internal class RestoreV0IntegrationTest : TransportTest() {
assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo))) assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo)))
// find data only for full backup // find data only for full backup
coEvery { kvRestorePlugin.hasDataForPackage(token, packageInfo) } returns false coEvery { legacyPlugin.hasDataForPackage(token, packageInfo) } returns false
coEvery { fullRestorePlugin.hasDataForPackage(token, packageInfo) } returns true coEvery { legacyPlugin.hasDataForFullPackage(token, packageInfo) } returns true
val restoreDescription = restore.nextRestorePackage() ?: fail() val restoreDescription = restore.nextRestorePackage() ?: fail()
assertEquals(packageInfo.packageName, restoreDescription.packageName) assertEquals(packageInfo.packageName, restoreDescription.packageName)
@ -223,7 +224,7 @@ internal class RestoreV0IntegrationTest : TransportTest() {
val inputStream = ByteArrayInputStream(encryptedData) val inputStream = ByteArrayInputStream(encryptedData)
val outputStream = ByteArrayOutputStream() val outputStream = ByteArrayOutputStream()
coEvery { coEvery {
fullRestorePlugin.getInputStreamForPackage( legacyPlugin.getInputStreamForPackage(
token, token,
packageInfo packageInfo
) )