test(core/browser/platform): 26 extreme RED/GREEN TDD cycles and full regression hardening (3,235 PASS)
This commit is contained in:
parent
bcd242691f
commit
8677853822
100 changed files with 4814 additions and 333 deletions
204
tests/Paca.Tests/Core/AiMediaAndShaderEnginesExtremeRedTests.cs
Normal file
204
tests/Paca.Tests/Core/AiMediaAndShaderEnginesExtremeRedTests.cs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Paca.Core.Detection;
|
||||
using Paca.Core.Gateway;
|
||||
using Paca.Core.Media;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Core;
|
||||
|
||||
public class AiMediaAndShaderEnginesExtremeRedTests
|
||||
{
|
||||
private const string SampleInput = "C:\\Videos\\source.mp4";
|
||||
private const string SampleOutput = "C:\\Videos\\shorts.mp4";
|
||||
|
||||
// ==========================================
|
||||
// 1. AiHighlightClipper
|
||||
// ==========================================
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(-100)]
|
||||
[InlineData(double.NaN)]
|
||||
public void AiHighlightClipper_DetectHighlights_ZeroOrNegativeDuration_ReturnsEmpty(double duration)
|
||||
{
|
||||
var highlights = AiHighlightClipper.DetectHighlights(duration);
|
||||
Assert.NotNull(highlights);
|
||||
Assert.Empty(highlights);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(-10)]
|
||||
[InlineData(double.NaN)]
|
||||
public void AiHighlightClipper_DetectHighlights_ZeroOrNegativeWindowSeconds_DoesNotCrashOrLoopInfinitely(double windowSec)
|
||||
{
|
||||
var highlights = AiHighlightClipper.DetectHighlights(120.0, windowSeconds: windowSec);
|
||||
Assert.NotNull(highlights);
|
||||
Assert.NotEmpty(highlights);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AiHighlightClipper_BuildFfmpegShortsCommand_SameInputAndOutput_ThrowsInvalidOperationException()
|
||||
{
|
||||
var spec = new ShortsClipSpec();
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
AiHighlightClipper.BuildFfmpegShortsCommand(SampleInput, SampleInput, spec));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, SampleOutput)]
|
||||
[InlineData(SampleInput, null)]
|
||||
[InlineData("", SampleOutput)]
|
||||
[InlineData(SampleInput, " ")]
|
||||
public void AiHighlightClipper_BuildFfmpegShortsCommand_NullOrWhitespacePaths_ThrowsArgumentException(string? inPath, string? outPath)
|
||||
{
|
||||
var spec = new ShortsClipSpec();
|
||||
Assert.Throws<ArgumentException>(() =>
|
||||
AiHighlightClipper.BuildFfmpegShortsCommand(inPath!, outPath!, spec));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AiHighlightClipper_BuildFfmpegShortsCommand_NullSpec_ThrowsArgumentNullException()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() =>
|
||||
AiHighlightClipper.BuildFfmpegShortsCommand(SampleInput, SampleOutput, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AiHighlightClipper_BuildFfmpegShortsCommand_PathsWithQuotes_Stripped()
|
||||
{
|
||||
var spec = new ShortsClipSpec();
|
||||
string maliciousIn = "C:\\Videos\\so\"urce.mp4";
|
||||
string maliciousOut = "C:\\Videos\\sh\"orts.mp4";
|
||||
|
||||
var args = AiHighlightClipper.BuildFfmpegShortsCommand(maliciousIn, maliciousOut, spec);
|
||||
Assert.NotNull(args);
|
||||
Assert.DoesNotContain(args, a => a.Contains('"'));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 2. FftAudioWaveformEngine
|
||||
// ==========================================
|
||||
|
||||
[Fact]
|
||||
public void FftAudioWaveformEngine_BuildFfmpegEqualizerFilter_NullOrEmptyBands_ReturnsEmptyString()
|
||||
{
|
||||
Assert.Equal(string.Empty, FftAudioWaveformEngine.BuildFfmpegEqualizerFilter(null!));
|
||||
Assert.Equal(string.Empty, FftAudioWaveformEngine.BuildFfmpegEqualizerFilter(new List<EqualizerBand>()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FftAudioWaveformEngine_BuildFfmpegEqualizerFilter_ListContainingNullBands_SkipsSafely()
|
||||
{
|
||||
var bands = new List<EqualizerBand>
|
||||
{
|
||||
null!,
|
||||
new() { FrequencyHz = 1000, GainDb = 3.5 },
|
||||
null!
|
||||
};
|
||||
|
||||
var filter = FftAudioWaveformEngine.BuildFfmpegEqualizerFilter(bands);
|
||||
Assert.NotNull(filter);
|
||||
Assert.Contains("equalizer=f=1000", filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FftAudioWaveformEngine_BuildFfmpegEqualizerFilter_InCommaDecimalCulture_UsesDotDecimalSeparator()
|
||||
{
|
||||
var originalCulture = Thread.CurrentThread.CurrentCulture;
|
||||
try
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE"); // German culture uses ',' for decimal
|
||||
|
||||
var bands = new List<EqualizerBand>
|
||||
{
|
||||
new() { FrequencyHz = 500, GainDb = 4.5 }
|
||||
};
|
||||
|
||||
var filter = FftAudioWaveformEngine.BuildFfmpegEqualizerFilter(bands);
|
||||
Assert.Contains("g=4.5", filter);
|
||||
Assert.DoesNotContain("g=4,5", filter);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = originalCulture;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 3. NeuralShaderUpscaler
|
||||
// ==========================================
|
||||
|
||||
[Fact]
|
||||
public void NeuralShaderUpscaler_GenerateHlslShaderCode_NullConfig_DoesNotThrow()
|
||||
{
|
||||
var shader = NeuralShaderUpscaler.GenerateHlslShaderCode(null!);
|
||||
Assert.NotNull(shader);
|
||||
Assert.Contains("float4 PS_NeuralUpscale", shader);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0)]
|
||||
[InlineData(-1920, -1080)]
|
||||
public void NeuralShaderUpscaler_GenerateHlslShaderCode_ZeroOrNegativeDimensions_FallsBackToDefaultResolution(int w, int h)
|
||||
{
|
||||
var config = new ShaderUpscaleConfig { TargetWidth = w, TargetHeight = h };
|
||||
var shader = NeuralShaderUpscaler.GenerateHlslShaderCode(config);
|
||||
Assert.NotNull(shader);
|
||||
Assert.DoesNotContain("1.0 / 0", shader);
|
||||
Assert.DoesNotContain("1.0 / -", shader);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NeuralShaderUpscaler_GenerateHlslShaderCode_InCommaDecimalCulture_UsesDotDecimalSeparator()
|
||||
{
|
||||
var originalCulture = Thread.CurrentThread.CurrentCulture;
|
||||
try
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR"); // French culture uses ',' for decimal
|
||||
|
||||
var config = new ShaderUpscaleConfig { Sharpness = 2.5 };
|
||||
var shader = NeuralShaderUpscaler.GenerateHlslShaderCode(config);
|
||||
|
||||
Assert.Contains("2.50", shader);
|
||||
Assert.DoesNotContain("2,50", shader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = originalCulture;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 4. PacaConnectCodeGenerator
|
||||
// ==========================================
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("PACA-12345")] // 5 chars instead of 6
|
||||
[InlineData("PACA-1234567")] // 7 chars
|
||||
[InlineData("PACA-000000")] // '0' is disallowed
|
||||
[InlineData("PACA-111111")] // '1' is disallowed
|
||||
[InlineData("PACA-IIIIII")] // 'I' is disallowed
|
||||
[InlineData("PACA-OOOOOO")] // 'O' is disallowed
|
||||
[InlineData("OTHER-234567")] // wrong prefix
|
||||
public void PacaConnectCodeGenerator_IsValid_InvalidCodes_ReturnsFalse(string? code)
|
||||
{
|
||||
Assert.False(PacaConnectCodeGenerator.IsValid(code));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PacaConnectCodeGenerator_GenerateCode_AlwaysProducesValidCode()
|
||||
{
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
var code = PacaConnectCodeGenerator.GenerateCode();
|
||||
Assert.True(PacaConnectCodeGenerator.IsValid(code), $"Generated code '{code}' should be valid.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue