refactor(app): extract focused window lifetime
Move the exact retryable shutdown manifest, typed root snapshot, terminal reporting, and native-window-last release out of GameWindow. Keep session and GPU convergence as hard barriers while reporting persistent physical callback cleanup without stranding dependent owners. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
5a55d08106
commit
31e6e192b3
21 changed files with 1297 additions and 572 deletions
|
|
@ -159,4 +159,97 @@ public sealed class ResourceShutdownTransactionTests
|
|||
Assert.Equal(1, calls);
|
||||
Assert.True(transaction.IsComplete);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReportableFailureRetriesThenAllowsDependentStagesAndIsStructured()
|
||||
{
|
||||
var calls = new List<string>();
|
||||
var failure = new InvalidOperationException("physical detach failed");
|
||||
var transaction = new ResourceShutdownTransaction(
|
||||
new ResourceShutdownStage("physical ingress",
|
||||
[
|
||||
new(
|
||||
"mouse callback",
|
||||
() =>
|
||||
{
|
||||
calls.Add("detach");
|
||||
throw failure;
|
||||
},
|
||||
ResourceShutdownOperationPolicy.ReportAndContinue),
|
||||
]),
|
||||
new ResourceShutdownStage("dependent",
|
||||
[
|
||||
new("dependent", () => calls.Add("dependent")),
|
||||
]));
|
||||
|
||||
transaction.CompleteOrThrow();
|
||||
|
||||
Assert.Equal(["detach", "detach", "dependent"], calls);
|
||||
Assert.True(transaction.IsComplete);
|
||||
ResourceShutdownCleanupFailure cleanup = Assert.Single(
|
||||
transaction.CleanupFailures);
|
||||
Assert.Equal("physical ingress", cleanup.Stage);
|
||||
Assert.Equal("mouse callback", cleanup.Operation);
|
||||
Assert.Same(failure, cleanup.Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TransientReportableFailureConvergesWithoutCleanupFailure()
|
||||
{
|
||||
int calls = 0;
|
||||
var transaction = new ResourceShutdownTransaction(
|
||||
new ResourceShutdownStage("physical ingress",
|
||||
[
|
||||
new(
|
||||
"keyboard callback",
|
||||
() =>
|
||||
{
|
||||
if (calls++ == 0)
|
||||
throw new InvalidOperationException("transient");
|
||||
},
|
||||
ResourceShutdownOperationPolicy.ReportAndContinue),
|
||||
]));
|
||||
|
||||
transaction.CompleteOrThrow();
|
||||
|
||||
Assert.Equal(2, calls);
|
||||
Assert.Empty(transaction.CleanupFailures);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SettledReportableFailureNeverReplaysWhileHardBarrierRetries()
|
||||
{
|
||||
int softCalls = 0;
|
||||
int hardCalls = 0;
|
||||
bool allowHard = false;
|
||||
var transaction = new ResourceShutdownTransaction(
|
||||
new ResourceShutdownStage("mixed",
|
||||
[
|
||||
new(
|
||||
"soft",
|
||||
() =>
|
||||
{
|
||||
softCalls++;
|
||||
throw new InvalidOperationException("soft");
|
||||
},
|
||||
ResourceShutdownOperationPolicy.ReportAndContinue),
|
||||
new("hard", () =>
|
||||
{
|
||||
hardCalls++;
|
||||
if (!allowHard)
|
||||
throw new InvalidOperationException("hard");
|
||||
}),
|
||||
]));
|
||||
|
||||
Assert.Throws<AggregateException>(transaction.CompleteOrThrow);
|
||||
int settledSoftCalls = softCalls;
|
||||
allowHard = true;
|
||||
|
||||
transaction.CompleteOrThrow();
|
||||
|
||||
Assert.Equal(settledSoftCalls, softCalls);
|
||||
Assert.True(hardCalls > 1);
|
||||
Assert.True(transaction.IsComplete);
|
||||
Assert.Single(transaction.CleanupFailures);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue