releases/tests/Paca.Tests/Core/MediaStorageGarbageCollectorGateTests.cs

90 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Paca.Mobile.Core;
using Xunit;
namespace Paca.Tests.Core;
public class MediaStorageGarbageCollectorGateTests
{
[Fact]
public void Gate321_MediaStorageGarbageCollector_ProtectsActiveFiles_AndSelectsStaleOnly()
{
var now = new DateTime(2026, 9, 4, 20, 30, 0);
var candidateFiles = new List<CandidateFileInfo>
{
// Stale part file from 3 days ago (150 MB)
new("C:\\downloads\\movie.mp4.part", 150 * 1024 * 1024, now.AddDays(-3)),
// Active part file created 10 minutes ago (50 MB) -> MUST BE PROTECTED!
new("C:\\downloads\\active.mp4.part", 50 * 1024 * 1024, now.AddMinutes(-10)),
// Normal finished mp4 from 2 days ago -> MUST NOT BE TOUCHED!
new("C:\\downloads\\finished.mp4", 500 * 1024 * 1024, now.AddDays(-2)),
// Stale tmp fragment from 40 hours ago (80 MB)
new("C:\\downloads\\stream_frag.tmp", 80 * 1024 * 1024, now.AddHours(-40))
};
var minAge = TimeSpan.FromHours(24);
var orphans = MediaStorageGarbageCollector.FilterOrphanFiles(candidateFiles, minAge, now);
Assert.Equal(2, orphans.Count);
Assert.Contains(orphans, x => x.Path.EndsWith("movie.mp4.part"));
Assert.Contains(orphans, x => x.Path.EndsWith("stream_frag.tmp"));
Assert.DoesNotContain(orphans, x => x.Path.EndsWith("active.mp4.part"));
Assert.DoesNotContain(orphans, x => x.Path.EndsWith("finished.mp4"));
}
[Fact]
public void Gate322_MediaStorageGarbageCollector_CalculatesReclaimableSpace_Correctly()
{
var now = new DateTime(2026, 9, 4, 20, 30, 0);
var candidateFiles = new List<CandidateFileInfo>
{
new("C:\\temp\\a.part", 200 * 1024 * 1024, now.AddDays(-2)),
new("C:\\temp\\b.frag", 300 * 1024 * 1024, now.AddDays(-5))
};
var result = MediaStorageGarbageCollector.AnalyzeReclaimableSpace(candidateFiles, TimeSpan.FromHours(24), now);
Assert.Equal(2, result.OrphanCount);
Assert.Equal(500 * 1024 * 1024, result.TotalReclaimableBytes);
Assert.Equal(500.0, result.TotalReclaimableMb);
}
[Fact]
public void Gate323_MediaStorageGarbageCollector_RecognizesAllTemporaryExtensions()
{
var tempExts = new[] { ".part", ".tmp", ".frag", ".ytdl", ".download" };
foreach (var ext in tempExts)
{
Assert.True(MediaStorageGarbageCollector.IsTemporaryExtension($"file{ext}"));
}
Assert.False(MediaStorageGarbageCollector.IsTemporaryExtension("video.mp4"));
Assert.False(MediaStorageGarbageCollector.IsTemporaryExtension("audio.mp3"));
Assert.False(MediaStorageGarbageCollector.IsTemporaryExtension("subtitles.vtt"));
}
[Fact]
public void Gate324_MediaStorageGarbageCollector_PerformsBatchDeletion_Gracefully()
{
var filesToDelete = new List<string> { "file1.part", "file2.part", "file3.part" };
var deletedList = new List<string>();
var result = MediaStorageGarbageCollector.ExecuteCleanUpWithDeleter(
filesToDelete,
deleter: path =>
{
if (path == "file2.part") throw new System.IO.IOException("File in use");
deletedList.Add(path);
}
);
Assert.Equal(2, result.SuccessCount);
Assert.Equal(1, result.FailedCount);
Assert.Equal(2, deletedList.Count);
Assert.Contains("file2.part", result.FailedFiles[0].Path);
}
}