Repository navigation
test: synchronize rejected-create cancellation with response observation - #21417
David Fowler (davidfowl) wants to merge 1 commit into
Conversation
Arm the existing 10 ms cancellation interval when the client disposes the observed Forbidden response, rather than before the HTTP send. Preserve the definite cancellation assertions and verify only one send. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 21417Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 21417" |
Tests selector2 / 100 PR test projects · 0 PR jobs, from 1 changed file. Selected PR test projects (2 / 100)
Selected PR jobs (0)none How these were chosen — grouped by what changed🧪 Job reasonsnone Selection computed for commit |
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues remain for the test-only change that synchronizes cancellation with disposal of the rejected create response.
No open issues 🎉
What changed in this PR
Addresses the test timing race in #20931 by ordering cancellation after the client observes a rejected create response. Production behavior is unchanged.
Changes:
- Starts the existing 10 ms cancellation timer when the Forbidden response is disposed, using a small callback helper.
- Preserves the one-minute retry delay and assertions that cancellation remains definite with an exact
TaskCanceledException. - Adds an assertion that exactly one request is sent.
| File | Description |
|---|---|
tests/Aspire.Hosting.Azure.Tests/AzureSandboxesTests.cs |
Synchronizes cancellation with response disposal and verifies a single send. |
Review effort: Balanced
|
This conflict comes from #21591, which has merged into 🤖 Posted by AspireAgent (AI Agent) |
|
Closing as superseded by #21591 (same fix). 🤖 Posted by AspireAgent (AI Agent) |
Description
Fixes #20931's test-phase guarantee in
AzureDevComputeClientKeepsCancellationAfterRejectedCreateDefinite; no production behavior changes.The test starts a 10 ms cancellation timer before calling the client, but expects cancellation after the client has observed a rejected create. Those phases have no ordering guarantee: default
HttpClient.SendAsyncincludes response buffering, and cancellation before it returns is correctly classified as potentially ambiguous.Start with an unarmed cancellation source and arm the same 10 ms interval when the client disposes the observed Forbidden response, immediately before its existing retry delay. Preserve the configured one-minute retry delay,
AzureDevComputeCreateException, definiteResponseMayHaveBeenLost == false, and exactTaskCanceledExceptionassertions; add an exact one-send assertion.Only
tests/Aspire.Hosting.Azure.Tests/AzureSandboxesTests.cschanges (+25/-2), including a minimal response-disposal callback helper. No dependencies, production changes, timeout increases, retries, skips, diagnostic logging, buffering instrumentation or workflow changes are included.Native evidence and limits
Controlled counterexample — run 40968736046, attempt 1, at
f884f0a: normal build had zero warnings/errors; six actual cases executed, five passed and one deliberately failed the original definite assertion. Cancellation during actual response buffering produced one send andResponseMayHaveBeenLost == truebefore the repository client observed the rejection.TaskCanceledExceptionwas logged; the later type assertion was not executed afterAssert.Falsefailed.Native qualification — run 40971773666, attempt 1, job 123790016435: normal restore/build completed with zero warnings/errors and seven unique actual cases passed, with zero failures, skips or unknown outcomes and no observed duplicate/retry executions.
The complete native TRX was downloaded and checked, including unique test/execution IDs and phase-marker ordering. The pre-observation case retains the correct ambiguous production contract; it does not weaken the repaired original's definite assertion.
Qualification ran at a separate diagnostic child,
5c3c411, whose parent is this clean repair head5ead38f. The repaired method and callback helper are byte-identical between them. The diagnostic child and its workflow are not included in this PR. Normal CI/Final Results for this clean PR head remain required; qualification-child success is not a substitute.This is controlled phase-boundary evidence, not reproduction of the historical natural failure. The original timer-based test passed before the repair as well; do not read these results as “old original red, new original green” or as a production service fix. The repaired test explicitly orders cancellation after response observation rather than relying on elapsed time from before dispatch.
This PR is deliberately draft for review and normal CI. No merge is requested by this publication.
Checklist
<remarks />and<code />elements on your triple slash comments?🤖 Posted by AspireAgent (AI Agent)