PlayoutModeSchedulerBaseTests.AddFiller.Should_Not_Crash_Mid_Roll_{Zero,One}_Chapters passed new PlayoutItem() to AddFiller — and a default PlayoutItem.Start is DateTime.MinValue (year 1). The mid-roll Pad path (PlayoutModeSchedulerBase.cs:609) computes StartOffset + … - TimeSpan.FromMinutes(currentMinute) + …. Because PlayoutItem.StartOffset does new DateTimeOffset(Start, TimeSpan.Zero).ToLocalTime(), a non-zero local UTC offset makes currentMinute non-zero, so subtracting it underflows DateTimeOffset.MinValue → ArgumentOutOfRangeException. Under TZ=UTC the offset is 0, currentMinute == 0, nothing is subtracted, and it stays in range — which is why CI was green but local non-UTC runs failed.
This is not reachable in production (real playout items never start at MinValue), so it's a test-data artifact, not a product bug — no hardening of AddFiller needed.
Fix
Seed the two fixtures with a realistic Start (startState.CurrentTime.UtcDateTime), matching the convention already used by the passing AddFiller tests in the same file. No production code changed.
Verification
The two tests pass under UTC, Europe/Brussels, and Asia/Kolkata (+5:30); the full ErsatzTV.Core.Tests suite now passes under any timezone (484/0) — confirmed under all three.
Docs
Updated docs/contributing.md §8 (the suite is now timezone-independent; documented the "use a real Start, not default MinValue" rule) per its §10 deviation policy — same PR as the change.
## Root cause
`PlayoutModeSchedulerBaseTests.AddFiller.Should_Not_Crash_Mid_Roll_{Zero,One}_Chapters` passed `new PlayoutItem()` to `AddFiller` — and a default `PlayoutItem.Start` is `DateTime.MinValue` (year 1). The mid-roll Pad path (`PlayoutModeSchedulerBase.cs:609`) computes `StartOffset + … - TimeSpan.FromMinutes(currentMinute) + …`. Because `PlayoutItem.StartOffset` does `new DateTimeOffset(Start, TimeSpan.Zero).ToLocalTime()`, a **non-zero local UTC offset** makes `currentMinute` non-zero, so subtracting it underflows `DateTimeOffset.MinValue` → `ArgumentOutOfRangeException`. Under `TZ=UTC` the offset is 0, `currentMinute == 0`, nothing is subtracted, and it stays in range — which is why **CI was green** but local non-UTC runs failed.
This is **not reachable in production** (real playout items never start at `MinValue`), so it's a test-data artifact, not a product bug — no hardening of `AddFiller` needed.
## Fix
Seed the two fixtures with a realistic `Start` (`startState.CurrentTime.UtcDateTime`), matching the convention already used by the passing `AddFiller` tests in the same file. No production code changed.
## Verification
The two tests pass under **UTC, Europe/Brussels, and Asia/Kolkata (+5:30)**; the **full `ErsatzTV.Core.Tests` suite now passes under any timezone (484/0)** — confirmed under all three.
## Docs
Updated `docs/contributing.md` §8 (the suite is now timezone-independent; documented the "use a real `Start`, not default `MinValue`" rule) per its §10 deviation policy — same PR as the change.
fixes #24
Should_Not_Crash_Mid_Roll_{Zero,One}_Chapters passed 'new PlayoutItem()'
to AddFiller, whose Start defaults to DateTime.MinValue. The mid-roll Pad
path (PlayoutModeSchedulerBase.cs:609) subtracts 'currentMinute' minutes
from StartOffset; since StartOffset does ToLocalTime(), a non-zero local
offset makes currentMinute non-zero, underflowing DateTimeOffset.MinValue
and throwing ArgumentOutOfRangeException. Under UTC the offset is 0 so it
stays in range (hence CI was green). Unreachable in production — real
playout items never start at MinValue — so this is a test-data artifact,
not a product bug.
Fix: seed the fixtures with a real Start (startState.CurrentTime.UtcDateTime),
matching the convention in the passing AddFiller tests. Verified across
UTC, Europe/Brussels, and Asia/Kolkata (+5:30); full Core.Tests now passes
under any timezone (484/0). Updated docs/contributing.md §8 per its §10
deviation policy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
timothy
merged commit fe4cd39070 into main2026-06-27 14:29:59 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Root cause
PlayoutModeSchedulerBaseTests.AddFiller.Should_Not_Crash_Mid_Roll_{Zero,One}_Chapterspassednew PlayoutItem()toAddFiller— and a defaultPlayoutItem.StartisDateTime.MinValue(year 1). The mid-roll Pad path (PlayoutModeSchedulerBase.cs:609) computesStartOffset + … - TimeSpan.FromMinutes(currentMinute) + …. BecausePlayoutItem.StartOffsetdoesnew DateTimeOffset(Start, TimeSpan.Zero).ToLocalTime(), a non-zero local UTC offset makescurrentMinutenon-zero, so subtracting it underflowsDateTimeOffset.MinValue→ArgumentOutOfRangeException. UnderTZ=UTCthe offset is 0,currentMinute == 0, nothing is subtracted, and it stays in range — which is why CI was green but local non-UTC runs failed.This is not reachable in production (real playout items never start at
MinValue), so it's a test-data artifact, not a product bug — no hardening ofAddFillerneeded.Fix
Seed the two fixtures with a realistic
Start(startState.CurrentTime.UtcDateTime), matching the convention already used by the passingAddFillertests in the same file. No production code changed.Verification
The two tests pass under UTC, Europe/Brussels, and Asia/Kolkata (+5:30); the full
ErsatzTV.Core.Testssuite now passes under any timezone (484/0) — confirmed under all three.Docs
Updated
docs/contributing.md§8 (the suite is now timezone-independent; documented the "use a realStart, not defaultMinValue" rule) per its §10 deviation policy — same PR as the change.fixes #24
Should_Not_Crash_Mid_Roll_{Zero,One}_Chapters passed 'new PlayoutItem()' to AddFiller, whose Start defaults to DateTime.MinValue. The mid-roll Pad path (PlayoutModeSchedulerBase.cs:609) subtracts 'currentMinute' minutes from StartOffset; since StartOffset does ToLocalTime(), a non-zero local offset makes currentMinute non-zero, underflowing DateTimeOffset.MinValue and throwing ArgumentOutOfRangeException. Under UTC the offset is 0 so it stays in range (hence CI was green). Unreachable in production — real playout items never start at MinValue — so this is a test-data artifact, not a product bug. Fix: seed the fixtures with a real Start (startState.CurrentTime.UtcDateTime), matching the convention in the passing AddFiller tests. Verified across UTC, Europe/Brussels, and Asia/Kolkata (+5:30); full Core.Tests now passes under any timezone (484/0). Updated docs/contributing.md §8 per its §10 deviation policy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>