test(core/browser/platform): 26 extreme RED/GREEN TDD cycles and full regression hardening (3,235 PASS)
Some checks failed
release / test (push) Failing after 14m5s
release / windows (push) Has been cancelled
release / android (push) Has been cancelled
release / linux (push) Has been cancelled
release / macos (push) Has been cancelled

This commit is contained in:
Yun Chan 2026-09-18 23:32:32 +09:00
parent bcd242691f
commit 8677853822
100 changed files with 4814 additions and 333 deletions

View file

@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Paca.Core.Hls;
using Paca.Core.Platform;
using Xunit;
namespace Paca.Tests.Core;
/// <summary>
/// Cycle 4: 극한 RED 시나리오 - 카오스 멀티스레딩 동시성 무결성 및 경로 순회(Path Traversal) / 파일 락 방어선 검증
/// </summary>
public class ConcurrencyAndCacheIntegrityExtremeRedTests
{
[Fact]
public void Cycle4_Gate1_VideoDeduplicator_ConcurrentStress_MustNotThrowOrCorrupt()
{
var deduplicator = new VideoDeduplicator(maxHammingThreshold: 5);
const int TaskCount = 32;
const int IterationsPerTask = 200;
Parallel.For(0, TaskCount, taskId =>
{
for (int i = 0; i < IterationsPerTask; i++)
{
var filePath = $"C:/media/video_{taskId}_{i}.mp4";
ulong hash = (ulong)(taskId * 10000 + i);
// 동시 등록
deduplicator.RegisterVideo(filePath, hash);
// 동시 검색
var match = deduplicator.FindDuplicate(hash);
Assert.NotNull(match);
Assert.Equal(0, match.HammingDistance);
}
});
Assert.Equal(TaskCount * IterationsPerTask, deduplicator.RegisteredCount);
}
[Fact]
public void Cycle4_Gate2_MultiSourceSegmentAccelerator_ConcurrentStress_MustNotThrow()
{
var accelerator = new MultiSourceSegmentAccelerator();
for (int i = 0; i < 5; i++)
{
accelerator.AddMirror($"https://cdn{i}.example.com/hls/");
}
const int TaskCount = 32;
const int IterationsPerTask = 200;
Parallel.For(0, TaskCount, taskId =>
{
for (int i = 0; i < IterationsPerTask; i++)
{
var targetMirror = $"https://cdn{i % 5}.example.com/hls/";
if (i % 3 == 0)
{
accelerator.RecordFailure(targetMirror);
}
else if (i % 3 == 1)
{
accelerator.RecordLatency(targetMirror, TimeSpan.FromMilliseconds(20 + i));
}
else
{
var mirror = accelerator.SelectBestMirror(i);
Assert.NotEmpty(mirror);
var fastest = accelerator.GetFastestMirror();
Assert.NotNull(fastest);
}
}
});
}
[Fact]
public void Cycle4_Gate3_PredictiveChunkPrefetcher_ConcurrentStress_MustNotThrow()
{
var prefetcher = new PredictiveChunkPrefetcher(initialWindowSize: 3, minWindowSize: 1, maxWindowSize: 10, maxSamples: 10);
const int TaskCount = 32;
const int IterationsPerTask = 200;
Parallel.For(0, TaskCount, taskId =>
{
for (int i = 0; i < IterationsPerTask; i++)
{
long bytes = 1_000_000 + (taskId * 50_000);
var duration = TimeSpan.FromMilliseconds(200 + (i % 100));
prefetcher.RecordChunkDownload(bytes, duration);
var window = prefetcher.CalculateOptimalPrefetchWindow();
Assert.InRange(window, 1, 10);
}
});
}
[Fact]
public void Cycle4_Gate4_PartialChunkIntegrityCache_PathTraversalDefense_ReconcileAndClean()
{
var tempRoot = Path.Combine(Path.GetTempPath(), "paca_traversal_" + Guid.NewGuid().ToString("N"));
var partsDir = Path.Combine(tempRoot, "parts");
Directory.CreateDirectory(partsDir);
// 상위 디렉터리에 피해를 줄 수 있는 카나리아 파일 생성
var canaryFile = Path.Combine(tempRoot, "canary_sensitive_data.txt");
File.WriteAllText(canaryFile, "CRITICAL DATA DO NOT DELETE");
try
{
var cache = new PartialChunkIntegrityCache();
// 악의적인 path traversal 청크 이름 주입 ("../../canary_sensitive_data.txt")
var report = cache.ReconcileAndClean(
partsDir,
totalSegments: 1,
getChunkName: _ => "../../canary_sensitive_data.txt"
);
// parts 디렉터리 외부의 카나리아 파일이 삭제되지 않고 온전히 보존되어야 함
Assert.True(File.Exists(canaryFile), "상위 디렉터리의 카나리아 파일이 Path Traversal 로 인해 삭제되었습니다!");
Assert.Equal("CRITICAL DATA DO NOT DELETE", File.ReadAllText(canaryFile));
}
finally
{
try { if (Directory.Exists(tempRoot)) Directory.Delete(tempRoot, true); } catch { }
}
}
[Fact]
public void Cycle4_Gate5_PartialChunkIntegrityCache_VerifyChunkFile_LockedFileDefense()
{
var tempFile = Path.Combine(Path.GetTempPath(), "paca_locked_" + Guid.NewGuid().ToString("N") + ".seg");
File.WriteAllBytes(tempFile, new byte[1024]);
try
{
var cache = new PartialChunkIntegrityCache();
// 백신 또는 외부 프로세스가 독점 락(FileShare.None)을 잡고 있는 상황 시뮬레이션
using var lockedStream = new FileStream(tempFile, FileMode.Open, FileAccess.Read, FileShare.None);
// unhandled IOException 크래시 없이 Corrupt 또는 Partial 로 안전하게 처리되어야 함
var state = cache.VerifyChunkFile(tempFile, expectedBytes: 1024, expectedSha256: "dummy_hash");
Assert.True(state == ChunkIntegrityState.Corrupt || state == ChunkIntegrityState.Partial);
}
finally
{
try { if (File.Exists(tempFile)) File.Delete(tempFile); } catch { }
}
}
}