using System; using Xunit; using ytLive.Services; namespace ytLive.Tests; /// /// TASK 65 slice 1 — the replay ring as pure memory. /// /// The two rules that matter and are easy to break later: the cap is by bytes (bitrate moves, /// seconds do not), and a snapshot is always init-segment-first, because an MP4 without its moov is not a /// video, it is noise. /// public sealed class ClipRingTests { [Fact] public void Snapshot_IsInitThenFragmentsInOrder() { var ring = new ClipRing(1024); ring.SetInit(new byte[] { 1, 2 }); ring.Append(new byte[] { 3 }); ring.Append(new byte[] { 4, 5 }); Assert.Equal(new byte[] { 1, 2, 3, 4, 5 }, ring.Snapshot()); Assert.Equal(5, ring.Bytes); Assert.Equal(2, ring.FragmentCount); } [Fact] public void TheCapDropsOldestFragments_SoTheClipEndsAtTheKeypress() { var ring = new ClipRing(capBytes: 10); ring.SetInit(new byte[2]); for (var i = 0; i < 5; i++) ring.Append(new byte[3]); // 2 + 15 = 17 → trims Assert.True(ring.Bytes <= 10); Assert.Equal(2, ring.FragmentCount); // newest two survive var snapshot = ring.Snapshot(); Assert.Equal(2 + 3 + 3, snapshot.Length); } [Fact] public void NothingBuffered_SnapshotsEmpty_SoTheCallerCannotWriteAZeroByteFile() { var ring = new ClipRing(1024); Assert.True(ring.IsEmpty); Assert.Empty(ring.Snapshot()); ring.SetInit(new byte[4]); Assert.True(ring.IsEmpty); // init alone is not a clip Assert.Empty(ring.Snapshot()); } [Fact] public void ClearForgetsTheInit_SoTheNextEncoderStartCannotReuseAStaleHeader() { var ring = new ClipRing(1024); ring.SetInit(new byte[] { 9 }); ring.Append(new byte[] { 8 }); ring.Clear(); Assert.True(ring.IsEmpty); Assert.Equal(0, ring.Bytes); ring.Append(new byte[] { 7 }); Assert.Empty(ring.Snapshot()); // still no init → not playable } }