feat(client): add E2E connection test and batch encoding tests
D-030 Layer 3: E2E test spawns the Rust server binary, connects via LocalBridge, sends a batched MoveNorth input, and verifies the player moved to (16.5, 15.5). Also adds batch encoding roundtrip tests, framed batch test, and Player entity fixture decode test. 43/43 pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,33 +42,58 @@ func test_decode_snapshot_empty() -> void:
|
||||
assert_that(snapshot.entities.size()).is_equal(0)
|
||||
|
||||
|
||||
func test_decode_snapshot_player() -> void:
|
||||
var bytes = _load_fixture("snapshot_player")
|
||||
var snapshot = Protocol.decode_snapshot(bytes)
|
||||
|
||||
assert_that(snapshot).is_not_null()
|
||||
assert_that(snapshot.tick).is_equal(1)
|
||||
assert_that(snapshot.entities.size()).is_equal(1)
|
||||
|
||||
var player = snapshot.entities[0]
|
||||
assert_that(player.entity_id).is_equal(100)
|
||||
assert_float(player.x).is_equal_approx(16.5, 0.001)
|
||||
assert_float(player.y).is_equal_approx(16.5, 0.001)
|
||||
assert_that(player.z).is_equal(0)
|
||||
assert_that(player.kind.variant).is_equal("Player")
|
||||
assert_that(player.kind.data).is_null()
|
||||
|
||||
|
||||
func test_decode_snapshot_multi_entity() -> void:
|
||||
var bytes = _load_fixture("snapshot_multi_entity")
|
||||
var snapshot = Protocol.decode_snapshot(bytes)
|
||||
|
||||
assert_that(snapshot).is_not_null()
|
||||
assert_that(snapshot.tick).is_equal(999)
|
||||
assert_that(snapshot.entities.size()).is_equal(3)
|
||||
assert_that(snapshot.entities.size()).is_equal(4)
|
||||
|
||||
# Player at (16.5, 16.5, 0)
|
||||
var player = snapshot.entities[0]
|
||||
assert_that(player.entity_id).is_equal(1)
|
||||
assert_float(player.x).is_equal_approx(16.5, 0.001)
|
||||
assert_float(player.y).is_equal_approx(16.5, 0.001)
|
||||
assert_that(player.z).is_equal(0)
|
||||
assert_that(player.kind.variant).is_equal("Player")
|
||||
|
||||
# NPC at (5, 10, 0)
|
||||
var npc = snapshot.entities[0]
|
||||
assert_that(npc.entity_id).is_equal(1)
|
||||
var npc = snapshot.entities[1]
|
||||
assert_that(npc.entity_id).is_equal(2)
|
||||
assert_float(npc.x).is_equal_approx(5.0, 0.001)
|
||||
assert_float(npc.y).is_equal_approx(10.0, 0.001)
|
||||
assert_that(npc.z).is_equal(0)
|
||||
assert_that(npc.kind.variant).is_equal("Npc")
|
||||
|
||||
# Object at (15.5, 3, 1)
|
||||
var obj = snapshot.entities[1]
|
||||
assert_that(obj.entity_id).is_equal(2)
|
||||
var obj = snapshot.entities[2]
|
||||
assert_that(obj.entity_id).is_equal(3)
|
||||
assert_float(obj.x).is_equal_approx(15.5, 0.001)
|
||||
assert_float(obj.y).is_equal_approx(3.0, 0.001)
|
||||
assert_that(obj.z).is_equal(1)
|
||||
assert_that(obj.kind.variant).is_equal("Object")
|
||||
|
||||
# Terrain at (0, 0, -1)
|
||||
var terrain = snapshot.entities[2]
|
||||
assert_that(terrain.entity_id).is_equal(3)
|
||||
var terrain = snapshot.entities[3]
|
||||
assert_that(terrain.entity_id).is_equal(4)
|
||||
assert_float(terrain.x).is_equal_approx(0.0, 0.001)
|
||||
assert_float(terrain.y).is_equal_approx(0.0, 0.001)
|
||||
assert_that(terrain.z).is_equal(-1)
|
||||
@@ -169,6 +194,63 @@ func test_encode_produces_nonempty_bytes() -> void:
|
||||
assert_that(bytes.size()).is_greater(0)
|
||||
|
||||
|
||||
# -- Batch input encoding (Vec<PlayerInput> wire format) -----------------------
|
||||
|
||||
func test_encode_player_inputs_single() -> void:
|
||||
var inputs: Array = [{"tick": 10, "action_name": "MoveNorth"}]
|
||||
var bytes := Protocol.encode_player_inputs(inputs)
|
||||
assert_that(bytes.size()).is_greater(0)
|
||||
|
||||
# Decode as raw msgpack — should be an array with one element
|
||||
var raw: Variant = Messagepack.decode(bytes)
|
||||
assert_that(raw.status).is_null()
|
||||
assert_that(raw.value is Array).is_true()
|
||||
assert_that(raw.value.size()).is_equal(1)
|
||||
assert_that(raw.value[0]["tick"]).is_equal(10)
|
||||
assert_that(raw.value[0]["action"]).is_equal("MoveNorth")
|
||||
|
||||
|
||||
func test_encode_player_inputs_multiple() -> void:
|
||||
var inputs: Array = [
|
||||
{"tick": 1, "action_name": "MoveNorth"},
|
||||
{"tick": 1, "action_name": "Interact"},
|
||||
{"tick": 2, "action_name": "MoveSouthwest"},
|
||||
]
|
||||
var bytes := Protocol.encode_player_inputs(inputs)
|
||||
assert_that(bytes.size()).is_greater(0)
|
||||
|
||||
var raw: Variant = Messagepack.decode(bytes)
|
||||
assert_that(raw.status).is_null()
|
||||
assert_that(raw.value.size()).is_equal(3)
|
||||
assert_that(raw.value[0]["action"]).is_equal("MoveNorth")
|
||||
assert_that(raw.value[1]["action"]).is_equal("Interact")
|
||||
assert_that(raw.value[2]["action"]).is_equal("MoveSouthwest")
|
||||
|
||||
|
||||
func test_encode_player_inputs_with_data_variant() -> void:
|
||||
var inputs: Array = [
|
||||
{"tick": 5, "action_name": "UsePerceptionMode", "action_data": "thermal"},
|
||||
]
|
||||
var bytes := Protocol.encode_player_inputs(inputs)
|
||||
assert_that(bytes.size()).is_greater(0)
|
||||
|
||||
var raw: Variant = Messagepack.decode(bytes)
|
||||
assert_that(raw.status).is_null()
|
||||
assert_that(raw.value[0]["action"] is Dictionary).is_true()
|
||||
assert_that(raw.value[0]["action"]["UsePerceptionMode"]).is_equal("thermal")
|
||||
|
||||
|
||||
func test_encode_player_inputs_empty() -> void:
|
||||
var inputs: Array = []
|
||||
var bytes := Protocol.encode_player_inputs(inputs)
|
||||
assert_that(bytes.size()).is_greater(0)
|
||||
|
||||
var raw: Variant = Messagepack.decode(bytes)
|
||||
assert_that(raw.status).is_null()
|
||||
assert_that(raw.value is Array).is_true()
|
||||
assert_that(raw.value.size()).is_equal(0)
|
||||
|
||||
|
||||
# -- Diagonal movement fixtures (D-030 Layer 1 cross-language) -----------------
|
||||
|
||||
func test_decode_diagonal_fixtures() -> void:
|
||||
|
||||
Reference in New Issue
Block a user