153 lines
5.5 KiB
C#
153 lines
5.5 KiB
C#
using dy.net.job;
|
|
using dy.net.model.dto;
|
|
using dy.net.model.entity;
|
|
using dy.net.model.response;
|
|
using dy.net.service;
|
|
using Quartz;
|
|
|
|
namespace dy.net.Tests;
|
|
|
|
public class QuartzTaskContextTests
|
|
{
|
|
[Fact]
|
|
public void EmptyScheduledJobData_DoesNotRequireManualTaskKeys()
|
|
{
|
|
var context = DouyinBasicSyncJob.ResolveTaskContext(new JobDataMap());
|
|
|
|
Assert.Null(context.TaskId);
|
|
Assert.Equal(VideoTaskTrigger.Scheduled, context.Trigger);
|
|
}
|
|
|
|
[Fact]
|
|
public void ManualJobData_ReusesProvidedTaskId()
|
|
{
|
|
var data = new JobDataMap
|
|
{
|
|
["video-task-id"] = "task-id",
|
|
["video-task-trigger"] = "manual"
|
|
};
|
|
|
|
var context = DouyinBasicSyncJob.ResolveTaskContext(data);
|
|
|
|
Assert.Equal("task-id", context.TaskId);
|
|
Assert.Equal(VideoTaskTrigger.Manual, context.Trigger);
|
|
}
|
|
|
|
[Fact]
|
|
public void LocalRecord_IsReplacedWhenCurrentStorageIsWebDav()
|
|
{
|
|
var local = new dy.net.model.entity.DouyinVideo { StorageType = StorageType.Local };
|
|
var remote = new dy.net.model.entity.DouyinVideo { StorageType = StorageType.WebDav };
|
|
|
|
Assert.True(DouyinBasicSyncJob.ShouldReplaceOldStorageRecord(local, StorageType.WebDav));
|
|
Assert.False(DouyinBasicSyncJob.ShouldReplaceOldStorageRecord(remote, StorageType.WebDav));
|
|
Assert.False(DouyinBasicSyncJob.ShouldReplaceOldStorageRecord(remote, StorageType.Local));
|
|
Assert.False(DouyinBasicSyncJob.ShouldReplaceOldStorageRecord(null, StorageType.WebDav));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(true, null, null)]
|
|
[InlineData(false, true, null)]
|
|
[InlineData(false, false, true)]
|
|
[InlineData(false, false, false)]
|
|
public void BestMatchedVideoUrl_MissingMediaData_ReturnsNull(
|
|
bool nullAweme,
|
|
bool? nullVideo,
|
|
bool? nullBitRates)
|
|
{
|
|
Aweme aweme = null;
|
|
if (!nullAweme)
|
|
{
|
|
aweme = new Aweme();
|
|
if (nullVideo != true)
|
|
aweme.Video = new Video { BitRate = nullBitRates == true ? null : new List<VideoBitRate>() };
|
|
}
|
|
|
|
var selected = DouyinBasicSyncJob.GetBestMatchedVideoUrl(aweme, new AppConfig());
|
|
|
|
Assert.Null(selected);
|
|
}
|
|
|
|
[Fact]
|
|
public void BestMatchedVideoUrl_IgnoresMalformedBitRatesAndEmptyUrls()
|
|
{
|
|
var aweme = new Aweme
|
|
{
|
|
Video = new Video
|
|
{
|
|
BitRate = new List<VideoBitRate>
|
|
{
|
|
null,
|
|
new() { PlayAddr = null },
|
|
new() { PlayAddr = new PlayAddr { UrlList = null } },
|
|
new() { PlayAddr = new PlayAddr { UrlList = new List<string> { "", " " } } }
|
|
}
|
|
}
|
|
};
|
|
|
|
Assert.Null(DouyinBasicSyncJob.GetBestMatchedVideoUrl(aweme, new AppConfig()));
|
|
Assert.Empty(DouyinBasicSyncJob.GetMediaCandidates(aweme, null));
|
|
}
|
|
|
|
[Fact]
|
|
public void BestMatchedVideoUrl_PrefersH265AndFallsBackToH264()
|
|
{
|
|
var h264Low = BitRate("https://media.test/h264-low", isH265: 0, value: 100);
|
|
var h264High = BitRate("https://media.test/h264-high", isH265: 0, value: 300);
|
|
var h265 = BitRate("https://media.test/h265", isH265: 1, value: 200);
|
|
var aweme = new Aweme { Video = new Video { BitRate = new List<VideoBitRate> { h264Low, h265, h264High } } };
|
|
|
|
Assert.Same(h265, DouyinBasicSyncJob.GetBestMatchedVideoUrl(aweme, new AppConfig { VideoEncoder = 265 }));
|
|
Assert.Same(h264High, DouyinBasicSyncJob.GetBestMatchedVideoUrl(aweme, new AppConfig { VideoEncoder = 264 }));
|
|
|
|
aweme.Video.BitRate = new List<VideoBitRate> { h264Low, h264High };
|
|
Assert.Same(h264High, DouyinBasicSyncJob.GetBestMatchedVideoUrl(aweme, new AppConfig { VideoEncoder = 265 }));
|
|
}
|
|
|
|
[Fact]
|
|
public void MediaCandidates_UsesSelectedFirstAndRemovesEmptyAndDuplicateUrls()
|
|
{
|
|
var selected = BitRate("https://media.test/preferred", isH265: 1, value: 200);
|
|
selected.PlayAddr.UrlList.Add("https://media.test/shared");
|
|
var fallback = BitRate("https://media.test/shared", isH265: 0, value: 100);
|
|
fallback.PlayAddr.UrlList.Add("");
|
|
fallback.PlayAddr.UrlList.Add("https://media.test/fallback");
|
|
var aweme = new Aweme
|
|
{
|
|
Video = new Video { BitRate = new List<VideoBitRate> { null, fallback, selected } }
|
|
};
|
|
|
|
var candidates = DouyinBasicSyncJob.GetMediaCandidates(aweme, selected);
|
|
|
|
Assert.Equal(new[]
|
|
{
|
|
"https://media.test/preferred",
|
|
"https://media.test/shared",
|
|
"https://media.test/fallback"
|
|
}, candidates);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(VideoTypeEnum.dy_favorite, true)]
|
|
[InlineData(VideoTypeEnum.dy_collects, true)]
|
|
[InlineData(VideoTypeEnum.dy_follows, true)]
|
|
[InlineData(VideoTypeEnum.dy_custom_collect, true)]
|
|
[InlineData(VideoTypeEnum.dy_mix, true)]
|
|
[InlineData(VideoTypeEnum.dy_series, true)]
|
|
[InlineData(VideoTypeEnum.ImageVideo, false)]
|
|
[InlineData(VideoTypeEnum.dy_followuser, false)]
|
|
[InlineData(VideoTypeEnum.dy_followuser_once, false)]
|
|
[InlineData(VideoTypeEnum.dy_live_monitor, false)]
|
|
public void ManualVideoSyncType_OnlyAllowsDownloadJobs(VideoTypeEnum type, bool expected)
|
|
{
|
|
Assert.Equal(expected, DouyinQuartzJobService.IsVideoSyncType(type));
|
|
}
|
|
|
|
private static VideoBitRate BitRate(string url, int isH265, int value) => new()
|
|
{
|
|
IsH265 = isH265,
|
|
BitRateValue = value,
|
|
PlayAddr = new PlayAddr { UrlList = new List<string> { url } }
|
|
};
|
|
}
|