refactor(battlenode): close §A boolean-blindness items (MinedToken, Stock, KeyActionType)
Behavior-preserving; 231 BattleNode tests green.
- MinedToken record struct replaces the transpose-prone (int Idx, long CardId,
CardOwner IsSelf) tuple returned by KnownListBuilder.Mine*. Positional deconstruct
keeps the Record*From call sites unchanged.
- enum Stock { Normal, Bypass } replaces the negative `bool noStock` on
IBattleParticipant.PushAsync and DispatchRoute, threaded through both participants,
BattleSession, and all handler construction sites.
- enum KeyActionType mirrors the client's SendKeyActionDataManager.KeyActionType;
the StripKeyActionForOpponent guard compares named values, KeyActionEntry.Type is
the enum (wire-identical via JsonNumberEnumConverter).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -414,7 +414,7 @@ public class CaptureConformanceTests
|
||||
.MineCopyTokens(orderList, new Dictionary<int, long>(), otherMap)
|
||||
.ToList();
|
||||
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (49, 123_456_789L, CardOwner.Opponent) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new SVSim.BattleNode.Sessions.Dispatch.MinedToken(49, 123_456_789L, CardOwner.Opponent) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -116,7 +116,7 @@ public class BattleSessionDispatchConcurrencyTests
|
||||
public Task RaiseAsync(MsgEnvelope env) =>
|
||||
FrameEmitted?.Invoke(env, CancellationToken.None) ?? Task.CompletedTask;
|
||||
|
||||
public Task PushAsync(MsgEnvelope env, bool noStock, CancellationToken ct) => _detector.EnterAsync();
|
||||
public Task PushAsync(MsgEnvelope env, Stock stock, CancellationToken ct) => _detector.EnterAsync();
|
||||
public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
|
||||
public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
@@ -653,7 +653,7 @@ public class BattleSessionDispatchTests
|
||||
Assert.That(pb.KnownList!.Single().CardId, Is.EqualTo(100_011_010L), "generating deck card revealed");
|
||||
// keyAction forwarded as {type,cardId}; selectCard stripped for the hidden choice.
|
||||
Assert.That(pb.KeyAction, Is.Not.Null);
|
||||
Assert.That(pb.KeyAction!.Single().Type, Is.EqualTo(1));
|
||||
Assert.That(pb.KeyAction!.Single().Type, Is.EqualTo(KeyActionType.Choice));
|
||||
Assert.That(pb.KeyAction.Single().CardId, Is.EqualTo(100_011_010L));
|
||||
Assert.That(pb.KeyAction.Single().SelectCard, Is.Null, "the pick stays hidden for open:0");
|
||||
}
|
||||
@@ -864,8 +864,8 @@ public class BattleSessionDispatchTests
|
||||
Assert.That(((BattleFinishBody)aRoute.Frame.Body).Result, Is.EqualTo(BattleResult.RetireLose));
|
||||
Assert.That(bRoute.Frame.Uri, Is.EqualTo(NetworkBattleUri.BattleFinish));
|
||||
Assert.That(((BattleFinishBody)bRoute.Frame.Body).Result, Is.EqualTo(BattleResult.RetireWin));
|
||||
Assert.That(aRoute.NoStock, Is.True);
|
||||
Assert.That(bRoute.NoStock, Is.True);
|
||||
Assert.That(aRoute.Stock, Is.EqualTo(Stock.Bypass));
|
||||
Assert.That(bRoute.Stock, Is.EqualTo(Stock.Bypass));
|
||||
Assert.That(s.Phase, Is.EqualTo(BattleSessionPhase.Terminal));
|
||||
}
|
||||
|
||||
@@ -1099,7 +1099,7 @@ public class BattleSessionDispatchTests
|
||||
public MatchContext Context { get; }
|
||||
public event Func<MsgEnvelope, CancellationToken, Task>? FrameEmitted;
|
||||
public FakeParticipant(long viewerId, MatchContext context) { ViewerId = viewerId; Context = context; }
|
||||
public Task PushAsync(MsgEnvelope env, bool noStock, CancellationToken ct) => Task.CompletedTask;
|
||||
public Task PushAsync(MsgEnvelope env, Stock stock, CancellationToken ct) => Task.CompletedTask;
|
||||
public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
|
||||
public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
@@ -1117,7 +1117,7 @@ public class BattleSessionDispatchTests
|
||||
public BattleSessionPhase Phase { get; set; } = BattleSessionPhase.AwaitingInitNetwork;
|
||||
public event Func<MsgEnvelope, CancellationToken, Task>? FrameEmitted;
|
||||
public FakeRealParticipant(long viewerId, MatchContext context) { ViewerId = viewerId; Context = context; }
|
||||
public Task PushAsync(MsgEnvelope env, bool noStock, CancellationToken ct) => Task.CompletedTask;
|
||||
public Task PushAsync(MsgEnvelope env, Stock stock, CancellationToken ct) => Task.CompletedTask;
|
||||
public Task RunAsync(CancellationToken ct) => Task.CompletedTask;
|
||||
public Task TerminateAsync(BattleFinishReason reason) => Task.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
@@ -14,7 +14,7 @@ public class BattleSessionStateTests
|
||||
public MatchContext Context { get; }
|
||||
public event Func<SVSim.BattleNode.Protocol.MsgEnvelope, CancellationToken, Task>? FrameEmitted;
|
||||
public StubParticipant(long id, MatchContext ctx) { ViewerId = id; Context = ctx; }
|
||||
public Task PushAsync(SVSim.BattleNode.Protocol.MsgEnvelope e, bool n, CancellationToken c) => Task.CompletedTask;
|
||||
public Task PushAsync(SVSim.BattleNode.Protocol.MsgEnvelope e, Stock n, CancellationToken c) => Task.CompletedTask;
|
||||
public Task RunAsync(CancellationToken c) => Task.CompletedTask;
|
||||
public Task TerminateAsync(BattleFinishReason r) => Task.CompletedTask;
|
||||
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
|
||||
|
||||
@@ -131,7 +131,7 @@ public class KnownListBuilderTests
|
||||
var orderList = new List<object?> { AddOp(new[] { 31L, 32L }, 900111010L) };
|
||||
var mined = KnownListBuilder.MineAddOps(orderList).ToList();
|
||||
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (31, 900111010L, CardOwner.Self), (32, 900111010L, CardOwner.Self) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new MinedToken(31, 900111010L, CardOwner.Self), new MinedToken(32, 900111010L, CardOwner.Self) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -142,7 +142,7 @@ public class KnownListBuilderTests
|
||||
// it; the caller routes it into the OTHER side's map.
|
||||
var orderList = new List<object?> { AddOp(new[] { 31L }, 900111010L, isSelf: 0) };
|
||||
Assert.That(KnownListBuilder.MineAddOps(orderList),
|
||||
Is.EquivalentTo(new[] { (31, 900111010L, CardOwner.Opponent) }));
|
||||
Is.EquivalentTo(new[] { new MinedToken(31, 900111010L, CardOwner.Opponent) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -205,7 +205,7 @@ public class KnownListBuilderTests
|
||||
AddOp(new[] { 32L }, 900811090L),
|
||||
};
|
||||
var mined = KnownListBuilder.MineAddOps(orderList).ToList();
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (31, 900111010L, CardOwner.Self), (32, 900811090L, CardOwner.Self) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new MinedToken(31, 900111010L, CardOwner.Self), new MinedToken(32, 900811090L, CardOwner.Self) }));
|
||||
}
|
||||
|
||||
// A choice/Discover add op as it arrives in a RawBody: candidates-only (no concrete cardId —
|
||||
@@ -248,7 +248,7 @@ public class KnownListBuilderTests
|
||||
var keyAction = KeyActionChoice(generatingCardId: 810014030L, chosen: new[] { 810041260L }, open: 0);
|
||||
|
||||
Assert.That(KnownListBuilder.MineChoicePicks(orderList, keyAction),
|
||||
Is.EquivalentTo(new[] { (46, 810041260L, CardOwner.Self) }));
|
||||
Is.EquivalentTo(new[] { new MinedToken(46, 810041260L, CardOwner.Self) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -260,7 +260,7 @@ public class KnownListBuilderTests
|
||||
var keyAction = KeyActionChoice(810014030L, new[] { 101041020L }, open: 0);
|
||||
|
||||
Assert.That(KnownListBuilder.MineChoicePicks(orderList, keyAction),
|
||||
Is.EquivalentTo(new[] { (46, 101041020L, CardOwner.Opponent) }));
|
||||
Is.EquivalentTo(new[] { new MinedToken(46, 101041020L, CardOwner.Opponent) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -303,7 +303,7 @@ public class KnownListBuilderTests
|
||||
|
||||
Assert.That(stripped, Is.Not.Null);
|
||||
Assert.That(stripped!.Count, Is.EqualTo(1));
|
||||
Assert.That(stripped[0].Type, Is.EqualTo(1));
|
||||
Assert.That(stripped[0].Type, Is.EqualTo(KeyActionType.Choice));
|
||||
Assert.That(stripped[0].CardId, Is.EqualTo(810014030L));
|
||||
Assert.That(stripped[0].SelectCard, Is.Null);
|
||||
}
|
||||
@@ -357,7 +357,7 @@ public class KnownListBuilderTests
|
||||
var selfMap = new Dictionary<int, long> { [5] = 100_011_010L };
|
||||
var otherMap = new Dictionary<int, long>();
|
||||
var mined = KnownListBuilder.MineCopyTokens(orderList, selfMap, otherMap).ToList();
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (31, 100_011_010L, CardOwner.Self) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new MinedToken(31, 100_011_010L, CardOwner.Self) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -369,7 +369,7 @@ public class KnownListBuilderTests
|
||||
var selfMap = new Dictionary<int, long>();
|
||||
var otherMap = new Dictionary<int, long> { [21] = 900_841_330L };
|
||||
var mined = KnownListBuilder.MineCopyTokens(orderList, selfMap, otherMap).ToList();
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (49, 900_841_330L, CardOwner.Opponent) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new MinedToken(49, 900_841_330L, CardOwner.Opponent) }));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -422,7 +422,7 @@ public class KnownListBuilderTests
|
||||
var orderList = new List<object?> { CopyOp(new[] { 31L, 32L }, baseIdx: 5L, isSelf: 1) };
|
||||
var selfMap = new Dictionary<int, long> { [5] = 700L };
|
||||
var mined = KnownListBuilder.MineCopyTokens(orderList, selfMap, new Dictionary<int, long>()).ToList();
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { (31, 700L, CardOwner.Self), (32, 700L, CardOwner.Self) }));
|
||||
Assert.That(mined, Is.EquivalentTo(new[] { new MinedToken(31, 700L, CardOwner.Self), new MinedToken(32, 700L, CardOwner.Self) }));
|
||||
}
|
||||
|
||||
// A uList entry as it arrives in a RawBody. Minimal = the 5 always-present fields
|
||||
|
||||
@@ -22,7 +22,7 @@ public class NoOpBotParticipantTests
|
||||
Cat: EmitCategory.Battle, PubSeq: null, PlaySeq: null,
|
||||
Body: new ResultCodeOnlyBody());
|
||||
|
||||
Assert.DoesNotThrowAsync(() => p.PushAsync(env, noStock: false, CancellationToken.None));
|
||||
Assert.DoesNotThrowAsync(() => p.PushAsync(env, Stock.Normal, CancellationToken.None));
|
||||
Assert.That(fired, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ public class RealParticipantTests
|
||||
// First ordered push gets playSeq = 1; second = 2; etc.
|
||||
// Inspect the participant's outbound sequencer state via its public Archive.
|
||||
var env = NewEnvelope(NetworkBattleUri.Matched);
|
||||
p.PushAsync(env, noStock: false, CancellationToken.None).Wait();
|
||||
p.PushAsync(env, noStock: false, CancellationToken.None).Wait();
|
||||
p.PushAsync(env, Stock.Normal, CancellationToken.None).Wait();
|
||||
p.PushAsync(env, Stock.Normal, CancellationToken.None).Wait();
|
||||
|
||||
Assert.That(p.Outbound.Archive.Count, Is.EqualTo(2));
|
||||
Assert.That(p.Outbound.Archive[1].PlaySeq, Is.EqualTo(1));
|
||||
@@ -37,7 +37,7 @@ public class RealParticipantTests
|
||||
var p = new RealParticipant(ws, viewerId: 1, FixtureCtx(),
|
||||
NullLogger<RealParticipant>.Instance);
|
||||
|
||||
p.PushAsync(NewEnvelope(NetworkBattleUri.BattleFinish), noStock: true, CancellationToken.None).Wait();
|
||||
p.PushAsync(NewEnvelope(NetworkBattleUri.BattleFinish), Stock.Bypass, CancellationToken.None).Wait();
|
||||
|
||||
// No playSeq archive entry for no-stock pushes.
|
||||
Assert.That(p.Outbound.Archive.Count, Is.EqualTo(0));
|
||||
|
||||
Reference in New Issue
Block a user