Files
live_recorder/tests/LiveRecorder.Tests/StorageGuardServiceTests.cs
T

117 lines
4.3 KiB
C#

using LiveRecorder.Application.Abstractions.Storage;
using LiveRecorder.Application.Models.Settings;
using LiveRecorder.Infrastructure.Services;
using Microsoft.Extensions.Logging.Abstractions;
namespace LiveRecorder.Tests;
public sealed class StorageGuardServiceTests
{
private readonly StorageGuardService _service = new(NullLogger<StorageGuardService>.Instance);
[Fact]
public void DisabledProtection_StillReportsActualCapacityWithoutBlockingRecording()
{
var settings = CreateSettings(enableStorageGuard: false);
var result = _service.CheckCanStartOrResume(settings);
Assert.False(result.IsEnabled);
Assert.True(result.IsAvailable);
Assert.True(result.HasEnoughSpace);
Assert.True(result.CanStartNewRecording);
Assert.False(result.ShouldPauseActive);
Assert.True(result.TotalBytes > 0);
Assert.Equal(result.TotalBytes, result.UsedBytes + result.AvailableBytes);
Assert.InRange(result.UsagePercent, 0, 100);
Assert.InRange(result.FreePercent, 0, 100);
Assert.InRange(result.UsagePercent + result.FreePercent, 99.8, 100.2);
}
[Fact]
public void EnabledProtection_ReportsConfiguredThresholdsAndConsistentPercentages()
{
var settings = CreateSettings(enableStorageGuard: true);
settings.StorageGreenThresholdPercent = 35;
settings.StorageRedThresholdPercent = 12;
var result = _service.CheckCanStartOrResume(settings);
Assert.True(result.IsEnabled);
Assert.True(result.IsAvailable);
Assert.Equal(35, result.GreenThresholdPercent);
Assert.Equal(12, result.RedThresholdPercent);
Assert.Equal(result.TotalBytes, result.UsedBytes + result.AvailableBytes);
Assert.InRange(result.UsagePercent + result.FreePercent, 99.8, 100.2);
}
[Fact]
public void InvalidPath_ReturnsUnavailableStateInsteadOfThrowing()
{
var settings = CreateSettings(enableStorageGuard: true);
settings.OutputRoot = "invalid\0path";
var result = _service.CheckCanStartOrResume(settings);
Assert.True(result.IsEnabled);
Assert.False(result.IsAvailable);
Assert.False(result.HasEnoughSpace);
Assert.False(result.CanStartNewRecording);
Assert.Equal(StorageTier.Red, result.Tier);
Assert.Equal(0, result.TotalBytes);
}
[Fact]
public void RedPercentageTier_DoesNotBlockFinalizeWhenAbsoluteTemporarySpaceIsAvailable()
{
var settings = CreateSettings(enableStorageGuard: true);
settings.PauseRecordingWhenFreeSpaceBelowMegabytes = 0;
settings.ResumeRecordingWhenFreeSpaceAboveMegabytes = 0;
settings.StorageGreenThresholdPercent = 90;
settings.StorageRedThresholdPercent = 85;
var result = _service.CheckCanFinalize(settings, estimatedTemporaryBytes: 1);
Assert.Equal(StorageTier.Red, result.Tier);
Assert.True(result.HasEnoughSpace);
Assert.True(result.ShouldPauseActive);
}
[Fact]
public void Finalize_ReservesSourceEstimateInAdditionToPauseThreshold()
{
var settings = CreateSettings(enableStorageGuard: true);
settings.PauseRecordingWhenFreeSpaceBelowMegabytes = int.MaxValue;
var result = _service.CheckCanFinalize(settings, estimatedTemporaryBytes: 1024);
Assert.False(result.HasEnoughSpace);
Assert.True(result.RequiredBytes > 1024);
}
[Fact]
public void MultiSegmentFinalize_UsesConcatDemuxerWithoutMaterializingCombinedTs()
{
var arguments = FfmpegService.BuildMp4FinalizeArgumentList(
"/records/input.ffconcat",
"/records/output.remux.mp4",
strategy: default,
useConcatDemuxer: true);
Assert.Contains("concat", arguments);
Assert.Contains("-safe", arguments);
Assert.Contains("/records/input.ffconcat", arguments);
Assert.DoesNotContain(".concat.ts", arguments);
}
private static SystemSettingsDto CreateSettings(bool enableStorageGuard) => new()
{
OutputRoot = Path.GetTempPath(),
EnableStorageGuard = enableStorageGuard,
PauseRecordingWhenFreeSpaceBelowMegabytes = 1024,
ResumeRecordingWhenFreeSpaceAboveMegabytes = 4096,
StorageGreenThresholdPercent = 30,
StorageRedThresholdPercent = 10
};
}