From e7fde0192d172c1402912ff50797d47afb48d107 Mon Sep 17 00:00:00 2001 From: Nomads_Reach <144523850+NomadsReach@users.noreply.github.com> Date: Sat, 15 Aug 2026 23:38:18 -0400 Subject: [PATCH] Test Protocol V2 player state validation --- server/tests/test_player_state.py | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 server/tests/test_player_state.py diff --git a/server/tests/test_player_state.py b/server/tests/test_player_state.py new file mode 100644 index 0000000..c961a49 --- /dev/null +++ b/server/tests/test_player_state.py @@ -0,0 +1,80 @@ +from __future__ import annotations + +from player_state import normalize_player_state_packet +from server_core import _normalize_action_events + + +def valid_packet() -> dict: + return { + "type": "playerState", + "playerId": 9999, + "characterName": "Sole Survivor", + "equippedItems": [ + {"slot": "rightHand", "formId": "ff"}, + {"slot": "body", "formId": ""}, + ], + "appearance": { + "version": 4, + "raceFormId": "13746", + "height": 1.0, + "morphWeight": {"thin": 0.2, "muscular": 0.3, "large": 0.5}, + "bodyTintColor": {"r": 1, "g": 2, "b": 3, "a": 255}, + "hairColorFormId": "", + "facialHairColorFormId": "", + "complexionFormId": "", + "isFemale": False, + "headParts": ["1a2b"], + "morphs": [{"id": "10", "value": 0.5}], + "morphRegions": [0.25], + "facialBoneMorphs": [ + { + "id": "20", + "position": [0.0, 1.0, 2.0], + "rotation": [3.0, 4.0, 5.0], + "scale": [1.0, 1.0, 1.0], + } + ], + "tints": [{"id": 1, "type": 2, "value": 3, "color": "ff00ff00", "swatch": 4}], + }, + "actionEvents": [{"sequence": 7, "type": 3, "eventName": "fireSingle"}], + } + + +def test_player_state_normalizes_only_reliable_fields(): + clean = normalize_player_state_packet(valid_packet(), _normalize_action_events) + assert clean is not None + assert clean["type"] == "playerState" + assert "playerId" not in clean + assert clean["equippedItems"][0]["formId"] == "000000FF" + assert clean["appearance"]["raceFormId"] == "00013746" + assert clean["appearance"]["headParts"] == ["00001A2B"] + assert clean["appearance"]["tints"][0]["color"] == "FF00FF00" + assert clean["actionEvents"][0]["sequence"] == 7 + + +def test_empty_player_state_is_rejected(): + assert normalize_player_state_packet({"type": "playerState"}, _normalize_action_events) is None + + +def test_invalid_equipment_is_rejected(): + packet = valid_packet() + packet["equippedItems"][0]["formId"] = "not-a-form" + assert normalize_player_state_packet(packet, _normalize_action_events) is None + + +def test_invalid_appearance_numbers_are_rejected(): + packet = valid_packet() + packet["appearance"]["height"] = float("nan") + assert normalize_player_state_packet(packet, _normalize_action_events) is None + + +def test_invalid_action_event_is_rejected_instead_of_silently_dropped(): + packet = valid_packet() + packet["actionEvents"] = [{"sequence": 7, "type": 3, "eventName": "notAllowed"}] + assert normalize_player_state_packet(packet, _normalize_action_events) is None + + +def test_character_name_is_bounded(): + packet = valid_packet() + packet["characterName"] = "x" * 129 + assert normalize_player_state_packet(packet, _normalize_action_events) is None