From 8d0be21baad22339840d0e3ec8b7bb23fca9b7a9 Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Fri, 15 Nov 2024 18:56:27 +0100 Subject: [PATCH 1/9] Created tests for CachingRepository --- gradle/libs.versions.toml | 4 + new-player/build.gradle.kts | 2 + .../repository/CachingRepositoryTest.kt | 95 +++++++++++++++++++ .../repository/MockMediaRepository.kt | 79 +++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt create mode 100644 new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 31dcd972..7a4a9872 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,10 +25,12 @@ junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" appcompat = "1.7.0" +kotlinxCoroutinesTest = "1.9.0" material = "1.12.0" androidx = "1.9.0" constraintlayout = "2.1.4" material3 = "1.2.1" +mockk = "1.13.13" uiTooling = "1.6.8" materialIconsExtendedAndroid = "1.7.0-beta05" media3 = "1.3.1" @@ -55,6 +57,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "androidx" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } @@ -79,6 +82,7 @@ androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +mockk = { module = "io.mockk:mockk", version.ref = "mockk" } okhttp-android = { group = "com.squareup.okhttp3", name = "okhttp-android", version.ref = "okhttpAndroid" } coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } reorderable = { group = "sh.calvin.reorderable", name = "reorderable", version.ref = "reorderable" } diff --git a/new-player/build.gradle.kts b/new-player/build.gradle.kts index ec8c434b..5acf227f 100644 --- a/new-player/build.gradle.kts +++ b/new-player/build.gradle.kts @@ -81,6 +81,8 @@ dependencies { ksp(libs.androidx.hilt.compiler) testImplementation(libs.junit) + testImplementation(libs.kotlinx.coroutines.test) + testImplementation(libs.mockk) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt new file mode 100644 index 00000000..0aea6727 --- /dev/null +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt @@ -0,0 +1,95 @@ +package net.newpipe.newplayer.repository + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.Test +import org.junit.Assert.* +import org.junit.BeforeClass + +@OptIn(ExperimentalCoroutinesApi::class) +class CachingRepositoryTest { + val mockMediaRepository = MockMediaRepository() + val delayTestRepository = DelayTestRepository(mockMediaRepository, 100) + val repository = CachingRepository(delayTestRepository) + + companion object { + @JvmStatic + @BeforeClass + fun init() { + Dispatchers.setMain(StandardTestDispatcher()) + } + + @JvmStatic + @BeforeClass + fun reset() { + Dispatchers.resetMain() + } + } + + @Test + fun getRepoInfo() { + val repoInfo = repository.getRepoInfo() + assertTrue(repoInfo.pullsDataFromNetwork) + assertTrue(repoInfo.canHandleTimestampedLinks) + } + + @Test + fun getMetaInfo() = runTest { + val metaInfo = repository.getMetaInfo("test") + assertEquals("Test title", metaInfo.title) + } + + @Test + fun getStreams_returnsCorrectList() = runTest { + val streams = repository.getStreams("item") + assertEquals(3, streams.size) + assertEquals("item1", streams.get(0).item) + assertEquals("item2", streams.get(1).item) + assertEquals("item3", streams.get(2).item) + } + + @Test + fun getSubtitles_returnsCorrectList() = runTest { + val subtitles = repository.getSubtitles("item") + assertEquals(3, subtitles.size) + assertEquals("subtitle1", subtitles.get(0).identifier) + assertEquals("subtitle2", subtitles.get(1).identifier) + assertEquals("subtitle3", subtitles.get(2).identifier) + } + + @Test + fun getPreviewThumbnail() = runTest { + val previewThumbnail = repository.getPreviewThumbnail("item", 1000) + assertNull(previewThumbnail) + } + + @Test + fun getPreviewThumbnailInfo() = runTest { + val previewThumbnailInfo = repository.getPreviewThumbnailsInfo("item") + assertEquals(10, previewThumbnailInfo.count) + assertEquals(500, previewThumbnailInfo.distanceInMS) + } + + @Test + fun getChapters_returnsCorrectList() = runTest { + val chapters = repository.getChapters("item") + assertEquals(3, chapters.size) + assertEquals("chapter1", chapters.get(0).chapterTitle) + assertEquals("chapter2", chapters.get(1).chapterTitle) + assertEquals("chapter3", chapters.get(2).chapterTitle) + } + + @Test + fun getTimestampLink() = runTest { + assertEquals("test/link", repository.getTimestampLink("item", 0)) + } + + @Test + fun getHttpDataSourceFactory() { + assertNotNull(repository.getHttpDataSourceFactory("item")) + } +} \ No newline at end of file diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt new file mode 100644 index 00000000..8ce9e4f6 --- /dev/null +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt @@ -0,0 +1,79 @@ +/* NewPlayer + * + * @author Christian Schabesberger + * + * Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de> + * + * NewPlayer 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. + * + * NewPlayer 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 NewPlayer. If not, see <http://www.gnu.org/licenses/>. + */ + +package net.newpipe.newplayer.repository + +import android.net.Uri +import androidx.media3.common.MediaMetadata +import androidx.media3.datasource.DefaultHttpDataSource +import androidx.media3.datasource.HttpDataSource +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import net.newpipe.newplayer.data.Chapter +import net.newpipe.newplayer.data.Stream +import net.newpipe.newplayer.data.Subtitle + +/** + * Simple MediaRepository with mock values + */ +class MockMediaRepository : MediaRepository { + val uriMock: Uri + + init { + mockkStatic(Uri::class) + every { Uri.parse(any()) } returns mockk("Uri") + uriMock = Uri.parse("test/uri") + } + + override fun getRepoInfo() = MediaRepository.RepoMetaInfo(canHandleTimestampedLinks = true, pullsDataFromNetwork = true) + + override suspend fun getMetaInfo(item: String) = MediaMetadata.Builder().setTitle("Test title").build() + + override suspend fun getStreams(item: String) = listOf( + Stream("item1", uriMock, emptyList()), + Stream("item2", uriMock, emptyList()), + Stream("item3", uriMock, emptyList()) + ) + + override suspend fun getSubtitles(item: String) = listOf( + Subtitle(uriMock, "subtitle1"), + Subtitle(uriMock, "subtitle2"), + Subtitle(uriMock, "subtitle3") + ) + + override suspend fun getPreviewThumbnail(item: String, timestampInMs: Long) = null + + override suspend fun getPreviewThumbnailsInfo(item: String) = MediaRepository.PreviewThumbnailsInfo(10, 500) + + override suspend fun getChapters(item: String) = listOf( + Chapter(0, "chapter1", null), + Chapter(5000, "chapter2", null), + Chapter(1000, "chapter3", null), + ) + + override suspend fun getTimestampLink(item: String, timestampInSeconds: Long) = "test/link" + + override fun getHttpDataSourceFactory(item: String): HttpDataSource.Factory { + val factory = DefaultHttpDataSource.Factory() + factory.setUserAgent("TestUserAgent") + return factory + } +} \ No newline at end of file From f21d57df07085fba05725d96422e90796e5c943e Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Mon, 18 Nov 2024 12:15:48 +0100 Subject: [PATCH 2/9] Improved CachingRepository tests by checking the cache mechanism --- .../repository/CachingRepositoryTest.kt | 80 +++++++++++++++++-- .../repository/MockMediaRepository.kt | 20 ----- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt index 0aea6727..5ea246ee 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt @@ -1,5 +1,8 @@ package net.newpipe.newplayer.repository +import io.mockk.clearMocks +import io.mockk.coVerify +import io.mockk.spyk import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher @@ -8,13 +11,13 @@ import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.setMain import org.junit.Test import org.junit.Assert.* +import org.junit.Before import org.junit.BeforeClass @OptIn(ExperimentalCoroutinesApi::class) class CachingRepositoryTest { - val mockMediaRepository = MockMediaRepository() - val delayTestRepository = DelayTestRepository(mockMediaRepository, 100) - val repository = CachingRepository(delayTestRepository) + val mockMediaRepository = spyk(MockMediaRepository()) + val repository = CachingRepository(mockMediaRepository) companion object { @JvmStatic @@ -30,6 +33,11 @@ class CachingRepositoryTest { } } + @Before + fun resetSpy() { + clearMocks(mockMediaRepository) + } + @Test fun getRepoInfo() { val repoInfo = repository.getRepoInfo() @@ -39,10 +47,18 @@ class CachingRepositoryTest { @Test fun getMetaInfo() = runTest { - val metaInfo = repository.getMetaInfo("test") + val metaInfo = repository.getMetaInfo("item") assertEquals("Test title", metaInfo.title) } + @Test + fun getMetaInfo_callActualRepositoryOnceForSameItem() = runTest { + repository.getMetaInfo("item") + repository.getMetaInfo("item") + repository.getMetaInfo("item") + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + } + @Test fun getStreams_returnsCorrectList() = runTest { val streams = repository.getStreams("item") @@ -52,6 +68,14 @@ class CachingRepositoryTest { assertEquals("item3", streams.get(2).item) } + @Test + fun getStreams_callActualRepositoryOnceForSameItem() = runTest { + repository.getStreams("item") + repository.getStreams("item") + repository.getStreams("item") + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + } + @Test fun getSubtitles_returnsCorrectList() = runTest { val subtitles = repository.getSubtitles("item") @@ -61,6 +85,14 @@ class CachingRepositoryTest { assertEquals("subtitle3", subtitles.get(2).identifier) } + @Test + fun getSubtitles_callActualRepositoryOnceForSameItem() = runTest { + repository.getSubtitles("item") + repository.getSubtitles("item") + repository.getSubtitles("item") + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + } + @Test fun getPreviewThumbnail() = runTest { val previewThumbnail = repository.getPreviewThumbnail("item", 1000) @@ -68,10 +100,26 @@ class CachingRepositoryTest { } @Test - fun getPreviewThumbnailInfo() = runTest { - val previewThumbnailInfo = repository.getPreviewThumbnailsInfo("item") - assertEquals(10, previewThumbnailInfo.count) - assertEquals(500, previewThumbnailInfo.distanceInMS) + fun getPreviewThumbnail_callActualRepositoryOnceForSameItem() = runTest { + repository.getPreviewThumbnail("item", 1000) + repository.getPreviewThumbnail("item", 1000) + repository.getPreviewThumbnail("item", 1000) + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnail("item", 1000) } + } + + @Test + fun getPreviewThumbnailsInfo() = runTest { + val previewThumbnailsInfo = repository.getPreviewThumbnailsInfo("item") + assertEquals(10, previewThumbnailsInfo.count) + assertEquals(500, previewThumbnailsInfo.distanceInMS) + } + + @Test + fun getPreviewThumbnailsInfo_callActualRepositoryOnceForSameItem() = runTest { + repository.getPreviewThumbnailsInfo("item") + repository.getPreviewThumbnailsInfo("item") + repository.getPreviewThumbnailsInfo("item") + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } } @Test @@ -83,11 +131,27 @@ class CachingRepositoryTest { assertEquals("chapter3", chapters.get(2).chapterTitle) } + @Test + fun getChapters_callActualRepositoryOnceForSameItem() = runTest { + repository.getChapters("item") + repository.getChapters("item") + repository.getChapters("item") + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + @Test fun getTimestampLink() = runTest { assertEquals("test/link", repository.getTimestampLink("item", 0)) } + @Test + fun getTimestampLink_callActualRepositoryOnceForSameItem() = runTest { + repository.getTimestampLink("item", 0) + repository.getTimestampLink("item", 0) + repository.getTimestampLink("item", 0) + coVerify (exactly = 1) { mockMediaRepository.getTimestampLink("item", 0) } + } + @Test fun getHttpDataSourceFactory() { assertNotNull(repository.getHttpDataSourceFactory("item")) diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt index 8ce9e4f6..22e273e6 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/MockMediaRepository.kt @@ -1,23 +1,3 @@ -/* NewPlayer - * - * @author Christian Schabesberger - * - * Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de> - * - * NewPlayer 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. - * - * NewPlayer 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 NewPlayer. If not, see <http://www.gnu.org/licenses/>. - */ - package net.newpipe.newplayer.repository import android.net.Uri From 94e1015ac932815091b01b28cfa5fb2d57d9dfff Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Tue, 19 Nov 2024 18:00:23 +0100 Subject: [PATCH 3/9] Created PrefetchingRepository tests --- .../repository/CachingRepositoryTest.kt | 30 +++ .../repository/PrefetchingRepositoryTest.kt | 195 ++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt index 5ea246ee..48dd3f93 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt @@ -156,4 +156,34 @@ class CachingRepositoryTest { fun getHttpDataSourceFactory() { assertNotNull(repository.getHttpDataSourceFactory("item")) } + + // TODO +// @Test +// fun flush_flushTheCaches() = runTest { +// repository.getMetaInfo("item") +// repository.getStreams("item") +// repository.getSubtitles("item") +// repository.getPreviewThumbnail("item", 1000) +// repository.getPreviewThumbnailsInfo("item") +// repository.getChapters("item") +// repository.getTimestampLink("item", 0) +// +// repository.flush() +// +// repository.getMetaInfo("item") +// repository.getStreams("item") +// repository.getSubtitles("item") +// repository.getPreviewThumbnail("item", 1000) +// repository.getPreviewThumbnailsInfo("item") +// repository.getChapters("item") +// repository.getTimestampLink("item", 0) +// +// coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } +// coVerify (exactly = 2) { mockMediaRepository.getStreams("item") } +// coVerify (exactly = 2) { mockMediaRepository.getSubtitles("item") } +// coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnail("item", 1000) } +// coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnailsInfo("item") } +// coVerify (exactly = 2) { mockMediaRepository.getChapters("item") } +// coVerify (exactly = 2) { mockMediaRepository.getTimestampLink("item", 0) } +// } } \ No newline at end of file diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt new file mode 100644 index 00000000..f9625ee1 --- /dev/null +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt @@ -0,0 +1,195 @@ +package net.newpipe.newplayer.repository; + +import io.mockk.clearMocks +import io.mockk.coVerify +import io.mockk.spyk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.BeforeClass +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class PrefetchingRepositoryTest { + val mockMediaRepository = spyk(MockMediaRepository()) + val cachingRepository = spyk(CachingRepository(mockMediaRepository)) + val repository = PrefetchingRepository(cachingRepository) + + companion object { + @JvmStatic + @BeforeClass + fun init() { + Dispatchers.setMain(StandardTestDispatcher()) + } + + @JvmStatic + @BeforeClass + fun reset() { + Dispatchers.resetMain() + } + } + + @Before + fun clean() { + clearMocks(mockMediaRepository) + repository.reset() + } + + @Test + fun getMetaInfo() = runTest { + val metaInfo = repository.getMetaInfo("item") + assertEquals("Test title", metaInfo.title) + } + + @Test + fun getMetaInfo_prefetchAllItemData() = runTest { + repository.getMetaInfo("item") + + coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + + @Test + fun getStreams_returnsCorrectList() = runTest { + val streams = repository.getStreams("item") + assertEquals(3, streams.size) + assertEquals("item1", streams.get(0).item) + assertEquals("item2", streams.get(1).item) + assertEquals("item3", streams.get(2).item) + } + + @Test + fun getStreams_prefetchAllItemData() = runTest { + repository.getStreams("item") + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 2) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + + @Test + fun getSubtitles_returnsCorrectList() = runTest { + val subtitles = repository.getSubtitles("item") + assertEquals(3, subtitles.size) + assertEquals("subtitle1", subtitles.get(0).identifier) + assertEquals("subtitle2", subtitles.get(1).identifier) + assertEquals("subtitle3", subtitles.get(2).identifier) + } + + @Test + fun getSubtitles_prefetchAllItemData() = runTest { + repository.getSubtitles("item") + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 2) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + + @Test + fun getPreviewThumbnail() = runTest { + val previewThumbnail = repository.getPreviewThumbnail("item", 1000) + assertNull(previewThumbnail) + } + + @Test + fun getPreviewThumbnail_prefetchAllItemData() = runTest { + repository.getPreviewThumbnail("item", 1000) + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnail("item",1000) } + } + + @Test + fun getPreviewThumbnailsInfo() = runTest { + val previewThumbnailsInfo = repository.getPreviewThumbnailsInfo("item") + assertEquals(10, previewThumbnailsInfo.count) + assertEquals(500, previewThumbnailsInfo.distanceInMS) + } + + @Test + fun getPreviewThumbnailsInfo_prefetchAllItemData() = runTest { + repository.getPreviewThumbnailsInfo("item") + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + + @Test + fun getChapters_returnsCorrectList() = runTest { + val chapters = repository.getChapters("item") + assertEquals(3, chapters.size) + assertEquals("chapter1", chapters.get(0).chapterTitle) + assertEquals("chapter2", chapters.get(1).chapterTitle) + assertEquals("chapter3", chapters.get(2).chapterTitle) + } + + @Test + fun getChapters_prefetchAllItemData() = runTest { + repository.getChapters("item") + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 2) { mockMediaRepository.getChapters("item") } + } + + @Test + fun prefetch() = runTest { + repository.prefetch("item") + + coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + + //This request should not call the prefetch since data are already prefetched + repository.getMetaInfo("item") + + //Check that the repository was called only one time for each type of data since prefetch was already done + // except for getMetaInfo which is used here to trigger the automatic prefetch + coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } + + @Test + fun reset_resetAlreadySeenItemsInfo() = runTest { + repository.getMetaInfo("item") + repository.reset() + repository.getMetaInfo("item") + repository.reset() + repository.getMetaInfo("item") + repository.reset() + + coVerify (exactly = 6) { cachingRepository.getMetaInfo("item") } + coVerify (exactly = 3) { cachingRepository.getStreams("item") } + coVerify (exactly = 3) { cachingRepository.getSubtitles("item") } + coVerify (exactly = 3) { cachingRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 3) { cachingRepository.getChapters("item") } + } + +} From baff73e2e695d29aeae39a045b708345fbb269b3 Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Wed, 20 Nov 2024 07:54:42 +0100 Subject: [PATCH 4/9] Fix prefetch function in PrefetchingRepository --- .../repository/PrefetchingRepository.kt | 5 ++++- .../repository/PrefetchingRepositoryTest.kt | 22 +++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/new-player/src/main/java/net/newpipe/newplayer/repository/PrefetchingRepository.kt b/new-player/src/main/java/net/newpipe/newplayer/repository/PrefetchingRepository.kt index bbaa3af2..eb2e1fde 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/repository/PrefetchingRepository.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/repository/PrefetchingRepository.kt @@ -118,7 +118,10 @@ class PrefetchingRepository( * Manually trigger a prefetch of [item] without performing an actual request. */ suspend fun prefetch(item:String) { - requestAll(item) + if(!hasBeenSeenBefore.contains(item)) { + hasBeenSeenBefore.add(item) + requestAll(item) + } } /** diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt index f9625ee1..c60d8543 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt @@ -38,6 +38,7 @@ class PrefetchingRepositoryTest { @Before fun clean() { clearMocks(mockMediaRepository) + clearMocks(cachingRepository) repository.reset() } @@ -155,25 +156,28 @@ class PrefetchingRepositoryTest { } @Test - fun prefetch() = runTest { + fun prefetch_prefetchInformationOfNewItem() = runTest { repository.prefetch("item") + repository.getTimestampLink("item", 1000) coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + } - //This request should not call the prefetch since data are already prefetched + @Test + fun prefetch_notPrefetchInformationOfAlreadySeenItem() = runTest { repository.getMetaInfo("item") + clearMocks(cachingRepository) + repository.prefetch("item") - //Check that the repository was called only one time for each type of data since prefetch was already done - // except for getMetaInfo which is used here to trigger the automatic prefetch - coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } - coVerify (exactly = 1) { mockMediaRepository.getStreams("item") } - coVerify (exactly = 1) { mockMediaRepository.getSubtitles("item") } - coVerify (exactly = 1) { mockMediaRepository.getPreviewThumbnailsInfo("item") } - coVerify (exactly = 1) { mockMediaRepository.getChapters("item") } + coVerify (exactly = 0) { cachingRepository.getMetaInfo("item") } + coVerify (exactly = 0) { cachingRepository.getStreams("item") } + coVerify (exactly = 0) { cachingRepository.getSubtitles("item") } + coVerify (exactly = 0) { cachingRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 0) { cachingRepository.getChapters("item") } } @Test From e3bb450c96d8e4ff93b57d224e2e93e96691607e Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Wed, 20 Nov 2024 14:14:09 +0100 Subject: [PATCH 5/9] PrefetchingRepository tests completed --- .../newpipe/newplayer/repository/PrefetchingRepositoryTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt index c60d8543..dbb81f7d 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/PrefetchingRepositoryTest.kt @@ -158,6 +158,7 @@ class PrefetchingRepositoryTest { @Test fun prefetch_prefetchInformationOfNewItem() = runTest { repository.prefetch("item") + //TODO: understand why without this call the spy is not updated and the test fails repository.getTimestampLink("item", 1000) coVerify (exactly = 1) { mockMediaRepository.getMetaInfo("item") } @@ -188,6 +189,8 @@ class PrefetchingRepositoryTest { repository.reset() repository.getMetaInfo("item") repository.reset() + //TODO: understand why without this call the spy is not updated and the test fails + repository.getTimestampLink("item", 1000) coVerify (exactly = 6) { cachingRepository.getMetaInfo("item") } coVerify (exactly = 3) { cachingRepository.getStreams("item") } From c8c8b41c8aa26c891db31e93bab8bc6f89414524 Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Fri, 22 Nov 2024 10:58:30 +0100 Subject: [PATCH 6/9] Prepared test class for NewPlayerImpl --- .../newpipe/newplayer/NewPlayerImpltest.kt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt diff --git a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt new file mode 100644 index 00000000..53062fe1 --- /dev/null +++ b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt @@ -0,0 +1,50 @@ +package net.newpipe.newplayer + +import android.app.Activity +import android.app.Application +import io.mockk.mockk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.setMain +import net.newpipe.newplayer.repository.DelayTestRepository +import net.newpipe.newplayer.repository.MockMediaRepository +import org.junit.BeforeClass +import org.junit.Test + +//TODO +// * onPlayBackError +// * prepare +// * play +// * pause +// * addToPlaylist +// * movePlaylistItem +// * removePlaylistItem +// * playStream +// * selectChapter +// * release +// * getItemFromMediaItem + +@OptIn(ExperimentalCoroutinesApi::class) +class NewPlayerImpltest { + val app = mockk<Application>(relaxed = true) + val playerActivityClass = Activity::class.java + val repository = DelayTestRepository(MockMediaRepository(), 100) + val player = NewPlayerImpl(app, playerActivityClass, repository) + + companion object { + @JvmStatic + @BeforeClass + fun init() { + Dispatchers.setMain(StandardTestDispatcher()) + } + + @JvmStatic + @BeforeClass + fun reset() { + Dispatchers.resetMain() + } + } + +} \ No newline at end of file From e3091c47fe8dc9083cb11d70c479fbe840a8e437 Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Wed, 4 Dec 2024 14:36:39 +0100 Subject: [PATCH 7/9] NewPlayerImpl tests: tested prepare function --- .../newpipe/newplayer/NewPlayerImpltest.kt | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt index 53062fe1..8422c906 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt @@ -2,7 +2,25 @@ package net.newpipe.newplayer import android.app.Activity import android.app.Application +import android.content.ComponentName +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.content.pm.ServiceInfo +import android.os.Looper +import android.text.TextUtils +import android.util.Log +import androidx.media3.exoplayer.ExoPlayer +import androidx.media3.session.MediaController +import androidx.media3.session.SessionToken +import com.google.common.util.concurrent.Futures +import io.mockk.clearMocks +import io.mockk.every import io.mockk.mockk +import io.mockk.mockkConstructor +import io.mockk.mockkStatic +import io.mockk.spyk +import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher @@ -10,12 +28,12 @@ import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain import net.newpipe.newplayer.repository.DelayTestRepository import net.newpipe.newplayer.repository.MockMediaRepository +import org.junit.Before import org.junit.BeforeClass import org.junit.Test //TODO // * onPlayBackError -// * prepare // * play // * pause // * addToPlaylist @@ -28,10 +46,46 @@ import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class NewPlayerImpltest { - val app = mockk<Application>(relaxed = true) + val mockExoPlayer = mockk<ExoPlayer>(relaxed = true) + val mockApp = mockk<Application>(relaxed = true) val playerActivityClass = Activity::class.java val repository = DelayTestRepository(MockMediaRepository(), 100) - val player = NewPlayerImpl(app, playerActivityClass, repository) + var player = NewPlayerImpl(mockApp, playerActivityClass, repository) + + init { + mockkStatic(Looper::class) + mockkStatic(TextUtils::class) + mockkStatic(Log::class) + mockkStatic(ExoPlayer::class) + mockkStatic(ExoPlayer.Builder::class) + mockkStatic(TextUtils::class) + mockkConstructor(ComponentName::class) + mockkConstructor(Intent::class) + mockkConstructor(SessionToken::class) + mockkConstructor(ExoPlayer.Builder::class) + mockkConstructor(MediaController.Builder::class) + + val mockLooper = mockk<Looper>(relaxed = true) + val mockMediaController = mockk<MediaController>(relaxed = true) + val mockPackageManager = mockk<PackageManager>(relaxed = true) + val mockResolveInfo = mockk<ResolveInfo>(relaxed = true) + val mockServiceInfo = mockk<ServiceInfo>(relaxed = true) + mockResolveInfo.serviceInfo = mockServiceInfo + mockServiceInfo.name = "ComponentNameTest" + + every { Looper.myLooper() } returns mockLooper + every { TextUtils.isEmpty(any()) } returns true + every { Log.i(any(), any()) } returns 1 + every { anyConstructed<ComponentName>().packageName } returns "net.newpipe.newplayer.test" + every { anyConstructed<ComponentName>().className } returns "ComponentNameTest" + every { anyConstructed<ComponentName>().hashCode() } returns 1 + every { anyConstructed<Intent>().setPackage(any()) } returns mockk<Intent>(relaxed = true) + every { anyConstructed<ExoPlayer.Builder>().build() } returns mockExoPlayer + every { TextUtils.equals(any(), any()) } returns true + every { anyConstructed<MediaController.Builder>().buildAsync() } returns Futures.immediateFuture(mockMediaController) + every { mockApp.packageManager } returns mockPackageManager + every { mockPackageManager.queryIntentServices(any(), any<Int>()) } returns listOf(mockResolveInfo) + } companion object { @JvmStatic @@ -47,4 +101,52 @@ class NewPlayerImpltest { } } + @Before + fun resetSpy() { + clearMocks(mockExoPlayer) + player = NewPlayerImpl(mockApp, playerActivityClass, repository) + } + + @Test + fun prepare_setupNewExoplayer() { + player.prepare() + verify (exactly = 1) { anyConstructed<ExoPlayer.Builder>().build() } + } + + @Test + fun prepare_notSetupNewExoPlayerWhenAlreadySetUp() { + // Setup new ExoPlayer + player.prepare() + + // Call prepare with an already set up ExoPlayer + player.prepare() + + //ExoPlayer should be built only one time + verify (exactly = 1) { anyConstructed<ExoPlayer.Builder>().build() } + } + + @Test + fun prepare_prepareExoPlayer() { + player.prepare() + verify (exactly = 1) { mockExoPlayer.prepare() } + } + + @Test + fun prepare_setUpMediaController() { + player.prepare() + verify (exactly = 1) { anyConstructed<MediaController.Builder>().buildAsync() } + } + + @Test + fun prepare_notSetUpMediaController() { + // Setup media controller + player.prepare() + + // Call prepare with an already set up media controller + player.prepare() + + //Media controller should be built only one time + verify (exactly = 1) { anyConstructed<MediaController.Builder>().buildAsync() } + } + } \ No newline at end of file From ab39f5dede2066d44b588e0185799be18c6e06da Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Wed, 4 Dec 2024 15:51:57 +0100 Subject: [PATCH 8/9] NewPlayerImpl tests: tested play and pause functions --- .../newpipe/newplayer/NewPlayerImpltest.kt | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt index 8422c906..3bb5e4ce 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt @@ -19,7 +19,6 @@ import io.mockk.every import io.mockk.mockk import io.mockk.mockkConstructor import io.mockk.mockkStatic -import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -32,18 +31,6 @@ import org.junit.Before import org.junit.BeforeClass import org.junit.Test -//TODO -// * onPlayBackError -// * play -// * pause -// * addToPlaylist -// * movePlaylistItem -// * removePlaylistItem -// * playStream -// * selectChapter -// * release -// * getItemFromMediaItem - @OptIn(ExperimentalCoroutinesApi::class) class NewPlayerImpltest { val mockExoPlayer = mockk<ExoPlayer>(relaxed = true) @@ -107,6 +94,13 @@ class NewPlayerImpltest { player = NewPlayerImpl(mockApp, playerActivityClass, repository) } + @Test + fun onPlayBackError_pauseExoPlayer() { + player.prepare() + player.onPlayBackError(Exception("test")) + verify (exactly = 1) { mockExoPlayer.pause() } + } + @Test fun prepare_setupNewExoplayer() { player.prepare() @@ -149,4 +143,27 @@ class NewPlayerImpltest { verify (exactly = 1) { anyConstructed<MediaController.Builder>().buildAsync() } } + @Test + fun play_playIfCurrentMediaItemIsNotNull() { + player.prepare() + player.play() + verify (exactly = 1) { mockExoPlayer.play() } + } + + @Test + fun play_notPlayIfCurrentMediaItemIsNull() { + player.prepare() + every { mockExoPlayer.currentMediaItem } returns null + player.play() + verify (exactly = 0) { mockExoPlayer.play() } + } + + @Test + fun pause() { + player.prepare() + player.pause() + verify (exactly = 1) { mockExoPlayer.pause() } + } + + } \ No newline at end of file From 99eac56dfc95b50fb3e1afa92085838a5da4bdf7 Mon Sep 17 00:00:00 2001 From: Nicholas Sala <salanicholas.14@gmail.com> Date: Sun, 8 Dec 2024 17:22:17 +0100 Subject: [PATCH 9/9] NewPlayerImpl tests: tested addToPlaylist, movePlaylistItem, removePlaylistItem, selectChapter and release functions --- .../newpipe/newplayer/NewPlayerImpltest.kt | 79 ++++++++++++++++++- .../repository/CachingRepositoryTest.kt | 59 +++++++------- 2 files changed, 105 insertions(+), 33 deletions(-) diff --git a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt index 3bb5e4ce..7263dfa3 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/NewPlayerImpltest.kt @@ -10,6 +10,7 @@ import android.content.pm.ServiceInfo import android.os.Looper import android.text.TextUtils import android.util.Log +import androidx.media3.common.MediaItem import androidx.media3.exoplayer.ExoPlayer import androidx.media3.session.MediaController import androidx.media3.session.SessionToken @@ -22,18 +23,20 @@ import io.mockk.mockkStatic import io.mockk.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain import net.newpipe.newplayer.repository.DelayTestRepository import net.newpipe.newplayer.repository.MockMediaRepository import org.junit.Before import org.junit.BeforeClass +import org.junit.Ignore import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) class NewPlayerImpltest { val mockExoPlayer = mockk<ExoPlayer>(relaxed = true) + val mockMediaController = mockk<MediaController>(relaxed = true) val mockApp = mockk<Application>(relaxed = true) val playerActivityClass = Activity::class.java val repository = DelayTestRepository(MockMediaRepository(), 100) @@ -53,7 +56,6 @@ class NewPlayerImpltest { mockkConstructor(MediaController.Builder::class) val mockLooper = mockk<Looper>(relaxed = true) - val mockMediaController = mockk<MediaController>(relaxed = true) val mockPackageManager = mockk<PackageManager>(relaxed = true) val mockResolveInfo = mockk<ResolveInfo>(relaxed = true) val mockServiceInfo = mockk<ServiceInfo>(relaxed = true) @@ -78,7 +80,7 @@ class NewPlayerImpltest { @JvmStatic @BeforeClass fun init() { - Dispatchers.setMain(StandardTestDispatcher()) + Dispatchers.setMain(UnconfinedTestDispatcher()) } @JvmStatic @@ -165,5 +167,74 @@ class NewPlayerImpltest { verify (exactly = 1) { mockExoPlayer.pause() } } - + @Test + fun addToPlaylist_prepareExoPlayerIfNotPrepared() { + player.addToPlaylist("item") + verify (exactly = 1) { mockExoPlayer.prepare() } + } + + @Test + fun addToPlaylist_notPrepareExoPlayerIfAlreadyPrepared() { + player.prepare() + clearMocks(mockExoPlayer) + player.addToPlaylist("item") + verify (exactly = 0) { mockExoPlayer.prepare() } + } + + @Ignore("Find a way to test code inside launchJobAndCollectError") + @Test + fun addToPlaylist_addMediaSource() { + player.addToPlaylist("item") +// try { +// Dispatchers.Main.job.join() +// } catch (e : Exception) { } +// coVerify (exactly = 2) { mockExoPlayer.addMediaSource(any()) } + } + + @Test + fun movePlaylistItem() { + player.prepare() + player.movePlaylistItem(0, 1) + verify (exactly = 1){ mockExoPlayer.moveMediaItem(0, 1) } + } + + @Test + fun removePlaylistItem_removeItem() { + player.prepare() + val mediaItem = MediaItem.Builder().setMediaId("123").build() + every { mockExoPlayer.mediaItemCount } returns 1 + every { mockExoPlayer.getMediaItemAt(any()) } returns mediaItem + player.removePlaylistItem(123) + verify (exactly = 1) { mockExoPlayer.removeMediaItem(0) } + } + + @Test + fun removePlaylistItem_notRemoveItem() { + player.prepare() + val mediaItem = MediaItem.Builder().setMediaId("123").build() + every { mockExoPlayer.mediaItemCount } returns 1 + every { mockExoPlayer.getMediaItemAt(any()) } returns mediaItem + player.removePlaylistItem(124) + verify (exactly = 0) { mockExoPlayer.removeMediaItem(0) } + } + + @Ignore("Mock currentChapters.value and test the selection of a chapter") + @Test + fun selectChapter() { + player.selectChapter(0) + } + + @Test(expected = IndexOutOfBoundsException::class) + fun selectChapter_throwsException() { + player.selectChapter(3) + } + + @Test + fun release() { + player.prepare() + player.release() + verify (exactly = 1) { mockMediaController.release() } + verify (exactly = 1) { mockExoPlayer.release() } + } + } \ No newline at end of file diff --git a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt index 48dd3f93..bec4e4d1 100644 --- a/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt +++ b/new-player/src/test/java/net/newpipe/newplayer/repository/CachingRepositoryTest.kt @@ -13,6 +13,7 @@ import org.junit.Test import org.junit.Assert.* import org.junit.Before import org.junit.BeforeClass +import org.junit.Ignore @OptIn(ExperimentalCoroutinesApi::class) class CachingRepositoryTest { @@ -157,33 +158,33 @@ class CachingRepositoryTest { assertNotNull(repository.getHttpDataSourceFactory("item")) } - // TODO -// @Test -// fun flush_flushTheCaches() = runTest { -// repository.getMetaInfo("item") -// repository.getStreams("item") -// repository.getSubtitles("item") -// repository.getPreviewThumbnail("item", 1000) -// repository.getPreviewThumbnailsInfo("item") -// repository.getChapters("item") -// repository.getTimestampLink("item", 0) -// -// repository.flush() -// -// repository.getMetaInfo("item") -// repository.getStreams("item") -// repository.getSubtitles("item") -// repository.getPreviewThumbnail("item", 1000) -// repository.getPreviewThumbnailsInfo("item") -// repository.getChapters("item") -// repository.getTimestampLink("item", 0) -// -// coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } -// coVerify (exactly = 2) { mockMediaRepository.getStreams("item") } -// coVerify (exactly = 2) { mockMediaRepository.getSubtitles("item") } -// coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnail("item", 1000) } -// coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnailsInfo("item") } -// coVerify (exactly = 2) { mockMediaRepository.getChapters("item") } -// coVerify (exactly = 2) { mockMediaRepository.getTimestampLink("item", 0) } -// } + @Ignore("Test flush if the job is cancelled using cacheRepoScope and the test is interrupted") + @Test + fun flush_flushTheCaches() = runTest { + repository.getMetaInfo("item") + repository.getStreams("item") + repository.getSubtitles("item") + repository.getPreviewThumbnail("item", 1000) + repository.getPreviewThumbnailsInfo("item") + repository.getChapters("item") + repository.getTimestampLink("item", 0) + + repository.flush() + + repository.getMetaInfo("item") + repository.getStreams("item") + repository.getSubtitles("item") + repository.getPreviewThumbnail("item", 1000) + repository.getPreviewThumbnailsInfo("item") + repository.getChapters("item") + repository.getTimestampLink("item", 0) + + coVerify (exactly = 2) { mockMediaRepository.getMetaInfo("item") } + coVerify (exactly = 2) { mockMediaRepository.getStreams("item") } + coVerify (exactly = 2) { mockMediaRepository.getSubtitles("item") } + coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnail("item", 1000) } + coVerify (exactly = 2) { mockMediaRepository.getPreviewThumbnailsInfo("item") } + coVerify (exactly = 2) { mockMediaRepository.getChapters("item") } + coVerify (exactly = 2) { mockMediaRepository.getTimestampLink("item", 0) } + } } \ No newline at end of file