125 lines
4.3 KiB
C#
125 lines
4.3 KiB
C#
using System.IO;
|
|
using Paca.App.Core;
|
|
using Paca.App.ViewModels;
|
|
using Paca.Browser;
|
|
using Paca.Browser.Tabs;
|
|
using Paca.Core.Config;
|
|
using Paca.Core.Detection;
|
|
using Paca.Core.Platform;
|
|
using Paca.Core.Utils;
|
|
|
|
namespace Paca.Tests.Infrastructure;
|
|
|
|
public sealed class MockPipelineProcessRunner : IProcessRunner
|
|
{
|
|
public List<ProcessSpec> Specs { get; } = new();
|
|
|
|
public Task<ProcessResult> RunAsync(ProcessSpec spec, Action<string, string>? onLine, CancellationToken ct)
|
|
{
|
|
Specs.Add(spec);
|
|
return Task.FromResult(new ProcessResult(0, "OK", ""));
|
|
}
|
|
}
|
|
|
|
public sealed class MockPipelineCloudStorageClient : ICloudStorageClient
|
|
{
|
|
public List<string> UploadedList { get; } = new();
|
|
|
|
public Task<bool> UploadAsync(string localFilePath, string remoteDestination, Action<long, long>? onProgress, CancellationToken ct)
|
|
{
|
|
UploadedList.Add($"{localFilePath} -> {remoteDestination}");
|
|
return Task.FromResult(true);
|
|
}
|
|
|
|
public Task<bool> ExistsAsync(string remoteDestination, CancellationToken ct)
|
|
{
|
|
return Task.FromResult(UploadedList.Any(u => u.EndsWith(remoteDestination)));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 40개 마일스톤 전 영역 통합 오케스트레이션 파이프라인 하네스.
|
|
/// </summary>
|
|
public sealed class GrandUnifiedPipeline : IDisposable
|
|
{
|
|
public string TempDir { get; }
|
|
public AppConfig Config { get; }
|
|
public TabManager TabManager { get; }
|
|
public AdBlockRuleEngine AdBlockEngine { get; }
|
|
public MemoryTurboGuard MemoryGuard { get; }
|
|
public DownloadManager DownloadManager { get; }
|
|
public VideoDeduplicator Deduplicator { get; }
|
|
public QoSTrafficShaper TrafficShaper { get; }
|
|
public ChaosMonkeyStressDefense ChaosDefense { get; }
|
|
public AudioNormalizer AudioNormalizer { get; }
|
|
public HdrToneMapper HdrToneMapper { get; }
|
|
public ChapterSplitter ChapterSplitter { get; }
|
|
public DualSubtitleEngine DualSubtitleEngine { get; }
|
|
public CloudSyncGateway CloudGateway { get; }
|
|
public MockPipelineProcessRunner ProcessRunner { get; }
|
|
public MockPipelineCloudStorageClient CloudClient { get; }
|
|
|
|
private readonly List<DownloadItemViewModel> _detectedItems = new();
|
|
|
|
private GrandUnifiedPipeline()
|
|
{
|
|
TempDir = Path.Combine(Path.GetTempPath(), "VD_Grand_" + Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(TempDir);
|
|
|
|
Config = new AppConfig
|
|
{
|
|
OutputFolder = Path.Combine(TempDir, "downloads")
|
|
};
|
|
Directory.CreateDirectory(Config.OutputFolder);
|
|
|
|
ProcessRunner = new MockPipelineProcessRunner();
|
|
CloudClient = new MockPipelineCloudStorageClient();
|
|
|
|
TabManager = new TabManager(() => new TabItem(), _ => { });
|
|
AdBlockEngine = new AdBlockRuleEngine();
|
|
MemoryGuard = new MemoryTurboGuard(TimeSpan.FromMinutes(10));
|
|
|
|
DownloadManager = new DownloadManager(
|
|
Config,
|
|
_ => Task.FromResult(new List<Microsoft.Web.WebView2.Core.CoreWebView2Cookie>()),
|
|
_ => { });
|
|
|
|
DownloadManager.ItemDetected += item => _detectedItems.Add(item);
|
|
|
|
Deduplicator = new VideoDeduplicator(maxHammingThreshold: 5);
|
|
TrafficShaper = new QoSTrafficShaper(maxBandwidthBytesPerSec: 10_000_000);
|
|
ChaosDefense = new ChaosMonkeyStressDefense(failureRate: 0.3);
|
|
AudioNormalizer = new AudioNormalizer(ProcessRunner);
|
|
HdrToneMapper = new HdrToneMapper(ProcessRunner);
|
|
ChapterSplitter = new ChapterSplitter(ProcessRunner);
|
|
DualSubtitleEngine = new DualSubtitleEngine();
|
|
CloudGateway = new CloudSyncGateway(CloudClient);
|
|
}
|
|
|
|
public static GrandUnifiedPipeline Create() => new();
|
|
|
|
public IReadOnlyList<DownloadItemViewModel> DetectedItems => _detectedItems;
|
|
|
|
public void SimulateWebRequest(string url, MediaKind? mediaKind = null, string? pageUrl = null)
|
|
{
|
|
var uri = new Uri(url);
|
|
|
|
// 1. 광고 차단 검사
|
|
if (AdBlockEngine.ShouldBlock(uri))
|
|
return;
|
|
|
|
// 2. 미디어 감지
|
|
if (mediaKind.HasValue)
|
|
{
|
|
DownloadManager.OnDetected(new DetectionContext(url, pageUrl ?? "https://test.local", mediaKind.Value));
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(TempDir))
|
|
{
|
|
try { Directory.Delete(TempDir, true); } catch { }
|
|
}
|
|
}
|
|
}
|