[db] allow setting a preferred repo per app

This commit is contained in:
Torsten Grote
2023-10-16 18:16:48 -03:00
parent f4a1d92933
commit 704234c9df
11 changed files with 1327 additions and 59 deletions

View File

@@ -62,6 +62,28 @@ internal class AppDaoTest : AppTest() {
assertEquals(0, appDao.countLocalizedFileLists())
}
@Test
fun testAppRepoPref() {
// insert same app into three repos (repoId1 has highest weight)
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
val repoId3 = repoDao.insertOrReplace(getRandomRepo())
val repoId1 = repoDao.insertOrReplace(getRandomRepo())
appDao.insert(repoId1, packageName, app1, locales)
appDao.insert(repoId2, packageName, app2, locales)
appDao.insert(repoId3, packageName, app3, locales)
// app from repo with highest weight is returned, if no prefs are set
assertEquals(app1, appDao.getApp(packageName).getOrFail()?.toMetadataV2()?.sort())
// prefer repo3 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId3))
assertEquals(app3, appDao.getApp(packageName).getOrFail()?.toMetadataV2()?.sort())
// prefer repo1 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId1))
assertEquals(app1, appDao.getApp(packageName).getOrFail()?.toMetadataV2()?.sort())
}
@Test
fun testGetSameAppFromTwoReposOneDisabled() {
// insert same app into two repos (repoId2 has highest weight)
@@ -149,6 +171,13 @@ internal class AppDaoTest : AppTest() {
assertEquals(3, appDao.getNumberOfAppsInCategory("A"))
assertEquals(2, appDao.getNumberOfAppsInCategory("B"))
assertEquals(0, appDao.getNumberOfAppsInCategory("C"))
// app1 as a variant of app2 in another repo will show one more app in B
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
appDao.insert(repoId2, packageName2, app1, locales)
assertEquals(3, appDao.getNumberOfAppsInCategory("A"))
assertEquals(3, appDao.getNumberOfAppsInCategory("B"))
assertEquals(0, appDao.getNumberOfAppsInCategory("C"))
}
@Test

View File

@@ -451,6 +451,48 @@ internal class AppListItemsTest : AppTest() {
}
}
@Test
fun testFromRepoFromAppPrefs() {
// insert same app into three repos (repoId1 has highest weight)
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
val repoId3 = repoDao.insertOrReplace(getRandomRepo())
val repoId1 = repoDao.insertOrReplace(getRandomRepo())
appDao.insert(repoId2, packageName, app2, locales)
appDao.insert(repoId1, packageName, app1, locales)
appDao.insert(repoId3, packageName, app3, locales)
// app from repo1 with highest weight gets returned
getItems { apps ->
assertEquals(1, apps.size)
assertEquals(packageName, apps[0].packageName)
assertEquals(app1, apps[0])
}
// prefer repo3 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId3))
getItems { apps ->
assertEquals(1, apps.size)
assertEquals(packageName, apps[0].packageName)
assertEquals(app3, apps[0])
}
// prefer repo2 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId2))
getItems { apps ->
assertEquals(1, apps.size)
assertEquals(packageName, apps[0].packageName)
assertEquals(app2, apps[0])
}
// prefer repo1 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId1))
getItems { apps ->
assertEquals(1, apps.size)
assertEquals(packageName, apps[0].packageName)
assertEquals(app1, apps[0])
}
}
@Test
fun testOnlyFromGivenCategories() {
// insert three apps
@@ -476,6 +518,16 @@ internal class AppListItemsTest : AppTest() {
).forEach { apps ->
assertEquals(0, apps.size)
}
// we'll add app1 as a variant of app2, so it should be in category B as well
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
appDao.insert(repoId2, packageName2, app1, locales)
listOf(
appDao.getAppListItemsByName("B").getOrFail(),
appDao.getAppListItemsByLastUpdated("B").getOrFail(),
).forEach { apps ->
assertEquals(3, apps.size) // all apps are in B now
}
}
@Test

View File

@@ -159,6 +159,63 @@ internal class AppOverviewItemsTest : AppTest() {
}
}
@Test
fun testGetByRepoPref() {
// insert same app into three repos (repoId1 has highest weight)
val repoId2 = repoDao.insertOrReplace(getRandomRepo())
val repoId3 = repoDao.insertOrReplace(getRandomRepo())
val repoId1 = repoDao.insertOrReplace(getRandomRepo())
appDao.insert(repoId1, packageName, app1, locales)
appDao.insert(repoId2, packageName, app2, locales)
appDao.insert(repoId3, packageName, app3, locales)
// app is returned correctly from repo1
appDao.getAppOverviewItems().getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app1, apps[0])
}
appDao.getAppOverviewItems("A").getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app1, apps[0])
}
// prefer repo3 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId3))
appDao.getAppOverviewItems().getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app3, apps[0])
}
appDao.getAppOverviewItems("B").getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app3, apps[0])
}
// prefer repo2 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId2))
appDao.getAppOverviewItems().getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app2, apps[0])
}
appDao.getAppOverviewItems("A").getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app2, apps[0])
}
appDao.getAppOverviewItems("B").getOrFail().let { apps ->
assertEquals(0, apps.size) // app2 is not in category B
}
// prefer repo1 for this app
appPrefsDao.update(AppPrefs(packageName, preferredRepoId = repoId1))
appDao.getAppOverviewItems().getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app1, apps[0])
}
appDao.getAppOverviewItems("A").getOrFail().let { apps ->
assertEquals(1, apps.size)
assertEquals(app1, apps[0])
}
}
@Test
fun testSortOrder() {
// insert two apps with one version each

View File

@@ -10,6 +10,7 @@ import io.mockk.every
import io.mockk.mockkObject
import kotlinx.coroutines.Dispatchers
import org.fdroid.database.TestUtils.assertRepoEquals
import org.fdroid.database.TestUtils.getOrFail
import org.fdroid.database.TestUtils.toMetadataV2
import org.fdroid.database.TestUtils.toPackageVersionV2
import org.fdroid.index.v1.IndexV1StreamProcessor
@@ -111,7 +112,7 @@ internal abstract class DbTest {
packageV2.metadata,
appDao.getApp(repoId, packageName)?.toMetadataV2()?.sort()
)
val versions = versionDao.getAppVersions(repoId, packageName).map {
val versions = versionDao.getAppVersions(repoId, packageName).getOrFail().map {
it.toPackageVersionV2()
}.associateBy { it.file.sha256 }
assertEquals(packageV2.versions.size, versions.size, "number of versions")

View File

@@ -255,7 +255,7 @@ internal class RepositoryDaoTest : DbTest() {
// data is there as expected
assertEquals(1, repoDao.getRepositories().size)
assertEquals(1, appDao.getAppMetadata().size)
assertEquals(1, versionDao.getAppVersions(repoId, packageName).size)
assertEquals(1, versionDao.getAppVersions(repoId, packageName).getOrFail().size)
assertTrue(versionDao.getVersionedStrings(repoId, packageName).isNotEmpty())
// clearing the repo removes apps and versions
@@ -264,7 +264,7 @@ internal class RepositoryDaoTest : DbTest() {
assertEquals(0, appDao.countApps())
assertEquals(0, appDao.countLocalizedFiles())
assertEquals(0, appDao.countLocalizedFileLists())
assertEquals(0, versionDao.getAppVersions(repoId, packageName).size)
assertEquals(0, versionDao.getAppVersions(repoId, packageName).getOrFail().size)
assertEquals(0, versionDao.getVersionedStrings(repoId, packageName).size)
// preferences are not touched by clearing
assertEquals(repositoryPreferences, repoDao.getRepositoryPreferences(repoId))

View File

@@ -35,6 +35,22 @@ internal class VersionTest : DbTest() {
versionId2 to packageVersion2,
)
private fun getAppVersion1(repoId: Long): AppVersion {
val version = getVersion1(repoId)
return AppVersion(
version = version,
versionedStrings = packageVersion1.manifest.getVersionedStrings(version),
)
}
private fun getAppVersion2(repoId: Long): AppVersion {
val version = getVersion2(repoId)
return AppVersion(
version = version,
versionedStrings = packageVersion2.manifest.getVersionedStrings(version),
)
}
private fun getVersion1(repoId: Long) =
packageVersion1.toVersion(repoId, packageName, versionId1, isCompatible1)
@@ -55,25 +71,22 @@ internal class VersionTest : DbTest() {
appDao.insert(repoId, packageName, getRandomMetadataV2())
versionDao.insert(repoId, packageName, versionId1, packageVersion1, isCompatible1)
val appVersions = versionDao.getAppVersions(repoId, packageName)
val appVersions = versionDao.getAppVersions(repoId, packageName).getOrFail()
assertEquals(1, appVersions.size)
val appVersion = appVersions[0]
assertEquals(versionId1, appVersion.version.versionId)
assertEquals(getVersion1(repoId), appVersion.version)
val manifest = packageVersion1.manifest
assertEquals(manifest.usesPermission.toSet(), appVersion.usesPermission.toSet())
assertEquals(manifest.usesPermissionSdk23.toSet(), appVersion.usesPermissionSdk23.toSet())
assertEquals(
manifest.features.map { it.name }.toSet(),
appVersion.version.manifest.features?.toSet()
)
assertEquals(getAppVersion1(repoId), appVersions[0])
val manifest = packageVersion1.manifest
val versionedStrings = versionDao.getVersionedStrings(repoId, packageName)
val expectedSize = manifest.usesPermission.size + manifest.usesPermissionSdk23.size
assertEquals(expectedSize, versionedStrings.size)
// getting version by repo produces same result
val versionsByRepo = versionDao.getAppVersions(repoId, packageName).getOrFail()
assertEquals(1, versionsByRepo.size)
assertEquals(getAppVersion1(repoId), versionsByRepo[0])
versionDao.deleteAppVersion(repoId, packageName, versionId1)
assertEquals(0, versionDao.getAppVersions(repoId, packageName).size)
assertEquals(0, versionDao.getAppVersions(repoId, packageName).getOrFail().size)
assertEquals(0, versionDao.getVersionedStrings(repoId, packageName).size)
}
@@ -86,39 +99,29 @@ internal class VersionTest : DbTest() {
versionDao.insert(repoId, packageName, versionId2, packageVersion2, isCompatible2)
// get app versions from DB and assign them correctly
val appVersions = versionDao.getAppVersions(packageName).getOrFail()
assertEquals(2, appVersions.size)
val appVersion = if (versionId1 == appVersions[0].version.versionId) {
appVersions[0]
} else appVersions[1]
val appVersion2 = if (versionId2 == appVersions[0].version.versionId) {
appVersions[0]
} else appVersions[1]
listOf(
versionDao.getAppVersions(packageName).getOrFail(),
versionDao.getAppVersions(repoId, packageName).getOrFail(),
).forEach { appVersions ->
assertEquals(2, appVersions.size)
val appVersion = if (versionId1 == appVersions[0].version.versionId) {
appVersions[0]
} else appVersions[1]
val appVersion2 = if (versionId2 == appVersions[0].version.versionId) {
appVersions[0]
} else appVersions[1]
// check first version matches
assertEquals(getVersion1(repoId), appVersion.version)
val manifest = packageVersion1.manifest
assertEquals(manifest.usesPermission.toSet(), appVersion.usesPermission.toSet())
assertEquals(manifest.usesPermissionSdk23.toSet(), appVersion.usesPermissionSdk23.toSet())
assertEquals(
manifest.features.map { it.name }.toSet(),
appVersion.version.manifest.features?.toSet()
)
// check first version matches
assertEquals(getAppVersion1(repoId), appVersion)
// check second version matches
assertEquals(getVersion2(repoId), appVersion2.version)
val manifest2 = packageVersion2.manifest
assertEquals(manifest2.usesPermission.toSet(), appVersion2.usesPermission.toSet())
assertEquals(manifest2.usesPermissionSdk23.toSet(),
appVersion2.usesPermissionSdk23.toSet())
assertEquals(
manifest.features.map { it.name }.toSet(),
appVersion.version.manifest.features?.toSet()
)
// check second version matches
assertEquals(getAppVersion2(repoId), appVersion2)
}
// delete app and check that all associated data also gets deleted
appDao.deleteAppMetadata(repoId, packageName)
assertEquals(0, versionDao.getAppVersions(repoId, packageName).size)
assertEquals(0, versionDao.getAppVersions(packageName).getOrFail().size)
assertEquals(0, versionDao.getAppVersions(repoId, packageName).getOrFail().size)
assertEquals(0, versionDao.getVersionedStrings(repoId, packageName).size)
}
@@ -138,6 +141,10 @@ internal class VersionTest : DbTest() {
assertEquals(3, versionDao.getAppVersions(packageName).getOrFail().size)
assertEquals(3, versionDao.getVersions(listOf(packageName)).size)
// query by repo only returns the versions from each repo
assertEquals(2, versionDao.getAppVersions(repoId, packageName).getOrFail().size)
assertEquals(1, versionDao.getAppVersions(repoId2, packageName).getOrFail().size)
// disable second repo
repoDao.setRepositoryEnabled(repoId2, false)
@@ -155,8 +162,10 @@ internal class VersionTest : DbTest() {
versionDao.insert(repoId, packageName, versionId3, packageVersion3, true)
val versions1 = versionDao.getAppVersions(packageName).getOrFail()
val versions2 = versionDao.getVersions(listOf(packageName))
val versions3 = versionDao.getAppVersions(repoId, packageName).getOrFail()
assertEquals(3, versions1.size)
assertEquals(3, versions2.size)
assertEquals(3, versions3.size)
// check that they are sorted as expected
listOf(
@@ -166,6 +175,7 @@ internal class VersionTest : DbTest() {
).sortedDescending().forEachIndexed { i, versionCode ->
assertEquals(versionCode, versions1[i].version.manifest.versionCode)
assertEquals(versionCode, versions2[i].versionCode)
assertEquals(versionCode, versions3[i].version.manifest.versionCode)
}
}