using System; using Paca.Mobile.Core; using Xunit; namespace Paca.Tests.Core; public class DynamicConcurrencyTunerGateTests { [Fact] public void Gate237_DynamicConcurrencyTuner_Initializes_WithSensibleDefaults() { var tunerNormal = new DynamicConcurrencyTuner(isMetered: false); Assert.Equal(4, tunerNormal.CurrentConcurrency); Assert.Equal(16, tunerNormal.MaxConcurrency); var tunerMetered = new DynamicConcurrencyTuner(isMetered: true); Assert.Equal(2, tunerMetered.CurrentConcurrency); Assert.Equal(3, tunerMetered.MaxConcurrency); } [Fact] public void Gate238_DynamicConcurrencyTuner_ScalesUp_OnHighThroughputAndZeroErrors() { var tuner = new DynamicConcurrencyTuner(isMetered: false, initialConcurrency: 4); // Record 3 fast chunk completions without error (e.g. 10MB/s each) tuner.RecordChunkResult(bytesDownloaded: 5_000_000, durationMs: 500, isError: false); tuner.RecordChunkResult(bytesDownloaded: 5_000_000, durationMs: 480, isError: false); tuner.RecordChunkResult(bytesDownloaded: 5_000_000, durationMs: 450, isError: false); Assert.True(tuner.CurrentConcurrency > 4, $"Concurrency should scale up from 4, but is {tuner.CurrentConcurrency}"); } [Fact] public void Gate239_DynamicConcurrencyTuner_ScalesDownImmediately_OnErrorOrRateLimit() { var tuner = new DynamicConcurrencyTuner(isMetered: false, initialConcurrency: 8); // Encounter network error or rate-limit tuner.RecordChunkResult(bytesDownloaded: 0, durationMs: 1000, isError: true, isRateLimited: true); Assert.True(tuner.CurrentConcurrency <= 4, $"Concurrency should be halved on error, but is {tuner.CurrentConcurrency}"); } [Fact] public void Gate240_DynamicConcurrencyTuner_MeteredMode_StrictCap() { var tuner = new DynamicConcurrencyTuner(isMetered: true, initialConcurrency: 2); // Record 10 fast chunks for (int i = 0; i < 10; i++) { tuner.RecordChunkResult(bytesDownloaded: 10_000_000, durationMs: 200, isError: false); } Assert.True(tuner.CurrentConcurrency <= 3, $"Metered concurrency must not exceed 3, but is {tuner.CurrentConcurrency}"); } }