test(battle-node): delete scripted participant + scripted-only builder tests

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-03 19:55:00 -04:00
parent 3fe378d801
commit 963adbbd1b
4 changed files with 0 additions and 255 deletions

View File

@@ -166,62 +166,6 @@ public class ScriptedLifecycleTests
"single-arg overload (non-interactive opponent) keeps the placeholder hand.");
}
[Test]
public void BuildClientSwap_has_empty_idxList_in_RawBody()
{
var env = ScriptedLifecycle.BuildClientSwap();
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.Swap));
Assert.That(env.ViewerId, Is.EqualTo(ScriptedLifecycle.FakeOpponentViewerId));
var raw = (RawBody)env.Body;
Assert.That(raw.Entries.ContainsKey("idxList"), Is.True);
var idx = (System.Collections.IEnumerable)raw.Entries["idxList"]!;
Assert.That(idx.Cast<object>().Count(), Is.EqualTo(0), "bot keeps its dealt hand (empty mulligan).");
}
[Test]
public void BuildClientHandshakeFrames_carry_expected_uris()
{
Assert.That(ScriptedLifecycle.BuildClientInitNetwork().Uri, Is.EqualTo(NetworkBattleUri.InitNetwork));
Assert.That(ScriptedLifecycle.BuildClientInitBattle().Uri, Is.EqualTo(NetworkBattleUri.InitBattle));
Assert.That(ScriptedLifecycle.BuildClientLoaded().Uri, Is.EqualTo(NetworkBattleUri.Loaded));
}
[Test]
public void BuildOpponentTurnStart_HasUriTurnStartAndSpin()
{
var env = ScriptedLifecycle.BuildOpponentTurnStart();
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.TurnStart));
var body = (OpponentTurnStartBody)env.Body;
Assert.That(body.Spin, Is.EqualTo(100));
}
[Test]
public void BuildOpponentTurnEnd_emits_TurnEnd_uri_with_turn_state_zero()
{
var env = ScriptedLifecycle.BuildOpponentTurnEnd();
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.TurnEnd));
Assert.That(env.ViewerId, Is.EqualTo(ScriptedLifecycle.FakeOpponentViewerId));
Assert.That(env.Cat, Is.EqualTo(EmitCategory.Battle));
var body = (TurnEndBody)env.Body;
Assert.That(body.TurnState, Is.EqualTo(0));
Assert.That(body.ResultCode, Is.EqualTo(1));
}
[Test]
public void BuildOpponentJudge_emits_Judge_uri_with_spin_and_default_result_code()
{
var env = ScriptedLifecycle.BuildOpponentJudge();
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.Judge));
Assert.That(env.ViewerId, Is.EqualTo(ScriptedLifecycle.FakeOpponentViewerId));
Assert.That(env.Cat, Is.EqualTo(EmitCategory.Battle));
var body = (JudgeBody)env.Body;
Assert.That(body.Spin, Is.EqualTo(ScriptedProfiles.OpponentJudgeSpin));
Assert.That(body.ResultCode, Is.EqualTo(1));
}
private static MatchContext FixtureCtx(IReadOnlyList<long>? deck = null) => new(
SelfDeckCardIds: deck ?? Enumerable.Range(1, 30).Select(i => 100_011_010L).ToList(),
ClassId: "1", CharaId: "1", CardMasterName: "card_master_node_10015",

View File

@@ -147,42 +147,6 @@ public class TypedBodyWireShapeTests
Assert.That(node["oppo"]!.AsArray().Count, Is.EqualTo(3));
}
[Test]
public void BuildOpponentTurnStart_SerializesSpinAndResultCode()
{
var env = ScriptedLifecycle.BuildOpponentTurnStart();
var json = MsgEnvelope.ToJson(env);
var node = JsonNode.Parse(json)!.AsObject();
Assert.That(node["spin"]!.GetValue<int>(), Is.EqualTo(100));
Assert.That(node["resultCode"]!.GetValue<int>(), Is.EqualTo(1));
Assert.That(node["uri"]!.GetValue<string>(), Is.EqualTo("TurnStart"));
}
[Test]
public void BuildOpponentTurnEnd_SerializesTurnStateAndResultCode()
{
var env = ScriptedLifecycle.BuildOpponentTurnEnd();
var json = MsgEnvelope.ToJson(env);
var node = JsonNode.Parse(json)!.AsObject();
Assert.That(node["turnState"]!.GetValue<int>(), Is.EqualTo(0));
Assert.That(node["resultCode"]!.GetValue<int>(), Is.EqualTo(1));
Assert.That(node["uri"]!.GetValue<string>(), Is.EqualTo("TurnEnd"));
}
[Test]
public void BuildOpponentJudge_SerializesSpinAndResultCode()
{
var env = ScriptedLifecycle.BuildOpponentJudge();
var json = MsgEnvelope.ToJson(env);
var node = JsonNode.Parse(json)!.AsObject();
Assert.That(node["spin"]!.GetValue<int>(), Is.EqualTo(100));
Assert.That(node["resultCode"]!.GetValue<int>(), Is.EqualTo(1));
Assert.That(node["uri"]!.GetValue<string>(), Is.EqualTo("Judge"));
}
/// <summary>
/// Wire-shape fixture: 30 copies of the legacy DummyCardId (100_011_010L) so the
/// existing literal assertions on <c>selfDeck[0].cardId</c> (line 81 above) keep working

View File

@@ -1,87 +0,0 @@
using NUnit.Framework;
using SVSim.BattleNode.Lifecycle;
using SVSim.BattleNode.Protocol;
using SVSim.BattleNode.Protocol.Bodies;
using SVSim.BattleNode.Sessions;
using SVSim.BattleNode.Sessions.Participants;
namespace SVSim.UnitTests.BattleNode.Sessions.Participants;
[TestFixture]
public class ScriptedBotParticipantTests
{
[Test]
public async Task RunAsync_emits_InitNetwork_to_kick_off_handshake()
{
var p = new ScriptedBotParticipant();
var emitted = new List<NetworkBattleUri>();
p.FrameEmitted += (env, _) => { emitted.Add(env.Uri); return Task.CompletedTask; };
await p.RunAsync(CancellationToken.None);
Assert.That(emitted, Is.EqualTo(new[] { NetworkBattleUri.InitNetwork }));
}
[TestCase(NetworkBattleUri.InitNetwork, NetworkBattleUri.InitBattle)]
[TestCase(NetworkBattleUri.Matched, NetworkBattleUri.Loaded)]
[TestCase(NetworkBattleUri.Deal, NetworkBattleUri.Swap)]
public async Task PushAsync_handshake_push_emits_next_client_frame(
NetworkBattleUri pushed, NetworkBattleUri expectedEmit)
{
var p = new ScriptedBotParticipant();
var emitted = new List<NetworkBattleUri>();
p.FrameEmitted += (env, _) => { emitted.Add(env.Uri); return Task.CompletedTask; };
await p.PushAsync(NewEnvelope(pushed), noStock: false, CancellationToken.None);
Assert.That(emitted, Is.EqualTo(new[] { expectedEmit }));
}
[Test]
public async Task PushAsync_TurnEnd_fires_three_FrameEmitted_in_order()
{
var p = new ScriptedBotParticipant();
var emitted = new List<NetworkBattleUri>();
p.FrameEmitted += (env, _) => { emitted.Add(env.Uri); return Task.CompletedTask; };
await p.PushAsync(NewEnvelope(NetworkBattleUri.TurnEnd), noStock: false, CancellationToken.None);
Assert.That(emitted, Is.EqualTo(new[]
{
NetworkBattleUri.TurnStart, NetworkBattleUri.TurnEnd, NetworkBattleUri.Judge,
}));
}
[Test]
public async Task PushAsync_non_reactive_uris_emit_nothing()
{
var p = new ScriptedBotParticipant();
var fired = 0;
p.FrameEmitted += (_, _) => { fired++; return Task.CompletedTask; };
foreach (var uri in new[]
{
NetworkBattleUri.BattleStart, NetworkBattleUri.Swap, NetworkBattleUri.Ready,
NetworkBattleUri.PlayActions, NetworkBattleUri.TurnStart, NetworkBattleUri.Echo,
NetworkBattleUri.Judge, NetworkBattleUri.BattleFinish, NetworkBattleUri.TurnEndFinal,
})
{
await p.PushAsync(NewEnvelope(uri), noStock: false, CancellationToken.None);
}
Assert.That(fired, Is.EqualTo(0));
}
[Test]
public void Implements_IHasHandshakePhase_starting_at_AwaitingInitNetwork()
{
var p = new ScriptedBotParticipant();
Assert.That(p, Is.InstanceOf<IHasHandshakePhase>());
Assert.That(((IHasHandshakePhase)p).Phase, Is.EqualTo(BattleSessionPhase.AwaitingInitNetwork));
}
private static MsgEnvelope NewEnvelope(NetworkBattleUri uri) =>
new(uri, ViewerId: 1, Uuid: "u", Bid: null, Try: 0,
Cat: EmitCategory.Battle, PubSeq: null, PlaySeq: null,
Body: new ResultCodeOnlyBody());
}

View File

@@ -1,76 +0,0 @@
using Microsoft.Extensions.Logging.Abstractions;
using NUnit.Framework;
using SVSim.BattleNode.Bridge;
using SVSim.BattleNode.Lifecycle;
using SVSim.BattleNode.Protocol;
using SVSim.BattleNode.Protocol.Bodies;
using SVSim.BattleNode.Sessions;
using SVSim.BattleNode.Sessions.Participants;
namespace SVSim.UnitTests.BattleNode.Sessions;
[TestFixture]
public class ScriptedBotHandshakeIntegrationTests
{
[Test]
public async Task RealBot_completes_handshake_and_both_sides_reach_Ready_through_barrier()
{
var bot = new ScriptedBotParticipant(); // B — real participant under test
var player = new RecordingPlayer(viewerId: 1, PlayerCtx());
var session = new BattleSession("bid-int-1", BattleType.Scripted, player, bot,
NullLogger<BattleSession>.Instance);
// Wire the bot's emissions into the session the way BattleSession's ctor does for
// real participants (the ctor already subscribed; we just need to start RunAsync,
// which fires the bot's InitNetwork and lets the reactive cascade settle).
await bot.RunAsync(CancellationToken.None);
// After the bot's cascade, the bot has emitted InitNetwork→InitBattle→Loaded→Swap
// and is parked awaiting the player's Swap (barrier holds its Ready).
Assert.That(((IHasHandshakePhase)bot).Phase, Is.EqualTo(BattleSessionPhase.AfterReady),
"Bot should have driven its own handshake to AfterReady.");
Assert.That(player.Received, Does.Not.Contain(NetworkBattleUri.Ready),
"Player hasn't swapped yet → barrier must withhold the bot-triggered Ready from the player too.");
// Now drive the player's handshake through Swap; the player's Swap should release
// Ready to BOTH sides.
session.ComputeFrames(player, Env(NetworkBattleUri.InitNetwork));
session.ComputeFrames(player, Env(NetworkBattleUri.InitBattle));
var loadedRoutes = session.ComputeFrames(player, Env(NetworkBattleUri.Loaded));
var bs = (BattleStartBody)loadedRoutes[0].Frame.Body;
Assert.That(bs.TurnState, Is.EqualTo(0), "Player (A) goes first.");
var swapRoutes = session.ComputeFrames(player, Env(NetworkBattleUri.Swap));
Assert.That(swapRoutes.Any(r => ReferenceEquals(r.Target, player) && r.Frame.Uri == NetworkBattleUri.Ready),
Is.True, "Player's Swap (the second) releases Ready to the player.");
Assert.That(swapRoutes.Any(r => ReferenceEquals(r.Target, bot) && r.Frame.Uri == NetworkBattleUri.Ready),
Is.True, "...and to the bot.");
}
private sealed class RecordingPlayer : IBattleParticipant, IHasHandshakePhase
{
public long ViewerId { get; }
public MatchContext Context { get; }
public BattleSessionPhase Phase { get; set; } = BattleSessionPhase.AwaitingInitNetwork;
public List<NetworkBattleUri> Received { get; } = new();
public event Func<MsgEnvelope, CancellationToken, Task>? FrameEmitted;
public RecordingPlayer(long viewerId, MatchContext ctx) { ViewerId = viewerId; Context = ctx; }
public Task PushAsync(MsgEnvelope env, bool noStock, CancellationToken ct)
{ Received.Add(env.Uri); return Task.CompletedTask; }
public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
private void Touch() => FrameEmitted?.Invoke(null!, default);
}
private static MatchContext PlayerCtx() => new(
SelfDeckCardIds: Enumerable.Range(1, 30).Select(_ => 100_011_010L).ToList(),
ClassId: "1", CharaId: "1", CardMasterName: "card_master_node_10015",
CountryCode: "KOR", UserName: "Player", SleeveId: "3000011",
EmblemId: "701441011", DegreeId: "300003", FieldId: 43, IsOfficial: 0, BattleType: 11);
private static MsgEnvelope Env(NetworkBattleUri uri) =>
new(uri, ViewerId: 1, Uuid: "u", Bid: null, Try: 0, Cat: EmitCategory.Battle,
PubSeq: null, PlaySeq: null, Body: new RawBody(new Dictionary<string, object?>()));
}