Loading app/src/test/java/foundation/e/apps/data/install/workmanager/InstallWorkManagerTest.kt 0 → 100644 +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() } } Loading
app/src/test/java/foundation/e/apps/data/install/workmanager/InstallWorkManagerTest.kt 0 → 100644 +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() } }