From 44b62dcc648ecf4003250b68c1f1f6b74ee24f58 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Sun, 20 Sep 2026 23:55:17 +1000 Subject: [PATCH] test(ha): pin the default gated task key set --- .../ScheduledTasks/ScanLeaderOptionsTests.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/Jellyfin.Server.Implementations.Tests/ScheduledTasks/ScanLeaderOptionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/ScheduledTasks/ScanLeaderOptionsTests.cs index 19a038397f..b7a67dfe06 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/ScheduledTasks/ScanLeaderOptionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/ScheduledTasks/ScanLeaderOptionsTests.cs @@ -38,6 +38,42 @@ public class ScanLeaderOptionsTests $"Gated keys match no scheduled task: {string.Join(", ", unmatched)}. Known keys: {string.Join(", ", registeredKeys.Order(StringComparer.Ordinal))}"); } + /// + /// A key dropped from the default set silently un-gates that task on every replica, so the whole + /// set is pinned against a hand-maintained expectation rather than read back from the options. + /// + [Fact] + public void DefaultGatedTaskKeys_Should_BeTheExpectedSet() + { + string[] expected = + { + "AudioNormalization", + "CleanupUserDataTask", + "DownloadLyrics", + "DownloadSubtitles", + "KeyframeExtraction", + "MoveTrickplayImages", + "OptimizeDatabaseTask", + "PluginUpdates", + "RefreshChapterImages", + "RefreshGuide", + "RefreshInternetChannels", + "RefreshLibrary", + "RefreshPeople", + "RefreshTrickplayImages", + "TaskExtractMediaSegments", + "TmdbRefreshUpcomingEpisodes" + }; + + var actual = new ScanLeaderOptions().GatedTaskKeys; + var missing = expected.Except(actual, StringComparer.Ordinal).ToList(); + var unexpected = actual.Except(expected, StringComparer.Ordinal).ToList(); + + Assert.True( + missing.Count == 0 && unexpected.Count == 0, + $"Default gated task keys drifted. Missing: {Describe(missing)}. Unexpected: {Describe(unexpected)}."); + } + /// /// The key universe is only as complete as the assemblies it is read from, so a task added to an /// unscanned assembly must fail here rather than narrow what the previous test can catch. @@ -69,6 +105,9 @@ public class ScanLeaderOptionsTests Assert.True(missing.Count == 0, $"Assemblies declaring scheduled tasks but not scanned: {string.Join(", ", missing)}"); } + private static string Describe(IReadOnlyCollection keys) + => keys.Count == 0 ? "none" : string.Join(", ", keys.Order(StringComparer.Ordinal)); + private static HashSet DiscoverScheduledTaskKeys(IEnumerable assemblies) { var keys = new HashSet(StringComparer.Ordinal);