test(clock): time-budget facts run on a fake clock (STORY-442, closes #723) - #787
Merged
Merged
Conversation
…ed ones (gh-#723) Orchestration.Tests adds Microsoft.Extensions.TimeProvider.Testing via dotnet add package (CPM already pinned it); both hand-rolled Fakes/FakeTimeProvider.cs are deleted and 34 consumers across Orchestration.Tests/Tts.Tests switch to the real fake. Story241's DST facts move the local time zone to a post-construction SetLocalTimeZone call, since Microsoft's ctor has no localTimeZone parameter. Story243's per-unit render-budget fact pumps the clock past each render's own budget as an interim shape, since the render double itself still rides real wall time until T483 puts it on the fake clock too. Story442's AC1/AC2 pins go green. Timers now really fire on Advance instead of silently riding the wall clock, so the per-unit render budget race stops depending on real-time scheduling luck.
) FakeTtsSegmentSource now takes a TimeProvider (default TimeProvider.System) and delays RenderAsync on it instead of the wall clock; both production-chain harnesses (Story243, ProductionChainHarness) hand it the chain's own FakeTimeProvider. PullUnitsRacingTheRenderBudgetAsync replaces T482's interim real-wait pump, advancing one render-vs-budget pair per step so at most a single fake timer fires per Advance call. Story442's six AC3/AC4 facts are green: the handoff budget race is now decided purely by fake-clock due order, never by which wall-clock timer happens to win on a given runner.
…ncellation (gh-#723) Each attempt's Llm:TimeoutSeconds budget is now a CancellationTokenSource(delay, timeProvider) linked with the caller's token, replacing the wall-clock CancelAfter; the NewAttemptBudget helper is folded inline at both call sites. Story442 AC5/AC6 facts go green in ~50ms. A never-answering LLM now resolves to Timeout as soon as fake time passes the budget, so the fact no longer waits on the wall clock; production behaviour (real TimeProvider) is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #723. PR-3 of the gh-#777 epic (STORY-442).
⏱️ What
FakeTimeProviderreplaces the two hand-rolled fakes in Orchestration.Tests and Tts.Tests (package added withdotnet add package; 34 consumers; Story241 sets its zone withSetLocalTimeZone). Timers now really fire onAdvance.PullUnitsRacingTheRenderBudgetAsyncadvances one budget-vs-render pair per step.AdScriptWriter's per-attemptLlm:TimeoutSecondsbudget is aCancellationTokenSource(delay, timeProvider)linked with the caller's token, replacing wall-clockCancelAfter. Production behaviour is unchanged; a never-answering LLM resolves toTimeoutwhen fake time passes the budget.🔁 Fifty runs (T485 wire, dev box)
✅ Gate
dotnet test GenWave.sln --filter "Category!=Integration" -- xUnit.MaxParallelThreads=3: all nine projects green (Orchestration 443 passed / 3 skipped, Ads 222 / 3, Host 2909 / 203, Architecture 150 / 10; 0 failed).📝 Follow-up (out of scope)
ScenarioEachAttemptHasItsOwnTimeoutBudgetin Tts.Tests' Story390 still spends about 3.6 s on the real clock; it can ride the fake clock now that the writer's budget is TimeProvider-driven.