package com.doublesymmetry.trackplayer import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.source.MediaSource import com.doublesymmetry.trackplayer.models.TrackPlayerMediaItem import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config /** * Tests that [LivenessRoutingMediaSourceFactory] routes live tracks to the * uncached factory and everything else to the cache-backed one. Live segments * are write-once-read-once, so caching them only churns the bounded LRU and * evicts reusable VOD content — mirroring iOS, where the proxy streams live * segments through without persisting. */ @OptIn(UnstableApi::class) @RunWith(RobolectricTestRunner::class) @Config(sdk = [33]) class LivenessRoutingMediaSourceFactoryTest { private fun mediaItem(isLive: Boolean?) = TrackPlayerMediaItem(url = "https://example.com/stream.m3u8", isLive = isLive) .asMediaItem() @Test fun `live item routes to the uncached factory`() { val cached = mockk(relaxed = true) val uncached = mockk(relaxed = true) val factory = LivenessRoutingMediaSourceFactory(cached, uncached) val item = mediaItem(isLive = true) factory.createMediaSource(item) verify(exactly = 1) { uncached.createMediaSource(item) } verify(exactly = 0) { cached.createMediaSource(any()) } } @Test fun `non-live item routes to the cached factory`() { val cached = mockk(relaxed = true) val uncached = mockk(relaxed = true) val factory = LivenessRoutingMediaSourceFactory(cached, uncached) val item = mediaItem(isLive = false) factory.createMediaSource(item) verify(exactly = 1) { cached.createMediaSource(item) } verify(exactly = 0) { uncached.createMediaSource(any()) } } @Test fun `item with no isLive flag routes to the cached factory`() { val cached = mockk(relaxed = true) val uncached = mockk(relaxed = true) val factory = LivenessRoutingMediaSourceFactory(cached, uncached) val item = mediaItem(isLive = null) factory.createMediaSource(item) verify(exactly = 1) { cached.createMediaSource(item) } verify(exactly = 0) { uncached.createMediaSource(any()) } } @Test fun `supported types come from the cached factory`() { val cached = mockk(relaxed = true) val uncached = mockk(relaxed = true) every { cached.supportedTypes } returns intArrayOf(1, 2, 3) val factory = LivenessRoutingMediaSourceFactory(cached, uncached) assert(factory.supportedTypes.toList() == listOf(1, 2, 3)) } }