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

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

test: add tests for InstallWorkManager

parent 308e1ec3
Loading
Loading
Loading
Loading
+187 −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.install.workmanager

import android.app.Application
import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.impl.WorkManagerImpl
import androidx.work.impl.model.WorkSpec
import androidx.work.testing.WorkManagerTestInitHelper
import com.google.common.truth.Truth.assertThat
import foundation.e.apps.data.install.models.AppInstall
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import java.util.UUID
import java.util.concurrent.TimeUnit

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.N])
class InstallWorkManagerTest {

    private lateinit var context: Application
    private lateinit var workManager: WorkManager

    @Before
    fun setup() {
        context = ApplicationProvider.getApplicationContext()
        WorkManagerTestInitHelper.initializeTestWorkManager(context)
        InstallWorkManager.context = context
        workManager = WorkManager.getInstance(context)
        workManager.cancelAllWork().result.get()
    }

    @After
    fun teardown() {
        workManager.cancelAllWork().result.get()
        Thread.interrupted()
    }

    @Test
    fun enqueueWork_buildsExpectedRequestForInstall() {
        val appInstall = AppInstall(id = "id.install", packageName = "foundation.e.install")

        InstallWorkManager.enqueueWork(appInstall).result.get()

        val uniqueWorkName = InstallWorkManager.getUniqueWorkName(appInstall.packageName)
        val workInfo = workManager.getWorkInfosForUniqueWork(uniqueWorkName).get().single()
        val workSpec = getWorkSpec(workInfo.id)

        assertThat(workInfo.tags).containsAtLeast(appInstall.id, InstallWorkManager.INSTALL_WORK_NAME)
        assertThat(workSpec.input.getString(InstallAppWorker.INPUT_DATA_FUSED_DOWNLOAD))
            .isEqualTo(appInstall.id)
        assertThat(workSpec.input.getBoolean(InstallAppWorker.IS_UPDATE_WORK, true)).isFalse()
        assertThat(workSpec.constraints.requiredNetworkType).isEqualTo(NetworkType.CONNECTED)
        assertThat(workSpec.constraints.requiresStorageNotLow()).isTrue()
    }

    @Test
    fun enqueueWork_setsUpdateFlagWhenRequested() {
        val appInstall = AppInstall(id = "id.update", packageName = "foundation.e.update")

        InstallWorkManager.enqueueWork(appInstall, isUpdateWork = true).result.get()

        val uniqueWorkName = InstallWorkManager.getUniqueWorkName(appInstall.packageName)
        val workInfo = workManager.getWorkInfosForUniqueWork(uniqueWorkName).get().single()
        val workSpec = getWorkSpec(workInfo.id)

        assertThat(workSpec.input.getBoolean(InstallAppWorker.IS_UPDATE_WORK, false)).isTrue()
    }

    @Test
    fun cancelWork_cancelsAllWorkByTag() {
        val tag = "id.cancel"
        val request = OneTimeWorkRequestBuilder<NoOpWorker>()
            .setInitialDelay(1, TimeUnit.HOURS)
            .addTag(tag)
            .build()

        workManager.enqueue(request).result.get()

        InstallWorkManager.cancelWork(tag)

        val state = waitUntilFinished(request.id)
        assertThat(state).isEqualTo(WorkInfo.State.CANCELLED)
    }

    @Test
    fun checkWorkIsAlreadyAvailable_returnsTrueWhenActiveWorkExists() {
        val tag = "id.active"
        val request = OneTimeWorkRequestBuilder<NoOpWorker>()
            .setInitialDelay(1, TimeUnit.HOURS)
            .addTag(tag)
            .build()

        workManager.enqueue(request).result.get()

        assertThat(InstallWorkManager.checkWorkIsAlreadyAvailable(tag)).isTrue()
    }

    @Test
    fun checkWorkIsAlreadyAvailable_returnsFalseWhenOnlyFinishedWorkExists() {
        val tag = "id.finished"
        val request = OneTimeWorkRequestBuilder<NoOpWorker>()
            .setInitialDelay(1, TimeUnit.HOURS)
            .addTag(tag)
            .build()

        workManager.enqueue(request).result.get()
        InstallWorkManager.cancelWork(tag)
        waitUntilFinished(request.id)

        assertThat(InstallWorkManager.checkWorkIsAlreadyAvailable(tag)).isFalse()
    }

    @Test
    fun checkWorkIsAlreadyAvailable_returnsFalseWhenNoWorkExistsForTag() {
        assertThat(InstallWorkManager.checkWorkIsAlreadyAvailable("id.missing")).isFalse()
    }

    @Test
    fun checkWorkIsAlreadyAvailable_returnsFalseWhenThreadIsInterrupted() {
        Thread.currentThread().interrupt()

        val result = InstallWorkManager.checkWorkIsAlreadyAvailable("id.interrupted")

        assertThat(result).isFalse()
        assertThat(Thread.currentThread().isInterrupted).isFalse()
    }

    @Test
    fun getUniqueWorkName_returnsExpectedValueForNormalAndEmptyPackage() {
        assertThat(InstallWorkManager.getUniqueWorkName("foundation.e.apps"))
            .isEqualTo("${InstallWorkManager.INSTALL_WORK_NAME}/foundation.e.apps")
        assertThat(InstallWorkManager.getUniqueWorkName(""))
            .isEqualTo("${InstallWorkManager.INSTALL_WORK_NAME}/")
    }

    private fun getWorkSpec(workId: UUID): WorkSpec {
        val workManagerImpl = WorkManagerImpl.getInstance(context)
        return requireNotNull(workManagerImpl.workDatabase.workSpecDao().getWorkSpec(workId.toString()))
    }

    private fun waitUntilFinished(workId: UUID): WorkInfo.State {
        repeat(30) {
            val state = requireNotNull(workManager.getWorkInfoById(workId).get()).state
            if (state.isFinished) {
                return state
            }
            Thread.sleep(50)
        }
        return requireNotNull(workManager.getWorkInfoById(workId).get()).state
    }

    class NoOpWorker(
        appContext: Context,
        workerParams: WorkerParameters
    ) : Worker(appContext, workerParams) {
        override fun doWork(): Result = Result.success()
    }
}