using System; using System.Collections.Generic; using Paca.Mobile.Core; using Xunit; namespace Paca.Tests.Mobile; /// /// 로컬 기기 디스커버리, 원격 클립보드, 절전/데이터 가드 및 복원성 게이트 (Gate 109 ~ Gate 114) /// public class MobileAdvancedConnectivityGateTests { [Fact] public void Gate109_PacaHostBeacon_Discovery_Audit() { var beacon = new PacaHostBeacon(); var beaconPayload = "PACA_BEACON|DESKTOP-PACA|192.168.1.100:52100|token123"; var host = beacon.ParseBeacon(beaconPayload); Assert.NotNull(host); Assert.Equal("DESKTOP-PACA", host.HostName); Assert.Equal("192.168.1.100:52100", host.Endpoint); Assert.Equal("token123", host.AuthToken); } [Fact] public void Gate110_CrossDeviceClipboardSync_Audit() { var clipSync = new CrossDeviceClipboardSync(); string? receivedUrl = null; clipSync.OnMediaUrlReceived += url => receivedUrl = url; // PC로부터 수신된 클립보드 패킷 처리 clipSync.ProcessIncomingPayload("https://twitter.com/test/status/123456"); Assert.Equal("https://twitter.com/test/status/123456", receivedUrl); // 비미디어 텍스트는 필터링되어 무시되어야 함 receivedUrl = null; clipSync.ProcessIncomingPayload("Hello this is not a media url"); Assert.Null(receivedUrl); } [Fact] public void Gate111_MobilePowerSaverPolicy_Audit() { var policy = new MobilePowerSaverPolicy(); // 기본 6 세그먼트 Assert.Equal(6, policy.GetRecommendedSegments(batteryLevelPercent: 80, isCharging: false)); // 배터리 15% 이하 저전력 모드 -> 2개로 제한 Assert.Equal(2, policy.GetRecommendedSegments(batteryLevelPercent: 12, isCharging: false)); // 충전 중일 때는 100% 터보 허용 Assert.Equal(16, policy.GetRecommendedSegments(batteryLevelPercent: 12, isCharging: true)); } [Fact] public void Gate112_MobileDataSaverGuard_Audit() { var dataGuard = new MobileDataSaverGuard(); // 100MB 기본 임계값 Assert.Equal(100_000_000L, dataGuard.CellularWarningThresholdBytes); // Wi-Fi 상태에서는 대용량도 즉시 허용 Assert.True(dataGuard.CanDownload(fileSizeBytes: 500_000_000, isWifi: true)); // 셀룰러 상태에서 500MB는 경고 플래그 Assert.False(dataGuard.CanDownload(fileSizeBytes: 500_000_000, isWifi: false)); // 셀룰러 상태에서 50MB는 허용 Assert.True(dataGuard.CanDownload(fileSizeBytes: 50_000_000, isWifi: false)); } [Fact] public void Gate113_MobileThumbnailCacheManager_Audit() { var cache = new MobileThumbnailCacheManager(); Assert.Null(cache.Get("test-key")); cache.Put("test-key", new byte[] { 0xFF, 0xD8, 0xFF }); var cached = cache.Get("test-key"); Assert.NotNull(cached); Assert.Equal(3, cached.Length); // 캐시 삭제 cache.Evict("test-key"); Assert.Null(cache.Get("test-key")); } [Fact] public void Gate114_NetworkFlapping_Stress_Resilience_Audit() { var qm = new MobileQueueManager(); var guard = new MobileNetworkGuard(qm); var item = qm.Enqueue("https://example.com/live.m3u8", "Live Stream"); item.Status = MobileQueueStatus.Downloading; // 10회 연속 단절 및 재연결 플래핑 스트레스 for (int i = 0; i < 10; i++) { guard.OnNetworkLost(); Assert.Equal(MobileQueueStatus.PausedNetwork, item.Status); guard.OnNetworkRestored(isWifi: (i % 2 == 0)); Assert.Equal(MobileQueueStatus.Downloading, item.Status); } } }