releases/tests/Paca.Tests/Core/M3u8ParserByteRangeAndfMp4ExtremeRedTests.cs
Yun Chan 8677853822
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
test(core/browser/platform): 26 extreme RED/GREEN TDD cycles and full regression hardening (3,235 PASS)
2026-09-18 23:32:32 +09:00

131 lines
3.7 KiB
C#

using System;
using Paca.Core.Hls;
using Paca.Core.Models;
using Xunit;
namespace Paca.Tests.Core;
public class M3u8ParserByteRangeAndfMp4ExtremeRedTests
{
private static readonly Uri Base = new("https://cdn.example.com/stream/playlist.m3u8");
[Fact]
public void M3u8Parser_ByteRange_ExplicitLengthAndOffset_ParsedCorrectly()
{
var text = @"#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-BYTERANGE:1000@500
segment.ts";
var playlist = M3u8Parser.Parse(text, Base);
Assert.Single(playlist.Segments);
var seg = playlist.Segments[0];
Assert.Equal(1000, seg.ByteRangeLength);
Assert.Equal(500, seg.ByteRangeOffset);
}
[Fact]
public void M3u8Parser_ByteRange_SequentialImplicitOffset_AccumulatesCorrectly()
{
var text = @"#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-BYTERANGE:1000@0
segment.ts
#EXT-X-BYTERANGE:2000
segment.ts
#EXT-X-BYTERANGE:1500
segment.ts";
var playlist = M3u8Parser.Parse(text, Base);
Assert.Equal(3, playlist.Segments.Count);
Assert.Equal(1000, playlist.Segments[0].ByteRangeLength);
Assert.Equal(0, playlist.Segments[0].ByteRangeOffset);
Assert.Equal(2000, playlist.Segments[1].ByteRangeLength);
Assert.Equal(1000, playlist.Segments[1].ByteRangeOffset);
Assert.Equal(1500, playlist.Segments[2].ByteRangeLength);
Assert.Equal(3000, playlist.Segments[2].ByteRangeOffset);
}
[Fact]
public void M3u8Parser_ByteRange_InvalidNegativeOrNonNumeric_IgnoredGracefully()
{
var text = @"#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-BYTERANGE:-500@-100
segment1.ts
#EXT-X-BYTERANGE:invalid@nan
segment2.ts";
var playlist = M3u8Parser.Parse(text, Base);
Assert.Equal(2, playlist.Segments.Count);
Assert.Null(playlist.Segments[0].ByteRangeLength);
Assert.Null(playlist.Segments[0].ByteRangeOffset);
Assert.Null(playlist.Segments[1].ByteRangeLength);
Assert.Null(playlist.Segments[1].ByteRangeOffset);
}
[Fact]
public void M3u8Parser_InitSegment_WithByteRange_ParsedCorrectly()
{
var text = @"#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-MAP:URI=""init.mp4"",BYTERANGE=""800@0""
#EXTINF:6.0,
segment1.m4s";
var playlist = M3u8Parser.Parse(text, Base);
Assert.NotNull(playlist.InitSegment);
Assert.Equal("https://cdn.example.com/stream/init.mp4", playlist.InitSegment.AbsoluteUri);
Assert.Equal(800, playlist.InitByteRangeLength);
Assert.Equal(0, playlist.InitByteRangeOffset);
}
[Fact]
public void M3u8Parser_NullBaseUrl_ReturnsEmptyPlaylistWithoutCrashing()
{
var text = @"#EXTM3U
#EXT-X-TARGETDURATION:10
segment.ts";
var playlist = M3u8Parser.Parse(text, null!);
Assert.NotNull(playlist);
Assert.Empty(playlist.Segments);
}
[Fact]
public void Variant_NegativeOrMalformedResolution_ClampsToZero()
{
var v = new Variant(new Uri("https://example.com/v.m3u8"), 1000, "-1920x-1080", "avc1");
Assert.Equal(0, v.Width);
Assert.Equal(0, v.Height);
}
[Fact]
public void Variant_ComplexResolution_ParsesWidthAndHeight()
{
var v = new Variant(new Uri("https://example.com/v.m3u8"), 1000, "1920x1080@60fps", "avc1");
Assert.Equal(1920, v.Width);
Assert.Equal(1080, v.Height);
}
[Fact]
public void M3u8Parser_MediaSequence_Int64Overflow_DoesNotGoNegative()
{
var text = @"#EXTM3U
#EXT-X-MEDIA-SEQUENCE:9223372036854775807
#EXTINF:6.0,
seg1.ts
#EXTINF:6.0,
seg2.ts";
var playlist = M3u8Parser.Parse(text, Base);
Assert.Equal(2, playlist.Segments.Count);
Assert.True(playlist.Segments[0].Sequence >= 0);
Assert.True(playlist.Segments[1].Sequence >= 0);
}
}