Add tests for AppSelectionManager
This commit is contained in:
parent
6143ec04ed
commit
05c39e98fa
3 changed files with 414 additions and 1 deletions
|
@ -181,6 +181,8 @@ dependencies {
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:${libs.versions.junit5.get()}")
|
testImplementation("org.junit.jupiter:junit-jupiter-api:${libs.versions.junit5.get()}")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-params:${libs.versions.junit5.get()}")
|
testImplementation("org.junit.jupiter:junit-jupiter-params:${libs.versions.junit5.get()}")
|
||||||
testImplementation("io.mockk:mockk:${libs.versions.mockk.get()}")
|
testImplementation("io.mockk:mockk:${libs.versions.mockk.get()}")
|
||||||
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:${libs.versions.coroutines.get()}")
|
||||||
|
testImplementation("app.cash.turbine:turbine:1.0.0")
|
||||||
testImplementation("org.bitcoinj:bitcoinj-core:0.16.2")
|
testImplementation("org.bitcoinj:bitcoinj-core:0.16.2")
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${libs.versions.junit5.get()}")
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${libs.versions.junit5.get()}")
|
||||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:${libs.versions.junit5.get()}")
|
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:${libs.versions.junit5.get()}")
|
||||||
|
|
|
@ -18,6 +18,7 @@ import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SYSTEM
|
||||||
import com.stevesoltys.seedvault.ui.systemData
|
import com.stevesoltys.seedvault.ui.systemData
|
||||||
import com.stevesoltys.seedvault.worker.FILE_BACKUP_ICONS
|
import com.stevesoltys.seedvault.worker.FILE_BACKUP_ICONS
|
||||||
import com.stevesoltys.seedvault.worker.IconManager
|
import com.stevesoltys.seedvault.worker.IconManager
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
@ -38,6 +39,7 @@ internal class AppSelectionManager(
|
||||||
private val pluginManager: StoragePluginManager,
|
private val pluginManager: StoragePluginManager,
|
||||||
private val iconManager: IconManager,
|
private val iconManager: IconManager,
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
|
private val workDispatcher: CoroutineDispatcher = Dispatchers.IO,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val initialState = SelectedAppsState(
|
private val initialState = SelectedAppsState(
|
||||||
|
@ -84,7 +86,7 @@ internal class AppSelectionManager(
|
||||||
selectedApps.value =
|
selectedApps.value =
|
||||||
SelectedAppsState(apps = items, allSelected = true, iconsLoaded = false)
|
SelectedAppsState(apps = items, allSelected = true, iconsLoaded = false)
|
||||||
// download icons
|
// download icons
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
coroutineScope.launch(workDispatcher) {
|
||||||
val plugin = pluginManager.appPlugin
|
val plugin = pluginManager.appPlugin
|
||||||
val token = restorableBackup.token
|
val token = restorableBackup.token
|
||||||
val packagesWithIcons = try {
|
val packagesWithIcons = try {
|
||||||
|
|
|
@ -0,0 +1,409 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 The Calyx Institute
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.stevesoltys.seedvault.restore
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import app.cash.turbine.TurbineTestContext
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER
|
||||||
|
import com.stevesoltys.seedvault.getRandomString
|
||||||
|
import com.stevesoltys.seedvault.metadata.BackupMetadata
|
||||||
|
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||||
|
import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
||||||
|
import com.stevesoltys.seedvault.plugins.StoragePlugin
|
||||||
|
import com.stevesoltys.seedvault.plugins.StoragePluginManager
|
||||||
|
import com.stevesoltys.seedvault.transport.TransportTest
|
||||||
|
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_CONTACTS
|
||||||
|
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SETTINGS
|
||||||
|
import com.stevesoltys.seedvault.ui.PACKAGE_NAME_SYSTEM
|
||||||
|
import com.stevesoltys.seedvault.worker.FILE_BACKUP_ICONS
|
||||||
|
import com.stevesoltys.seedvault.worker.IconManager
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertNull
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.Assertions.fail
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
internal class AppSelectionManagerTest : TransportTest() {
|
||||||
|
|
||||||
|
private val storagePluginManager: StoragePluginManager = mockk()
|
||||||
|
private val iconManager: IconManager = mockk()
|
||||||
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
|
private val scope = TestScope(testDispatcher)
|
||||||
|
|
||||||
|
private val packageName1 = "org.example.1"
|
||||||
|
private val packageName2 = "org.example.2"
|
||||||
|
private val packageName3 = "org.example.3"
|
||||||
|
private val packageName4 = "org.example.4"
|
||||||
|
private val backupMetadata = BackupMetadata(
|
||||||
|
token = Random.nextLong(),
|
||||||
|
salt = getRandomString(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private val appSelectionManager = AppSelectionManager(
|
||||||
|
context = context,
|
||||||
|
pluginManager = storagePluginManager,
|
||||||
|
iconManager = iconManager,
|
||||||
|
coroutineScope = scope,
|
||||||
|
workDispatcher = testDispatcher,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `apps without backup and APK, as well as system apps are filtered out`() = runTest {
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
val initialState = awaitItem()
|
||||||
|
assertEquals(emptyList<SelectableAppItem>(), initialState.apps)
|
||||||
|
assertTrue(initialState.allSelected)
|
||||||
|
assertFalse(initialState.iconsLoaded)
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
PACKAGE_NAME_SETTINGS to PackageMetadata(), // no backup and no APK
|
||||||
|
packageName1 to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
// only the meta system app item remains
|
||||||
|
assertEquals(1, initialApps.apps.size)
|
||||||
|
assertEquals(PACKAGE_NAME_SYSTEM, initialApps.apps[0].packageName)
|
||||||
|
assertTrue(initialApps.allSelected)
|
||||||
|
assertFalse(initialApps.iconsLoaded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `apps get sorted by name, special items on top`() = runTest {
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
packageName1 to PackageMetadata(
|
||||||
|
time = 23L,
|
||||||
|
name = "B",
|
||||||
|
),
|
||||||
|
packageName2 to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
name = "A",
|
||||||
|
),
|
||||||
|
PACKAGE_NAME_SETTINGS to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
assertEquals(4, initialApps.apps.size)
|
||||||
|
assertEquals(PACKAGE_NAME_SETTINGS, initialApps.apps[0].packageName)
|
||||||
|
assertEquals(PACKAGE_NAME_SYSTEM, initialApps.apps[1].packageName)
|
||||||
|
assertEquals(packageName2, initialApps.apps[2].packageName)
|
||||||
|
assertEquals(packageName1, initialApps.apps[3].packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test app selection`() = runTest {
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
packageName1 to PackageMetadata(time = 23L),
|
||||||
|
packageName2 to PackageMetadata(time = 42L),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
// first all are selected
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
assertEquals(3, initialApps.apps.size)
|
||||||
|
initialApps.apps.forEach { assertTrue(it.selected) }
|
||||||
|
assertTrue(initialApps.allSelected)
|
||||||
|
|
||||||
|
// deselect last app in list
|
||||||
|
appSelectionManager.onAppSelected(initialApps.apps[2])
|
||||||
|
val oneDeselected = awaitItem()
|
||||||
|
oneDeselected.apps.forEach {
|
||||||
|
if (it.packageName == packageName2) assertFalse(it.selected)
|
||||||
|
else assertTrue(it.selected)
|
||||||
|
}
|
||||||
|
assertFalse(oneDeselected.allSelected)
|
||||||
|
|
||||||
|
// select all apps
|
||||||
|
appSelectionManager.onCheckAllAppsClicked()
|
||||||
|
val allSelected = awaitItem()
|
||||||
|
allSelected.apps.forEach { assertTrue(it.selected) }
|
||||||
|
assertTrue(allSelected.allSelected)
|
||||||
|
|
||||||
|
// de-select all apps
|
||||||
|
appSelectionManager.onCheckAllAppsClicked()
|
||||||
|
val noneSelected = awaitItem()
|
||||||
|
noneSelected.apps.forEach { assertFalse(it.selected) }
|
||||||
|
assertFalse(noneSelected.allSelected)
|
||||||
|
|
||||||
|
// re-select first (meta) app
|
||||||
|
appSelectionManager.onAppSelected(noneSelected.apps[0])
|
||||||
|
val firstSelected = awaitItem()
|
||||||
|
firstSelected.apps.forEach {
|
||||||
|
if (it.packageName == PACKAGE_NAME_SYSTEM) assertTrue(it.selected)
|
||||||
|
else assertFalse(it.selected)
|
||||||
|
}
|
||||||
|
assertFalse(firstSelected.allSelected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test icon loading`() = scope.runTest {
|
||||||
|
expectIconLoading(setOf(packageName1)) // only icons found for packageName1
|
||||||
|
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
packageName1 to PackageMetadata(time = 23),
|
||||||
|
packageName2 to PackageMetadata(time = 42L),
|
||||||
|
PACKAGE_NAME_SETTINGS to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
// all apps (except special ones) have an unknown item state initially
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
assertEquals(4, initialApps.apps.size)
|
||||||
|
initialApps.apps.forEach {
|
||||||
|
assertNull(it.hasIcon)
|
||||||
|
}
|
||||||
|
|
||||||
|
// all apps except packageName2 have icons now
|
||||||
|
val itemsWithIcons = awaitItem()
|
||||||
|
itemsWithIcons.apps.forEach {
|
||||||
|
if (it.packageName == packageName2) assertFalse(it.hasIcon ?: fail())
|
||||||
|
else assertTrue(it.hasIcon ?: fail())
|
||||||
|
}
|
||||||
|
assertTrue(itemsWithIcons.iconsLoaded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `test icon loading fails`() = scope.runTest {
|
||||||
|
val appPlugin: StoragePlugin<*> = mockk()
|
||||||
|
every { storagePluginManager.appPlugin } returns appPlugin
|
||||||
|
coEvery {
|
||||||
|
appPlugin.getInputStream(backupMetadata.token, FILE_BACKUP_ICONS)
|
||||||
|
} throws IOException()
|
||||||
|
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
packageName1 to PackageMetadata(time = 23),
|
||||||
|
packageName2 to PackageMetadata(time = 42L),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
assertEquals(3, initialApps.apps.size)
|
||||||
|
|
||||||
|
// no apps have icons now (except special system app), but their state is known
|
||||||
|
val itemsWithoutIcons = awaitItem()
|
||||||
|
itemsWithoutIcons.apps.forEach {
|
||||||
|
if (it.packageName == PACKAGE_NAME_SYSTEM) assertTrue(it.hasIcon ?: fail())
|
||||||
|
else assertFalse(it.hasIcon ?: fail())
|
||||||
|
}
|
||||||
|
assertTrue(itemsWithoutIcons.iconsLoaded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `finishing selection filters unselected apps, leaves system apps`() = runTest {
|
||||||
|
testFiltering { backup ->
|
||||||
|
val itemsWithIcons = awaitItem()
|
||||||
|
|
||||||
|
// unselect app1 and contacts app
|
||||||
|
val app1 = itemsWithIcons.apps.find { it.packageName == packageName1 } ?: fail()
|
||||||
|
val contacts = itemsWithIcons.apps.find { it.packageName == PACKAGE_NAME_CONTACTS }
|
||||||
|
?: fail()
|
||||||
|
appSelectionManager.onAppSelected(app1)
|
||||||
|
awaitItem()
|
||||||
|
appSelectionManager.onAppSelected(contacts)
|
||||||
|
|
||||||
|
// assert that both apps are unselected
|
||||||
|
val finalSelection = awaitItem()
|
||||||
|
// we have 6 real apps (two are hidden) plus system meta item, makes 5
|
||||||
|
assertEquals(5, finalSelection.apps.size)
|
||||||
|
finalSelection.apps.forEach {
|
||||||
|
if (it.packageName in listOf(packageName1, PACKAGE_NAME_CONTACTS)) {
|
||||||
|
assertFalse(it.selected)
|
||||||
|
} else {
|
||||||
|
assertTrue(it.selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 apps should survive: app2, app3 (system app), app4 (hidden) and settings
|
||||||
|
val filteredBackup = appSelectionManager.onAppSelectionFinished(backup)
|
||||||
|
assertEquals(4, filteredBackup.packageMetadataMap.size)
|
||||||
|
assertEquals(
|
||||||
|
setOf(packageName2, packageName3, packageName4, PACKAGE_NAME_SETTINGS),
|
||||||
|
filteredBackup.packageMetadataMap.keys,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `finishing selection without system apps only removes non-special system apps`() = runTest {
|
||||||
|
testFiltering { backup ->
|
||||||
|
val itemsWithIcons = awaitItem()
|
||||||
|
|
||||||
|
// unselect all system apps and settings, contacts should stay
|
||||||
|
val systemMeta = itemsWithIcons.apps.find { it.packageName == PACKAGE_NAME_SYSTEM }
|
||||||
|
?: fail()
|
||||||
|
val settings = itemsWithIcons.apps.find { it.packageName == PACKAGE_NAME_SETTINGS }
|
||||||
|
?: fail()
|
||||||
|
appSelectionManager.onAppSelected(systemMeta)
|
||||||
|
awaitItem()
|
||||||
|
appSelectionManager.onAppSelected(settings)
|
||||||
|
|
||||||
|
// assert that both apps are unselected
|
||||||
|
val finalSelection = awaitItem()
|
||||||
|
// we have 6 real apps (two are hidden) plus system meta item, makes 5
|
||||||
|
assertEquals(5, finalSelection.apps.size)
|
||||||
|
finalSelection.apps.forEach {
|
||||||
|
if (it.packageName in listOf(PACKAGE_NAME_SYSTEM, PACKAGE_NAME_SETTINGS)) {
|
||||||
|
assertFalse(it.selected)
|
||||||
|
} else {
|
||||||
|
assertTrue(it.selected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 apps should survive: app1, app2, app4 (hidden) and contacts
|
||||||
|
val filteredBackup = appSelectionManager.onAppSelectionFinished(backup)
|
||||||
|
assertEquals(4, filteredBackup.packageMetadataMap.size)
|
||||||
|
assertEquals(
|
||||||
|
setOf(packageName1, packageName2, packageName4, PACKAGE_NAME_CONTACTS),
|
||||||
|
filteredBackup.packageMetadataMap.keys,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `@pm@ doesn't get filtered out`() = runTest {
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mutableMapOf(
|
||||||
|
MAGIC_PACKAGE_MANAGER to PackageMetadata(
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
// only system apps meta item in list
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
assertEquals(1, initialApps.apps.size)
|
||||||
|
assertEquals(PACKAGE_NAME_SYSTEM, initialApps.apps[0].packageName)
|
||||||
|
|
||||||
|
// actual filtered backup includes @pm@ only
|
||||||
|
val filteredBackup = appSelectionManager.onAppSelectionFinished(backup)
|
||||||
|
assertEquals(1, filteredBackup.packageMetadataMap.size)
|
||||||
|
assertEquals(
|
||||||
|
setOf(MAGIC_PACKAGE_MANAGER),
|
||||||
|
filteredBackup.packageMetadataMap.keys,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRestorableBackup(map: Map<String, PackageMetadata>): RestorableBackup {
|
||||||
|
return RestorableBackup(backupMetadata.copy(packageMetadataMap = map as PackageMetadataMap))
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun testFiltering(
|
||||||
|
block: suspend TurbineTestContext<SelectedAppsState>.(RestorableBackup) -> Unit,
|
||||||
|
) {
|
||||||
|
expectIconLoading()
|
||||||
|
appSelectionManager.selectedAppsFlow.test {
|
||||||
|
awaitItem()
|
||||||
|
|
||||||
|
val backup = getRestorableBackup(
|
||||||
|
mapOf(
|
||||||
|
packageName1 to PackageMetadata(time = 23L),
|
||||||
|
packageName2 to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = true,
|
||||||
|
),
|
||||||
|
packageName3 to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
packageName4 to PackageMetadata(), // no backup and no APK
|
||||||
|
PACKAGE_NAME_CONTACTS to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
PACKAGE_NAME_SETTINGS to PackageMetadata(
|
||||||
|
time = 42L,
|
||||||
|
system = true,
|
||||||
|
isLaunchableSystemApp = false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
appSelectionManager.onRestoreSetChosen(backup)
|
||||||
|
|
||||||
|
val initialApps = awaitItem()
|
||||||
|
// we have 6 real apps (two are hidden) plus system meta item, makes 5
|
||||||
|
assertEquals(5, initialApps.apps.size)
|
||||||
|
block(backup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expectIconLoading(icons: Set<String> = setOf(packageName1, packageName2)) {
|
||||||
|
val appPlugin: StoragePlugin<*> = mockk()
|
||||||
|
val inputStream = ByteArrayInputStream(Random.nextBytes(42))
|
||||||
|
every { storagePluginManager.appPlugin } returns appPlugin
|
||||||
|
coEvery {
|
||||||
|
appPlugin.getInputStream(backupMetadata.token, FILE_BACKUP_ICONS)
|
||||||
|
} returns inputStream
|
||||||
|
every {
|
||||||
|
iconManager.downloadIcons(backupMetadata.version, backupMetadata.token, inputStream)
|
||||||
|
} returns icons
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue