Skip to content

Commit

Permalink
Merge pull request #237 from johnpooch/john=bug-squash-2
Browse files Browse the repository at this point in the history
Bug squash
  • Loading branch information
johnpooch authored Apr 28, 2021
2 parents 4a5dec5 + 26537ee commit 81a58bf
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 32 deletions.
7 changes: 7 additions & 0 deletions core/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def process_turn(turn, dry_run=False):
the turn the adjudicator. Update the turn based on the adjudicator
response.
"""
# Remove pending turnend
try:
turn.turnend.delete()
except models.TurnEnd.DoesNotExist:
pass

logger.info('Processing turn: {}'.format(turn))
turn_data = TurnSerializer(turn).data
outcome = process_game_state(turn_data)
Expand All @@ -40,6 +46,7 @@ def process_turn(turn, dry_run=False):
winning_nation = new_turn.check_for_winning_nation()
if winning_nation:
turn.game.set_winner(winning_nation)

return new_turn


Expand Down
28 changes: 28 additions & 0 deletions core/migrations/0008_auto_20210426_1518.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.1.7 on 2021-04-26 14:18

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0007_auto_20210425_1732'),
]

operations = [
migrations.AlterField(
model_name='game',
name='build_deadline',
field=models.CharField(choices=[(None, 'None'), ('twelve_hours', '12 hours'), ('twenty_four_hours', '24 hours'), ('two_days', '2 days'), ('three_days', '3 days'), ('five_days', '5 days'), ('seven_days', '7 days')], max_length=100, null=True),
),
migrations.AlterField(
model_name='game',
name='order_deadline',
field=models.CharField(choices=[(None, 'None'), ('twelve_hours', '12 hours'), ('twenty_four_hours', '24 hours'), ('two_days', '2 days'), ('three_days', '3 days'), ('five_days', '5 days'), ('seven_days', '7 days')], max_length=100, null=True),
),
migrations.AlterField(
model_name='game',
name='retreat_deadline',
field=models.CharField(choices=[(None, 'None'), ('twelve_hours', '12 hours'), ('twenty_four_hours', '24 hours'), ('two_days', '2 days'), ('three_days', '3 days'), ('five_days', '5 days'), ('seven_days', '7 days')], max_length=100, null=True),
),
]
7 changes: 2 additions & 5 deletions core/models/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,16 @@ class Game(models.Model, AutoSlug):
order_deadline = models.CharField(
null=True,
choices=DeadlineFrequency.CHOICES,
default=DeadlineFrequency.TWENTY_FOUR_HOURS,
max_length=100,
)
retreat_deadline = models.CharField(
null=False,
null=True,
choices=DeadlineFrequency.CHOICES,
default=DeadlineFrequency.TWENTY_FOUR_HOURS,
max_length=100,
)
build_deadline = models.CharField(
null=False,
null=True,
choices=DeadlineFrequency.CHOICES,
default=DeadlineFrequency.TWELVE_HOURS,
max_length=100,
)
process_on_finalized_orders = models.BooleanField(
Expand Down
7 changes: 4 additions & 3 deletions core/models/turn.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ def new(self, **kwargs):
instance.
"""
turn = self.create(**kwargs)
td = timespan.get_timespan(turn.deadline).timedelta
turn_end_dt = timezone.now() + td
TurnEnd.objects.new(turn, turn_end_dt)
if turn.deadline:
td = timespan.get_timespan(turn.deadline).timedelta
turn_end_dt = timezone.now() + td
TurnEnd.objects.new(turn, turn_end_dt)
return turn


Expand Down
6 changes: 6 additions & 0 deletions core/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from core.models.base import DrawStatus, GameStatus
from core.models.mixins import AutoSlug
from core.utils.models import super_receiver
from project.celery import app


def set_id(instance):
Expand Down Expand Up @@ -72,6 +73,11 @@ def set_game_state_if_draw_accepted(sender, instance, **kwargs):
game.set_winners(*nations)


@receiver(signals.pre_delete, sender=models.TurnEnd)
def revoke_task_on_delete(sender, instance, **kwargs):
app.control.revoke(instance.task_id)


@receiver(reset_password_token_created)
def password_reset_token_created(sender, instance, reset_password_token, *args, **kwargs):
"""
Expand Down
6 changes: 6 additions & 0 deletions core/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@


apply_async_path = 'core.tasks.process_turn.apply_async'
revoke_task_on_delete_path = 'celery.app.control.Control.revoke'


set_status_path = 'core.models.Draw.set_status'
Expand Down Expand Up @@ -55,6 +56,11 @@ def patch_process_turn_apply_async(self):
self.apply_async = apply_async.start()
self.apply_async.return_value = AsyncResult(id=self.dummy_task_id)

def patch_revoke_task_on_delete(self):
self.revoke_task_on_delete_patcher = patch(revoke_task_on_delete_path)
self.revoke_task_on_delete_patch = self.revoke_task_on_delete_patcher.start()
self.addCleanup(self.revoke_task_on_delete_patcher.stop)

def patch_set_status(self):
self.set_status_patcher = patch(set_status_path)
self.set_status_patch = self.set_status_patcher.start()
Expand Down
5 changes: 4 additions & 1 deletion core/tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.utils import timezone

from core import factories, models
from core.models.base import GameStatus, Phase, Season
from core.models.base import DeadlineFrequency, GameStatus, Phase, Season
from core.tests import DiplomacyTestCaseMixin


Expand All @@ -18,6 +18,9 @@ def setUp(self):
variant=self.variant,
num_players=7,
created_by=self.users[0],
order_deadline=DeadlineFrequency.TWENTY_FOUR_HOURS,
retreat_deadline=DeadlineFrequency.TWELVE_HOURS,
build_deadline=DeadlineFrequency.TWELVE_HOURS,
)
self.game.participants.add(*self.users)
self.patch_process_turn_apply_async()
Expand Down
1 change: 1 addition & 0 deletions core/tests/test_set_turn_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def setUp(self):
self.yesterday_string = self.yesterday.strftime(self.date_format)

self.patch_process_turn_apply_async()
self.patch_revoke_task_on_delete()

def call_command(self, slug, date_string):
call_command(self.command, slug, date_string, stdout=self.out)
Expand Down
21 changes: 16 additions & 5 deletions core/tests/test_turn.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,6 @@ def test_turn_end_none(self):
turn = self.create_test_turn(game=self.game)
self.assertIsNone(turn.turn_end)

def test_turn_end(self):
turn = self.create_test_turn(game=self.game, turn_end=True)
turn_end = models.TurnEnd.objects.get()
self.assertEqual(turn.turn_end, turn_end)

def test_deadline_order(self):
self.game.order_deadline = DeadlineFrequency.SEVEN_DAYS
self.game.save()
Expand Down Expand Up @@ -317,9 +312,12 @@ def setUp(self):
self.user = factories.UserFactory()
self.game = self.create_test_game()
self.game.participants.add(self.user)
self.patch_process_turn_apply_async()

def test_new(self):
self.assertEqual(models.TurnEnd.objects.count(), 0)
self.game.retreat_deadline = DeadlineFrequency.FIVE_DAYS
self.game.save()
turn = models.Turn.objects.new(
game=self.game,
phase=Phase.RETREAT,
Expand All @@ -329,3 +327,16 @@ def test_new(self):
turn_end = models.TurnEnd.objects.get()
self.assertEqual(turn_end.turn, turn)
self.assertSimilarTimestamp(turn_end.datetime, self.tomorrow)

def test_new_no_deadline(self):
self.assertEqual(models.TurnEnd.objects.count(), 0)
self.game.order_deadline = None
self.game.save()
turn = models.Turn.objects.new(
game=self.game,
phase=Phase.ORDER,
season=Season.SPRING,
year=1901,
)
with self.assertRaises(models.TurnEnd.DoesNotExist):
turn.turnend
6 changes: 5 additions & 1 deletion core/tests/test_turn_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from core import factories, models
from core.tasks import process_turn
from core.tests import DiplomacyTestCaseMixin
from core.models.base import Phase, Season
from core.models.base import DeadlineFrequency, Phase, Season


process_path = 'core.tasks._process_turn'
Expand All @@ -23,8 +23,12 @@ def setUp(self):
variant=self.variant,
num_players=7,
created_by=self.user,
order_deadline=DeadlineFrequency.TWENTY_FOUR_HOURS,
retreat_deadline=DeadlineFrequency.TWELVE_HOURS,
build_deadline=DeadlineFrequency.TWELVE_HOURS,
)
self.patch_process_turn_apply_async()
self.patch_revoke_task_on_delete()

def create_turn(self):
return models.Turn.objects.create(
Expand Down
5 changes: 5 additions & 0 deletions service/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class Meta:
fields = (
'id',
'name',
'variant',
)


Expand Down Expand Up @@ -384,6 +385,10 @@ class Meta:
'piece_type',
'via_convoy',
'turn',
'outcome',
'illegal',
'illegal_code',
'illegal_verbose',
)
read_only_fields = (
'nation',
Expand Down
26 changes: 9 additions & 17 deletions service/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from core import factories, models
from core.tests import DiplomacyTestCaseMixin
from core.models.base import (
DrawStatus, DrawResponse, GameStatus, OrderType, Phase, PieceType, Season,
SurrenderStatus
DeadlineFrequency, DrawStatus, DrawResponse, GameStatus, OrderType, Phase, PieceType,
Season, SurrenderStatus
)
from service import validators

Expand Down Expand Up @@ -64,12 +64,9 @@ def test_list_games_converts_camel_to_snake_query_params(self):
self.assertEqual(len(response.data), 1)


class TestGetCreateGame(BaseTestCase):
class TestCreateGame(BaseTestCase):

def test_get_create_game(self):
"""
Get create game returns a form.
"""
user = factories.UserFactory()
self.client.force_authenticate(user=user)

Expand All @@ -81,16 +78,10 @@ def test_get_create_game(self):
)

def test_get_create_game_unauthenticated(self):
"""
Cannot get create game when unauthenticated.
"""
url = reverse('create-game')
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


class TestCreateGame(BaseTestCase):

def test_post_invalid_game(self):
"""
Posting invalid game data causes a 400 error.
Expand All @@ -104,17 +95,15 @@ def test_post_invalid_game(self):
self.assertEqual(response.status_code, 400)

def test_post_valid_game(self):
"""
Posting valid game data creates a game instance and redirects to
`user-games` view. The user is automatically added as a participant of
the game.
"""
user = factories.UserFactory()
self.client.force_authenticate(user=user)
variant = models.Variant.objects.get(id='standard')

data = {
'name': 'Test Game',
'order_deadline': DeadlineFrequency.TWENTY_FOUR_HOURS,
'retreat_deadline': DeadlineFrequency.TWELVE_HOURS,
'build_deadline': DeadlineFrequency.TWELVE_HOURS,
}
url = reverse('create-game')
response = self.client.post(url, data, format='json')
Expand All @@ -126,6 +115,9 @@ def test_post_valid_game(self):
created_by=user,
variant=variant,
participants=user,
order_deadline=DeadlineFrequency.TWENTY_FOUR_HOURS,
retreat_deadline=DeadlineFrequency.TWELVE_HOURS,
build_deadline=DeadlineFrequency.TWELVE_HOURS,
)
)

Expand Down

0 comments on commit 81a58bf

Please sign in to comment.