Cavoke  1.1.0
A Platform for creating and hosting multiplayer turn-based board games
Loading...
Searching...
No Matches
test_tictactoe.py
1import logging
2import threading
3import time
4import uuid
5from typing import List
6
7import cavoke_openapi_client
8import pytest
9from cavoke_openapi_client.api import default_api
10
11tictactoe_game_id = "tictactoe"
12
13
14def test_check_tictactoe_available():
15 """
16 Checks whether tictactoe game is available
17 """
18 with cavoke_openapi_client.ApiClient(pytest.server_config) as api_client:
19 api_instance = default_api.DefaultApi(api_client)
20 games: List[default_api.GameInfo] = api_instance.list_games()
21 assert any(e.id == tictactoe_game_id for e in
22 games), f"Expected {tictactoe_game_id} in games. All other f{tictactoe_game_id} tests will fail as well."
23
24
25def test_simple_game():
26 """
27 Creates a tictactoe session and plays a simple round with itself, checking the state after every move.
28 """
29 with cavoke_openapi_client.ApiClient(pytest.server_config) as api_client:
30 api_instance = default_api.DefaultApi(api_client)
31 alice_id = str(uuid.uuid4())
32 bob_id = str(uuid.uuid4())
33
34 session: default_api.SessionInfo = api_instance.create_session(tictactoe_game_id, user_id=alice_id)
35 assert session.game_id == tictactoe_game_id
36
37 time.sleep(0.2)
38
39 s2 = api_instance.join_session(session.session_id, user_id=bob_id)
40 assert s2.status == 0
41
42 api_instance.start_session(session.session_id, user_id=alice_id)
43
44 # Move
45 moves = [
46 (0, 'X 4'),
47 (1, 'O 2'),
48 (0, 'X 8'),
49 (1, 'O 0'),
50 (0, 'X 1'),
51 (1, 'O 7'),
52 (0, 'X 3'),
53 (1, 'O 5'),
54 (0, 'X 6'),
55 ]
56 for player_id, move in moves:
57 assert api_instance.session_info(session.session_id, user_id=bob_id).status == 1
58 api_instance.send_move(session.session_id, user_id=bob_id if player_id else alice_id,
59 game_move=default_api.GameMove(move))
60 time.sleep(0.1) # for synchronizing moves
61
62 final_session: default_api.SessionInfo = api_instance.session_info(session.session_id, user_id=bob_id)
63 final_state: default_api.GameState = api_instance.get_update(session.session_id, user_id=alice_id)
64 assert final_session.session_id == session.session_id
65 assert final_session.status == 2
66 assert final_state.state == 'OXOXXOXOX'
67
68
69@pytest.mark.parametrize('execution_number', range(10))
70def test_transaction_isolation_on_game_end(execution_number):
71 """
72 Test for correct transaction isolation. There was a bug, when transactions were not isolated properly,
73 therefore producing invalid a game state with broken invariant
74 """
75 with cavoke_openapi_client.ApiClient(pytest.server_config) as api_client:
76 api_instance = default_api.DefaultApi(api_client)
77 alice_id = str(uuid.uuid4())
78 bob_id = str(uuid.uuid4())
79
80 session: default_api.SessionInfo = api_instance.create_session(tictactoe_game_id, user_id=alice_id)
81 assert session.game_id == tictactoe_game_id
82
83 s2 = api_instance.join_session(session.session_id, user_id=bob_id)
84 assert s2.status == 0
85
86 api_instance.start_session(session.session_id, user_id=alice_id)
87
88 # Move
89 moves = [
90 (0, 'X 4'),
91 (1, 'O 2'),
92 (0, 'X 8'),
93 (1, 'O 0'),
94 (0, 'X 1'),
95 (1, 'O 7'),
96 (0, 'X 3'),
97 (1, 'O 5')
98 ]
99 for player_id, move in moves:
100 assert api_instance.session_info(session.session_id, user_id=bob_id).status == 1
101 api_instance.send_move(session.session_id, user_id=bob_id if player_id else alice_id,
102 game_move=default_api.GameMove(move))
103 time.sleep(0.1) # for synchronizing moves
104
105 do_spamming = True
106
107 def spam_x6_player_1():
108 logging.debug('Commencing spamming')
109 for i in range(50):
110 logging.debug(f'req {i}')
111 api_instance.send_move(session.session_id, user_id=bob_id, game_move=default_api.GameMove('X 6'), async_req=True)
112 time.sleep(0.1)
113 if not do_spamming:
114 break
115 logging.debug('Spamming stopped')
116
117 t_spam = threading.Thread(target=spam_x6_player_1)
118 t_spam.start()
119
120 time.sleep(1)
121
122 api_instance.send_move(session.session_id, user_id=alice_id, game_move=default_api.GameMove('X 6'), _request_timeout=10)
123
124 do_spamming = False
125 logging.debug('Spamming stopped. Checking final.')
126
127 final_session: default_api.SessionInfo = api_instance.session_info(session.session_id, user_id=alice_id)
128 final_state: default_api.GameState = api_instance.get_update(session.session_id, user_id=alice_id)
129 logging.debug(str(final_state))
130
131 time.sleep(1)
132
133 assert final_session.session_id == session.session_id
134 if not final_state.is_terminal:
135 logging.warning("Session is not finished! Skipping.")
136 else:
137 assert final_state.state == 'OXOXXOXOX'
138
139
140@pytest.mark.parametrize('execution_number', range(5))
141def test_requests_flood(execution_number):
142 """
143 Makes many requests to internal game (via boost process) and checks that the server is alive.
144 Previously there was a server segmentation fault caused here.
145 """
146 with cavoke_openapi_client.ApiClient(pytest.server_config) as api_client:
147 api_instance = default_api.DefaultApi(api_client)
148 alice_id = str(uuid.uuid4())
149
150 session: default_api.SessionInfo = api_instance.create_session(tictactoe_game_id, user_id=alice_id)
151 assert session.game_id == tictactoe_game_id
152 logging.debug('Starting spamming...')
153 for i in range(50):
154 logging.debug(f'req {i}')
155 api_instance.validate_session(session.session_id, user_id=alice_id, async_req=True)
156 logging.debug('Spamming stopped.')
157 assert api_instance.health(_request_timeout=10) == "OK"