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(() => 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(() => AiHighlightClipper.BuildFfmpegShortsCommand(inPath!, outPath!, spec)); } [Fact] public void AiHighlightClipper_BuildFfmpegShortsCommand_NullSpec_ThrowsArgumentNullException() { Assert.Throws(() => 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())); } [Fact] public void FftAudioWaveformEngine_BuildFfmpegEqualizerFilter_ListContainingNullBands_SkipsSafely() { var bands = new List { 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 { 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."); } } }