File size: 3,416 Bytes
4be6a52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from fastapi.testclient import TestClient

from stackcraft.server import create_app


def test_game_action_replay_round_trip():
    with TestClient(create_app()) as client:
        first = client.post("/api/games", json={"seed": 42}).json()
        other = client.post("/api/games", json={"seed": 42}).json()
        assert first["board"] == other["board"]
        assert first["current"] == other["current"]
        assert "seed" not in first
        game_id = first["id"]
        result = client.post(
            f"/api/games/{game_id}/moves",
            json={"action_id": first["legal_actions"][0]["id"], "expected_pieces": 0},
        )
        assert result.status_code == 200
        assert result.json()["pieces"] == 1
        assert client.get(f"/api/games/{other['id']}").json()["pieces"] == 0
        replay = client.get(f"/api/games/{game_id}/replay").json()
        restored = client.post("/api/replays", json=replay)
        assert restored.status_code == 200
        frames = restored.json()["frames"]
        assert len(frames) == 2
        assert frames[-1] == {k: v for k, v in result.json().items() if k != "id"}


def test_invalid_move_preserves_game_and_unknown_sessions_fail():
    with TestClient(create_app()) as client:
        original = client.post("/api/games", json={"seed": 7}).json()
        path = f"/api/games/{original['id']}"
        assert (
            client.post(
                path + "/moves", json={"action_id": "r9x99", "expected_pieces": 0}
            ).status_code
            == 422
        )
        assert client.get(path).json() == original
        assert client.get("/api/games/missing").status_code == 404


def test_retry_after_lost_response_cannot_place_another_piece():
    with TestClient(create_app()) as client:
        state = client.post("/api/games", json={"seed": 42}).json()
        path = f"/api/games/{state['id']}"
        request = {"action_id": "r0x3", "expected_pieces": 0}
        accepted = client.post(path + "/moves", json=request)
        assert accepted.status_code == 200
        retry = client.post(path + "/moves", json=request)
        assert retry.status_code == 409
        assert client.get(path).json() == accepted.json()


def test_input_validation_and_health():
    with TestClient(create_app()) as client:
        assert client.get("/health").json() == {"status": "ok"}
        for seed in [-1, True, "42", 2**53]:
            assert client.post("/api/games", json={"seed": seed}).status_code == 422
        assert client.post("/api/replays", json={"actions": "not a list"}).status_code == 422
        assert client.post("/api/replays", json={"actions": ["r0x0"] * 2001}).status_code == 422


def test_packaged_race_replays_validate_against_current_engine():
    with TestClient(create_app()) as client:
        response = client.get("/static/baseline-demo.json")
        assert response.status_code == 200
        race = response.json()
        assert [player["id"] for player in race["players"]] == ["base", "trained", "heuristic"]
        for player in race["players"]:
            assert player["replay"]["seed"] == race["seed"]
            replay = client.post("/api/replays", json=player["replay"])
            assert replay.status_code == 200
            final = replay.json()["frames"][-1]
            assert final["pieces"] <= race["max_pieces"]
            assert final["score"] == player["replay"]["final"]["score"]