test(battle-node): PvP handshake dispatch sees cross-perspective contexts
Tests assert that for Type=Pvp, A's InitBattle gets Matched with A's ctx as selfInfo and B's ctx as oppoInfo, and symmetrically for B. Same for Loaded/BattleStart. Swap stays per-sender (each runs their own mulligan).
This commit is contained in:
@@ -189,6 +189,99 @@ public class BattleSessionDispatchTests
|
||||
Assert.That(a.Phase, Is.EqualTo(BattleSessionPhase.AwaitingInitNetwork));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_InitBattle_from_A_pushes_Matched_with_B_oppoInfo_to_A_only()
|
||||
{
|
||||
var (s, a, b) = NewPvpSession();
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
var routes = s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
|
||||
Assert.That(routes.Count, Is.EqualTo(1));
|
||||
Assert.That(routes[0].Target, Is.SameAs(a));
|
||||
Assert.That(routes[0].Frame.Uri, Is.EqualTo(NetworkBattleUri.Matched));
|
||||
|
||||
var body = (MatchedBody)routes[0].Frame.Body;
|
||||
Assert.That(body.SelfInfo.UserName, Is.EqualTo("PlayerA"),
|
||||
"Matched.selfInfo must reflect the sender (A).");
|
||||
Assert.That(body.SelfInfo.OppoId, Is.EqualTo(b.ViewerId));
|
||||
Assert.That(body.OppoInfo.UserName, Is.EqualTo("PlayerB"),
|
||||
"Matched.oppoInfo must reflect the OTHER participant (B).");
|
||||
Assert.That(body.OppoInfo.OppoId, Is.EqualTo(a.ViewerId));
|
||||
Assert.That(body.SelfInfo.Seed, Is.EqualTo(body.OppoInfo.Seed),
|
||||
"Both sides must see the same seed.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_InitBattle_from_B_pushes_Matched_with_A_oppoInfo_to_B_only()
|
||||
{
|
||||
var (s, a, b) = NewPvpSession();
|
||||
s.ComputeFrames(b, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
var routes = s.ComputeFrames(b, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
|
||||
Assert.That(routes.Count, Is.EqualTo(1));
|
||||
Assert.That(routes[0].Target, Is.SameAs(b));
|
||||
var body = (MatchedBody)routes[0].Frame.Body;
|
||||
Assert.That(body.SelfInfo.UserName, Is.EqualTo("PlayerB"));
|
||||
Assert.That(body.OppoInfo.UserName, Is.EqualTo("PlayerA"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_Loaded_from_A_pushes_BattleStart_with_B_oppoInfo_plus_Deal_to_A()
|
||||
{
|
||||
var (s, a, b) = NewPvpSession();
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
var routes = s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.Loaded));
|
||||
|
||||
Assert.That(routes.Count, Is.EqualTo(2));
|
||||
Assert.That(routes[0].Frame.Uri, Is.EqualTo(NetworkBattleUri.BattleStart));
|
||||
Assert.That(routes[1].Frame.Uri, Is.EqualTo(NetworkBattleUri.Deal));
|
||||
Assert.That(routes.All(r => ReferenceEquals(r.Target, a)), Is.True);
|
||||
|
||||
var bs = (BattleStartBody)routes[0].Frame.Body;
|
||||
Assert.That(bs.SelfInfo.ClassId, Is.EqualTo("3"), "A is class 3 per fixture.");
|
||||
Assert.That(bs.OppoInfo.ClassId, Is.EqualTo("5"), "B is class 5 per fixture.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_Swap_from_A_pushes_SwapResponse_plus_Ready_to_A_only()
|
||||
{
|
||||
var (s, a, b) = NewPvpSession();
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.Loaded));
|
||||
var routes = s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.Swap));
|
||||
|
||||
Assert.That(routes.Select(r => r.Frame.Uri),
|
||||
Is.EqualTo(new[] { NetworkBattleUri.Swap, NetworkBattleUri.Ready }));
|
||||
Assert.That(routes.All(r => ReferenceEquals(r.Target, a)), Is.True);
|
||||
Assert.That(a.Phase, Is.EqualTo(BattleSessionPhase.AfterReady));
|
||||
Assert.That(b.Phase, Is.EqualTo(BattleSessionPhase.AwaitingInitNetwork),
|
||||
"Swap from A doesn't advance B's phase.");
|
||||
}
|
||||
|
||||
private static (BattleSession, FakeRealParticipant, FakeRealParticipant) NewPvpSession()
|
||||
{
|
||||
var a = new FakeRealParticipant(viewerId: 1001, PlayerACtx());
|
||||
var b = new FakeRealParticipant(viewerId: 2002, PlayerBCtx());
|
||||
var s = new BattleSession("bid-pvp-1", BattleType.Pvp, a, b, NullLogger<BattleSession>.Instance);
|
||||
return (s, a, b);
|
||||
}
|
||||
|
||||
private static MatchContext PlayerACtx() => new(
|
||||
SelfDeckCardIds: Enumerable.Range(1, 30).Select(_ => 100_011_010L).ToList(),
|
||||
ClassId: "3", CharaId: "3", CardMasterName: "card_master_node_10015",
|
||||
CountryCode: "KOR", UserName: "PlayerA", SleeveId: "3000011",
|
||||
EmblemId: "701441011", DegreeId: "300003", FieldId: 43, IsOfficial: 0,
|
||||
BattleType: 11);
|
||||
|
||||
private static MatchContext PlayerBCtx() => new(
|
||||
SelfDeckCardIds: Enumerable.Range(1, 30).Select(_ => 200_011_010L).ToList(),
|
||||
ClassId: "5", CharaId: "5", CardMasterName: "card_master_node_10015",
|
||||
CountryCode: "JPN", UserName: "PlayerB", SleeveId: "3000022",
|
||||
EmblemId: "701441022", DegreeId: "300004", FieldId: 44, IsOfficial: 0,
|
||||
BattleType: 11);
|
||||
|
||||
private static (BattleSession, FakeRealParticipant, FakeParticipant) NewSession()
|
||||
{
|
||||
var a = new FakeRealParticipant(viewerId: 1, FixtureCtx());
|
||||
|
||||
Reference in New Issue
Block a user