using System; using System.Collections.Generic; using Paca.Core.Hls; using Paca.Core.Platform; using Xunit; namespace Paca.Tests.Core; public class AdaptiveStreamingBitrateControllerGateTests { private readonly List _sampleVariants = new() { new Variant(new Uri("https://paca.stream/v_1080.m3u8"), 6_000_000, "1920x1080", "avc1"), new Variant(new Uri("https://paca.stream/v_720.m3u8"), 2_800_000, "1280x720", "avc1"), new Variant(new Uri("https://paca.stream/v_480.m3u8"), 1_200_000, "854x480", "avc1"), new Variant(new Uri("https://paca.stream/v_360.m3u8"), 600_000, "640x360", "avc1") }; [Fact] public void Gate464_AdaptiveStreamingBitrateController_CalculatesEwmaSpeed_Accurately() { var controller = new AdaptiveStreamingBitrateController(); // 1MB in 1 sec = 8,000,000 bps controller.RecordSample(bytes: 1_000_000, duration: TimeSpan.FromSeconds(1)); var speed1 = controller.CurrentBandwidthBps; Assert.Equal(8_000_000, speed1); // Next sample: 500KB in 1 sec = 4,000,000 bps // EWMA with alpha 0.5: 0.5 * 4M + 0.5 * 8M = 6,000,000 bps controller.RecordSample(bytes: 500_000, duration: TimeSpan.FromSeconds(1), alpha: 0.5); var speed2 = controller.CurrentBandwidthBps; Assert.Equal(6_000_000, speed2); } [Fact] public void Gate465_AdaptiveStreamingBitrateController_SelectsHighestQuality_UnderHighestStrategy() { var controller = new AdaptiveStreamingBitrateController(BitrateSelectionStrategy.HighestQuality); var selected = controller.SelectVariant(_sampleVariants); Assert.NotNull(selected); Assert.Equal(6_000_000, selected.Bandwidth); Assert.Equal(1080, selected.Height); } [Fact] public void Gate466_AdaptiveStreamingBitrateController_SelectsLowestBandwidth_UnderDataSaverStrategy() { var controller = new AdaptiveStreamingBitrateController(BitrateSelectionStrategy.DataSaver); var selected = controller.SelectVariant(_sampleVariants); Assert.NotNull(selected); Assert.Equal(600_000, selected.Bandwidth); Assert.Equal(360, selected.Height); } [Fact] public void Gate467_AdaptiveStreamingBitrateController_SelectsOptimalVariant_UnderDynamicAdaptiveStrategy() { var controller = new AdaptiveStreamingBitrateController(BitrateSelectionStrategy.DynamicAdaptive); // Network throughput: 3,500,000 bps. With safety headroom 0.85 -> safe budget = 2,975,000 bps // Should select 720p (2,800,000 bps) controller.SetEstimatedBandwidth(3_500_000); var selected = controller.SelectVariant(_sampleVariants); Assert.NotNull(selected); Assert.Equal(2_800_000, selected.Bandwidth); Assert.Equal(720, selected.Height); } [Fact] public void Gate468_AdaptiveStreamingBitrateController_EnforcesTargetCap_WhenConfigured() { // Strategy is Highest, but MaxCap is 3,000,000 bps -> should cap at 720p (2.8M) var controller = new AdaptiveStreamingBitrateController( strategy: BitrateSelectionStrategy.HighestQuality, maxBitrateCapBps: 3_000_000 ); var selected = controller.SelectVariant(_sampleVariants); Assert.NotNull(selected); Assert.Equal(2_800_000, selected.Bandwidth); Assert.Equal(720, selected.Height); } [Fact] public void Gate469_AdaptiveStreamingBitrateController_AppliesHysteresisDamping_ToPreventThrashing() { var controller = new AdaptiveStreamingBitrateController( strategy: BitrateSelectionStrategy.DynamicAdaptive, consecutiveSamplesForSwitch: 2 ); // Initial: 1080p controller.SetEstimatedBandwidth(10_000_000); var initial = controller.SelectVariant(_sampleVariants); Assert.Equal(1080, initial.Height); // Transient dip for 1 sample: 1,500,000 bps (480p territory: 1.5M * 0.85 = 1.275M >= 1.2M) controller.SetEstimatedBandwidth(1_500_000); var damped = controller.SelectVariant(_sampleVariants); // Hysteresis holds 1080p on first dip! Assert.Equal(1080, damped.Height); // Second consecutive dip confirms downshift var confirmed = controller.SelectVariant(_sampleVariants); Assert.Equal(480, confirmed.Height); } [Fact] public void Gate470_AdaptiveStreamingBitrateController_IntegratesWithBatterySaver_ToDownshift() { var powerManager = new BatterySaverPowerManager(); // Simulate battery at 15% (Critical battery saving active) powerManager.UpdateBatteryState(percent: 15, isCharging: false); var controller = new AdaptiveStreamingBitrateController( strategy: BitrateSelectionStrategy.DynamicAdaptive, powerManager: powerManager ); // Even with 10Gbps unlimited network, Battery Saver enforces max 720p / 3Mbps to preserve CPU/GPU decode cycles controller.SetEstimatedBandwidth(100_000_000); var selected = controller.SelectVariant(_sampleVariants); Assert.NotNull(selected); Assert.True(selected.Bandwidth <= 3_000_000); Assert.True(selected.Height <= 720); } }