fix(battle-node): emit envelope keys before body keys in MsgEnvelope.ToJson
Client RealTimeNetworkAgent.SetNetworkInfo iterates the synchronize-data dict in insertion order. The "uri" key, when recognized as Matched, calls GameMgr.InitializeSelfInfo which sets _selfDeck = null. Any "selfDeck" processed before "uri" gets wiped; Matching.StartBattleLoad then crashes on null.Select(...). Pre-refactor ToJson built a Dictionary envelope-first then appended body keys, so the bug never surfaced. The typed-body rewrite inverted the order — restoring envelope-first matches the prod wire. Regression test BuildMatched_KeyOrder_PutsUriBeforeSelfDeckAndSelfInfo locks the contract. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,31 @@ namespace SVSim.UnitTests.BattleNode.Lifecycle;
|
||||
[TestFixture]
|
||||
public class TypedBodyWireShapeTests
|
||||
{
|
||||
[Test]
|
||||
public void BuildMatched_KeyOrder_PutsUriBeforeSelfDeckAndSelfInfo()
|
||||
{
|
||||
// Regression: the client's RealTimeNetworkAgent.SetNetworkInfo iterates the
|
||||
// synchronize-data dict in insertion order. When it hits "uri" and recognizes
|
||||
// "Matched", it calls GameMgr.InitializeSelfInfo() which sets _selfDeck = null.
|
||||
// Any "selfDeck" / "selfInfo" key processed BEFORE "uri" is wiped before
|
||||
// Matching.StartBattleLoad reads it back, and GetSelfDeck().Select(...) crashes
|
||||
// with "Value cannot be null. Parameter name: source". The prod wire format
|
||||
// emits envelope keys (uri first) before body keys; we must too.
|
||||
var env = ScriptedLifecycle.BuildMatched(
|
||||
playerViewerId: 1, opponentViewerId: 2, battleId: "b");
|
||||
var json = MsgEnvelope.ToJson(env);
|
||||
|
||||
var uriIdx = json.IndexOf("\"uri\":", StringComparison.Ordinal);
|
||||
var selfDeckIdx = json.IndexOf("\"selfDeck\":", StringComparison.Ordinal);
|
||||
var selfInfoIdx = json.IndexOf("\"selfInfo\":", StringComparison.Ordinal);
|
||||
|
||||
Assert.That(uriIdx, Is.GreaterThan(-1), "uri must be present");
|
||||
Assert.That(selfDeckIdx, Is.GreaterThan(-1), "selfDeck must be present");
|
||||
Assert.That(selfInfoIdx, Is.GreaterThan(-1), "selfInfo must be present");
|
||||
Assert.That(uriIdx, Is.LessThan(selfDeckIdx), "uri must appear BEFORE selfDeck");
|
||||
Assert.That(uriIdx, Is.LessThan(selfInfoIdx), "uri must appear BEFORE selfInfo");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMatched_SerializesAllWireKeysExpectedByTheClient()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user