87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
import asyncio
|
|
|
|
from engine.network.client import GameClient
|
|
from engine.network.protocol import DEFAULT_PORT, decode_message, encode_message
|
|
from engine.network.server import GameServer
|
|
|
|
|
|
def run(coro):
|
|
return asyncio.run(asyncio.wait_for(coro, timeout=5))
|
|
|
|
|
|
def test_default_port_is_42069():
|
|
assert DEFAULT_PORT == 42069
|
|
|
|
|
|
def test_encode_decode_round_trip():
|
|
message = {"type": "move", "entity_id": "p1", "x": 3, "y": 4}
|
|
decoded = decode_message(encode_message(message).rstrip(b"\n"))
|
|
assert decoded == message
|
|
|
|
|
|
def test_two_clients_see_each_others_join_and_move():
|
|
async def scenario():
|
|
server = GameServer(host="127.0.0.1", port=0)
|
|
await server.start()
|
|
try:
|
|
alice = GameClient("alice", "Alice", host="127.0.0.1", port=server.port)
|
|
bob = GameClient("bob", "Bob", host="127.0.0.1", port=server.port)
|
|
|
|
await alice.connect()
|
|
await bob.connect() # bob's hello -> alice should see a "join" for bob
|
|
join_event = await alice.receive()
|
|
assert join_event == {"type": "join", "entity_id": "bob", "name": "Bob"}
|
|
|
|
await bob.send_move("demo_world", 5, 5, 0)
|
|
move_event = await alice.receive()
|
|
assert move_event == {"type": "move", "entity_id": "bob", "map_id": "demo_world", "x": 5, "y": 5, "z": 0}
|
|
|
|
await bob.close()
|
|
leave_event = await alice.receive()
|
|
assert leave_event == {"type": "leave", "entity_id": "bob"}
|
|
|
|
await alice.close()
|
|
finally:
|
|
await server.stop()
|
|
|
|
run(scenario())
|
|
|
|
|
|
def test_broadcast_excludes_the_sender():
|
|
async def scenario():
|
|
server = GameServer(host="127.0.0.1", port=0)
|
|
await server.start()
|
|
try:
|
|
alice = GameClient("alice", "Alice", host="127.0.0.1", port=server.port)
|
|
await alice.connect()
|
|
await alice.send_move("demo_world", 1, 1, 0)
|
|
# nothing else connected, so alice's own move should never be echoed back to her;
|
|
# confirm by racing a short timeout against receive()
|
|
try:
|
|
await asyncio.wait_for(alice.receive(), timeout=0.2)
|
|
assert False, "sender should not receive its own broadcast"
|
|
except asyncio.TimeoutError:
|
|
pass
|
|
await alice.close()
|
|
finally:
|
|
await server.stop()
|
|
|
|
run(scenario())
|
|
|
|
|
|
def test_server_reports_connected_clients():
|
|
async def scenario():
|
|
server = GameServer(host="127.0.0.1", port=0)
|
|
await server.start()
|
|
try:
|
|
assert server.clients == {}
|
|
alice = GameClient("alice", "Alice", host="127.0.0.1", port=server.port)
|
|
await alice.connect()
|
|
await asyncio.sleep(0.1) # let the server process the hello
|
|
assert "alice" in server.clients
|
|
await alice.close()
|
|
finally:
|
|
await server.stop()
|
|
|
|
run(scenario())
|