From 56ea526cce7b2c1d1018236eb2c22d97443ddf72 Mon Sep 17 00:00:00 2001 From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com> Date: Fri, 5 Feb 2021 20:13:16 +0100 Subject: [PATCH 1/2] Add instrumented tests for LocalPlaylistManager.createPlaylist --- .../playlist/LocalPlaylistManagerTest.kt | 85 +++++++++++++++++++ .../testUtil/TrampolineSchedulerRule.kt | 34 ++++++++ 2 files changed, 119 insertions(+) create mode 100644 app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt create mode 100644 app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt diff --git a/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt new file mode 100644 index 000000000..9883105f3 --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/local/playlist/LocalPlaylistManagerTest.kt @@ -0,0 +1,85 @@ +package org.schabi.newpipe.local.playlist + +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.Timeout +import org.schabi.newpipe.database.AppDatabase +import org.schabi.newpipe.database.stream.model.StreamEntity +import org.schabi.newpipe.extractor.stream.StreamType +import org.schabi.newpipe.testUtil.TrampolineSchedulerRule +import java.util.concurrent.TimeUnit + +class LocalPlaylistManagerTest { + + private lateinit var manager: LocalPlaylistManager + private lateinit var database: AppDatabase + + @get:Rule + val trampolineScheduler = TrampolineSchedulerRule() + + @get:Rule + val timeout = Timeout(10, TimeUnit.SECONDS) + + @Before + fun setup() { + database = Room.inMemoryDatabaseBuilder( + ApplicationProvider.getApplicationContext(), + AppDatabase::class.java + ) + .allowMainThreadQueries() + .build() + + manager = LocalPlaylistManager(database) + } + + @After + fun cleanUp() { + database.close() + } + + @Test + fun createPlaylist() { + val stream = StreamEntity( + serviceId = 1, url = "https://newpipe.net/", title = "title", + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + ) + + val result = manager.createPlaylist("name", listOf(stream)) + + // This should not behave like this. + // Currently list of all stream ids is returned instead of playlist id + result.test().await().assertValue(listOf(1L)) + } + + @Test + fun createPlaylist_emptyPlaylistMustReturnEmpty() { + val result = manager.createPlaylist("name", emptyList()) + + // This should not behave like this. + // It should throw an error because currently the result is null + result.test().await().assertComplete() + manager.playlists.test().awaitCount(1).assertValue(emptyList()) + } + + @Test() + fun createPlaylist_nonExistentStreamsAreUpserted() { + val stream = StreamEntity( + serviceId = 1, url = "https://newpipe.net/", title = "title", + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + ) + database.streamDAO().insert(stream) + val upserted = StreamEntity( + serviceId = 1, url = "https://newpipe.net/2", title = "title2", + streamType = StreamType.VIDEO_STREAM, duration = 1, uploader = "uploader" + ) + + val result = manager.createPlaylist("name", listOf(stream, upserted)) + + result.test().await().assertComplete() + database.streamDAO().all.test().awaitCount(1).assertValue(listOf(stream, upserted)) + } +} diff --git a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt new file mode 100644 index 000000000..1f8ded812 --- /dev/null +++ b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt @@ -0,0 +1,34 @@ +package org.schabi.newpipe.testUtil + +import io.reactivex.rxjava3.android.plugins.RxAndroidPlugins +import io.reactivex.rxjava3.plugins.RxJavaPlugins +import io.reactivex.rxjava3.schedulers.Schedulers +import org.junit.rules.TestRule +import org.junit.runner.Description +import org.junit.runners.model.Statement + +/** + * Always run on [Schedulers.trampoline] + */ +class TrampolineSchedulerRule : TestRule { + + private val scheduler = Schedulers.trampoline() + + override fun apply(base: Statement, description: Description): Statement = + object : Statement() { + override fun evaluate() { + try { + RxJavaPlugins.setComputationSchedulerHandler { scheduler } + RxJavaPlugins.setIoSchedulerHandler { scheduler } + RxJavaPlugins.setNewThreadSchedulerHandler { scheduler } + RxJavaPlugins.setSingleSchedulerHandler { scheduler } + RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler } + + base.evaluate() + } finally { + RxJavaPlugins.reset() + RxAndroidPlugins.reset() + } + } + } +} From 2aa5f68b7b6327f0f33b06fedd6f57aafe896689 Mon Sep 17 00:00:00 2001 From: XiangRongLin <41164160+XiangRongLin@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:13:16 +0200 Subject: [PATCH 2/2] Add comment explaining usage Schedulers.trampoline in detail --- .../org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt index 1f8ded812..8a12d2439 100644 --- a/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt +++ b/app/src/androidTest/java/org/schabi/newpipe/testUtil/TrampolineSchedulerRule.kt @@ -8,7 +8,10 @@ import org.junit.runner.Description import org.junit.runners.model.Statement /** - * Always run on [Schedulers.trampoline] + * Always run on [Schedulers.trampoline]. + * This executes the task in the current thread in FIFO manner. + * This ensures that tasks are run quickly inside the tests + * and not scheduled away to another thread for later execution */ class TrampolineSchedulerRule : TestRule {