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

Verified Commit c4cc8359 authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

test: add tests for AppManagerImpl

Fix broken test classes.
parent 4c31d240
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ interface RepositoryModule {

    @Singleton
    @Binds
    fun getFdroidRepository(fusedManagerImpl: FDroidRepository): IFdroidRepository
    fun getFdroidRepository(fdroidRepository: FDroidRepository): IFdroidRepository

    @Singleton
    @Binds
+82 −7
Original line number Diff line number Diff line
@@ -17,35 +17,41 @@

package foundation.e.apps.data.install

import android.os.Build
import android.app.DownloadManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageInfo
import android.net.Uri
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.fdroid.FDroidRepository
import foundation.e.apps.data.install.download.data.DownloadProgressLD
import foundation.e.apps.data.installation.repository.AppInstallRepository
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.data.installation.model.SharedLib
import foundation.e.apps.data.install.pkg.AppLoungePackageManager
import foundation.e.apps.data.install.pkg.PwaManager
import foundation.e.apps.data.install.sharedlib.SharedLibraryManager
import foundation.e.apps.domain.preferences.AppPreferencesRepository
import foundation.e.apps.data.install.workmanager.InstallWorkManager
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.data.installation.model.SharedLib
import foundation.e.apps.data.installation.repository.AppInstallRepository
import foundation.e.apps.domain.model.install.Status
import foundation.e.apps.domain.preferences.AppPreferencesRepository
import foundation.e.apps.installProcessor.FakeAppInstallDAO
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.slot
import io.mockk.unmockkObject
import io.mockk.verify
import android.net.Uri
import java.io.File
import java.nio.file.Files
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -60,6 +66,7 @@ import org.robolectric.shadows.ShadowPackageManager
class AppManagerImplTest {

    private lateinit var tempDir: File
    private lateinit var appInstallDAO: FakeAppInstallDAO
    private val downloadManager = mockk<DownloadManager>(relaxed = true)
    private val notificationManager = mockk<NotificationManager>(relaxed = true)
    private val pwaManager = mockk<PwaManager>(relaxed = true)
@@ -76,13 +83,14 @@ class AppManagerImplTest {
    @Before
    fun setUp() {
        tempDir = Files.createTempDirectory("appManagerImplTest").toFile()
        appInstallDAO = FakeAppInstallDAO()
        val sharedLibraryManager = SharedLibraryManager(tempDir.absolutePath, context)

        appManager = AppManagerImpl(
            tempDir.absolutePath,
            downloadManager,
            notificationManager,
            AppInstallRepository(FakeAppInstallDAO()),
            AppInstallRepository(appInstallDAO),
            pwaManager,
            appLoungePackageManager,
            sharedLibraryManager,
@@ -100,6 +108,7 @@ class AppManagerImplTest {
        shadowPackageManager.deletePackage("com.example.lib.missing")
        DownloadProgressLD.setDownloadId(-1)
        tempDir.deleteRecursively()
        unmockkObject(InstallWorkManager)
    }

    @Test
@@ -208,6 +217,72 @@ class AppManagerImplTest {
        verify(exactly = 3) { downloadManager.enqueue(any()) }
    }

    @Test
    fun addDownload_enqueuesWhenNoExistingDownload() = runTest {
        val appInstall = initTest()

        val isSuccessful = appManager.addDownload(appInstall)

        assertTrue(isSuccessful)
        assertEquals(1, appInstallDAO.getDownloadList().size)
    }

    @Test
    fun addDownload_returnsFalseWhenWorkAndExistingDownloadAreAvailable() = runTest {
        val appInstall = initTest(hasAnyExistingWork = true)
        appInstallDAO.addDownload(appInstall)

        val isSuccessful = appManager.addDownload(appInstall)

        assertFalse(isSuccessful)
    }

    @Test
    fun addDownload_returnsTrueWhenOnlyWorkExists() = runTest {
        val appInstall = initTest(hasAnyExistingWork = true)

        val isSuccessful = appManager.addDownload(appInstall)

        assertTrue(isSuccessful)
    }

    @Test
    fun addDownload_returnsFalseWhenExistingDownloadIsNotEligible() = runTest {
        val appInstall = initTest()
        appInstallDAO.addDownload(appInstall)

        val isSuccessful = appManager.addDownload(appInstall)

        assertFalse(isSuccessful)
    }

    @Test
    fun addDownload_returnsTrueWhenExistingDownloadHasInstallationIssue() = runTest {
        val appInstall = initTest()
        appInstall.status = Status.INSTALLATION_ISSUE
        appInstallDAO.addDownload(appInstall)

        val isSuccessful = appManager.addDownload(appInstall)

        assertTrue(isSuccessful)
    }

    private fun initTest(hasAnyExistingWork: Boolean = false): AppInstall {
        mockkObject(InstallWorkManager)
        every { InstallWorkManager.checkWorkIsAlreadyAvailable(any(), any()) } returns hasAnyExistingWork
        return createAppInstall()
    }

    private fun createAppInstall(
        packageName: String? = null,
        downloadUrlList: MutableList<String>? = null
    ) = AppInstall(
        id = "121",
        status = Status.AWAITING,
        downloadURLList = downloadUrlList ?: mutableListOf("apk1", "apk2"),
        packageName = packageName ?: "com.unit.test"
    )

    private fun createApk(relativeDir: String, name: String) {
        val directory = File(tempDir, relativeDir).apply { mkdirs() }
        File(directory, name).writeText("apk")
+7 −11
Original line number Diff line number Diff line
@@ -17,23 +17,19 @@

package foundation.e.apps.data.install

import android.content.Context
import foundation.e.apps.data.application.AppManager
import foundation.e.apps.domain.model.install.Status
import foundation.e.apps.data.fdroid.FDroidRepository
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.data.install.download.data.DownloadProgress
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.domain.model.install.Status
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test

class AppManagerWrapperProgressTest {
class DownloadProgressTrackerTest {

    private val context = mockk<Context>(relaxed = true)
    private val appManager = mockk<AppManager>(relaxed = true)
    private val fdroidRepository = mockk<FDroidRepository>(relaxed = true)
    private val appManagerWrapper = DownloadProgressTracker(appManager)
    private val downloadProgressTracker = DownloadProgressTracker(appManager)

    @Test
    fun calculateProgress_emptyDownloadIds_returnsZero() = runTest {
@@ -48,7 +44,7 @@ class AppManagerWrapperProgressTest {
            bytesDownloadedSoFar = mutableMapOf(1L to 50L),
        )

        val percent = appManagerWrapper.calculateProgress(appInstall, progress)
        val percent = downloadProgressTracker.calculateProgress(appInstall, progress)

        assertEquals(0, percent)
    }
@@ -66,7 +62,7 @@ class AppManagerWrapperProgressTest {
            bytesDownloadedSoFar = mutableMapOf(1L to 50L),
        )

        val percent = appManagerWrapper.calculateProgress(appInstall, progress)
        val percent = downloadProgressTracker.calculateProgress(appInstall, progress)

        assertEquals(0, percent)
    }
@@ -84,7 +80,7 @@ class AppManagerWrapperProgressTest {
            bytesDownloadedSoFar = mutableMapOf(1L to 200L, 2L to 150L),
        )

        val percent = appManagerWrapper.calculateProgress(appInstall, progress)
        val percent = downloadProgressTracker.calculateProgress(appInstall, progress)

        assertEquals(100, percent)
    }
+0 −124
Original line number Diff line number Diff line
/*
 * Copyright MURENA SAS 2023
 * Apps  Quickly and easily install Android apps onto your device!
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package foundation.e.apps.fusedManager

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import foundation.e.apps.data.application.AppManager
import foundation.e.apps.data.install.workmanager.InstallWorkManager
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.domain.model.install.Status
import foundation.e.apps.installProcessor.FakeAppInstallDAO
import foundation.e.apps.util.MainCoroutineRule
import io.mockk.every
import io.mockk.mockkObject
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
import org.junit.Rule
import org.junit.Test
import org.mockito.MockitoAnnotations

@OptIn(ExperimentalCoroutinesApi::class)
class AppManagerWrapperTest {
    @Rule
    @JvmField
    val instantExecutorRule = InstantTaskExecutorRule()

    // Sets the main coroutines dispatcher to a TestCoroutineScope for unit testing.
    @ExperimentalCoroutinesApi
    @get:Rule
    var mainCoroutineRule = MainCoroutineRule()

    private lateinit var appInstallDAO: FakeAppInstallDAO
    private lateinit var fakeAppManager: FakeAppManager

    private lateinit var appInstallationManager: AppManager

    @Before
    fun setup() {
        MockitoAnnotations.openMocks(this)
        appInstallDAO = FakeAppInstallDAO()
        fakeAppManager = FakeAppManager(appInstallDAO)
//        appInstallationManager = AppInstallationManagerImpl(fakeAppManager) // FIXME: make it compile
    }

    @Test
    fun addDownload() = runTest {
        val fusedDownload = initTest()

        val isSuccessful = appInstallationManager.addDownload(fusedDownload)
        assertTrue("addDownload", isSuccessful)
        assertEquals("addDownload", 1, appInstallDAO.getDownloadList().size)
    }

    private fun initTest(hasAnyExistingWork: Boolean = false): AppInstall {
        mockkObject(InstallWorkManager)
        every { InstallWorkManager.checkWorkIsAlreadyAvailable(any(), any()) } returns hasAnyExistingWork
        return createFusedDownload()
    }

    @Test
    fun `addDownload when work and FusedDownload Both are available`() = runTest {
        val fusedDownload = initTest(true)
        appInstallDAO.appInstallList.add(fusedDownload)

        val isSuccessful = appInstallationManager.addDownload(fusedDownload)
        assertFalse("addDownload", isSuccessful)
    }

    @Test
    fun `addDownload when only work exists`() = runTest {
        val fusedDownload = initTest(true)

        val isSuccessful = appInstallationManager.addDownload(fusedDownload)
        assertTrue("addDownload", isSuccessful)
    }

    @Test
    fun `addDownload when on FusedDownload exists`() = runTest {
        val fusedDownload = initTest()
        appInstallDAO.addDownload(fusedDownload)

        val isSuccessful = appInstallationManager.addDownload(fusedDownload)
        assertFalse("addDownload", isSuccessful)
    }

    @Test
    fun `addDownload when fusedDownload already exists And has installation issue`() = runTest {
        val fusedDownload = initTest()
        fusedDownload.status = Status.INSTALLATION_ISSUE
        appInstallDAO.addDownload(fusedDownload)

        val isSuccessful = appInstallationManager.addDownload(fusedDownload)
        assertTrue("addDownload", isSuccessful)
    }

    private fun createFusedDownload(
        packageName: String? = null,
        downloadUrlList: MutableList<String>? = null
    ) = AppInstall(
        id = "121",
        status = Status.AWAITING,
        downloadURLList = downloadUrlList ?: mutableListOf("apk1", "apk2"),
        packageName = packageName ?: "com.unit.test"
    )
}
+0 −138
Original line number Diff line number Diff line
/*
 * Copyright MURENA SAS 2023
 * Apps  Quickly and easily install Android apps onto your device!
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package foundation.e.apps.fusedManager

import android.content.Context
import androidx.lifecycle.LiveData
import foundation.e.apps.data.application.AppManager
import foundation.e.apps.data.installation.local.AppInstallDAO
import foundation.e.apps.data.installation.model.AppInstall
import foundation.e.apps.domain.model.install.Status
import java.io.File

class FakeAppManager(private val appInstallDAO: AppInstallDAO) : AppManager {
    override fun createNotificationChannels() {
        TODO("Not yet implemented")
    }

    override suspend fun enqueueAppInstall(appInstall: AppInstall) {
        appInstall.status = Status.QUEUED
        appInstallDAO.addDownload(appInstall)
    }

    override suspend fun addDownload(appInstall: AppInstall): Boolean {
        TODO("Not yet implemented")
    }

    override suspend fun getDownloadById(appInstall: AppInstall): AppInstall? {
        return appInstallDAO.getDownloadById(appInstall.id)
    }

    override suspend fun getDownloadList(): List<AppInstall> {
        TODO("Not yet implemented")
    }

    override fun getDownloadLiveList(): LiveData<List<AppInstall>> {
        TODO("Not yet implemented")
    }

    override suspend fun updateDownloadStatus(appInstall: AppInstall, status: Status) {
        TODO("Not yet implemented")
    }

    override suspend fun downloadApp(appInstall: AppInstall, isUpdate: Boolean) {
        TODO("Not yet implemented")
    }

    override suspend fun installApp(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override suspend fun cancelDownload(appInstall: AppInstall, packageName: String) {
        TODO("Not yet implemented")
    }

    override suspend fun getFusedDownload(downloadId: Long, packageName: String): AppInstall {
        TODO("Not yet implemented")
    }

    override fun flushOldDownload(packageName: String) {
        TODO("Not yet implemented")
    }

    override suspend fun downloadNativeApp(appInstall: AppInstall, isUpdate: Boolean) {
        TODO("Not yet implemented")
    }

    override fun getGplayInstallationPackagePath(
        appInstall: AppInstall,
        it: String,
        parentPath: String,
        count: Int
    ): File {
        TODO("Not yet implemented")
    }

    override fun createObbFileForDownload(appInstall: AppInstall, url: String): File {
        TODO("Not yet implemented")
    }

    override fun moveOBBFilesToOBBDirectory(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override fun getBaseApkPath(appInstall: AppInstall): String {
        return "root/data/apps/${appInstall.packageName}/${appInstall.packageName}_1.apk"
    }

    override suspend fun reportInstallationIssue(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override suspend fun updateAwaiting(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override suspend fun updateUnavailable(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override suspend fun updateAppInstall(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override suspend fun insertAppInstallPurchaseNeeded(appInstall: AppInstall) {
        TODO("Not yet implemented")
    }

    override fun isAppInstalled(appInstall: AppInstall): Boolean {
        TODO("Not yet implemented")
    }

    override fun getInstallationStatus(appInstall: AppInstall): Status {
        TODO("Not yet implemented")
    }

    override suspend fun isFDroidApplicationSigned(
        context: Context,
        appInstall: AppInstall
    ): Boolean {
        TODO("Not yet implemented")
    }
}
Loading