diff --git a/app/build.gradle b/app/build.gradle index c7f1c027f464f23eb15efaddcb59ce3ad940cf29..aabd686f9e8d31404fa2f01f19b10e51a177d35e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -102,10 +102,16 @@ dependencies { implementation "com.google.dagger:hilt-android:$rootProject.ext.hilt_version" kapt "com.google.dagger:hilt-compiler:$rootProject.ext.hilt_version" + //Coroutines + def coroutines_version = '1.7.3' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" + //test testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation "androidx.work:work-testing:2.8.1" + androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" } kapt { diff --git a/gallery/src/androidTest/java/org/futo/circles/gallery/WorkerTest.kt b/app/src/androidTest/java/org/futo/circles/MediaBackupWorkerTest.kt similarity index 98% rename from gallery/src/androidTest/java/org/futo/circles/gallery/WorkerTest.kt rename to app/src/androidTest/java/org/futo/circles/MediaBackupWorkerTest.kt index d1b16b2b9ea745fef3b1d19b1afc3dacdea3c98e..bdf5a6d7ae0d4a03e2cd6dc9ac0c572c3876c216 100644 --- a/gallery/src/androidTest/java/org/futo/circles/gallery/WorkerTest.kt +++ b/app/src/androidTest/java/org/futo/circles/MediaBackupWorkerTest.kt @@ -1,4 +1,4 @@ -package org.futo.circles.gallery +package org.futo.circles import android.content.Context import android.os.Handler @@ -28,7 +28,7 @@ import java.util.UUID import java.util.concurrent.TimeUnit import kotlin.coroutines.resume -class WorkerTest { +class MediaBackupWorkerTest { lateinit var context: Context diff --git a/app/src/androidTest/java/org/futo/circles/RefreshTokenWorkerTest.kt b/app/src/androidTest/java/org/futo/circles/RefreshTokenWorkerTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..65ab1dd900bc231d445c5347d3dfc27e778a1775 --- /dev/null +++ b/app/src/androidTest/java/org/futo/circles/RefreshTokenWorkerTest.kt @@ -0,0 +1,118 @@ +package org.futo.circles + + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log +import androidx.lifecycle.Observer +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.platform.app.InstrumentationRegistry +import androidx.work.Configuration +import androidx.work.Constraints +import androidx.work.Data +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.NetworkType +import androidx.work.PeriodicWorkRequest +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkInfo +import androidx.work.WorkManager +import androidx.work.testing.SynchronousExecutor +import androidx.work.testing.WorkManagerTestInitHelper +import junit.framework.TestCase.assertTrue +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.futo.circles.auth.feature.token.RefreshTokenWorker +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import java.util.UUID +import java.util.concurrent.TimeUnit +import kotlin.coroutines.resume +import kotlin.math.max + +class RefreshTokenWorkerTest { + + lateinit var context: Context + + private val job = SupervisorJob() + private val testDispatcher = StandardTestDispatcher() + private val testScope = TestScope(job + testDispatcher) + + @get:Rule + val activityRule = ActivityScenarioRule(MainActivity::class.java) + + @Before + fun setup() { + context = InstrumentationRegistry.getInstrumentation().targetContext + val config = Configuration.Builder() + .setMinimumLoggingLevel(Log.DEBUG) + .setExecutor(SynchronousExecutor()) + .build() + WorkManagerTestInitHelper.initializeTestWorkManager(context, config) + } + + @Test + fun testPeriodicWork() = testScope.runTest { + val workManager = WorkManager.getInstance(context) + val testDriver = WorkManagerTestInitHelper.getTestDriver(context) + ?: throw IllegalArgumentException("test driver is null") + + + val expireTime = 3600000L + + val sessionIdData = Data.Builder() + .putString(RefreshTokenWorker.SESSION_ID_PARAM_KEY, "test") + .build() + + val flex = max(expireTime / 3, PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS) + + val refreshRequest = PeriodicWorkRequestBuilder<RefreshTokenWorker>( + expireTime, TimeUnit.MILLISECONDS, + flex, TimeUnit.MILLISECONDS + ) + .setConstraints( + Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() + ) + .setInputData(sessionIdData) + .build() + + WorkManager.getInstance(context).enqueueUniquePeriodicWork( + "test", + ExistingPeriodicWorkPolicy.UPDATE, + refreshRequest + ).result.get() + + testDriver.setPeriodDelayMet(refreshRequest.id) + testDriver.setAllConstraintsMet(refreshRequest.id) + val isSucceeded = awaitForWork(workManager, refreshRequest.id) + assertTrue(isSucceeded) + } + + private suspend fun awaitForWork( + workManager: WorkManager, + workId: UUID + ): Boolean { + val checkWorkerLiveState = workManager.getWorkInfoByIdLiveData(workId) + + return suspendCancellableCoroutine { + val observer = object : Observer<WorkInfo> { + override fun onChanged(value: WorkInfo) { + if (value.state == WorkInfo.State.ENQUEUED) { + checkWorkerLiveState.removeObserver(this) + it.resume(true) + } + if (value.state == WorkInfo.State.FAILED || value.state == WorkInfo.State.CANCELLED) { + checkWorkerLiveState.removeObserver(this) + it.resume(false) + } + } + } + Handler(Looper.getMainLooper()).post { checkWorkerLiveState.observeForever(observer) } + } + } + +} diff --git a/gallery/build.gradle b/gallery/build.gradle index c1fb762b90c67f0e198b8cddd5378c54c1fa4819..9a9613333055179ca3fe8013bcfe9f74282fa487 100644 --- a/gallery/build.gradle +++ b/gallery/build.gradle @@ -48,7 +48,7 @@ dependencies { implementation 'com.jsibbold:zoomage:1.3.1' //ExoPlayer - def exoplayer_version = '1.1.1' + def exoplayer_version = '1.2.0' implementation "androidx.media3:media3-exoplayer:$exoplayer_version" implementation "androidx.media3:media3-ui:$exoplayer_version" @@ -56,10 +56,6 @@ dependencies { def work_version = "2.8.1" implementation "androidx.work:work-runtime-ktx:$work_version" - //Coroutines - def coroutines_version = '1.7.3' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" - //Hilt implementation "com.google.dagger:hilt-android:$rootProject.ext.hilt_version" kapt "com.google.dagger:hilt-compiler:$rootProject.ext.hilt_version" @@ -68,8 +64,6 @@ dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - androidTestImplementation "androidx.work:work-testing:2.8.1" - androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" } kapt { diff --git a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/service/MediaBackupWorker.kt b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/service/MediaBackupWorker.kt index f04cb7b16cf75f1392287588b93220c90437695b..53189674b36615423f97d17c3a69c40eff659249 100644 --- a/gallery/src/main/java/org/futo/circles/gallery/feature/backup/service/MediaBackupWorker.kt +++ b/gallery/src/main/java/org/futo/circles/gallery/feature/backup/service/MediaBackupWorker.kt @@ -29,7 +29,7 @@ class MediaBackupWorker @AssistedInject constructor( mediaBackupDataSource.startMediaBackup() syncService?.stopAnyBackgroundSync() } catch (t: Throwable) { - Result.failure() + return Result.failure() } return Result.success() }