Skip to content

Commit

Permalink
Add tests for draw bug
Browse files Browse the repository at this point in the history
  • Loading branch information
Askaholic committed Feb 28, 2021
1 parent 8d95f77 commit b6281a5
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 10 deletions.
82 changes: 72 additions & 10 deletions tests/integration_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import gc

import pytest
from sqlalchemy import select

from server.db.models import game_player_stats
from server.games.game_results import GameOutcome
from server.protocol import Protocol
from tests.utils import fast_forward

Expand Down Expand Up @@ -336,6 +339,74 @@ async def test_partial_game_ended_rates_game(lobby_server, tmp_user):
await read_until_command(host_proto, "player_info", timeout=10)


@fast_forward(15)
async def test_ladder_game_draw_bug(lobby_server, database):
"""
This simulates the infamous "draw bug" where a player could self destruct
their own ACU in order to kill the enemy ACU and be awarded a victory
instead of a draw.
"""
proto1, proto2 = await queue_players_for_matchmaking(lobby_server)

msg1, msg2 = await asyncio.gather(*[
client_response(proto) for proto in (proto1, proto2)
])
game_id = msg1["uid"]
army1 = msg1["map_position"]
army2 = msg2["map_position"]

for proto in (proto1, proto2):
await proto.send_message({
"target": "game",
"command": "GameState",
"args": ["Launching"]
})
await read_until(
proto1,
lambda cmd: cmd["command"] == "game_info" and cmd["launched_at"]
)

# Player 1 ctrl-k's
for result in (
[army1, "defeat -10"],
[army1, "score 1"],
[army2, "defeat -10"]
):
for proto in (proto1, proto2):
await proto1.send_message({
"target": "game",
"command": "GameResult",
"args": result
})

for proto in (proto1, proto2):
await proto.send_message({
"target": "game",
"command": "GameEnded",
"args": []
})

ratings = await get_player_ratings(
proto1, "ladder1", "ladder2",
rating_type="ladder_1v1"
)

# Both start at (1500, 500).
# When rated as a draw the means should barely change.
assert abs(ratings["ladder1"][0] - 1500.) < 1
assert abs(ratings["ladder2"][0] - 1500.) < 1

async with database.acquire() as conn:
result = await conn.execute(
select([game_player_stats]).where(
game_player_stats.c.gameId == game_id
)
)
async for row in result:
assert row.result == GameOutcome.DEFEAT
assert row.score == 0


@fast_forward(15)
async def test_ladder_game_not_joinable(lobby_server):
"""
Expand All @@ -348,16 +419,7 @@ async def test_ladder_game_not_joinable(lobby_server):
await read_until_command(test_proto, "game_info")

msg = await read_until_command(proto1, "game_launch")
await proto1.send_message({
"command": "GameState",
"target": "game",
"args": ["Idle"]
})
await proto1.send_message({
"command": "GameState",
"target": "game",
"args": ["Lobby"]
})
await open_fa(proto1)

game_uid = msg["uid"]

Expand Down
18 changes: 18 additions & 0 deletions tests/unit_tests/test_laddergame.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from server.db.models import leaderboard_rating
from server.games import GameState, LadderGame, ValidityState
from server.games.game_results import GameOutcome
from server.rating import RatingType
from tests.unit_tests.test_game import add_connected_players

Expand Down Expand Up @@ -71,6 +72,23 @@ async def test_is_winner_on_draw(laddergame, players):
assert not laddergame.is_winner(players.joining)


async def test_game_result_draw_bug(laddergame, players):
laddergame.state = GameState.LOBBY
add_connected_players(laddergame, [players.hosting, players.joining])
await laddergame.launch()

await laddergame.add_result(players.hosting.id, 0, "defeat", -10)
await laddergame.add_result(players.hosting.id, 0, "score", 1)
await laddergame.add_result(players.joining.id, 1, "defeat", -10)

assert not laddergame.is_winner(players.hosting)
assert not laddergame.is_winner(players.joining)

results = await laddergame.resolve_game_results()
for summary in results.team_summaries:
assert summary.outcome is GameOutcome.DRAW


async def test_rate_game(laddergame: LadderGame, database, game_add_players):
laddergame.state = GameState.LOBBY
players = game_add_players(laddergame, 2)
Expand Down

0 comments on commit b6281a5

Please sign in to comment.