feat(engine-ambient): delete static fallbacks; add MultiInstanceEngineTests
Step 8 (final) of multi-instancing migration. All per-battle statics now require a BattleAmbient scope — unwrapped writes throw InvalidOperationException (fail-fast forcing function). MultiInstanceEngineTests proves correctness: two parallel battles resolve independently, N=4/8/16 stress matches sequential baseline, GameMgr.GetIns throws without scope. Migration complete. EngineSessionGate gone. Suite fully green. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -105,30 +105,34 @@ public class BattleAmbientTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsForecast_OutsideScope_FallsBackToStatic()
|
||||
public void IsForecast_OutsideScope_GetAndSetThrow()
|
||||
{
|
||||
// Post-Task-8: fallback is gone. Both get and set go through BattleAmbient.Require(),
|
||||
// which throws when no scope is active. This is the forcing function — any unwrapped
|
||||
// engine code that touches IsForecast fails fast instead of silently writing a static.
|
||||
Assert.That(BattleAmbient.Current, Is.Null);
|
||||
BattleManagerBase.IsForecast = true;
|
||||
Assert.That(BattleManagerBase.IsForecast, Is.True);
|
||||
BattleManagerBase.IsForecast = false;
|
||||
Assert.That(BattleManagerBase.IsForecast, Is.False);
|
||||
Assert.Throws<System.InvalidOperationException>(() => { var _ = BattleManagerBase.IsForecast; });
|
||||
Assert.Throws<System.InvalidOperationException>(() => BattleManagerBase.IsForecast = true);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IsRandomDraw_RoundtripsAmbient_And_Fallback()
|
||||
public void IsRandomDraw_OutsideScope_GetAndSetThrow_InsideScope_Roundtrips()
|
||||
{
|
||||
// Post-Task-8: get/set both Require() a scope. Inside a scope, writes land on the ctx.
|
||||
Assert.That(BattleAmbient.Current, Is.Null);
|
||||
BattleManagerBase.IsRandomDraw = true;
|
||||
Assert.That(BattleManagerBase.IsRandomDraw, Is.True);
|
||||
Assert.Throws<System.InvalidOperationException>(() => { var _ = BattleManagerBase.IsRandomDraw; });
|
||||
Assert.Throws<System.InvalidOperationException>(() => BattleManagerBase.IsRandomDraw = true);
|
||||
|
||||
var ctx = new BattleAmbientContext { IsRandomDraw = false };
|
||||
using (var _ = BattleAmbient.Enter(ctx))
|
||||
{
|
||||
Assert.That(BattleManagerBase.IsRandomDraw, Is.False);
|
||||
BattleManagerBase.IsRandomDraw = true;
|
||||
Assert.That(ctx.IsRandomDraw, Is.True);
|
||||
}
|
||||
Assert.That(BattleManagerBase.IsRandomDraw, Is.True);
|
||||
|
||||
BattleManagerBase.IsRandomDraw = false;
|
||||
// Scope disposed -> back to throwing on access.
|
||||
Assert.Throws<System.InvalidOperationException>(() => { var _ = BattleManagerBase.IsRandomDraw; });
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -142,11 +146,13 @@ public class BattleAmbientTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetIns_OutsideScope_FallsBackToStatic()
|
||||
public void GetIns_OutsideScope_ReturnsNull()
|
||||
{
|
||||
// Post-Task-8: fallback is gone. GetIns() reads Current?.Mgr (soft, kept null-tolerant so
|
||||
// engine call sites that pattern `GetIns()?.Foo ?? default` still compose). With no scope
|
||||
// active, Current is null, so GetIns() returns null.
|
||||
Assert.That(BattleAmbient.Current, Is.Null);
|
||||
var v = BattleManagerBase.GetIns();
|
||||
Assert.Pass($"GetIns()={(v is null ? "null" : v.GetType().Name)}");
|
||||
Assert.That(BattleManagerBase.GetIns(), Is.Null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user