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

Commit aa685d8e authored by Abhishek Aggarwal's avatar Abhishek Aggarwal Committed by Abhishek Aggarwal
Browse files

tests: Add tests for shared lib

parent 6309561c
Loading
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -98,17 +98,16 @@ class DownloadInfoApiImpl @Inject constructor(
            if (lib.downloadUrls.isEmpty()) {
                val libFiles = runCatching {
                    appSources.gplayRepo.getDownloadInfo(lib.packageName, lib.versionCode, lib.offerType)
                }.getOrElse { e ->
                    throw IllegalStateException(
                }.getOrElse {
                    error(
                        "Cannot install ${appInstall.packageName}: " +
                            "failed to fetch download info for required library ${lib.packageName}",
                        e
                    )
                }
                if (libFiles.isEmpty()) {
                    error(
                        "Cannot install ${appInstall.packageName}: " +
                            "no download URLs returned for required library ${lib.packageName}"
                            "no download URLs returned for required library ${lib.packageName}",
                    )
                }
                lib.downloadUrls = libFiles.map { it.url }
+1 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024-2026 MURENA SAS
 * Copyright (C) 2026 e Foundation
 *
 * 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
+1 −2
Original line number Diff line number Diff line
@@ -122,10 +122,9 @@ class AppInstallProcessor @Inject constructor(
                        Source.PLAY_STORE
                    ).first.dependentLibraries
                }.getOrElse {
                    throw IllegalStateException(
                    error(
                        "Cannot install ${application.package_name}: " +
                            "failed to fetch required shared library details",
                        it
                    )
                }
            }
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * 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.data.application.downloadInfo

import com.aurora.gplayapi.data.models.PlayFile
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.AppSourcesContainer
import foundation.e.apps.data.cleanapk.repositories.CleanApkAppsRepository
import foundation.e.apps.data.cleanapk.repositories.CleanApkPwaRepository
import foundation.e.apps.data.enums.Source
import foundation.e.apps.data.install.models.AppInstall
import foundation.e.apps.data.install.models.SharedLib
import foundation.e.apps.data.playstore.PlayStoreRepository
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlin.test.assertFailsWith
import org.junit.Before
import org.junit.Test

@OptIn(ExperimentalCoroutinesApi::class)
class DownloadInfoApiImplTest {

    private val gplayRepo = mockk<PlayStoreRepository>()
    private val cleanApkAppsRepo = mockk<CleanApkAppsRepository>()
    private val cleanApkPwaRepo = mockk<CleanApkPwaRepository>()

    private lateinit var downloadInfoApi: DownloadInfoApiImpl

    @Before
    fun setUp() {
        downloadInfoApi = DownloadInfoApiImpl(
            AppSourcesContainer(gplayRepo, cleanApkAppsRepo, cleanApkPwaRepo)
        )
    }

    @Test
    fun updateFusedDownloadWithDownloadingInfo_populatesMissingSharedLibraryUrls() = runTest {
        val sharedLib = SharedLib(
            packageName = "com.example.lib",
            versionCode = 11L,
            offerType = 3
        )
        val appInstall = AppInstall(
            packageName = "com.example.app",
            versionCode = 99L,
            offerType = 1,
            sharedLibs = listOf(sharedLib)
        )
        val mainFiles = listOf(playFile("https://example.org/app-base.apk"))
        val libFiles = listOf(
            playFile("https://example.org/lib-base.apk"),
            playFile("https://example.org/lib-config.apk")
        )

        coEvery { gplayRepo.getDownloadInfo("com.example.app", 99L, 1) } returns mainFiles
        coEvery { gplayRepo.getDownloadInfo("com.example.lib", 11L, 3) } returns libFiles

        downloadInfoApi.updateFusedDownloadWithDownloadingInfo(Source.PLAY_STORE, appInstall)

        assertThat(appInstall.downloadURLList).containsExactly("https://example.org/app-base.apk")
        assertThat(appInstall.files.map { it.url }).containsExactly("https://example.org/app-base.apk")
        assertThat(sharedLib.downloadUrls).containsExactly(
            "https://example.org/lib-base.apk",
            "https://example.org/lib-config.apk"
        )
    }

    @Test
    fun updateFusedDownloadWithDownloadingInfo_keepsExistingSharedLibraryUrls() = runTest {
        val sharedLib = SharedLib(
            packageName = "com.example.lib",
            versionCode = 11L,
            offerType = 3,
            downloadUrls = listOf("https://example.org/already-present.apk")
        )
        val appInstall = AppInstall(
            packageName = "com.example.app",
            versionCode = 99L,
            offerType = 1,
            sharedLibs = listOf(sharedLib)
        )
        val mainFiles = listOf(playFile("https://example.org/app-base.apk"))

        coEvery { gplayRepo.getDownloadInfo("com.example.app", 99L, 1) } returns mainFiles

        downloadInfoApi.updateFusedDownloadWithDownloadingInfo(Source.PLAY_STORE, appInstall)

        assertThat(sharedLib.downloadUrls).containsExactly("https://example.org/already-present.apk")
        coVerify(exactly = 0) { gplayRepo.getDownloadInfo("com.example.lib", any(), any()) }
    }

    @Test
    fun updateFusedDownloadWithDownloadingInfo_throwsWhenSharedLibraryHasNoDownloads() = runTest {
        val sharedLib = SharedLib(
            packageName = "com.example.lib",
            versionCode = 11L,
            offerType = 3
        )
        val appInstall = AppInstall(
            packageName = "com.example.app",
            versionCode = 99L,
            offerType = 1,
            sharedLibs = listOf(sharedLib)
        )

        coEvery { gplayRepo.getDownloadInfo("com.example.app", 99L, 1) } returns listOf(
            playFile("https://example.org/app-base.apk")
        )
        coEvery { gplayRepo.getDownloadInfo("com.example.lib", 11L, 3) } returns emptyList()

        val error = assertFailsWith<IllegalStateException> {
            downloadInfoApi.updateFusedDownloadWithDownloadingInfo(Source.PLAY_STORE, appInstall)
        }

        assertThat(error).hasMessageThat().contains("no download URLs returned for required library")
    }

    @Test
    fun updateFusedDownloadWithDownloadingInfo_throwsWhenSharedLibraryFetchFails() = runTest {
        val sharedLib = SharedLib(
            packageName = "com.example.lib",
            versionCode = 11L,
            offerType = 3
        )
        val appInstall = AppInstall(
            packageName = "com.example.app",
            versionCode = 99L,
            offerType = 1,
            sharedLibs = listOf(sharedLib)
        )

        coEvery { gplayRepo.getDownloadInfo("com.example.app", 99L, 1) } returns listOf(
            playFile("https://example.org/app-base.apk")
        )
        coEvery {
            gplayRepo.getDownloadInfo("com.example.lib", 11L, 3)
        } throws IllegalStateException("boom")

        val error = assertFailsWith<IllegalStateException> {
            downloadInfoApi.updateFusedDownloadWithDownloadingInfo(Source.PLAY_STORE, appInstall)
        }

        assertThat(error).hasMessageThat().contains(
            "failed to fetch download info for required library"
        )
        assertThat(error.cause).isNull()
    }

    private fun playFile(url: String): PlayFile {
        val file = mockk<PlayFile>()
        every { file.url } returns url
        return file
    }
}
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * 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.data.application.utils

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.aurora.gplayapi.Constants.Restriction
import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.Artwork
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.install.models.SharedLib
import io.mockk.every
import io.mockk.mockk
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@RunWith(RobolectricTestRunner::class)
class GplayApiExtensionsTest {

    private val context: Context = ApplicationProvider.getApplicationContext()

    @Test
    fun toApplication_mapsDependentLibraries() {
        val artwork = mockk<Artwork>()
        every { artwork.url } returns "https://example.com/icon.png"

        val app = mockk<App>(relaxed = true)
        every { app.id } returns 1
        every { app.developerName } returns "Dev"
        every { app.categoryName } returns "Category"
        every { app.description } returns "Description"
        every { app.iconArtwork } returns artwork
        every { app.updatedOn } returns "2024-01-01"
        every { app.versionCode } returns 1L
        every { app.versionName } returns "1.0"
        every { app.displayName } returns "App"
        every { app.screenshots } returns mutableListOf(artwork)
        every { app.packageName } returns "com.example.app"
        every { app.labeledRating } returns "4.5"
        every { app.offerType } returns 1
        every { app.shareUrl } returns "https://example.com"
        every { app.size } returns 1000L
        every { app.isFree } returns true
        every { app.price } returns "0"
        every { app.restriction } returns Restriction.NOT_RESTRICTED
        every { app.contentRating } returns mockk(relaxed = true)
        every { app.dependencies.dependentLibraries } returns mutableListOf(
            mockk(relaxed = true) {
                every { packageName } returns "com.example.lib.one"
                every { versionCode } returns 10L
                every { offerType } returns 2
            },
            mockk(relaxed = true) {
                every { packageName } returns "com.example.lib.two"
                every { versionCode } returns 20L
                every { offerType } returns 4
            }
        )

        val mapped = app.toApplication(context)

        assertThat(mapped.dependentLibraries).containsExactly(
            SharedLib(packageName = "com.example.lib.one", versionCode = 10L, offerType = 2),
            SharedLib(packageName = "com.example.lib.two", versionCode = 20L, offerType = 4)
        ).inOrder()
    }
}
Loading