Step 4 of multi-instancing migration. Three additional per-battle statics front-fronted by BattleAmbient.Current, each with a static fallback for unwrapped callers. ViewerId's SavedataManager-persisting setter is preserved on the fallback path; inside a scope, the setter is a no-op (the per-battle perspective is fixed at scope entry). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
193 lines
6.4 KiB
C#
193 lines
6.4 KiB
C#
#nullable enable
|
|
using SVSim.BattleEngine.Ambient;
|
|
using NUnit.Framework;
|
|
using System.Runtime.Serialization;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace SVSim.BattleEngine.Tests;
|
|
|
|
[TestFixture, Parallelizable(ParallelScope.Self)]
|
|
public class BattleAmbientTests
|
|
{
|
|
[Test]
|
|
public void Current_IsNull_WhenNoScope()
|
|
{
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void Require_Throws_WhenNoScope()
|
|
{
|
|
Assert.Throws<System.InvalidOperationException>(() => BattleAmbient.Require());
|
|
}
|
|
|
|
[Test]
|
|
public void Enter_SetsCurrent_RestoresOnDispose()
|
|
{
|
|
var ctx = new BattleAmbientContext { ViewerId = 42 };
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
using (var _ = BattleAmbient.Enter(ctx))
|
|
{
|
|
Assert.That(BattleAmbient.Current, Is.SameAs(ctx));
|
|
Assert.That(BattleAmbient.Require().ViewerId, Is.EqualTo(42));
|
|
}
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void Enter_Nested_RestoresPriorOnDispose()
|
|
{
|
|
var outer = new BattleAmbientContext { ViewerId = 1 };
|
|
var inner = new BattleAmbientContext { ViewerId = 2 };
|
|
using (var _o = BattleAmbient.Enter(outer))
|
|
{
|
|
Assert.That(BattleAmbient.Current!.ViewerId, Is.EqualTo(1));
|
|
using (var _i = BattleAmbient.Enter(inner))
|
|
{
|
|
Assert.That(BattleAmbient.Current!.ViewerId, Is.EqualTo(2));
|
|
}
|
|
Assert.That(BattleAmbient.Current!.ViewerId, Is.EqualTo(1));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task Enter_FlowsAcrossAwait()
|
|
{
|
|
var ctx = new BattleAmbientContext { ViewerId = 99 };
|
|
using (var _ = BattleAmbient.Enter(ctx))
|
|
{
|
|
await Task.Yield();
|
|
Assert.That(BattleAmbient.Current, Is.SameAs(ctx));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task Enter_IsolatedBetweenConcurrentTasks()
|
|
{
|
|
var ctxA = new BattleAmbientContext { ViewerId = 100 };
|
|
var ctxB = new BattleAmbientContext { ViewerId = 200 };
|
|
|
|
var taskA = Task.Run(async () => {
|
|
using var _ = BattleAmbient.Enter(ctxA);
|
|
await Task.Delay(20);
|
|
return BattleAmbient.Current!.ViewerId;
|
|
});
|
|
var taskB = Task.Run(async () => {
|
|
using var _ = BattleAmbient.Enter(ctxB);
|
|
await Task.Delay(20);
|
|
return BattleAmbient.Current!.ViewerId;
|
|
});
|
|
|
|
var results = await Task.WhenAll(taskA, taskB);
|
|
Assert.That(results[0], Is.EqualTo(100));
|
|
Assert.That(results[1], Is.EqualTo(200));
|
|
}
|
|
|
|
[Test]
|
|
public void IsForecast_ReadsAmbient_WhenScopeActive()
|
|
{
|
|
var ctx = new BattleAmbientContext { IsForecast = false };
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
Assert.That(BattleManagerBase.IsForecast, Is.False);
|
|
ctx.IsForecast = true;
|
|
Assert.That(BattleManagerBase.IsForecast, Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void IsForecast_WriteInsideScope_WritesAmbient_NotFallback()
|
|
{
|
|
var ctx = new BattleAmbientContext { IsForecast = false };
|
|
using (var _ = BattleAmbient.Enter(ctx))
|
|
{
|
|
BattleManagerBase.IsForecast = true;
|
|
Assert.That(ctx.IsForecast, Is.True);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void IsForecast_OutsideScope_FallsBackToStatic()
|
|
{
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
BattleManagerBase.IsForecast = true;
|
|
Assert.That(BattleManagerBase.IsForecast, Is.True);
|
|
BattleManagerBase.IsForecast = false;
|
|
Assert.That(BattleManagerBase.IsForecast, Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public void IsRandomDraw_RoundtripsAmbient_And_Fallback()
|
|
{
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
BattleManagerBase.IsRandomDraw = true;
|
|
Assert.That(BattleManagerBase.IsRandomDraw, Is.True);
|
|
|
|
var ctx = new BattleAmbientContext { IsRandomDraw = false };
|
|
using (var _ = BattleAmbient.Enter(ctx))
|
|
{
|
|
Assert.That(BattleManagerBase.IsRandomDraw, Is.False);
|
|
}
|
|
Assert.That(BattleManagerBase.IsRandomDraw, Is.True);
|
|
|
|
BattleManagerBase.IsRandomDraw = false;
|
|
}
|
|
|
|
[Test]
|
|
public void GetIns_ReadsAmbient_WhenScopeActive()
|
|
{
|
|
var fakeMgr = (BattleManagerBase)System.Runtime.Serialization
|
|
.FormatterServices.GetUninitializedObject(typeof(BattleManagerBase));
|
|
var ctx = new BattleAmbientContext { Mgr = fakeMgr };
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
Assert.That(BattleManagerBase.GetIns(), Is.SameAs(fakeMgr));
|
|
}
|
|
|
|
[Test]
|
|
public void GetIns_OutsideScope_FallsBackToStatic()
|
|
{
|
|
Assert.That(BattleAmbient.Current, Is.Null);
|
|
var v = BattleManagerBase.GetIns();
|
|
Assert.Pass($"GetIns()={(v is null ? "null" : v.GetType().Name)}");
|
|
}
|
|
|
|
[Test]
|
|
public void ViewerId_ReadsAmbient_WhenScopeActive()
|
|
{
|
|
var ctx = new BattleAmbientContext { ViewerId = 12345 };
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
Assert.That(Cute.Certification.ViewerId, Is.EqualTo(12345));
|
|
}
|
|
|
|
[Test]
|
|
public void RealTimeNetworkAgent_ReadsAmbient_WhenScopeActive()
|
|
{
|
|
var ctx = new BattleAmbientContext();
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
Assert.That(Wizard.ToolboxGame.RealTimeNetworkAgent, Is.Null);
|
|
var agent = (RealTimeNetworkAgent)System.Runtime.Serialization
|
|
.FormatterServices.GetUninitializedObject(typeof(RealTimeNetworkAgent));
|
|
ctx.NetworkAgent = agent;
|
|
Assert.That(Wizard.ToolboxGame.RealTimeNetworkAgent, Is.SameAs(agent));
|
|
}
|
|
|
|
[Test]
|
|
public void SetRealTimeNetworkBattle_InsideScope_WritesAmbient()
|
|
{
|
|
var ctx = new BattleAmbientContext();
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
var agent = (RealTimeNetworkAgent)System.Runtime.Serialization
|
|
.FormatterServices.GetUninitializedObject(typeof(RealTimeNetworkAgent));
|
|
Wizard.ToolboxGame.SetRealTimeNetworkBattle(agent);
|
|
Assert.That(ctx.NetworkAgent, Is.SameAs(agent));
|
|
}
|
|
|
|
[Test]
|
|
public void BattleRecoveryInfo_ReadsAmbient_WhenScopeActive()
|
|
{
|
|
var info = (Wizard.BattleRecoveryInfo)System.Runtime.Serialization
|
|
.FormatterServices.GetUninitializedObject(typeof(Wizard.BattleRecoveryInfo));
|
|
var ctx = new BattleAmbientContext { RecoveryInfo = info };
|
|
using var _ = BattleAmbient.Enter(ctx);
|
|
Assert.That(Wizard.Data.BattleRecoveryInfo, Is.SameAs(info));
|
|
}
|
|
}
|