Make RestoreCoordinator use the new storage API with salt and backup type
This breaks restores until all the other required changed have been implemented.
This commit is contained in:
parent
75cf014e5d
commit
4bdaaa0ce9
6 changed files with 159 additions and 25 deletions
|
@ -13,8 +13,10 @@ import android.os.ParcelFileDescriptor
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER
|
import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER
|
||||||
import com.stevesoltys.seedvault.R
|
import com.stevesoltys.seedvault.R
|
||||||
|
import com.stevesoltys.seedvault.crypto.Crypto
|
||||||
import com.stevesoltys.seedvault.header.UnsupportedVersionException
|
import com.stevesoltys.seedvault.header.UnsupportedVersionException
|
||||||
import com.stevesoltys.seedvault.metadata.BackupMetadata
|
import com.stevesoltys.seedvault.metadata.BackupMetadata
|
||||||
|
import com.stevesoltys.seedvault.metadata.BackupType
|
||||||
import com.stevesoltys.seedvault.metadata.DecryptionFailedException
|
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
|
||||||
|
@ -40,6 +42,7 @@ private val TAG = RestoreCoordinator::class.java.simpleName
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
internal class RestoreCoordinator(
|
internal class RestoreCoordinator(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
private val crypto: Crypto,
|
||||||
private val settingsManager: SettingsManager,
|
private val settingsManager: SettingsManager,
|
||||||
private val metadataManager: MetadataManager,
|
private val metadataManager: MetadataManager,
|
||||||
private val notificationManager: BackupNotificationManager,
|
private val notificationManager: BackupNotificationManager,
|
||||||
|
@ -193,22 +196,59 @@ internal class RestoreCoordinator(
|
||||||
val state = this.state ?: throw IllegalStateException("no state")
|
val state = this.state ?: throw IllegalStateException("no state")
|
||||||
|
|
||||||
if (!state.packages.hasNext()) return NO_MORE_PACKAGES
|
if (!state.packages.hasNext()) return NO_MORE_PACKAGES
|
||||||
val version = state.backupMetadata.version
|
|
||||||
val packageInfo = state.packages.next()
|
val packageInfo = state.packages.next()
|
||||||
val packageName = packageInfo.packageName
|
val version = state.backupMetadata.version
|
||||||
|
if (version == 0.toByte()) return nextRestorePackageV0(state, packageInfo)
|
||||||
|
|
||||||
|
val packageName = packageInfo.packageName
|
||||||
|
val type = try {
|
||||||
|
when (state.backupMetadata.packageMetadataMap[packageName]?.backupType) {
|
||||||
|
BackupType.KV -> {
|
||||||
|
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
|
||||||
|
if (plugin.hasData(state.token, name)) {
|
||||||
|
Log.i(TAG, "Found K/V data for $packageName.")
|
||||||
|
kv.initializeState(version, state.token, packageInfo, state.pmPackageInfo)
|
||||||
|
state.currentPackage = packageName
|
||||||
|
TYPE_KEY_VALUE
|
||||||
|
} else throw IOException("No data found for $packageName. Skipping.")
|
||||||
|
}
|
||||||
|
BackupType.FULL -> {
|
||||||
|
val name = crypto.getNameForPackage(state.backupMetadata.salt, packageName)
|
||||||
|
if (plugin.hasData(state.token, name)) {
|
||||||
|
Log.i(TAG, "Found full backup data for $packageName.")
|
||||||
|
full.initializeState(version, state.token, packageInfo)
|
||||||
|
state.currentPackage = packageName
|
||||||
|
TYPE_FULL_STREAM
|
||||||
|
} else throw IOException("No data found for $packageName. Skipping.")
|
||||||
|
}
|
||||||
|
null -> throw IOException("No backup type found for $packageName. Skipping.")
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Error finding restore data for $packageName.", e)
|
||||||
|
failedPackages.add(packageName)
|
||||||
|
// don't return null and cause abort here, but try next package
|
||||||
|
return nextRestorePackage()
|
||||||
|
}
|
||||||
|
return RestoreDescription(packageName, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun nextRestorePackageV0(
|
||||||
|
state: RestoreCoordinatorState,
|
||||||
|
packageInfo: PackageInfo
|
||||||
|
): RestoreDescription? {
|
||||||
|
val packageName = packageInfo.packageName
|
||||||
val type = try {
|
val type = try {
|
||||||
when {
|
when {
|
||||||
// check key/value data first and if available, don't even check for full data
|
// check key/value data first and if available, don't even check for full data
|
||||||
kv.hasDataForPackage(state.token, packageInfo) -> {
|
kv.hasDataForPackage(state.token, packageInfo) -> {
|
||||||
Log.i(TAG, "Found K/V data for $packageName.")
|
Log.i(TAG, "Found K/V data for $packageName.")
|
||||||
kv.initializeState(version, state.token, packageInfo, state.pmPackageInfo)
|
kv.initializeState(0x00, state.token, packageInfo, state.pmPackageInfo)
|
||||||
state.currentPackage = packageName
|
state.currentPackage = packageName
|
||||||
TYPE_KEY_VALUE
|
TYPE_KEY_VALUE
|
||||||
}
|
}
|
||||||
full.hasDataForPackage(state.token, packageInfo) -> {
|
full.hasDataForPackage(state.token, packageInfo) -> {
|
||||||
Log.i(TAG, "Found full backup data for $packageName.")
|
Log.i(TAG, "Found full backup data for $packageName.")
|
||||||
full.initializeState(version, state.token, packageInfo)
|
full.initializeState(0x00, state.token, packageInfo)
|
||||||
state.currentPackage = packageName
|
state.currentPackage = packageName
|
||||||
TYPE_FULL_STREAM
|
TYPE_FULL_STREAM
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,5 +7,7 @@ val restoreModule = module {
|
||||||
single { OutputFactory() }
|
single { OutputFactory() }
|
||||||
single { KVRestore(get<RestorePlugin>().kvRestorePlugin, get(), get(), get()) }
|
single { KVRestore(get<RestorePlugin>().kvRestorePlugin, get(), get(), get()) }
|
||||||
single { FullRestore(get<RestorePlugin>().fullRestorePlugin, get(), get(), get()) }
|
single { FullRestore(get<RestorePlugin>().fullRestorePlugin, get(), get(), get()) }
|
||||||
single { RestoreCoordinator(androidContext(), get(), get(), get(), get(), get(), get(), get()) }
|
single {
|
||||||
|
RestoreCoordinator(androidContext(), get(), get(), get(), get(), get(), get(), get(), get())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
||||||
FullRestore(fullRestorePlugin, outputFactory, headerReader, cryptoImpl)
|
FullRestore(fullRestorePlugin, outputFactory, headerReader, cryptoImpl)
|
||||||
private val restore = RestoreCoordinator(
|
private val restore = RestoreCoordinator(
|
||||||
context,
|
context,
|
||||||
|
crypto,
|
||||||
settingsManager,
|
settingsManager,
|
||||||
metadataManager,
|
metadataManager,
|
||||||
notificationManager,
|
notificationManager,
|
||||||
|
@ -186,7 +187,8 @@ internal class CoordinatorIntegrationTest : 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
|
every { crypto.getNameForPackage(metadata.salt, packageInfo.packageName) } returns name
|
||||||
|
coEvery { backupPlugin.hasData(token, name) } returns true
|
||||||
|
|
||||||
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
||||||
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
||||||
|
@ -262,7 +264,8 @@ internal class CoordinatorIntegrationTest : 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
|
every { crypto.getNameForPackage(metadata.salt, packageInfo.packageName) } returns name
|
||||||
|
coEvery { backupPlugin.hasData(token, name) } returns true
|
||||||
|
|
||||||
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
||||||
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
||||||
|
@ -288,6 +291,11 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test full backup and restore with two chunks`() = runBlocking {
|
fun `test full backup and restore with two chunks`() = runBlocking {
|
||||||
|
// package is of type FULL
|
||||||
|
val packageMetadata = metadata.packageMetadataMap[packageInfo.packageName]!!
|
||||||
|
metadata.packageMetadataMap[packageInfo.packageName] =
|
||||||
|
packageMetadata.copy(backupType = BackupType.FULL)
|
||||||
|
|
||||||
// return streams from plugin and app data
|
// return streams from plugin and app data
|
||||||
val bOutputStream = ByteArrayOutputStream()
|
val bOutputStream = ByteArrayOutputStream()
|
||||||
val bInputStream = ByteArrayInputStream(appData)
|
val bInputStream = ByteArrayInputStream(appData)
|
||||||
|
@ -327,9 +335,9 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata)
|
||||||
assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo)))
|
assertEquals(TRANSPORT_OK, restore.startRestore(token, arrayOf(packageInfo)))
|
||||||
|
|
||||||
// find data only for full backup
|
// finds data for full backup
|
||||||
coEvery { kvRestorePlugin.hasDataForPackage(token, packageInfo) } returns false
|
every { crypto.getNameForPackage(metadata.salt, packageInfo.packageName) } returns name
|
||||||
coEvery { fullRestorePlugin.hasDataForPackage(token, packageInfo) } returns true
|
coEvery { backupPlugin.hasData(token, name) } returns true
|
||||||
|
|
||||||
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
val restoreDescription = restore.nextRestorePackage() ?: fail()
|
||||||
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
assertEquals(packageInfo.packageName, restoreDescription.packageName)
|
||||||
|
|
|
@ -13,8 +13,11 @@ import com.stevesoltys.seedvault.crypto.Crypto
|
||||||
import com.stevesoltys.seedvault.getRandomBase64
|
import com.stevesoltys.seedvault.getRandomBase64
|
||||||
import com.stevesoltys.seedvault.getRandomString
|
import com.stevesoltys.seedvault.getRandomString
|
||||||
import com.stevesoltys.seedvault.metadata.BackupMetadata
|
import com.stevesoltys.seedvault.metadata.BackupMetadata
|
||||||
|
import com.stevesoltys.seedvault.metadata.BackupType
|
||||||
import com.stevesoltys.seedvault.metadata.METADATA_SALT_SIZE
|
import com.stevesoltys.seedvault.metadata.METADATA_SALT_SIZE
|
||||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||||
|
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||||
|
import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
||||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
|
@ -50,8 +53,13 @@ internal abstract class TransportTest {
|
||||||
salt = getRandomBase64(METADATA_SALT_SIZE),
|
salt = getRandomBase64(METADATA_SALT_SIZE),
|
||||||
androidVersion = Random.nextInt(),
|
androidVersion = Random.nextInt(),
|
||||||
androidIncremental = getRandomString(),
|
androidIncremental = getRandomString(),
|
||||||
deviceName = getRandomString()
|
deviceName = getRandomString(),
|
||||||
|
packageMetadataMap = PackageMetadataMap().apply {
|
||||||
|
put(packageInfo.packageName, PackageMetadata(backupType = BackupType.KV))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
protected val name = getRandomString(12)
|
||||||
|
protected val name2 = getRandomString(23)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
mockkStatic(Log::class)
|
mockkStatic(Log::class)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.os.ParcelFileDescriptor
|
||||||
import com.stevesoltys.seedvault.coAssertThrows
|
import com.stevesoltys.seedvault.coAssertThrows
|
||||||
import com.stevesoltys.seedvault.getRandomString
|
import com.stevesoltys.seedvault.getRandomString
|
||||||
import com.stevesoltys.seedvault.header.VERSION
|
import com.stevesoltys.seedvault.header.VERSION
|
||||||
|
import com.stevesoltys.seedvault.metadata.BackupType
|
||||||
import com.stevesoltys.seedvault.metadata.MetadataReader
|
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
|
||||||
|
@ -45,6 +46,7 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
|
|
||||||
private val restore = RestoreCoordinator(
|
private val restore = RestoreCoordinator(
|
||||||
context,
|
context,
|
||||||
|
crypto,
|
||||||
settingsManager,
|
settingsManager,
|
||||||
metadataManager,
|
metadataManager,
|
||||||
notificationManager,
|
notificationManager,
|
||||||
|
@ -66,6 +68,11 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
private val packageName = packageInfo.packageName
|
private val packageName = packageInfo.packageName
|
||||||
private val storageName = getRandomString()
|
private val storageName = getRandomString()
|
||||||
|
|
||||||
|
init {
|
||||||
|
metadata.packageMetadataMap[packageInfo2.packageName] =
|
||||||
|
PackageMetadata(backupType = BackupType.FULL)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getAvailableRestoreSets() builds set from plugin response`() = runBlocking {
|
fun `getAvailableRestoreSets() builds set from plugin response`() = runBlocking {
|
||||||
val encryptedMetadata = EncryptedMetadata(token) { inputStream }
|
val encryptedMetadata = EncryptedMetadata(token) { inputStream }
|
||||||
|
@ -210,37 +217,69 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nextRestorePackage() returns KV description and takes precedence`() = runBlocking {
|
fun `nextRestorePackage() returns KV description`() = runBlocking {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata)
|
||||||
restore.startRestore(token, packageInfoArray)
|
restore.startRestore(token, packageInfoArray)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } returns true
|
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
|
||||||
|
coEvery { plugin.hasData(token, name) } returns true
|
||||||
every { kv.initializeState(VERSION, token, packageInfo) } just Runs
|
every { kv.initializeState(VERSION, token, packageInfo) } just Runs
|
||||||
|
|
||||||
|
val expected = RestoreDescription(packageName, TYPE_KEY_VALUE)
|
||||||
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `v0 nextRestorePackage() returns KV description and takes precedence`() = runBlocking {
|
||||||
|
restore.beforeStartRestore(metadata.copy(version = 0x00))
|
||||||
|
restore.startRestore(token, packageInfoArray)
|
||||||
|
|
||||||
|
coEvery { kv.hasDataForPackage(token, packageInfo) } returns true
|
||||||
|
every { kv.initializeState(0x00, token, packageInfo) } just Runs
|
||||||
|
|
||||||
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
|
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
|
||||||
assertEquals(expected, restore.nextRestorePackage())
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nextRestorePackage() returns full description if no KV data found`() = runBlocking {
|
fun `v0 nextRestorePackage() returns full description if no KV data found`() = runBlocking {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata.copy(version = 0x00))
|
||||||
restore.startRestore(token, packageInfoArray)
|
restore.startRestore(token, packageInfoArray)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } returns false
|
coEvery { kv.hasDataForPackage(token, packageInfo) } returns false
|
||||||
coEvery { full.hasDataForPackage(token, packageInfo) } returns true
|
coEvery { full.hasDataForPackage(token, packageInfo) } returns true
|
||||||
every { full.initializeState(VERSION, token, packageInfo) } just Runs
|
every { full.initializeState(0x00, token, packageInfo) } just Runs
|
||||||
|
|
||||||
val expected = RestoreDescription(packageInfo.packageName, TYPE_FULL_STREAM)
|
val expected = RestoreDescription(packageInfo.packageName, TYPE_FULL_STREAM)
|
||||||
assertEquals(expected, restore.nextRestorePackage())
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `nextRestorePackage() returns NO_MORE_PACKAGES if data found`() = runBlocking {
|
fun `nextRestorePackage() returns NO_MORE_PACKAGES if data not found`() = runBlocking {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata)
|
||||||
restore.startRestore(token, packageInfoArray)
|
restore.startRestore(token, packageInfoArray2)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } returns false
|
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
|
||||||
coEvery { full.hasDataForPackage(token, packageInfo) } returns false
|
coEvery { plugin.hasData(token, name) } returns false
|
||||||
|
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
|
||||||
|
coEvery { plugin.hasData(token, name2) } returns false
|
||||||
|
|
||||||
|
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `nextRestorePackage() tries next package if one has no backup type()`() = runBlocking {
|
||||||
|
metadata.packageMetadataMap[packageName] =
|
||||||
|
metadata.packageMetadataMap[packageName]!!.copy(backupType = null)
|
||||||
|
restore.beforeStartRestore(metadata)
|
||||||
|
restore.startRestore(token, packageInfoArray2)
|
||||||
|
|
||||||
|
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
|
||||||
|
coEvery { plugin.hasData(token, name2) } returns true
|
||||||
|
every { full.initializeState(VERSION, token, packageInfo2) } just Runs
|
||||||
|
|
||||||
|
val expected = RestoreDescription(packageInfo2.packageName, TYPE_FULL_STREAM)
|
||||||
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
|
|
||||||
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
|
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
|
||||||
}
|
}
|
||||||
|
@ -250,15 +289,38 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata)
|
||||||
restore.startRestore(token, packageInfoArray2)
|
restore.startRestore(token, packageInfoArray2)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } returns true
|
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
|
||||||
|
coEvery { plugin.hasData(token, name) } returns true
|
||||||
every { kv.initializeState(VERSION, token, packageInfo) } just Runs
|
every { kv.initializeState(VERSION, token, packageInfo) } just Runs
|
||||||
|
|
||||||
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
|
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
|
||||||
assertEquals(expected, restore.nextRestorePackage())
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
|
|
||||||
|
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
|
||||||
|
coEvery { plugin.hasData(token, name2) } returns true
|
||||||
|
every { full.initializeState(VERSION, token, packageInfo2) } just Runs
|
||||||
|
|
||||||
|
val expected2 =
|
||||||
|
RestoreDescription(packageInfo2.packageName, TYPE_FULL_STREAM)
|
||||||
|
assertEquals(expected2, restore.nextRestorePackage())
|
||||||
|
|
||||||
|
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `v0 nextRestorePackage() returns all packages from startRestore()`() = runBlocking {
|
||||||
|
restore.beforeStartRestore(metadata.copy(version = 0x00))
|
||||||
|
restore.startRestore(token, packageInfoArray2)
|
||||||
|
|
||||||
|
coEvery { kv.hasDataForPackage(token, packageInfo) } returns true
|
||||||
|
every { kv.initializeState(0.toByte(), token, packageInfo) } just Runs
|
||||||
|
|
||||||
|
val expected = RestoreDescription(packageInfo.packageName, TYPE_KEY_VALUE)
|
||||||
|
assertEquals(expected, restore.nextRestorePackage())
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo2) } returns false
|
coEvery { kv.hasDataForPackage(token, packageInfo2) } returns false
|
||||||
coEvery { full.hasDataForPackage(token, packageInfo2) } returns true
|
coEvery { full.hasDataForPackage(token, packageInfo2) } returns true
|
||||||
every { full.initializeState(VERSION, token, packageInfo2) } just Runs
|
every { full.initializeState(0.toByte(), token, packageInfo2) } just Runs
|
||||||
|
|
||||||
val expected2 = RestoreDescription(packageInfo2.packageName, TYPE_FULL_STREAM)
|
val expected2 = RestoreDescription(packageInfo2.packageName, TYPE_FULL_STREAM)
|
||||||
assertEquals(expected2, restore.nextRestorePackage())
|
assertEquals(expected2, restore.nextRestorePackage())
|
||||||
|
@ -267,8 +329,8 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when kv#hasDataForPackage() throws, it tries next package`() = runBlocking {
|
fun `v0 when kv#hasDataForPackage() throws, it tries next package`() = runBlocking {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata.copy(version = 0x00))
|
||||||
restore.startRestore(token, packageInfoArray)
|
restore.startRestore(token, packageInfoArray)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } throws IOException()
|
coEvery { kv.hasDataForPackage(token, packageInfo) } throws IOException()
|
||||||
|
@ -277,8 +339,21 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when full#hasDataForPackage() throws, it tries next package`() = runBlocking {
|
fun `when plugin#hasData() throws, it tries next package`() = runBlocking {
|
||||||
restore.beforeStartRestore(metadata)
|
restore.beforeStartRestore(metadata)
|
||||||
|
restore.startRestore(token, packageInfoArray2)
|
||||||
|
|
||||||
|
every { crypto.getNameForPackage(metadata.salt, packageName) } returns name
|
||||||
|
coEvery { plugin.hasData(token, name) } returns false
|
||||||
|
every { crypto.getNameForPackage(metadata.salt, packageInfo2.packageName) } returns name2
|
||||||
|
coEvery { plugin.hasData(token, name2) } throws IOException()
|
||||||
|
|
||||||
|
assertEquals(NO_MORE_PACKAGES, restore.nextRestorePackage())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `v0 when full#hasDataForPackage() throws, it tries next package`() = runBlocking {
|
||||||
|
restore.beforeStartRestore(metadata.copy(version = 0x00))
|
||||||
restore.startRestore(token, packageInfoArray)
|
restore.startRestore(token, packageInfoArray)
|
||||||
|
|
||||||
coEvery { kv.hasDataForPackage(token, packageInfo) } returns false
|
coEvery { kv.hasDataForPackage(token, packageInfo) } returns false
|
||||||
|
|
|
@ -55,6 +55,7 @@ internal class RestoreV0IntegrationTest : TransportTest() {
|
||||||
FullRestore(fullRestorePlugin, outputFactory, headerReader, cryptoImpl)
|
FullRestore(fullRestorePlugin, outputFactory, headerReader, cryptoImpl)
|
||||||
private val restore = RestoreCoordinator(
|
private val restore = RestoreCoordinator(
|
||||||
context,
|
context,
|
||||||
|
crypto,
|
||||||
settingsManager,
|
settingsManager,
|
||||||
metadataManager,
|
metadataManager,
|
||||||
notificationManager,
|
notificationManager,
|
||||||
|
|
Loading…
Reference in a new issue