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,172 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Paca.Core.Media;
using Xunit;
namespace Paca.Tests.Media;
public class HardwareTranscoderAndCastingExtremeRedTests
{
[Fact]
public void BuildFfmpegTranscodeCommand_NullSpec_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() =>
HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("input.mp4", "output.mp4", null!));
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void BuildFfmpegTranscodeCommand_NullOrWhitespaceInput_ThrowsArgumentException(string? invalidInput)
{
var spec = new TranscodePresetSpec();
Assert.Throws<ArgumentException>(() =>
HardwareTranscoderStudio.BuildFfmpegTranscodeCommand(invalidInput!, "output.mp4", spec));
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void BuildFfmpegTranscodeCommand_NullOrWhitespaceOutput_ThrowsArgumentException(string? invalidOutput)
{
var spec = new TranscodePresetSpec();
Assert.Throws<ArgumentException>(() =>
HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("input.mp4", invalidOutput!, spec));
}
[Fact]
public void BuildFfmpegTranscodeCommand_SameInputAndOutput_ThrowsInvalidOperationException()
{
var tempFile = Path.GetTempFileName();
try
{
var spec = new TranscodePresetSpec();
Assert.Throws<InvalidOperationException>(() =>
HardwareTranscoderStudio.BuildFfmpegTranscodeCommand(tempFile, tempFile, spec));
}
finally
{
if (File.Exists(tempFile)) File.Delete(tempFile);
}
}
[Fact]
public void BuildFfmpegTranscodeCommand_QuotedPaths_StripsQuotesAndProducesValidArgs()
{
var spec = new TranscodePresetSpec { Backend = HardwareEncoderBackend.SoftwareCpu, Codec = VideoCodecTarget.H264 };
var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("\"C:\\input video.mp4\"", "\"C:\\out.mp4\"", spec);
Assert.Equal("C:\\input video.mp4", args[1]);
Assert.Equal("C:\\out.mp4", args.Last());
}
[Fact]
public void BuildFfmpegTranscodeCommand_NullOrEmptyAudioCodec_DefaultsToAac()
{
var spec = new TranscodePresetSpec { AudioCodec = " " };
var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mkv", "out.mp4", spec);
var aIndex = args.IndexOf("-c:a");
Assert.True(aIndex >= 0);
Assert.Equal("aac", args[aIndex + 1]);
}
[Theory]
[InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.AV1, "av1_nvenc")]
[InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.HEVC_H265, "hevc_nvenc")]
[InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.H264, "h264_nvenc")]
[InlineData(HardwareEncoderBackend.IntelQsv, VideoCodecTarget.AV1, "av1_qsv")]
[InlineData(HardwareEncoderBackend.IntelQsv, VideoCodecTarget.HEVC_H265, "hevc_qsv")]
[InlineData(HardwareEncoderBackend.AmdAmf, VideoCodecTarget.AV1, "av1_amf")]
[InlineData(HardwareEncoderBackend.AmdAmf, VideoCodecTarget.HEVC_H265, "hevc_amf")]
[InlineData(HardwareEncoderBackend.SoftwareCpu, VideoCodecTarget.AV1, "libsvtav1")]
[InlineData(HardwareEncoderBackend.SoftwareCpu, VideoCodecTarget.HEVC_H265, "libx265")]
public void BuildFfmpegTranscodeCommand_Backends_ProducesCorrectVideoCodec(
HardwareEncoderBackend backend, VideoCodecTarget codec, string expectedCodec)
{
var spec = new TranscodePresetSpec { Backend = backend, Codec = codec };
var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mp4", "out.mp4", spec);
var vIndex = args.IndexOf("-c:v");
Assert.True(vIndex >= 0);
Assert.Equal(expectedCodec, args[vIndex + 1]);
}
[Fact]
public void BuildFfmpegTranscodeCommand_NegativeBitrate_DoesNotEmitBitrateFlag()
{
var spec = new TranscodePresetSpec { TargetBitrateKbps = -100 };
var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mp4", "out.mp4", spec);
Assert.DoesNotContain("-b:v", args);
}
[Fact]
public void WebRtcCastingEngine_TerminateSession_NullSessionId_ReturnsFalseWithoutThrowing()
{
var engine = new WebRtcCastingEngine();
var result = engine.TerminateSession(null!);
Assert.False(result);
}
[Fact]
public void WebRtcCastingEngine_TerminateSession_UnknownSessionId_ReturnsFalse()
{
var engine = new WebRtcCastingEngine();
var result = engine.TerminateSession("non-existent-uuid");
Assert.False(result);
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void WebRtcCastingEngine_CreateCastSession_NullOrWhitespaceDevice_DefaultsToDefaultDisplay(string? deviceName)
{
var engine = new WebRtcCastingEngine();
var session = engine.CreateCastSession(deviceName!);
Assert.Equal("Default Display", session.TargetDeviceName);
}
[Fact]
public void WebRtcCastingEngine_GetSession_WorksCorrectly()
{
var engine = new WebRtcCastingEngine();
Assert.Null(engine.GetSession(null!));
Assert.Null(engine.GetSession("unknown-id"));
var created = engine.CreateCastSession("Living Room TV");
var found = engine.GetSession(created.SessionId);
Assert.NotNull(found);
Assert.Equal("Living Room TV", found.TargetDeviceName);
}
[Fact]
public void WebRtcCastingEngine_GenerateOffer_InvalidDimensions_NormalizesDimensions()
{
var engine = new WebRtcCastingEngine();
var desc = engine.GenerateOffer(null!, width: -50, height: 0, fps: -1);
Assert.Equal("offer", desc.Type);
Assert.Contains("v=0", desc.Sdp);
Assert.Contains("H264", desc.Sdp);
}
[Fact]
public void WebRtcCastingEngine_ThreadSafety_ConcurrentCreateAndTerminate()
{
var engine = new WebRtcCastingEngine();
Parallel.For(0, 50, i =>
{
var session = engine.CreateCastSession($"Device {i}");
Assert.NotNull(engine.GetSession(session.SessionId));
var terminated = engine.TerminateSession(session.SessionId);
Assert.True(terminated);
Assert.Null(engine.GetSession(session.SessionId));
});
Assert.Equal(0, engine.ActiveSessionsCount);
}
}