using System; using Paca.Mobile.Core; using Xunit; namespace Paca.Tests.Core; /// /// Gate 175 ~ 178: 지능형 실패 진단 및 스마트 자가 치유(Self-Healing) 엔진 기계적 검증 /// public class DownloadSelfHealingEngineGateTests { [Fact] public void Gate175_FailureDiagnostics_Classifies_429_RateLimit() { var rawError = "HTTP 429 Too Many Requests: Rate limit exceeded by YouTube server"; var diag = DownloadFailureDiagnostics.Analyze(rawError, httpStatusCode: 429); Assert.Equal(FailureCategory.RateLimited, diag.Category); Assert.True(diag.CanAutoRetry); Assert.Equal(TimeSpan.FromSeconds(60), diag.SuggestedDelay); Assert.Contains("요청 한도", diag.UserFriendlyMessage); } [Fact] public void Gate176_FailureDiagnostics_Classifies_DiskFull() { var rawError = "System.IO.IOException: There is not enough space on the disk"; var diag = DownloadFailureDiagnostics.Analyze(rawError); Assert.Equal(FailureCategory.DiskFull, diag.Category); Assert.False(diag.CanAutoRetry); // 디스크 공간 부족은 자동 재시도 불가(수동 정리 필요) Assert.Contains("저장 공간", diag.UserFriendlyMessage); } [Fact] public void Gate177_FailureDiagnostics_Classifies_NetworkLoss_And_Enables_AutoResume() { var rawError = "System.Net.Sockets.SocketException: The network connection was lost"; var diag = DownloadFailureDiagnostics.Analyze(rawError); Assert.Equal(FailureCategory.NetworkLoss, diag.Category); Assert.True(diag.CanAutoRetry); Assert.True(diag.CanAutoResume); // 이어받기 가능 Assert.Contains("인터넷 연결", diag.UserFriendlyMessage); } [Theory] [InlineData(1, 5)] // 1회차: 5초 [InlineData(2, 10)] // 2회차: 10초 [InlineData(3, 20)] // 3회차: 20초 [InlineData(4, 40)] // 4회차: 40초 public void Gate178_SelfHealingStrategy_ExponentialBackoff(int attempt, int expectedSeconds) { var delay = SelfHealingActionStrategy.CalculateExponentialBackoff(attempt, baseDelaySec: 5, maxDelaySec: 60); Assert.Equal(TimeSpan.FromSeconds(expectedSeconds), delay); } }