-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
439 improve current media item tracker (#440)
Co-authored-by: Gaëtan Muller <[email protected]>
Showing
18 changed files
with
1,261 additions
and
1,039 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
493 changes: 0 additions & 493 deletions
493
...stutils/src/main/java/ch/srgssr/pillarbox/player/test/utils/AnalyticsListenerCommander.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
190 changes: 190 additions & 0 deletions
190
...r/src/test/java/ch/srgssr/pillarbox/player/tracker/CurrentMediaItemTrackerAreEqualTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
/* | ||
* Copyright (c) SRG SSR. All rights reserved. | ||
* License information is available from the LICENSE file. | ||
*/ | ||
package ch.srgssr.pillarbox.player.tracker | ||
|
||
import androidx.media3.common.MediaItem | ||
import androidx.media3.common.MediaMetadata | ||
import androidx.media3.exoplayer.ExoPlayer | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import ch.srgssr.pillarbox.player.extension.getMediaItemTrackerData | ||
import ch.srgssr.pillarbox.player.extension.setTrackerData | ||
import org.junit.runner.RunWith | ||
import kotlin.test.Test | ||
import kotlin.test.assertFalse | ||
import kotlin.test.assertTrue | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class CurrentMediaItemTrackerAreEqualTest { | ||
|
||
@Test | ||
fun `areEqual both mediaItem are null`() { | ||
assertTrue(CurrentMediaItemTracker.areEqual(null, null)) | ||
} | ||
|
||
@Test | ||
fun `areEqual first mediaItem is null`() { | ||
assertFalse(CurrentMediaItemTracker.areEqual(null, MediaItem.EMPTY)) | ||
} | ||
|
||
@Test | ||
fun `areEqual second mediaItem is null`() { | ||
assertFalse(CurrentMediaItemTracker.areEqual(MediaItem.EMPTY, null)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with different media id without tag and url`() { | ||
val mediaItem = createMediaItemWithMediaId("M1") | ||
val mediaItem2 = createMediaItemWithMediaId("M2") | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with same media id without tag and url`() { | ||
val mediaItem = createMediaItemWithMediaId("M1") | ||
val mediaItem2 = createMediaItemWithMediaId("M1") | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with one default media id`() { | ||
val mediaItem = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID) | ||
val mediaItem2 = createMediaItemWithMediaId("M1") | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with both default media id`() { | ||
val mediaItem = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID) | ||
val mediaItem2 = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID) | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with same media id same url same tag`() { | ||
val mediaId = "M1" | ||
val url = "https://streaming.com/video.mp4" | ||
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1") | ||
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1") | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with same media id same url without tag`() { | ||
val mediaId = "M1" | ||
val url = "https://streaming.com/video.mp4" | ||
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url) | ||
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url) | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with same media id same url and different tag`() { | ||
val mediaId = "M1" | ||
val url = "https://streaming.com/video.mp4" | ||
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = null) | ||
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag2") | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual with same media id different url and same tag`() { | ||
val mediaId = "M1" | ||
val url = "https://streaming.com/video.mp4" | ||
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1") | ||
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = "https://streaming.com/video2.mp4", tag = "Tag1") | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual no media id same url different tag`() { | ||
val mediaItem = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTag("Tag1") | ||
.build() | ||
|
||
val mediaItem2 = mediaItem.buildUpon() | ||
.setTag("Tag2") | ||
.build() | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual same MediaItemTrackerData content`() { | ||
val mediaItem = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTrackerData(MediaItemTrackerData.Builder().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
|
||
val mediaItem2 = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTrackerData(MediaItemTrackerData.Builder().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual same MediaItemTrackerData`() { | ||
val mediaItem = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTrackerData(MediaItemTrackerData.Builder().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
|
||
val mediaItem2 = mediaItem.buildUpon() | ||
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areEqual same MediaItemTrackerData but different MediaMetadata`() { | ||
val mediaItem = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTrackerData(MediaItemTrackerData.Builder().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
|
||
val mediaItem2 = mediaItem.buildUpon() | ||
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().putData(Tracker::class.java, "data1").build()) | ||
.setMediaMetadata(MediaMetadata.Builder().setTitle("New title").build()) | ||
.build() | ||
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
@Test | ||
fun `areNotEqual different data`() { | ||
val mediaItem = MediaItem.Builder() | ||
.setUri("https://streaming.com/video.mp4") | ||
.setTrackerData(MediaItemTrackerData.Builder().putData(Tracker::class.java, "data1").build()) | ||
.build() | ||
|
||
val mediaItem2 = mediaItem.buildUpon() | ||
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().putData(Tracker::class.java, "data2").build()) | ||
.build() | ||
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2)) | ||
} | ||
|
||
private class Tracker : MediaItemTracker { | ||
override fun start(player: ExoPlayer, initialData: Any?) { | ||
// Nothing | ||
} | ||
|
||
override fun stop(player: ExoPlayer, reason: MediaItemTracker.StopReason, positionMs: Long) { | ||
// Nothing | ||
} | ||
} | ||
|
||
companion object { | ||
private fun createMediaItemWithMediaId( | ||
mediaId: String, | ||
url: String? = null, | ||
tag: Any? = null, | ||
): MediaItem { | ||
return MediaItem.Builder() | ||
.setUri(url) | ||
.setMediaId(mediaId) | ||
.setTag(tag) | ||
.build() | ||
} | ||
} | ||
} |
381 changes: 0 additions & 381 deletions
381
...ox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/CurrentMediaItemTrackerTest.kt
This file was deleted.
Oops, something went wrong.
44 changes: 44 additions & 0 deletions
44
pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/FakeMediaItemSource.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* Copyright (c) SRG SSR. All rights reserved. | ||
* License information is available from the LICENSE file. | ||
*/ | ||
package ch.srgssr.pillarbox.player.tracker | ||
|
||
import androidx.media3.common.MediaItem | ||
import ch.srgssr.pillarbox.player.data.MediaItemSource | ||
import ch.srgssr.pillarbox.player.extension.getMediaItemTrackerData | ||
import ch.srgssr.pillarbox.player.extension.setTrackerData | ||
|
||
class FakeMediaItemSource : MediaItemSource { | ||
override suspend fun loadMediaItem(mediaItem: MediaItem): MediaItem { | ||
val trackerData = mediaItem.getMediaItemTrackerData() | ||
val itemBuilder = mediaItem.buildUpon() | ||
|
||
if (mediaItem.localConfiguration == null) { | ||
val url = when (mediaItem.mediaId) { | ||
MEDIA_ID_1 -> URL_MEDIA_1 | ||
MEDIA_ID_2 -> URL_MEDIA_2 | ||
else -> URL_MEDIA_3 | ||
} | ||
itemBuilder.setUri(url) | ||
} | ||
|
||
if (mediaItem.mediaId == MEDIA_ID_NO_TRACKING_DATA) return itemBuilder.build() | ||
itemBuilder.setTrackerData( | ||
trackerData.buildUpon().putData(FakeMediaItemTracker::class.java, FakeMediaItemTracker.Data(mediaItem.mediaId)).build() | ||
) | ||
return itemBuilder.build() | ||
} | ||
|
||
companion object { | ||
const val MEDIA_ID_1 = "media:1" | ||
const val MEDIA_ID_2 = "media:2" | ||
const val MEDIA_ID_NO_TRACKING_DATA = "media:3" | ||
|
||
const val URL_MEDIA_1 = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" | ||
const val URL_MEDIA_2 = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" | ||
const val URL_MEDIA_3 = "https://rts-vod-amd.akamaized.net/ww/13317145/f1d49f18-f302-37ce-866c-1c1c9b76a824/master.m3u8" | ||
|
||
const val NEAR_END_POSITION_MS = 15_000L // the video has 17 sec duration | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/FakeMediaItemTracker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (c) SRG SSR. All rights reserved. | ||
* License information is available from the LICENSE file. | ||
*/ | ||
package ch.srgssr.pillarbox.player.tracker | ||
|
||
import androidx.media3.exoplayer.ExoPlayer | ||
|
||
class FakeMediaItemTracker : MediaItemTracker { | ||
data class Data(val id: String) | ||
|
||
override fun start(player: ExoPlayer, initialData: Any?) { | ||
require(initialData is Data) | ||
} | ||
|
||
override fun update(data: Any) { | ||
require(data is Data) | ||
} | ||
|
||
override fun stop(player: ExoPlayer, reason: MediaItemTracker.StopReason, positionMs: Long) { | ||
// Nothing | ||
} | ||
|
||
class Factory(private val fakeMediaItemTracker: FakeMediaItemTracker) : MediaItemTracker.Factory { | ||
override fun create(): MediaItemTracker { | ||
return fakeMediaItemTracker | ||
} | ||
} | ||
} | ||
|
||
class FakeTrackerProvider(private val fakeMediaItemTracker: FakeMediaItemTracker) : MediaItemTrackerProvider { | ||
override fun getMediaItemTrackerFactory(trackerClass: Class<*>): MediaItemTracker.Factory { | ||
return object : MediaItemTracker.Factory { | ||
override fun create(): MediaItemTracker { | ||
return fakeMediaItemTracker | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
632 changes: 632 additions & 0 deletions
632
pillarbox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MediaItemTrackerTest.kt
Large diffs are not rendered by default.
Oops, something went wrong.
125 changes: 125 additions & 0 deletions
125
...ox-player/src/test/java/ch/srgssr/pillarbox/player/tracker/MultiMediaItemTrackerUpdate.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* | ||
* Copyright (c) SRG SSR. All rights reserved. | ||
* License information is available from the LICENSE file. | ||
*/ | ||
package ch.srgssr.pillarbox.player.tracker | ||
|
||
import android.content.Context | ||
import androidx.media3.common.MediaItem | ||
import androidx.media3.common.Player | ||
import androidx.media3.datasource.DefaultHttpDataSource | ||
import androidx.media3.exoplayer.DefaultLoadControl | ||
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.PillarboxPlayer | ||
import ch.srgssr.pillarbox.player.SeekIncrement | ||
import ch.srgssr.pillarbox.player.data.MediaItemSource | ||
import ch.srgssr.pillarbox.player.extension.setTrackerData | ||
import io.mockk.clearAllMocks | ||
import io.mockk.spyk | ||
import io.mockk.verify | ||
import io.mockk.verifyOrder | ||
import org.junit.After | ||
import org.junit.Before | ||
import org.junit.runner.RunWith | ||
import kotlin.test.Test | ||
|
||
@RunWith(AndroidJUnit4::class) | ||
class MultiMediaItemTrackerUpdate { | ||
private lateinit var fakeClock: FakeClock | ||
|
||
@Before | ||
fun createPlayer() { | ||
fakeClock = FakeClock(true) | ||
} | ||
|
||
@After | ||
fun releasePlayer() { | ||
clearAllMocks() | ||
} | ||
|
||
@Test | ||
fun `Remove one tracker data update other tracker data when initialized both in MediaItemSource`() { | ||
val context = ApplicationProvider.getApplicationContext<Context>() | ||
val fakeMediaItemTracker = spyk(FakeMediaItemTracker()) | ||
val dummyMediaItemTracker = spyk(DummyTracker()) | ||
|
||
val player = PillarboxPlayer( | ||
context = context, | ||
dataSourceFactory = DefaultHttpDataSource.Factory(), | ||
seekIncrement = SeekIncrement(), | ||
loadControl = DefaultLoadControl(), | ||
clock = fakeClock, | ||
mediaItemSource = object : MediaItemSource { | ||
override suspend fun loadMediaItem(mediaItem: MediaItem): MediaItem { | ||
val trackerData = MediaItemTrackerData.Builder() | ||
.putData(DummyTracker::class.java, "DummyItemTracker") | ||
.putData(FakeMediaItemTracker::class.java, FakeMediaItemTracker.Data("FakeMediaItemTracker")) | ||
.build() | ||
return mediaItem.buildUpon() | ||
.setUri(FakeMediaItemSource.URL_MEDIA_1) | ||
.setTrackerData(trackerData) | ||
.build() | ||
} | ||
}, | ||
mediaItemTrackerProvider = MediaItemTrackerRepository().apply { | ||
registerFactory(DummyTracker::class.java, DummyTracker.Factory(dummyMediaItemTracker)) | ||
registerFactory(FakeMediaItemTracker::class.java, FakeMediaItemTracker.Factory(fakeMediaItemTracker)) | ||
} | ||
) | ||
player.apply { | ||
player.setMediaItem( | ||
MediaItem.Builder() | ||
.setMediaId(FakeMediaItemSource.MEDIA_ID_1) | ||
.build() | ||
) | ||
prepare() | ||
play() | ||
} | ||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY) | ||
|
||
val currentMediaItem = player.currentMediaItem!! | ||
val mediaUpdate = currentMediaItem.buildUpon() | ||
.setTrackerData( | ||
MediaItemTrackerData.Builder() | ||
.putData(FakeMediaItemTracker::class.java, FakeMediaItemTracker.Data("New Data")) | ||
.build() | ||
) | ||
.build() | ||
player.replaceMediaItem(0, mediaUpdate) | ||
|
||
verify(exactly = 0) { | ||
dummyMediaItemTracker.update(any()) | ||
} | ||
|
||
verify(exactly = 1) { | ||
dummyMediaItemTracker.start(any(), any()) | ||
} | ||
|
||
verifyOrder { | ||
fakeMediaItemTracker.start(any(), any()) | ||
fakeMediaItemTracker.update(FakeMediaItemTracker.Data("New Data")) | ||
} | ||
player.release() | ||
} | ||
|
||
internal class DummyTracker : MediaItemTracker { | ||
|
||
override fun start(player: ExoPlayer, initialData: Any?) { | ||
// Nothing it is dummy | ||
} | ||
|
||
override fun stop(player: ExoPlayer, reason: MediaItemTracker.StopReason, positionMs: Long) { | ||
// Nothing is is dummy | ||
} | ||
|
||
class Factory(private val dummyTracker: DummyTracker = DummyTracker()) : MediaItemTracker.Factory { | ||
override fun create(): MediaItemTracker { | ||
return dummyTracker | ||
} | ||
} | ||
} | ||
} |