Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cbf3ea53 authored by Hasib Prince's avatar Hasib Prince
Browse files

fixed some logic in fusedapiimpl

added some unit test
some refactoring
parent a1021890
Loading
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -27,14 +27,14 @@ class FdroidRepository @Inject constructor(
            }
    }

    suspend fun isFdroidApplication(packageName: String): Boolean {
        return fdroidApi.getFdroidInfoForPackage(packageName).isSuccessful
    }

    suspend fun isFdroidApplicationSigned(context: Context, packageName: String, apkFilePath: String, signature: String): Boolean {
        if (isFdroidApplication(packageName)) {
            return ApkSignatureManager.verifyFdroidSignature(context, apkFilePath, signature)
        }
        return false
    }

    private suspend fun isFdroidApplication(packageName: String): Boolean {
        return fdroidApi.getFdroidInfoForPackage(packageName).isSuccessful
    }
}
+36 −17
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ class FusedAPIImpl @Inject constructor(

    companion object {
        private const val CATEGORY_TITLE_REPLACEABLE_CONJUNCTION = "&"

        /*
         * Removing "private" access specifier to allow access in
         * MainActivityViewModel.timeoutAlertDialog
@@ -184,7 +185,10 @@ class FusedAPIImpl @Inject constructor(
     *
     * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5413
     */
    suspend fun getCategoriesList(type: Category.Type, authData: AuthData): Triple<List<FusedCategory>, String, ResultStatus> {
    suspend fun getCategoriesList(
        type: Category.Type,
        authData: AuthData
    ): Triple<List<FusedCategory>, String, ResultStatus> {
        val categoriesList = mutableListOf<FusedCategory>()
        val preferredApplicationType = preferenceManagerModule.preferredApplicationType()
        var apiStatus: ResultStatus = ResultStatus.OK
@@ -242,7 +246,8 @@ class FusedAPIImpl @Inject constructor(
                                gplayPackageResult = it.first
                            }
                        }
                    } catch (_: Exception) {}
                    } catch (_: Exception) {
                    }
                }
                getCleanapkSearchResult(query).let {
                    /* Cleanapk always returns something, it is never null.
@@ -314,7 +319,12 @@ class FusedAPIImpl @Inject constructor(
                             * If there had to be any timeout, it would already have happened
                             * while fetching package specific results.
                             */
                            ResultSupreme.Success(Pair(filterWithKeywordSearch(it.first), it.second))
                            ResultSupreme.Success(
                                Pair(
                                    filterWithKeywordSearch(it.first),
                                    it.second
                                )
                            )
                        }
                    )
                }
@@ -454,7 +464,8 @@ class FusedAPIImpl @Inject constructor(
    ): ResultSupreme<StreamBundle> {
        var streamBundle = StreamBundle()
        val status = runCodeBlockWithTimeout({
            streamBundle = gPlayAPIRepository.getNextStreamBundle(authData, homeUrl, currentStreamBundle)
            streamBundle =
                gPlayAPIRepository.getNextStreamBundle(authData, homeUrl, currentStreamBundle)
        })
        return ResultSupreme.create(status, streamBundle)
    }
@@ -466,7 +477,8 @@ class FusedAPIImpl @Inject constructor(
    ): ResultSupreme<StreamCluster> {
        var streamCluster = StreamCluster()
        val status = runCodeBlockWithTimeout({
            streamCluster = gPlayAPIRepository.getAdjustedFirstCluster(authData, streamBundle, pointer)
            streamCluster =
                gPlayAPIRepository.getAdjustedFirstCluster(authData, streamBundle, pointer)
        })
        return ResultSupreme.create(status, streamCluster)
    }
@@ -482,7 +494,10 @@ class FusedAPIImpl @Inject constructor(
        return ResultSupreme.create(status, streamCluster)
    }

    suspend fun getPlayStoreApps(browseUrl: String, authData: AuthData): ResultSupreme<List<FusedApp>> {
    suspend fun getPlayStoreApps(
        browseUrl: String,
        authData: AuthData
    ): ResultSupreme<List<FusedApp>> {
        val list = mutableListOf<FusedApp>()
        val status = runCodeBlockWithTimeout({
            list.addAll(
@@ -670,6 +685,11 @@ class FusedAPIImpl @Inject constructor(
            return if (fusedApp.origin == Origin.GPLAY) FilterLevel.UNKNOWN
            else FilterLevel.NONE
        }

        if (!fusedApp.isFree && fusedApp.price.isBlank()) {
            return FilterLevel.UI
        }

        if (fusedApp.restriction != Constants.Restriction.NOT_RESTRICTED) {
            /*
             * Check if app details can be shown. If not then remove the app from lists.
@@ -694,14 +714,9 @@ class FusedAPIImpl @Inject constructor(
            } catch (e: Exception) {
                return FilterLevel.UI
            }
        } else {
            if (!fusedApp.isFree && fusedApp.price.isBlank()) {
        } else if (fusedApp.originalSize == 0L) {
            return FilterLevel.UI
        }
            if (fusedApp.originalSize == 0L) {
                return FilterLevel.UI
            }
        }
        return FilterLevel.NONE
    }

@@ -1276,7 +1291,7 @@ class FusedAPIImpl @Inject constructor(

        oldHomeData.forEach {
            val fusedHome = newHomeData[oldHomeData.indexOf(it)]
            if (!it.title.contentEquals(fusedHome.title) || !areFusedAppsUpdated(it, fusedHome)) {
            if (!it.title.contentEquals(fusedHome.title) || areFusedAppsUpdated(it, fusedHome)) {
                return true
            }
        }
@@ -1288,15 +1303,18 @@ class FusedAPIImpl @Inject constructor(
        newFusedHome: FusedHome,
    ): Boolean {
        val fusedAppDiffUtil = HomeChildFusedAppDiffUtil()
        if (oldFusedHome.list.size != newFusedHome.list.size) {
            return true
        }

        oldFusedHome.list.forEach { oldFusedApp ->
            val indexOfOldFusedApp = oldFusedHome.list.indexOf(oldFusedApp)
            val fusedApp = newFusedHome.list[indexOfOldFusedApp]
            if (!fusedAppDiffUtil.areContentsTheSame(oldFusedApp, fusedApp)) {
                return false
                return true
            }
        }
        return true
        return false
    }

    /**
@@ -1325,7 +1343,8 @@ class FusedAPIImpl @Inject constructor(
            if (it.status == Status.INSTALLATION_ISSUE) {
                return@forEach
            }
            val currentAppStatus = pkgManagerModule.getPackageStatus(it.package_name, it.latest_version_code)
            val currentAppStatus =
                pkgManagerModule.getPackageStatus(it.package_name, it.latest_version_code)
            if (it.status != currentAppStatus) {
                return true
            }
+287 −0
Original line number Diff line number Diff line
@@ -18,14 +18,23 @@
package foundation.e.apps

import android.content.Context
import com.aurora.gplayapi.Constants
import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.AuthData
import foundation.e.apps.api.cleanapk.CleanAPKRepository
import foundation.e.apps.api.fused.FusedAPIImpl
import foundation.e.apps.api.fused.data.FusedApp
import foundation.e.apps.api.fused.data.FusedHome
import foundation.e.apps.api.gplay.GPlayAPIRepository
import foundation.e.apps.manager.pkg.PkgManagerModule
import foundation.e.apps.utils.enums.FilterLevel
import foundation.e.apps.utils.enums.Origin
import foundation.e.apps.utils.enums.Status
import foundation.e.apps.utils.modules.PWAManagerModule
import foundation.e.apps.utils.modules.PreferenceManagerModule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -35,6 +44,7 @@ import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.eq

@OptIn(ExperimentalCoroutinesApi::class)
class FusedApiImplTest {
    private lateinit var fusedAPIImpl: FusedAPIImpl

@@ -272,4 +282,281 @@ class FusedApiImplTest {
        val isAppStatusUpdated = fusedAPIImpl.isAnyAppInstallStatusChanged(oldAppList)
        assertFalse("hasInstallStatusUpdated", isAppStatusUpdated)
    }

    @Test
    fun isHomeDataUpdated() {
        val oldAppList = mutableListOf<FusedApp>(
            FusedApp(
                _id = "111",
                status = Status.INSTALLATION_ISSUE,
                name = "Demo One",
                package_name = "foundation.e.demoone",
                latest_version_code = 123
            ),
            FusedApp(
                _id = "112",
                status = Status.INSTALLED,
                name = "Demo Two",
                package_name = "foundation.e.demotwo",
                latest_version_code = 123
            ),
            FusedApp(
                _id = "113",
                status = Status.UNAVAILABLE,
                name = "Demo Three",
                package_name = "foundation.e.demothree",
                latest_version_code = 123
            )
        )
        val newAppList = mutableListOf<FusedApp>(
            FusedApp(
                _id = "111",
                status = Status.INSTALLATION_ISSUE,
                name = "Demo One",
                package_name = "foundation.e.demoone",
                latest_version_code = 123
            ),
            FusedApp(
                _id = "112",
                status = Status.UNAVAILABLE,
                name = "Demo Two",
                package_name = "foundation.e.demotwo",
                latest_version_code = 123
            ),
            FusedApp(
                _id = "113",
                status = Status.UNAVAILABLE,
                name = "Demo Three",
                package_name = "foundation.e.demothree",
                latest_version_code = 123
            )
        )
        val oldHomeData =
            listOf(FusedHome("Top Free Apps", oldAppList), FusedHome("Top Free Games", oldAppList))
        var newHomeData =
            listOf(FusedHome("Top Free Apps", oldAppList), FusedHome("Top Free Games", oldAppList))
        var isHomeDataUpdated = fusedAPIImpl.isHomeDataUpdated(newHomeData, oldHomeData)
        assertFalse("isHomeDataUpdated/NO", isHomeDataUpdated)
        newHomeData =
            listOf(FusedHome("Top Free Apps", oldAppList), FusedHome("Top Free Games", newAppList))
        isHomeDataUpdated = fusedAPIImpl.isHomeDataUpdated(newHomeData, oldHomeData)
        assertTrue("isHomeDataUpdated/YES", isHomeDataUpdated)
    }

    @Test
    fun isHomeDataUpdatedWhenBothAreEmpty() {
        val oldHomeData = listOf<FusedHome>()
        val newHomeData = listOf<FusedHome>()
        val isHomeDataUpdated = fusedAPIImpl.isHomeDataUpdated(oldHomeData, newHomeData)
        assertFalse("isHomeDataUpdated", isHomeDataUpdated)
    }

    @Test
    fun `is home data updated when fusedapp list size is not same`() {
        val oldAppList = mutableListOf(FusedApp(), FusedApp(), FusedApp())
        val newAppList = mutableListOf(FusedApp(), FusedApp())

        val oldHomeData =
            listOf(FusedHome("Top Free Apps", oldAppList), FusedHome("Top Free Games", oldAppList))
        var newHomeData =
            listOf(FusedHome("Top Free Apps", oldAppList), FusedHome("Top Free Games", newAppList))

        val isHomeDataUpdated = fusedAPIImpl.isHomeDataUpdated(newHomeData, oldHomeData)
        assertTrue("isHomeDataUpdated/YES", isHomeDataUpdated)
    }

    @Test
    fun getFusedAppInstallationStatusWhenPWA() {
        val fusedApp = FusedApp(
            _id = "113",
            status = Status.UNAVAILABLE,
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
            is_pwa = true
        )
        Mockito.`when`(pwaManagerModule.getPwaStatus(fusedApp)).thenReturn(fusedApp.status)
        val installationStatus = fusedAPIImpl.getFusedAppInstallationStatus(fusedApp)
        assertEquals("getFusedAppInstallationStatusWhenPWA", fusedApp.status, installationStatus)
    }

    @Test
    fun getFusedAppInstallationStatus() {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
        )
        Mockito.`when`(
            pkgManagerModule.getPackageStatus(
                fusedApp.package_name,
                fusedApp.latest_version_code
            )
        ).thenReturn(Status.INSTALLED)
        val installationStatus = fusedAPIImpl.getFusedAppInstallationStatus(fusedApp)
        assertEquals("getFusedAppInstallationStatusWhenPWA", Status.INSTALLED, installationStatus)
    }

    @Test
    fun `getAppFilterLevel when package name is empty`() = runTest {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "",
            latest_version_code = 123,
        )
        val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
        val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
        assertEquals("getAppFilterLevel", FilterLevel.UNKNOWN, filterLevel)
    }

    @Test
    fun `getAppFilterLevel when app is CleanApk`() = runTest {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
            origin = Origin.CLEANAPK
        )

        val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
        val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
        assertEquals("getAppFilterLevel", FilterLevel.NONE, filterLevel)
    }

    @Test
    fun `getAppFilterLevel when Authdata is NULL`() = runTest {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
            origin = Origin.CLEANAPK
        )
        val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, null)
        assertEquals("getAppFilterLevel", FilterLevel.NONE, filterLevel)
    }

    @Test
    fun `getAppFilterLevel when app is restricted and paid and no price`() = runTest {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
            origin = Origin.GPLAY,
            restriction = Constants.Restriction.UNKNOWN,
            isFree = false,
            price = ""
        )
        val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
        val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
        assertEquals("getAppFilterLevel", FilterLevel.UI, filterLevel)
    }

    @Test
    fun `getAppFilterLevel when app is not_restricted and paid and no price`() = runTest {
        val fusedApp = FusedApp(
            _id = "113",
            name = "Demo Three",
            package_name = "foundation.e.demothree",
            latest_version_code = 123,
            origin = Origin.GPLAY,
            restriction = Constants.Restriction.NOT_RESTRICTED,
            isFree = false,
            price = ""
        )
        val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
        val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
        assertEquals("getAppFilterLevel", FilterLevel.UI, filterLevel)
    }

    @Test
    fun `getAppFilterLevel when app is restricted and getAppDetails and getDownloadDetails returns success`() =
        runTest {
            val fusedApp = FusedApp(
                _id = "113",
                name = "Demo Three",
                package_name = "foundation.e.demothree",
                latest_version_code = 123,
                origin = Origin.GPLAY,
                restriction = Constants.Restriction.UNKNOWN,
                isFree = true,
                price = ""
            )
            val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
            Mockito.`when`(gPlayAPIRepository.getAppDetails(fusedApp.package_name, authData))
                .thenReturn(App(fusedApp.package_name))

            Mockito.`when`(
                gPlayAPIRepository.getDownloadInfo(
                    fusedApp.package_name,
                    fusedApp.latest_version_code,
                    fusedApp.offer_type,
                    authData
                )
            ).thenReturn(listOf())
            val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
            assertEquals("getAppFilterLevel", FilterLevel.NONE, filterLevel)
        }

    @Test
    fun `getAppFilterLevel when app is restricted and getAppDetails throws exception`() =
        runTest {
            val fusedApp = FusedApp(
                _id = "113",
                name = "Demo Three",
                package_name = "foundation.e.demothree",
                latest_version_code = 123,
                origin = Origin.GPLAY,
                restriction = Constants.Restriction.UNKNOWN,
                isFree = true,
                price = ""
            )
            val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
            Mockito.`when`(gPlayAPIRepository.getAppDetails(fusedApp.package_name, authData))
                .thenThrow(RuntimeException())

            Mockito.`when`(
                gPlayAPIRepository.getDownloadInfo(
                    fusedApp.package_name,
                    fusedApp.latest_version_code,
                    fusedApp.offer_type,
                    authData
                )
            ).thenReturn(listOf())
            val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
            assertEquals("getAppFilterLevel", FilterLevel.DATA, filterLevel)
        }

    @Test
    fun `getAppFilterLevel when app is restricted and getDownoadInfo throws exception`() =
        runTest {
            val fusedApp = FusedApp(
                _id = "113",
                name = "Demo Three",
                package_name = "foundation.e.demothree",
                latest_version_code = 123,
                origin = Origin.GPLAY,
                restriction = Constants.Restriction.UNKNOWN,
                isFree = true,
                price = ""
            )
            val authData = AuthData("e@e.email", "AtadyMsIAtadyM")
            Mockito.`when`(gPlayAPIRepository.getAppDetails(fusedApp.package_name, authData))
                .thenReturn(App(fusedApp.package_name))

            Mockito.`when`(
                gPlayAPIRepository.getDownloadInfo(
                    fusedApp.package_name,
                    fusedApp.latest_version_code,
                    fusedApp.offer_type,
                    authData
                )
            ).thenThrow(RuntimeException())
            val filterLevel = fusedAPIImpl.getAppFilterLevel(fusedApp, authData)
            assertEquals("getAppFilterLevel", FilterLevel.UI, filterLevel)
        }
}