From 4615146029b722fee8d2766a0464db87e350bf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Muller?= Date: Mon, 6 Jan 2025 09:23:59 +0100 Subject: [PATCH] 830 reduce flakiness of some tests (#846) --- .../analytics/SRGAnalyticsSingletonTest.kt | 4 +- .../pillarbox/analytics/SRGAnalyticsTest.kt | 7 + .../analytics/comscore/ComScoreSrgTest.kt | 4 +- .../core/business/PillarboxTestPlayer.kt | 37 +++++ .../tracker/SRGEventLoggerTrackerTest.kt | 17 ++- .../CommandersActTrackerIntegrationTest.kt | 18 +-- .../ComScoreTrackerIntegrationTest.kt | 15 +- .../tracker/comscore/ComScoreTrackerTest.kt | 4 +- pillarbox-demo-shared/build.gradle.kts | 1 + .../ui/integrationLayer/data/ContentTest.kt | 4 +- .../test/utils/TestPillarboxRunHelper.kt | 12 +- pillarbox-player/build.gradle.kts | 1 + .../player/IsPlayingAllTypeOfContentTest.kt | 14 +- ...=> PillarboxExoPlayerPlaybackSpeedTest.kt} | 61 ++++---- .../player/PillarboxMediaPeriodTest.kt | 143 ++++++++---------- .../player/PlayerCallbackFlowTest.kt | 48 +++--- .../TestIsPlaybackSpeedPossibleAtPosition.kt | 10 +- .../player/TestPlayerCallbackFlow.kt | 102 ++++++------- .../player/analytics/MetricsCollectorTest.kt | 8 +- .../analytics/PlaybackSessionManagerTest.kt | 18 +-- .../player/monitoring/MonitoringTest.kt | 2 +- .../player/network/RequestSenderTest.kt | 36 ++++- .../PillarboxMediaDescriptionAdapterTest.kt | 7 + .../player/session/PlayerSessionStateTest.kt | 8 +- .../player/tracker/MediaItemTrackerTest.kt | 2 +- .../PillarboxMediaMetaDataTrackerTest.kt | 26 ++-- .../pillarbox/player/utils/HeartbeatTest.kt | 7 +- 27 files changed, 324 insertions(+), 292 deletions(-) create mode 100644 pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/PillarboxTestPlayer.kt rename pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/{TestPillarboxExoPlayerPlaybackSpeed.kt => PillarboxExoPlayerPlaybackSpeedTest.kt} (61%) diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsSingletonTest.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsSingletonTest.kt index ce216978f..374b772fe 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsSingletonTest.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsSingletonTest.kt @@ -9,8 +9,8 @@ import android.content.Context import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.comscore.Analytics +import io.mockk.clearAllMocks import io.mockk.mockkStatic -import io.mockk.unmockkAll import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf import kotlin.test.AfterTest @@ -37,7 +37,7 @@ class SRGAnalyticsSingletonTest { @AfterTest fun tearDown() { - unmockkAll() + clearAllMocks() } @Test(expected = IllegalArgumentException::class) diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsTest.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsTest.kt index a5bba2226..71fae6643 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsTest.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/SRGAnalyticsTest.kt @@ -10,9 +10,11 @@ import ch.srgssr.pillarbox.analytics.commandersact.CommandersActPageView import ch.srgssr.pillarbox.analytics.comscore.ComScore import ch.srgssr.pillarbox.analytics.comscore.ComScorePageView import io.mockk.Called +import io.mockk.clearAllMocks import io.mockk.confirmVerified import io.mockk.mockk import io.mockk.verify +import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test @@ -31,6 +33,11 @@ class SRGAnalyticsTest { ) } + @AfterTest + fun tearDown() { + clearAllMocks() + } + @Test fun `sendPageView invokes comScore and commandersAct`() { val commandersActPageView = CommandersActPageView( diff --git a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrgTest.kt b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrgTest.kt index 4d5ac70b6..91bc8b18e 100644 --- a/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrgTest.kt +++ b/pillarbox-analytics/src/test/java/ch/srgssr/pillarbox/analytics/comscore/ComScoreSrgTest.kt @@ -10,11 +10,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import ch.srgssr.pillarbox.analytics.AnalyticsConfig import com.comscore.Analytics import com.comscore.PublisherConfiguration +import io.mockk.clearAllMocks import io.mockk.confirmVerified import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic -import io.mockk.unmockkAll import io.mockk.verify import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf @@ -44,7 +44,7 @@ class ComScoreSrgTest { @AfterTest fun tearDown() { - unmockkAll() + clearAllMocks() } @Test(expected = IllegalArgumentException::class) diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/PillarboxTestPlayer.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/PillarboxTestPlayer.kt new file mode 100644 index 000000000..dcb7e652a --- /dev/null +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/PillarboxTestPlayer.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) SRG SSR. All rights reserved. + * License information is available from the LICENSE file. + */ +package ch.srgssr.pillarbox.core.business + +import android.content.Context +import androidx.media3.common.C +import androidx.media3.exoplayer.DefaultLoadControl +import androidx.media3.test.utils.FakeClock +import androidx.test.core.app.ApplicationProvider +import ch.srgssr.pillarbox.player.PillarboxDsl +import ch.srgssr.pillarbox.player.PillarboxExoPlayer +import kotlin.coroutines.EmptyCoroutineContext + +/** + * Pillarbox ExoPlayer + * + * @param context The [Context], by default [ApplicationProvider.getApplicationContext] + * @param block The block to further configure the [PillarboxExoPlayer]. + * @return [PillarboxExoPlayer] configured for tests. + */ +@PillarboxDsl +fun PillarboxExoPlayer(context: Context = ApplicationProvider.getApplicationContext(), block: SRG.Builder.() -> Unit = {}): PillarboxExoPlayer { + return PillarboxExoPlayer(context, SRG) { + loadControl(DefaultLoadControl()) + clock(FakeClock(true)) + coroutineContext(EmptyCoroutineContext) + disableMonitoring() + block() + }.apply { + // FIXME Investigate why we need to disable the image track in tests + trackSelectionParameters = trackSelectionParameters.buildUpon() + .setTrackTypeDisabled(C.TRACK_TYPE_IMAGE, true) + .build() + } +} diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/SRGEventLoggerTrackerTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/SRGEventLoggerTrackerTest.kt index e67803a7e..25caa463f 100644 --- a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/SRGEventLoggerTrackerTest.kt +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/SRGEventLoggerTrackerTest.kt @@ -6,18 +6,31 @@ package ch.srgssr.pillarbox.core.business.tracker import androidx.media3.exoplayer.ExoPlayer import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.mockk.clearAllMocks import io.mockk.mockk import io.mockk.verifySequence import org.junit.runner.RunWith +import kotlin.test.AfterTest +import kotlin.test.BeforeTest import kotlin.test.Test @RunWith(AndroidJUnit4::class) class SRGEventLoggerTrackerTest { + private lateinit var player: ExoPlayer + + @BeforeTest + fun setUp() { + player = mockk(relaxed = true) + } + + @AfterTest + fun tearDown() { + clearAllMocks() + } + @Test fun `event logger`() { - val player = mockk(relaxed = true) val eventLogger = SRGEventLoggerTracker.Factory().create() - eventLogger.start(player, Unit) eventLogger.stop(player) diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/commandersact/CommandersActTrackerIntegrationTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/commandersact/CommandersActTrackerIntegrationTest.kt index 6a813cc94..e3fd50987 100644 --- a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/commandersact/CommandersActTrackerIntegrationTest.kt +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/commandersact/CommandersActTrackerIntegrationTest.kt @@ -6,7 +6,6 @@ package ch.srgssr.pillarbox.core.business.tracker.commandersact import android.content.Context import android.os.Looper -import androidx.media3.common.C import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.exoplayer.ExoPlayer @@ -42,7 +41,6 @@ import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf -import kotlin.coroutines.EmptyCoroutineContext import kotlin.math.abs import kotlin.test.AfterTest import kotlin.test.BeforeTest @@ -70,29 +68,21 @@ class CommandersActTrackerIntegrationTest { testDispatcher = UnconfinedTestDispatcher() val context = ApplicationProvider.getApplicationContext() - val mediaCompositionWithFallbackService = LocalMediaCompositionWithFallbackService(context) - player = PillarboxExoPlayer(context) { + player = PillarboxExoPlayer { + clock(clock) srgAssetLoader(context) { - mediaCompositionService(mediaCompositionWithFallbackService) + mediaCompositionService(LocalMediaCompositionWithFallbackService(context)) commanderActTrackerFactory(CommandersActTracker.Factory(commandersAct = commandersAct, coroutineContext = testDispatcher)) comscoreTrackerFactory(mockk(relaxed = true)) } - clock(clock) - // Use other CoroutineContext to avoid infinite loop because Heartbeat is also running in Pillarbox. - coroutineContext(EmptyCoroutineContext) - }.apply { - // FIXME Investigate why we need to disable the image track in tests - trackSelectionParameters = trackSelectionParameters.buildUpon() - .setTrackTypeDisabled(C.TRACK_TYPE_IMAGE, true) - .build() } } @AfterTest fun tearDown() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerIntegrationTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerIntegrationTest.kt index bd945aebc..8054c5428 100644 --- a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerIntegrationTest.kt +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerIntegrationTest.kt @@ -9,7 +9,6 @@ import android.os.Looper import android.view.SurfaceView import android.view.ViewGroup import androidx.core.view.updateLayoutParams -import androidx.media3.common.C import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.test.utils.FakeClock @@ -33,7 +32,6 @@ import io.mockk.verify import io.mockk.verifyOrder import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf -import kotlin.coroutines.EmptyCoroutineContext import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Ignore @@ -57,28 +55,21 @@ class ComScoreTrackerIntegrationTest { ComScoreTracker(streamingAnalytics) } val context = ApplicationProvider.getApplicationContext() - val mediaCompositionWithFallbackService = LocalMediaCompositionWithFallbackService(context) - player = PillarboxExoPlayer(context) { + player = PillarboxExoPlayer { clock(clock) - coroutineContext(EmptyCoroutineContext) srgAssetLoader(context) { - mediaCompositionService(mediaCompositionWithFallbackService) + mediaCompositionService(LocalMediaCompositionWithFallbackService(context)) comscoreTrackerFactory(comScoreFactory) commanderActTrackerFactory(mockk(relaxed = true)) } - }.apply { - // FIXME Investigate why we need to disable the image track in tests - trackSelectionParameters = trackSelectionParameters.buildUpon() - .setTrackTypeDisabled(C.TRACK_TYPE_IMAGE, true) - .build() } } @AfterTest fun tearDown() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test diff --git a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt index b6f503f16..a2da1f96d 100644 --- a/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt +++ b/pillarbox-core-business/src/test/java/ch/srgssr/pillarbox/core/business/tracker/comscore/ComScoreTrackerTest.kt @@ -11,11 +11,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import ch.srgssr.pillarbox.analytics.BuildConfig import com.comscore.Analytics import com.comscore.streaming.StreamingAnalytics +import io.mockk.clearAllMocks import io.mockk.confirmVerified import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic -import io.mockk.unmockkAll import io.mockk.verify import org.junit.runner.RunWith import kotlin.test.AfterTest @@ -33,7 +33,7 @@ class ComScoreTrackerTest { @AfterTest fun tearDown() { - unmockkAll() + clearAllMocks() } @Test diff --git a/pillarbox-demo-shared/build.gradle.kts b/pillarbox-demo-shared/build.gradle.kts index 937816ba4..95694962f 100644 --- a/pillarbox-demo-shared/build.gradle.kts +++ b/pillarbox-demo-shared/build.gradle.kts @@ -50,4 +50,5 @@ dependencies { debugImplementation(libs.androidx.compose.ui.tooling) testImplementation(libs.junit) + testImplementation(libs.kotlin.test) } diff --git a/pillarbox-demo-shared/src/test/java/ch/srgssr/pillarbox/demo/shared/ui/integrationLayer/data/ContentTest.kt b/pillarbox-demo-shared/src/test/java/ch/srgssr/pillarbox/demo/shared/ui/integrationLayer/data/ContentTest.kt index e0c62c548..92588877e 100644 --- a/pillarbox-demo-shared/src/test/java/ch/srgssr/pillarbox/demo/shared/ui/integrationLayer/data/ContentTest.kt +++ b/pillarbox-demo-shared/src/test/java/ch/srgssr/pillarbox/demo/shared/ui/integrationLayer/data/ContentTest.kt @@ -9,10 +9,10 @@ import ch.srg.dataProvider.integrationlayer.data.remote.Media import ch.srg.dataProvider.integrationlayer.data.remote.MediaType import ch.srg.dataProvider.integrationlayer.data.remote.Type import ch.srg.dataProvider.integrationlayer.data.remote.Vendor -import org.junit.Assert.assertEquals -import org.junit.Test import java.util.Date import java.util.Locale +import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds diff --git a/pillarbox-player-testutils/src/main/java/ch/srgssr/pillarbox/player/test/utils/TestPillarboxRunHelper.kt b/pillarbox-player-testutils/src/main/java/ch/srgssr/pillarbox/player/test/utils/TestPillarboxRunHelper.kt index c8c463a9b..af1f4cceb 100644 --- a/pillarbox-player-testutils/src/main/java/ch/srgssr/pillarbox/player/test/utils/TestPillarboxRunHelper.kt +++ b/pillarbox-player-testutils/src/main/java/ch/srgssr/pillarbox/player/test/utils/TestPillarboxRunHelper.kt @@ -4,6 +4,7 @@ */ package ch.srgssr.pillarbox.player.test.utils +import android.annotation.SuppressLint import android.os.Looper import androidx.media3.common.PlaybackParameters import androidx.media3.common.Player @@ -26,25 +27,26 @@ object TestPillarboxRunHelper { } /** - * Runs tasks of the main Looper until [Player.Listener.onEvents] matches the + * Runs tasks of the main [Looper] until [Player.Listener.onEvents] matches the * expected state or a playback error occurs. * - *

If a playback error occurs it will be thrown wrapped in an {@link IllegalStateException}. + *

If a playback error occurs it will be thrown wrapped in an [IllegalStateException]. * * @param player The [Player]. - * @param expectedEvent The expected [Player.Event] if null wait until first [Player.Listener.onEvents]. + * @param expectedEvents The expected [Player.Event]. If empty, waits until the first [Player.Listener.onEvents]. * @throws TimeoutException If the [RobolectricUtil.DEFAULT_TIMEOUT_MS] is exceeded. */ @Throws(TimeoutException::class) - fun runUntilEvent(player: Player, expectedEvent: @Player.Event Int? = null) { + fun runUntilEvents(player: Player, vararg expectedEvents: @Player.Event Int) { verifyMainTestThread(player) if (player is ExoPlayer) { verifyPlaybackThreadIsAlive(player) } val receivedCallback = AtomicBoolean(false) val listener: Player.Listener = object : Player.Listener { + @SuppressLint("WrongConstant") override fun onEvents(player: Player, events: Player.Events) { - if (expectedEvent?.let { events.contains(it) } != false) { + if (expectedEvents.isEmpty() || events.containsAny(*expectedEvents)) { receivedCallback.set(true) } } diff --git a/pillarbox-player/build.gradle.kts b/pillarbox-player/build.gradle.kts index 218ee7504..b8321a1cb 100644 --- a/pillarbox-player/build.gradle.kts +++ b/pillarbox-player/build.gradle.kts @@ -72,6 +72,7 @@ dependencies { androidTestImplementation(libs.androidx.test.monitor) androidTestRuntimeOnly(libs.androidx.test.runner) androidTestImplementation(libs.junit) + androidTestImplementation(libs.kotlin.test) androidTestRuntimeOnly(libs.kotlinx.coroutines.android) androidTestImplementation(libs.mockk) } diff --git a/pillarbox-player/src/androidTest/java/ch/srgssr/pillarbox/player/IsPlayingAllTypeOfContentTest.kt b/pillarbox-player/src/androidTest/java/ch/srgssr/pillarbox/player/IsPlayingAllTypeOfContentTest.kt index 35ddfbcdb..471805226 100644 --- a/pillarbox-player/src/androidTest/java/ch/srgssr/pillarbox/player/IsPlayingAllTypeOfContentTest.kt +++ b/pillarbox-player/src/androidTest/java/ch/srgssr/pillarbox/player/IsPlayingAllTypeOfContentTest.kt @@ -11,11 +11,13 @@ import androidx.media3.common.Player import androidx.media3.common.util.ConditionVariable import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation import ch.srgssr.pillarbox.player.utils.ContentUrls -import org.junit.Assert -import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.Parameterized import java.util.concurrent.atomic.AtomicReference +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue /** * Instrumented test, which will execute on an Android device. @@ -50,10 +52,10 @@ class IsPlayingAllTypeOfContentTest { if (player.playerError != null) { throw Exception(player.playerError) } - Assert.assertEquals(Player.STATE_READY, player.playbackState) - Assert.assertTrue(player.isPlaying) - Assert.assertNotNull(player.currentMediaItem) - Assert.assertEquals(player.currentMediaItem?.localConfiguration?.uri, Uri.parse(urlToTest)) + assertEquals(Player.STATE_READY, player.playbackState) + assertTrue(player.isPlaying) + assertNotNull(player.currentMediaItem) + assertEquals(player.currentMediaItem?.localConfiguration?.uri, Uri.parse(urlToTest)) player.release() } } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPillarboxExoPlayerPlaybackSpeed.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxExoPlayerPlaybackSpeedTest.kt similarity index 61% rename from pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPillarboxExoPlayerPlaybackSpeed.kt rename to pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxExoPlayerPlaybackSpeedTest.kt index 5f85572bc..083368910 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPillarboxExoPlayerPlaybackSpeed.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxExoPlayerPlaybackSpeedTest.kt @@ -4,40 +4,33 @@ */ package ch.srgssr.pillarbox.player -import android.content.Context import android.os.Looper import androidx.media3.common.C import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.common.Timeline.Window -import androidx.media3.test.utils.FakeClock import androidx.media3.test.utils.robolectric.TestPlayerRunHelper -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import ch.srgssr.pillarbox.player.extension.getPlaybackSpeed import ch.srgssr.pillarbox.player.test.utils.TestPillarboxRunHelper -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf -import kotlin.coroutines.EmptyCoroutineContext +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals @RunWith(AndroidJUnit4::class) -class TestPillarboxExoPlayerPlaybackSpeed { +class PillarboxExoPlayerPlaybackSpeedTest { private lateinit var player: PillarboxExoPlayer - @Before + @BeforeTest fun createPlayer() { - val context = ApplicationProvider.getApplicationContext() - player = PillarboxExoPlayer(context) { - clock(FakeClock(true)) - coroutineContext(EmptyCoroutineContext) - } + player = PillarboxExoPlayer() } - @After + @AfterTest fun releasePlayer() { player.release() shadowOf(Looper.getMainLooper()).idle() @@ -51,15 +44,15 @@ class TestPillarboxExoPlayerPlaybackSpeed { play() } TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) - Assert.assertEquals(Player.STATE_READY, player.playbackState) + assertEquals(Player.STATE_READY, player.playbackState) player.setPlaybackSpeed(2f) - Assert.assertEquals(1f, player.getPlaybackSpeed()) + assertEquals(1f, player.getPlaybackSpeed()) player.seekTo(0) TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) player.setPlaybackSpeed(2f) - Assert.assertEquals(1f, player.getPlaybackSpeed()) + assertEquals(1f, player.getPlaybackSpeed()) } @Test @@ -71,15 +64,15 @@ class TestPillarboxExoPlayerPlaybackSpeed { TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) player.setPlaybackSpeed(2f) - Assert.assertEquals(1f, player.getPlaybackSpeed()) + assertEquals(1f, player.getPlaybackSpeed()) player.seekTo(0) TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) player.setPlaybackSpeed(2f) - Assert.assertEquals(2f, player.getPlaybackSpeed()) - TestPillarboxRunHelper.runUntilEvent(player, Player.EVENT_IS_LOADING_CHANGED) - Assert.assertEquals(2f, player.getPlaybackSpeed()) + assertEquals(2f, player.getPlaybackSpeed()) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_IS_LOADING_CHANGED) + assertEquals(2f, player.getPlaybackSpeed()) } @Test @@ -90,16 +83,16 @@ class TestPillarboxExoPlayerPlaybackSpeed { TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) val liveEdgePosition = player.currentTimeline.getWindow(0, Window()).defaultPositionMs - Assert.assertNotEquals(C.TIME_UNSET, liveEdgePosition) + assertNotEquals(C.TIME_UNSET, liveEdgePosition) player.seekTo(liveEdgePosition - 5_000) TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) val speed = 2f player.setPlaybackSpeed(speed) - Assert.assertEquals(speed, player.getPlaybackSpeed()) + assertEquals(speed, player.getPlaybackSpeed()) TestPillarboxRunHelper.runUntilPlaybackParametersChanged(player) - Assert.assertEquals(1f, player.getPlaybackSpeed()) + assertEquals(1f, player.getPlaybackSpeed()) } @Test @@ -111,17 +104,17 @@ class TestPillarboxExoPlayerPlaybackSpeed { val speed = 2f player.setPlaybackSpeed(speed) - TestPillarboxRunHelper.runUntilEvent(player) - Assert.assertEquals(speed, player.getPlaybackSpeed()) + TestPillarboxRunHelper.runUntilEvents(player) + assertEquals(speed, player.getPlaybackSpeed()) player.setPlaybackSpeed(1f) - TestPillarboxRunHelper.runUntilEvent(player) - Assert.assertEquals(1f, player.getPlaybackSpeed()) + TestPillarboxRunHelper.runUntilEvents(player) + assertEquals(1f, player.getPlaybackSpeed()) } - companion object { - const val LIVE_DVR_URL = "https://rtsc3video.akamaized.net/hls/live/2042837/c3video/3/playlist.m3u8" - const val LIVE_ONLY_URL = "https://rtsc3video.akamaized.net/hls/live/2042837/c3video/3/playlist.m3u8?dw=0" - const val VOD_URL = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" + private companion object { + private const val LIVE_DVR_URL = "https://rtsc3video.akamaized.net/hls/live/2042837/c3video/3/playlist.m3u8" + private const val LIVE_ONLY_URL = "https://rtsc3video.akamaized.net/hls/live/2042837/c3video/3/playlist.m3u8?dw=0" + private const val VOD_URL = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" } } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxMediaPeriodTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxMediaPeriodTest.kt index 76fbf4120..c4061b947 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxMediaPeriodTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PillarboxMediaPeriodTest.kt @@ -6,6 +6,7 @@ package ch.srgssr.pillarbox.player import androidx.media3.common.Format import androidx.media3.common.TrackGroup +import androidx.media3.exoplayer.source.MediaPeriod import androidx.media3.exoplayer.source.TrackGroupArray import androidx.media3.test.utils.FakeMediaPeriod import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -17,128 +18,108 @@ import ch.srgssr.pillarbox.player.tracker.FactoryData import ch.srgssr.pillarbox.player.tracker.FakeMediaItemTracker import ch.srgssr.pillarbox.player.tracker.MediaItemTrackerData import ch.srgssr.pillarbox.player.tracker.MutableMediaItemTrackerData +import io.mockk.clearAllMocks import io.mockk.mockk import org.junit.runner.RunWith +import kotlin.test.AfterTest +import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) class PillarboxMediaPeriodTest { + private lateinit var format: Format + private lateinit var mediaPeriod: MediaPeriod + + @BeforeTest + fun setUp() { + format = Format.Builder() + .setId("FakeId") + .build() + mediaPeriod = FakeMediaPeriod( + /* trackGroupArray = */ TrackGroupArray(TrackGroup(format)), + /* allocator = */ mockk(relaxed = true), + /* singleSampleTimeUs = */ 0L, + /* mediaSourceEventDispatcher = */ mockk(relaxed = true), + ) + } + + @AfterTest + fun tearDown() { + clearAllMocks() + } @Test fun `test track group with no tracker data and no blocked time range`() { - val mediaItemTrackData = MediaItemTrackerData(MutableMediaItemTrackerData.EMPTY) - val blockedTimeRangeList = emptyList() val mediaPeriod = PillarboxMediaPeriod( - mediaPeriod = createFakeChildMediaPeriod(), - mediaItemTrackerData = mediaItemTrackData, - blockedTimeRanges = blockedTimeRangeList - ) - val expectedTrackGroup = TrackGroupArray( - TrackGroup(createDummyFormat("DummyId")) + mediaPeriod = mediaPeriod, + mediaItemTrackerData = emptyTrackerData, + blockedTimeRanges = emptyList(), ) + val expectedTrackGroup = TrackGroupArray(TrackGroup(format)) mediaPeriod.prepare(mockk(relaxed = true), 0) assertEquals(expectedTrackGroup, mediaPeriod.trackGroups) } @Test fun `test track group with tracker data and blocked time range`() { - val mutableMediaItemTrackerData = MutableMediaItemTrackerData() - mutableMediaItemTrackerData[Any()] = FactoryData(FakeMediaItemTracker.Factory(FakeMediaItemTracker()), FakeMediaItemTracker.Data("Test01")) - val mediaItemTrackerData = mutableMediaItemTrackerData.toMediaItemTrackerData() - val blockedTimeRangeList = listOf(BlockedTimeRange(0L, 100L), BlockedTimeRange(200L, 300L)) val mediaPeriod = PillarboxMediaPeriod( - mediaPeriod = createFakeChildMediaPeriod(), - mediaItemTrackerData = mediaItemTrackerData, - blockedTimeRanges = blockedTimeRangeList - ) - val expectedTrackGroup = TrackGroupArray( - TrackGroup(createDummyFormat("DummyId")), - TrackGroup( - "Pillarbox-Trackers", - Format.Builder() - .setId("TrackerData:0") - .setSampleMimeType(PILLARBOX_TRACKERS_MIME_TYPE) - .setCustomData(mediaItemTrackerData) - .build() - ), - TrackGroup( - "Pillarbox-BlockedTimeRanges", - Format.Builder() - .setSampleMimeType(PILLARBOX_BLOCKED_MIME_TYPE) - .setId("BlockedTimeRanges") - .setCustomData(blockedTimeRangeList) - .build(), - ) + mediaPeriod = mediaPeriod, + mediaItemTrackerData = trackerData, + blockedTimeRanges = blockedTimeRanges, ) + val expectedTrackGroup = TrackGroupArray(TrackGroup(format), trackTrackers, trackBlockedTimeRanges) mediaPeriod.prepare(mockk(relaxed = true), 0) assertEquals(expectedTrackGroup, mediaPeriod.trackGroups) } @Test fun `test track group with tracker data only`() { - val mutableMediaItemTrackerData = MutableMediaItemTrackerData() - mutableMediaItemTrackerData[Any()] = FactoryData(FakeMediaItemTracker.Factory(FakeMediaItemTracker()), FakeMediaItemTracker.Data("Test01")) - val mediaItemTrackerData = mutableMediaItemTrackerData.toMediaItemTrackerData() - val blockedTimeRangeList = emptyList() val mediaPeriod = PillarboxMediaPeriod( - mediaPeriod = createFakeChildMediaPeriod(), - mediaItemTrackerData = mediaItemTrackerData, - blockedTimeRanges = blockedTimeRangeList - ) - val expectedTrackGroup = TrackGroupArray( - TrackGroup(createDummyFormat("DummyId")), - TrackGroup( - "Pillarbox-Trackers", - Format.Builder() - .setId("TrackerData:0") - .setSampleMimeType(PILLARBOX_TRACKERS_MIME_TYPE) - .setCustomData(mediaItemTrackerData) - .build() - ) + mediaPeriod = mediaPeriod, + mediaItemTrackerData = trackerData, + blockedTimeRanges = emptyList(), ) + val expectedTrackGroup = TrackGroupArray(TrackGroup(format), trackTrackers) mediaPeriod.prepare(mockk(relaxed = true), 0) assertEquals(expectedTrackGroup, mediaPeriod.trackGroups) } @Test fun `test track group with blocked time range only`() { - val mediaItemTrackData = MediaItemTrackerData(MutableMediaItemTrackerData.EMPTY) - val blockedTimeRangeList = listOf(BlockedTimeRange(0L, 100L), BlockedTimeRange(200L, 300L)) val mediaPeriod = PillarboxMediaPeriod( - mediaPeriod = createFakeChildMediaPeriod(), - mediaItemTrackerData = mediaItemTrackData, - blockedTimeRanges = blockedTimeRangeList - ) - val expectedTrackGroup = TrackGroupArray( - TrackGroup(createDummyFormat("DummyId")), - TrackGroup( - "Pillarbox-BlockedTimeRanges", - Format.Builder() - .setSampleMimeType(PILLARBOX_BLOCKED_MIME_TYPE) - .setId("BlockedTimeRanges") - .setCustomData(blockedTimeRangeList) - .build(), - ) + mediaPeriod = mediaPeriod, + mediaItemTrackerData = emptyTrackerData, + blockedTimeRanges = blockedTimeRanges, ) + val expectedTrackGroup = TrackGroupArray(TrackGroup(format), trackBlockedTimeRanges) mediaPeriod.prepare(mockk(relaxed = true), 0) assertEquals(expectedTrackGroup, mediaPeriod.trackGroups) } - companion object { - fun createFakeChildMediaPeriod(trackGroupArray: TrackGroupArray = createFakeTracks()) = - FakeMediaPeriod(trackGroupArray, mockk(relaxed = true), 0L, mockk(relaxed = true)) + private companion object { + private val blockedTimeRanges = listOf(BlockedTimeRange(0L, 100L), BlockedTimeRange(200L, 300L)) + private val emptyTrackerData = MediaItemTrackerData(MutableMediaItemTrackerData.EMPTY) + private val trackerData = MutableMediaItemTrackerData().apply { + put(Any(), FactoryData(FakeMediaItemTracker.Factory(FakeMediaItemTracker()), FakeMediaItemTracker.Data("Test01"))) + }.toMediaItemTrackerData() - fun createDummyFormat(id: String) = Format.Builder() - .setId(id) - .build() + private val trackBlockedTimeRanges = TrackGroup( + "Pillarbox-BlockedTimeRanges", + Format.Builder() + .setId("BlockedTimeRanges") + .setSampleMimeType(PILLARBOX_BLOCKED_MIME_TYPE) + .setCustomData(blockedTimeRanges) + .build(), + ) - private fun createFakeTracks(): TrackGroupArray { - return TrackGroupArray( - TrackGroup( - createDummyFormat("DummyId") - ) - ) - } + private val trackTrackers = TrackGroup( + "Pillarbox-Trackers", + Format.Builder() + .setId("TrackerData:0") + .setSampleMimeType(PILLARBOX_TRACKERS_MIME_TYPE) + .setCustomData(trackerData) + .build(), + ) } } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PlayerCallbackFlowTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PlayerCallbackFlowTest.kt index 53b868fad..1541f0ae9 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PlayerCallbackFlowTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/PlayerCallbackFlowTest.kt @@ -12,6 +12,7 @@ import androidx.media3.exoplayer.ExoPlayer import androidx.media3.test.utils.robolectric.TestPlayerRunHelper import androidx.test.ext.junit.runners.AndroidJUnit4 import app.cash.turbine.test +import ch.srgssr.pillarbox.player.test.utils.TestPillarboxRunHelper import kotlinx.coroutines.test.runTest import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf @@ -19,6 +20,7 @@ import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertTrue import kotlin.time.Duration.Companion.milliseconds @@ -43,7 +45,7 @@ class PlayerCallbackFlowTest { @Test fun `is current media item live as flow, no media item`() = runTest { player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(false, awaitItem()) + assertFalse(awaitItem()) ensureAllEventsConsumed() } } @@ -52,10 +54,10 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, vod`() = runTest { player.setMediaItem(MediaItem.fromUri(VOD)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(false, awaitItem()) + assertFalse(awaitItem()) ensureAllEventsConsumed() } } @@ -64,10 +66,10 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, live`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(true, awaitItem()) + assertTrue(awaitItem()) ensureAllEventsConsumed() } } @@ -76,10 +78,10 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, live dvr`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE_DVR)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(true, awaitItem()) + assertTrue(awaitItem()) ensureAllEventsConsumed() } } @@ -88,14 +90,14 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, remove media item`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE_DVR)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.clearMediaItems() TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(false, awaitItem()) + assertFalse(awaitItem()) ensureAllEventsConsumed() } } @@ -104,14 +106,14 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, transition vod to live dvr`() = runTest { player.setMediaItems(listOf(MediaItem.fromUri(VOD), MediaItem.fromUri(LIVE_DVR))) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.seekToNextMediaItem() - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(true, awaitItem()) + assertTrue(awaitItem()) ensureAllEventsConsumed() } } @@ -120,14 +122,14 @@ class PlayerCallbackFlowTest { fun `is current media item live as flow, transition live dvr to vod`() = runTest { player.setMediaItems(listOf(MediaItem.fromUri(LIVE_DVR), MediaItem.fromUri(VOD))) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.seekToNextMediaItem() - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilTimelineChanged(player) player.isCurrentMediaItemLiveAsFlow().test { - assertEquals(false, awaitItem()) + assertFalse(awaitItem()) ensureAllEventsConsumed() } } @@ -144,7 +146,7 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, vod`() = runTest { player.setMediaItem(MediaItem.fromUri(VOD)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.getCurrentDefaultPositionAsFlow().test { assertEquals(0L, awaitItem()) @@ -156,7 +158,7 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, live`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.getCurrentDefaultPositionAsFlow().test { assertEquals(0L, awaitItem()) @@ -168,7 +170,7 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, live dvr`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE_DVR)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.getCurrentDefaultPositionAsFlow().test { val currentDefaultPositionInHours = awaitItem().milliseconds.inWholeHours @@ -182,7 +184,7 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, remove media item`() = runTest { player.setMediaItem(MediaItem.fromUri(LIVE_DVR)) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.clearMediaItems() @@ -198,11 +200,11 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, transition vod to live dvr`() = runTest { player.setMediaItems(listOf(MediaItem.fromUri(VOD), MediaItem.fromUri(LIVE))) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.seekToNextMediaItem() - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.getCurrentDefaultPositionAsFlow().test { assertEquals(0L, awaitItem()) @@ -214,11 +216,11 @@ class PlayerCallbackFlowTest { fun `get current default position as flow, transition live dvr to vod`() = runTest { player.setMediaItems(listOf(MediaItem.fromUri(LIVE), MediaItem.fromUri(VOD))) - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.seekToNextMediaItem() - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPillarboxRunHelper.runUntilEvents(player, Player.EVENT_TIMELINE_CHANGED, Player.EVENT_PLAYBACK_STATE_CHANGED) player.getCurrentDefaultPositionAsFlow().test { assertEquals(0L, awaitItem()) diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestIsPlaybackSpeedPossibleAtPosition.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestIsPlaybackSpeedPossibleAtPosition.kt index 4273cc7e0..52b785e7e 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestIsPlaybackSpeedPossibleAtPosition.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestIsPlaybackSpeedPossibleAtPosition.kt @@ -12,17 +12,17 @@ import ch.srgssr.pillarbox.player.test.utils.TestTimeline import io.mockk.clearAllMocks import io.mockk.every import io.mockk.mockk -import org.junit.After -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import org.junit.Test +import kotlin.test.AfterTest +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue import kotlin.time.Duration.Companion.hours import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds class TestIsPlaybackSpeedPossibleAtPosition { - @After + @AfterTest fun tearDown() { clearAllMocks() } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPlayerCallbackFlow.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPlayerCallbackFlow.kt index 63f5bdb74..56b4ee2ac 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPlayerCallbackFlow.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/TestPlayerCallbackFlow.kt @@ -23,30 +23,24 @@ import ch.srgssr.pillarbox.player.utils.StringUtil import io.mockk.clearAllMocks import io.mockk.every import io.mockk.mockk -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest -import org.junit.After -import org.junit.Assert -import org.junit.Before -import org.junit.Test import org.junit.runner.RunWith +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNull @RunWith(AndroidJUnit4::class) class TestPlayerCallbackFlow { private lateinit var player: Player - private lateinit var dispatcher: CoroutineDispatcher - @Before - @OptIn(ExperimentalCoroutinesApi::class) + @BeforeTest fun setUp() { - dispatcher = UnconfinedTestDispatcher() player = mockk(relaxed = true) } - @After + @AfterTest fun tearDown() { clearAllMocks() } @@ -57,11 +51,11 @@ class TestPlayerCallbackFlow { every { player.isPlaying } returns true val currentPositionFlow = player.currentPositionAsFlow() currentPositionFlow.test { - Assert.assertEquals(C.TIME_UNSET, awaitItem()) + assertEquals(C.TIME_UNSET, awaitItem()) every { player.currentPosition } returns 1000L - Assert.assertEquals(1000L, awaitItem()) + assertEquals(1000L, awaitItem()) every { player.currentPosition } returns 10_000L - Assert.assertEquals(10_000L, awaitItem()) + assertEquals(10_000L, awaitItem()) ensureAllEventsConsumed() } } @@ -75,7 +69,7 @@ class TestPlayerCallbackFlow { every { player.isPlaying } returns false every { player.currentPosition } returns 1000L player.currentPositionAsFlow().test { - Assert.assertEquals(1000L, awaitItem()) + assertEquals(1000L, awaitItem()) ensureAllEventsConsumed() } } @@ -85,9 +79,9 @@ class TestPlayerCallbackFlow { every { player.isPlaying } returns true player.currentBufferedPercentageAsFlow().test { every { player.bufferedPercentage } returns 0 - Assert.assertEquals(0.0f, awaitItem()) + assertEquals(0.0f, awaitItem()) every { player.bufferedPercentage } returns 75 - Assert.assertEquals(0.75f, awaitItem()) + assertEquals(0.75f, awaitItem()) ensureAllEventsConsumed() } } @@ -106,7 +100,7 @@ class TestPlayerCallbackFlow { Player.DISCONTINUITY_REASON_SKIP to C.TIME_UNSET, ) fakePlayer.currentPositionAsFlow().test { - Assert.assertEquals(0L, awaitItem()) + assertEquals(0L, awaitItem()) for ((reason, position) in discontinuityTests) { fakePlayer.onPositionDiscontinuity( mockk(), @@ -116,7 +110,7 @@ class TestPlayerCallbackFlow { } for ((reason, position) in discontinuityTests) { - Assert.assertEquals(StringUtil.discontinuityReasonString(reason), position, awaitItem()) + assertEquals(position, awaitItem(), StringUtil.discontinuityReasonString(reason)) } ensureAllEventsConsumed() } @@ -136,10 +130,10 @@ class TestPlayerCallbackFlow { every { player.duration } returns 40_000L fakePlayer.onTimelineChanged(Timeline.EMPTY, Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE) - Assert.assertEquals("initial duration", C.TIME_UNSET, awaitItem()) - Assert.assertEquals("State ready", 20_000L, awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED", 30_000L, awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_SOURCE_UPDATE", 40_000L, awaitItem()) + assertEquals(C.TIME_UNSET, awaitItem(), "initial duration") + assertEquals(20_000L, awaitItem(), "State ready") + assertEquals(30_000L, awaitItem(), "TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED") + assertEquals(40_000L, awaitItem(), "TIMELINE_CHANGE_REASON_SOURCE_UPDATE") ensureAllEventsConsumed() } } @@ -154,10 +148,10 @@ class TestPlayerCallbackFlow { fakePlayer.onIsPlayingChanged(true) fakePlayer.onIsPlayingChanged(false) - Assert.assertEquals("initial isPlaying", false, awaitItem()) - Assert.assertEquals("isPlaying", true, awaitItem()) - Assert.assertEquals("isPlaying", true, awaitItem()) - Assert.assertEquals("isPlaying", false, awaitItem()) + assertEquals(false, awaitItem(), "initial isPlaying") + assertEquals(true, awaitItem(), "isPlaying") + assertEquals(true, awaitItem(), "isPlaying") + assertEquals(false, awaitItem(), "isPlaying") ensureAllEventsConsumed() } } @@ -180,9 +174,9 @@ class TestPlayerCallbackFlow { fakePlayer.onPlaybackStateChanged(state) } - Assert.assertEquals("Initial state", Player.STATE_IDLE, awaitItem()) + assertEquals(Player.STATE_IDLE, awaitItem(), "Initial state") for (state in playbackStates) { - Assert.assertEquals(StringUtil.playerStateString(state), state, awaitItem()) + assertEquals(state, awaitItem(), StringUtil.playerStateString(state)) } ensureAllEventsConsumed() } @@ -199,9 +193,9 @@ class TestPlayerCallbackFlow { fakePlayer.onPlayerErrorChanged(error) fakePlayer.onPlayerErrorChanged(noError) - Assert.assertEquals("Initial error", null, awaitItem()) - Assert.assertEquals("error", error, awaitItem()) - Assert.assertEquals("error removed", noError, awaitItem()) + assertEquals(null, awaitItem(), "Initial error") + assertEquals(error, awaitItem(), "error") + assertEquals(noError, awaitItem(), "error removed") ensureAllEventsConsumed() } } @@ -214,8 +208,8 @@ class TestPlayerCallbackFlow { val fakePlayer = PlayerListenerCommander(player) fakePlayer.availableCommandsAsFlow().test { fakePlayer.onAvailableCommandsChanged(command2) - Assert.assertEquals(command1, awaitItem()) - Assert.assertEquals(command2, awaitItem()) + assertEquals(command1, awaitItem()) + assertEquals(command2, awaitItem()) ensureAllEventsConsumed() } } @@ -231,11 +225,11 @@ class TestPlayerCallbackFlow { fakePlayer.onShuffleModeEnabledChanged(true) fakePlayer.onShuffleModeEnabledChanged(false) - Assert.assertEquals("initial state", false, awaitItem()) - Assert.assertEquals(false, awaitItem()) - Assert.assertEquals(false, awaitItem()) - Assert.assertEquals(true, awaitItem()) - Assert.assertEquals(false, awaitItem()) + assertEquals(false, awaitItem(), "initial state") + assertEquals(false, awaitItem()) + assertEquals(false, awaitItem()) + assertEquals(true, awaitItem()) + assertEquals(false, awaitItem()) ensureAllEventsConsumed() } } @@ -250,9 +244,9 @@ class TestPlayerCallbackFlow { fakePlayer.onPlaybackParametersChanged(initialParameters.withSpeed(2.0f)) fakePlayer.onPlaybackParametersChanged(initialParameters.withSpeed(0.5f)) - Assert.assertEquals("Initial playback speed", initialPlaybackRate, awaitItem()) - Assert.assertEquals(2.0f, awaitItem()) - Assert.assertEquals(0.5f, awaitItem()) + assertEquals(initialPlaybackRate, awaitItem(), "Initial playback speed") + assertEquals(2.0f, awaitItem()) + assertEquals(0.5f, awaitItem()) ensureAllEventsConsumed() } } @@ -278,10 +272,10 @@ class TestPlayerCallbackFlow { fakePlayer.onMediaItemTransition(mockk(), reason) } - Assert.assertEquals("Initial index", 0, awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED", 2, awaitItem()) + assertEquals(0, awaitItem(), "Initial index") + assertEquals(2, awaitItem(), "TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED") for ((reason, index) in transitionReasonCases) { - Assert.assertEquals(StringUtil.mediaItemTransitionReasonString(reason), index, awaitItem()) + assertEquals(index, awaitItem(), StringUtil.mediaItemTransitionReasonString(reason)) } ensureAllEventsConsumed() } @@ -310,10 +304,10 @@ class TestPlayerCallbackFlow { fakePlayer.onMediaItemTransition(mediaItem, reason) } - Assert.assertNull("Initial", awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_SOURCE_UPDATE", mediaItemTimeLineSourceUpdate, awaitItem()) + assertNull(awaitItem(), "Initial") + assertEquals(mediaItemTimeLineSourceUpdate, awaitItem(), "TIMELINE_CHANGE_REASON_SOURCE_UPDATE") for ((reason, mediaItem) in transitionReasonCases) { - Assert.assertEquals(StringUtil.mediaItemTransitionReasonString(reason), mediaItem, awaitItem()) + assertEquals(mediaItem, awaitItem(), StringUtil.mediaItemTransitionReasonString(reason)) } ensureAllEventsConsumed() } @@ -341,9 +335,9 @@ class TestPlayerCallbackFlow { every { player.mediaItemCount } returns 1 fakePlayer.onTimelineChanged(mockk(), Player.TIMELINE_CHANGE_REASON_SOURCE_UPDATE) - Assert.assertEquals("Initial list", list1, awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED", list2, awaitItem()) - Assert.assertEquals("TIMELINE_CHANGE_REASON_SOURCE_UPDATE list", listOf(item1), awaitItem()) + assertEquals(list1, awaitItem(), "Initial list") + assertEquals(list2, awaitItem(), "TIMELINE_CHANGE_REASON_PLAYLIST_CHANGED") + assertEquals(listOf(item1), awaitItem(), "TIMELINE_CHANGE_REASON_SOURCE_UPDATE list") ensureAllEventsConsumed() } } @@ -357,8 +351,8 @@ class TestPlayerCallbackFlow { fakePlayer.videoSizeAsFlow().test { fakePlayer.onVideoSizeChanged(newSize) - Assert.assertEquals("Initial video size", initialSize, awaitItem()) - Assert.assertEquals("Updated video size", newSize, awaitItem()) + assertEquals(initialSize, awaitItem(), "Initial video size") + assertEquals(newSize, awaitItem(), "Updated video size") ensureAllEventsConsumed() } } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/MetricsCollectorTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/MetricsCollectorTest.kt index 248432046..1b063ebbd 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/MetricsCollectorTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/MetricsCollectorTest.kt @@ -42,23 +42,23 @@ class MetricsCollectorTest { player = PillarboxExoPlayer() player.metricsCollector.addListener(metricsListener) player.prepare() + player.play() clearMocks(metricsListener) } @AfterTest fun tearDown() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test fun `single item playback`() { player.setMediaItem(VOD1) - player.play() - TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) + TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED) // Session is finished when starting another media or when there is no more current item @@ -86,8 +86,8 @@ class MetricsCollectorTest { @Test fun `playback item transition`() { player.setMediaItems(listOf(VOD1, VOD2)) - player.play() + TestPlayerRunHelper.playUntilStartOfMediaItem(player, 1) TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_ENDED) // To ensure that the final `onSessionFinished` is triggered. diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/PlaybackSessionManagerTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/PlaybackSessionManagerTest.kt index 69cd6cd8f..d75928e83 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/PlaybackSessionManagerTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/analytics/PlaybackSessionManagerTest.kt @@ -4,15 +4,13 @@ */ package ch.srgssr.pillarbox.player.analytics -import android.content.Context import android.os.Looper import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.exoplayer.ExoPlayer -import androidx.media3.test.utils.FakeClock import androidx.media3.test.utils.robolectric.TestPlayerRunHelper -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import ch.srgssr.pillarbox.player.PillarboxExoPlayer import io.mockk.clearAllMocks import io.mockk.clearMocks import io.mockk.confirmVerified @@ -32,23 +30,15 @@ import kotlin.test.assertTrue @RunWith(AndroidJUnit4::class) class PlaybackSessionManagerTest { - private lateinit var clock: FakeClock private lateinit var player: ExoPlayer private lateinit var sessionManager: PlaybackSessionManager private lateinit var sessionManagerListener: PlaybackSessionManager.Listener @BeforeTest fun setUp() { - val context = ApplicationProvider.getApplicationContext() - - clock = FakeClock(true) sessionManagerListener = mockk(relaxed = true) - player = ExoPlayer.Builder(context) - .setClock(clock) - .build() - .apply { - prepare() - } + player = PillarboxExoPlayer() + player.prepare() sessionManager = PlaybackSessionManager().apply { setPlayer(player) @@ -60,9 +50,9 @@ class PlaybackSessionManagerTest { @AfterTest fun tearDown() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/monitoring/MonitoringTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/monitoring/MonitoringTest.kt index 440b84956..6c42459de 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/monitoring/MonitoringTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/monitoring/MonitoringTest.kt @@ -48,9 +48,9 @@ class MonitoringTest { @AfterTest fun tearDown() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/network/RequestSenderTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/network/RequestSenderTest.kt index 63b84f180..85ebee2a8 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/network/RequestSenderTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/network/RequestSenderTest.kt @@ -6,10 +6,15 @@ package ch.srgssr.pillarbox.player.network import ch.srgssr.pillarbox.player.network.RequestSender.send import ch.srgssr.pillarbox.player.network.RequestSender.toJsonRequestBody +import io.mockk.clearAllMocks +import io.mockk.every +import io.mockk.mockk import kotlinx.serialization.Serializable import kotlinx.serialization.SerializationException import kotlinx.serialization.encodeToString +import okhttp3.OkHttpClient import okhttp3.Request +import okhttp3.ResponseBody.Companion.toResponseBody import okio.Buffer import kotlin.test.AfterTest import kotlin.test.BeforeTest @@ -32,6 +37,8 @@ class RequestSenderTest { @AfterTest fun tearDown() { buffer.close() + + clearAllMocks() } @Test @@ -56,10 +63,11 @@ class RequestSenderTest { @Test fun `send request, 20x`() { + val okHttpClient = createFakeOkHttpClient(statusCode = 200, contentBody = "Hello") val result = Request.Builder() - .url("https://httpbin.org/get") + .url("https://server.com/") .build() - .send() + .send(okHttpClient) assertTrue(result.isSuccess) assertNotNull(result.getOrNull()) @@ -68,10 +76,11 @@ class RequestSenderTest { @Test fun `send request, 40x`() { + val okHttpClient = createFakeOkHttpClient(statusCode = 404, contentBody = "Not found") val result = Request.Builder() - .url("https://httpbin.org/status/404") + .url("https://server.com/") .build() - .send() + .send(okHttpClient) val exception = result.exceptionOrNull() assertFalse(result.isSuccess) @@ -88,6 +97,25 @@ class RequestSenderTest { assertEquals(jsonSerializer.encodeToString(data), buffer.readUtf8()) } + private companion object { + private fun createFakeOkHttpClient( + statusCode: Int, + contentBody: String, + ): OkHttpClient { + return mockk { + every { newCall(any()) } returns mockk { + every { execute() } returns mockk { + every { isSuccessful } returns (statusCode in 200..299) + every { body } returns contentBody.toResponseBody(RequestSender.MIME_TYPE_JSON) + every { message } returns contentBody + every { code } returns statusCode + every { close() } returns Unit + } + } + } + } + } + @Serializable private data class SerializableModel( val name: String, diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/notification/PillarboxMediaDescriptionAdapterTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/notification/PillarboxMediaDescriptionAdapterTest.kt index ddeb51528..e2a45f7fe 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/notification/PillarboxMediaDescriptionAdapterTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/notification/PillarboxMediaDescriptionAdapterTest.kt @@ -12,10 +12,12 @@ import androidx.media3.common.Player import androidx.media3.ui.PlayerNotificationManager.MediaDescriptionAdapter import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.mockk.clearAllMocks import io.mockk.every import io.mockk.mockk import org.junit.runner.RunWith import org.robolectric.Shadows.shadowOf +import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertContentEquals @@ -35,6 +37,11 @@ class PillarboxMediaDescriptionAdapterTest { mediaDescriptionAdapter = PillarboxMediaDescriptionAdapter(pendingIntent, context) } + @AfterTest + fun tearDown() { + clearAllMocks() + } + @Test fun `get current content title, with displayTitle and title in metadata`() { val displayTitle = "Media display title" diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/session/PlayerSessionStateTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/session/PlayerSessionStateTest.kt index d90419d0a..49b6cbd78 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/session/PlayerSessionStateTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/session/PlayerSessionStateTest.kt @@ -4,9 +4,7 @@ */ package ch.srgssr.pillarbox.player.session -import android.content.Context import android.os.Bundle -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import ch.srgssr.pillarbox.player.PillarboxExoPlayer import org.junit.runner.RunWith @@ -52,8 +50,7 @@ class PlayerSessionStateTest { @Test fun `to bundle`() { - val context = ApplicationProvider.getApplicationContext() - val player = PillarboxExoPlayer(context).apply { + val player = PillarboxExoPlayer().apply { smoothSeekingEnabled = false trackingEnabled = true } @@ -68,8 +65,7 @@ class PlayerSessionStateTest { @Test fun `to bundle with extra data`() { - val context = ApplicationProvider.getApplicationContext() - val player = PillarboxExoPlayer(context).apply { + val player = PillarboxExoPlayer().apply { smoothSeekingEnabled = false trackingEnabled = true } diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MediaItemTrackerTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MediaItemTrackerTest.kt index bf4d2d4dc..b2b0d700c 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MediaItemTrackerTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MediaItemTrackerTest.kt @@ -43,9 +43,9 @@ class MediaItemTrackerTest { @AfterTest fun releasePlayer() { - clearAllMocks() player.release() shadowOf(Looper.getMainLooper()).idle() + clearAllMocks() } @Test diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/PillarboxMediaMetaDataTrackerTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/PillarboxMediaMetaDataTrackerTest.kt index 8871481ba..09b3442fd 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/PillarboxMediaMetaDataTrackerTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/PillarboxMediaMetaDataTrackerTest.kt @@ -15,7 +15,7 @@ import ch.srgssr.pillarbox.player.PillarboxPlayer import ch.srgssr.pillarbox.player.asset.timeRange.Chapter import ch.srgssr.pillarbox.player.extension.setChapters import io.mockk.clearAllMocks -import io.mockk.spyk +import io.mockk.mockk import io.mockk.verify import io.mockk.verifyOrder import org.junit.runner.RunWith @@ -32,7 +32,7 @@ class PillarboxMediaMetaDataTrackerTest { @BeforeTest fun createPlayer() { - listener = spyk(object : PillarboxPlayer.Listener {}) + listener = mockk(relaxed = true) player = PillarboxExoPlayer() player.addListener(listener) player.prepare() @@ -112,18 +112,18 @@ class PillarboxMediaMetaDataTrackerTest { assertEquals(expectedChapters, receivedChapters) } - companion object { + private companion object { private const val URL = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" - const val ID_START_WITH_CHAPTER = "ID_START_WITH_CHAPTER" - const val ID_WITH_CHAPTER = "ID_WITH_CHAPTER" - const val NEAR_END_POSITION_MS = 15_000L // the video has 17 sec duration + private const val ID_START_WITH_CHAPTER = "ID_START_WITH_CHAPTER" + private const val ID_WITH_CHAPTER = "ID_WITH_CHAPTER" + private const val NEAR_END_POSITION_MS = 15_000L // the video has 17 sec duration - val CHAPTER_1 = Chapter(id = "Chapter1", 0, 5_000L, MediaMetadata.EMPTY) - val CHAPTER_2 = Chapter(id = "Chapter2", 5_000L, NEAR_END_POSITION_MS, MediaMetadata.EMPTY) - val CHAPTER_3 = Chapter(id = "Chapter3", 2_000L, 5_000L, MediaMetadata.EMPTY) - val CHAPTER_4 = Chapter(id = "Chapter4", 10_000L, NEAR_END_POSITION_MS, MediaMetadata.EMPTY) + private val CHAPTER_1 = Chapter(id = "Chapter1", 0, 5_000L, MediaMetadata.EMPTY) + private val CHAPTER_2 = Chapter(id = "Chapter2", 5_000L, NEAR_END_POSITION_MS, MediaMetadata.EMPTY) + private val CHAPTER_3 = Chapter(id = "Chapter3", 2_000L, 5_000L, MediaMetadata.EMPTY) + private val CHAPTER_4 = Chapter(id = "Chapter4", 10_000L, NEAR_END_POSITION_MS, MediaMetadata.EMPTY) - val MEDIA_ITEM = MediaItem.Builder() + private val MEDIA_ITEM = MediaItem.Builder() .setMediaId(ID_START_WITH_CHAPTER) .setUri(URL) .setMediaMetadata( @@ -132,7 +132,7 @@ class PillarboxMediaMetaDataTrackerTest { .build() ) .build() - val MEDIA_ITEM_WITH_CHAPTER = MediaItem.Builder() + private val MEDIA_ITEM_WITH_CHAPTER = MediaItem.Builder() .setMediaId(ID_WITH_CHAPTER) .setUri(URL) .setMediaMetadata( @@ -141,7 +141,7 @@ class PillarboxMediaMetaDataTrackerTest { .build() ) .build() - val NO_CHAPTER_MEDIA_ITEM = MediaItem.Builder() + private val NO_CHAPTER_MEDIA_ITEM = MediaItem.Builder() .setMediaId("NoChapter") .setUri(URL) .build() diff --git a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/utils/HeartbeatTest.kt b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/utils/HeartbeatTest.kt index e47cc91bb..763ce82ae 100644 --- a/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/utils/HeartbeatTest.kt +++ b/pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/utils/HeartbeatTest.kt @@ -4,11 +4,9 @@ */ package ch.srgssr.pillarbox.player.utils -import android.content.Context import android.os.Looper -import androidx.media3.exoplayer.ExoPlayer -import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 +import ch.srgssr.pillarbox.player.PillarboxExoPlayer import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -308,8 +306,7 @@ class HeartbeatTest { @Test fun `verify player is accessible from the task`() { - val context = ApplicationProvider.getApplicationContext() - val player = ExoPlayer.Builder(context).build() + val player = PillarboxExoPlayer() runTest(testDispatcher) { var taskCalled = false