diff --git a/ErsatzTV.Core.Tests/Scheduling/PlaybackOrderSupportTests.cs b/ErsatzTV.Core.Tests/Scheduling/PlaybackOrderSupportTests.cs index 541e9da47..7c64bafef 100644 --- a/ErsatzTV.Core.Tests/Scheduling/PlaybackOrderSupportTests.cs +++ b/ErsatzTV.Core.Tests/Scheduling/PlaybackOrderSupportTests.cs @@ -28,6 +28,20 @@ public class PlaybackOrderSupportTests } } + // Every SchedulingEngineKind must have a matrix entry, or Matrix[engine] throws KeyNotFoundException at + // runtime instead of failing here. This is the engine-axis counterpart to the order tripwire. + [Test] + public void EveryEngineKind_HasAMatrixEntry() + { + var classified = PlaybackOrderSupport.Engines.ToHashSet(); + + foreach (SchedulingEngineKind engine in Enum.GetValues()) + { + classified.ShouldContain(engine, + $"SchedulingEngineKind.{engine} has no PlaybackOrderSupport matrix entry (#403)."); + } + } + // The two sets must partition the enum: no order both supported and unsupported, and together they cover // exactly the enum (no stale entry for a removed value, no missing value). [Test] diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index a7e66db0b..4ae9bd4f9 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -1459,12 +1459,23 @@ public class PlayoutBuilder : IPlayoutBuilder goto default; default: - // An order the classic engine doesn't handle (#403). Say so instead of silently substituting a - // different, arbitrary-looking order; keep airing on the Random fallback so the channel does not - // go dark on one misconfigured item. - _logger.LogWarning( - "Playback order {PlaybackOrder} is not supported by classic scheduling; falling back to Random", - playbackOrder); + // Say so instead of silently substituting a different, arbitrary-looking order; keep airing on + // the Random fallback so the channel does not go dark on one misconfigured item (#403). A + // supported order can also land here via `goto default` (Marathon that couldn't build its + // enumerator) -- distinguish the two so the log doesn't claim a supported order is unsupported. + if (PlaybackOrderSupport.IsSupported(SchedulingEngineKind.Classic, playbackOrder)) + { + _logger.LogWarning( + "Could not build a {PlaybackOrder} enumerator for classic scheduling; falling back to Random", + playbackOrder); + } + else + { + _logger.LogWarning( + "Playback order {PlaybackOrder} is not supported by classic scheduling; falling back to Random", + playbackOrder); + } + return new RandomizedMediaCollectionEnumerator(mediaItems, state); } }