@file:androidx.annotation.OptIn(markerClass = [androidx.media3.common.util.UnstableApi::class]) package link.roadio.riff.player.playback import androidx.media3.common.C import androidx.media3.common.Player import link.roadio.riff.indexer.core.media.MediaId import link.roadio.riff.player.library.PlaybackCatalogTrack import link.roadio.riff.player.library.PlayerLibraryProjection import link.roadio.riff.player.library.PlayerPlaybackCatalog import link.roadio.riff.player.storage.PlaybackCheckpoint import link.roadio.riff.player.storage.PlaybackQueueKind import link.roadio.riff.player.storage.PlaybackQueueOccurrence import link.roadio.riff.player.storage.PlaybackQueueSnapshot import link.roadio.riff.userstate.BoundedReadList import org.junit.Assert.assertEquals import org.junit.Test class QueueTimelineTest { @Test fun restoreAndShuffleTraversalDoNotDecodeEveryCatalogOccurrence() { var reads = 0 val catalog = object : PlayerPlaybackCatalog { override val generation = 1L override val projection = PlayerLibraryProjection() override fun lookup( mediaId: MediaId, contextKey: String?, ordinal: Int, ): PlaybackCatalogTrack { reads++ return PlaybackCatalogTrack(null, emptyList(), emptyMap()) } } for (count in listOf(125_000, 125_001, 200_000, 200_001)) { val queue = PlaybackQueueSnapshot( 11, PlaybackQueueKind.MANUAL, 1, true, BoundedReadList(count) { PlaybackQueueOccurrence(Long.MIN_VALUE + it, it, count - 1 - it, MediaId(it.toLong())) }, PlaybackCheckpoint(Long.MIN_VALUE + count - 1), ) val prepared = prepareQueue(queue, catalog) assertEquals(0, reads) assertEquals(count - 1, prepared.startIndex) val timeline = QueueTimeline(prepared) assertEquals(count, timeline.windowCount) assertEquals(0, timeline.getFirstWindowIndex(false)) assertEquals(count - 1, timeline.getFirstWindowIndex(true)) assertEquals(0, timeline.getNextWindowIndex(count - 1, Player.REPEAT_MODE_ALL, false)) assertEquals(C.INDEX_UNSET, timeline.getNextWindowIndex(0, Player.REPEAT_MODE_OFF, true)) assertEquals(count - 1, timeline.getNextWindowIndex(0, Player.REPEAT_MODE_ALL, true)) assertEquals(10, timeline.getNextWindowIndex(10, Player.REPEAT_MODE_ONE, true)) assertEquals(11, timeline.getPreviousWindowIndex(10, Player.REPEAT_MODE_OFF, true)) assertEquals(C.INDEX_UNSET, timeline.getIndexOfPeriod(-1)) assertEquals(count - 1, timeline.getIndexOfPeriod(count - 1)) assertEquals(0, reads) } } @Test fun occurrenceIndexHandlesSignedIdsZeroAndProbeCollisions() { val ids = listOf(0L, Long.MIN_VALUE, Long.MAX_VALUE, -1L, 1L, 0x100000001L) val index = QueueOccurrenceIndex(ids.mapIndexed { ordinal, id -> PlaybackQueueOccurrence(id, ordinal, ordinal, MediaId(id)) }) ids.forEachIndexed { ordinal, id -> assertEquals(ordinal, index[id]) } assertEquals(null, index[442]) } }