-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unittests for
Contest
and Problem
models
- Loading branch information
1 parent
64325ad
commit 32a36de
Showing
4 changed files
with
497 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from django.contrib.auth.models import Permission, User | ||
|
||
from judge.models import Organization, Profile | ||
|
||
|
||
class UserFixturesMixin: | ||
# TODO: fixture? | ||
users_data = { | ||
'superuser': { | ||
'is_superuser': True, | ||
'is_staff': True, | ||
}, | ||
'staff_contest_1': { | ||
'is_staff': True, | ||
'_meta': { | ||
'permissions': ( | ||
'edit_own_contest', | ||
'see_private_contest', | ||
), | ||
}, | ||
}, | ||
'staff_contest_2': { | ||
'is_staff': True, | ||
'_meta': { | ||
'permissions': ( | ||
'edit_own_contest', | ||
'edit_all_contest', | ||
), | ||
}, | ||
}, | ||
'staff_problem_1': { | ||
'is_staff': True, | ||
'_meta': { | ||
'permissions': ( | ||
'edit_own_problem', | ||
'see_private_problem', | ||
), | ||
}, | ||
}, | ||
'staff_problem_2': { | ||
'is_staff': True, | ||
'_meta': { | ||
'permissions': ( | ||
'edit_own_problem', | ||
'edit_all_problem', | ||
), | ||
}, | ||
}, | ||
'staff_problem_3': { | ||
'is_staff': True, | ||
'_meta': { | ||
'permissions': ( | ||
'edit_own_problem', | ||
'edit_public_problem', | ||
), | ||
}, | ||
}, | ||
'staff_problem_4': { | ||
'_meta': { | ||
'permissions': ( | ||
'see_organization_problem', | ||
), | ||
}, | ||
}, | ||
'normal': {}, | ||
} | ||
|
||
@classmethod | ||
def setUpTestData(self): | ||
self.users = {} | ||
for username, all_data in self.users_data.items(): | ||
data = all_data.copy() | ||
metadata = data.pop('_meta', {}) | ||
user = User.objects.create( | ||
username=username, | ||
**data, | ||
) | ||
user.user_permissions.set(Permission.objects.filter(codename__in=metadata.get('permissions', ()))) | ||
self.users[username] = user | ||
|
||
self.profiles = {key: Profile.objects.create(user=user) for key, user in self.users.items()} | ||
|
||
self.organizations = { | ||
'open': Organization.objects.create( | ||
name='open', | ||
slug='open', | ||
short_name='open', | ||
registrant=self.profiles['superuser'], | ||
), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
from django.test import TestCase | ||
from django.utils import timezone | ||
|
||
from judge.models import Contest, ContestParticipation | ||
from judge.models.tests.base import UserFixturesMixin | ||
|
||
|
||
class ContestTestCase(UserFixturesMixin, TestCase): | ||
@classmethod | ||
def setUpTestData(self): | ||
super().setUpTestData() | ||
_now = timezone.now() | ||
self.basic_contest = Contest.objects.create( | ||
name='Basic Contest', | ||
key='basic', | ||
start_time=_now - timezone.timedelta(days=1), | ||
end_time=_now + timezone.timedelta(days=100), | ||
) | ||
self.basic_contest.organizers.add(self.profiles['superuser']) | ||
self.basic_contest.organizers.add(self.profiles['staff_contest_1']) | ||
|
||
self.hidden_scoreboard_contest = Contest.objects.create( | ||
name='Hidden Scoreboard Contest', | ||
key='hidden_scoreboard', | ||
start_time=_now - timezone.timedelta(days=1), | ||
end_time=_now + timezone.timedelta(days=100), | ||
is_visible=True, | ||
hide_scoreboard=True, | ||
problem_label_script=''' | ||
function(n) | ||
return tostring(math.floor(n)) | ||
end | ||
''', | ||
) | ||
|
||
self.profiles['normal'].current_contest = ContestParticipation.objects.create( | ||
contest=self.hidden_scoreboard_contest, | ||
user=self.profiles['normal'], | ||
) | ||
self.profiles['normal'].save() | ||
|
||
self.private_contest = Contest.objects.create( | ||
name='Private Contest', | ||
key='private', | ||
start_time=_now - timezone.timedelta(days=5), | ||
end_time=_now - timezone.timedelta(days=3), | ||
is_visible=True, | ||
is_private=True, | ||
is_organization_private=True, | ||
) | ||
self.private_contest.private_contestants.add(self.profiles['staff_contest_1']) | ||
|
||
def test_basic_contest(self): | ||
self.assertTrue(self.basic_contest.show_scoreboard) | ||
self.assertIsInstance(self.basic_contest.contest_window_length, timezone.timedelta) | ||
self.assertIsInstance(self.basic_contest._now, timezone.datetime) | ||
self.assertTrue(self.basic_contest.can_join) | ||
self.assertIsNone(self.basic_contest.time_before_start) | ||
self.assertIsInstance(self.basic_contest.time_before_end, timezone.timedelta) | ||
self.assertFalse(self.basic_contest.ended) | ||
self.assertEqual(str(self.basic_contest), self.basic_contest.name) | ||
self.assertEqual(self.basic_contest.get_label_for_problem(0), '1') | ||
|
||
def test_hidden_scoreboard_contest(self): | ||
self.assertFalse(self.hidden_scoreboard_contest.show_scoreboard) | ||
for i in range(3): | ||
with self.subTest(contest_problem_index=i): | ||
self.assertEqual(self.hidden_scoreboard_contest.get_label_for_problem(i), str(i)) | ||
|
||
def test_private_contest(self): | ||
self.assertTrue(self.private_contest.can_join) | ||
self.assertIsNone(self.private_contest.time_before_start) | ||
self.assertIsNone(self.private_contest.time_before_end) | ||
|
||
def _test_contest_user(self, contest, user, methods): | ||
for method, func in methods.items(): | ||
func( | ||
getattr(contest, method)(user), | ||
msg='Method %s failed for user "%s", contest "%s".' % (method, user.username, contest.name), | ||
) | ||
|
||
def test_basic_contest_superuser_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertTrue, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.basic_contest, self.users['superuser'], methods) | ||
|
||
def test_basic_contest_staff_contest_1_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertTrue, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.basic_contest, self.users['staff_contest_1'], methods) | ||
|
||
def test_basic_contest_staff_contest_2_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertTrue, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.basic_contest, self.users['staff_contest_2'], methods) | ||
|
||
def test_basic_contest_normal_user(self): | ||
with self.assertRaises(Contest.Inaccessible): | ||
self.basic_contest.access_check(self.users['normal']) | ||
|
||
methods = { | ||
# scoreboard checks don't do accessibility checks | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertFalse, | ||
'is_editable_by': self.assertFalse, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.basic_contest, self.users['normal'], methods) | ||
|
||
def test_hidden_scoreboard_contest_staff_contest_1_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertFalse, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.hidden_scoreboard_contest, self.users['staff_contest_1'], methods) | ||
|
||
def test_hidden_scoreboard_contest_staff_contest_2_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertTrue, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.hidden_scoreboard_contest, self.users['staff_contest_2'], methods) | ||
|
||
def test_hidden_scoreboard_contest_normal_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertFalse, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertFalse, | ||
'is_in_contest': self.assertTrue, | ||
} | ||
self._test_contest_user(self.hidden_scoreboard_contest, self.users['normal'], methods) | ||
|
||
def test_private_contest_staff_contest_1_user(self): | ||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertFalse, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.private_contest, self.users['staff_contest_1'], methods) | ||
|
||
def test_private_contest_normal_user(self): | ||
with self.assertRaises(Contest.PrivateContest): | ||
self.private_contest.access_check(self.users['normal']) | ||
self.private_contest.private_contestants.add(self.profiles['normal']) | ||
with self.assertRaises(Contest.PrivateContest): | ||
self.private_contest.access_check(self.users['normal']) | ||
self.private_contest.organizations.add(self.organizations['open']) | ||
self.profiles['normal'].organizations.add(self.organizations['open']) | ||
|
||
methods = { | ||
'can_see_own_scoreboard': self.assertTrue, | ||
'can_see_full_scoreboard': self.assertTrue, | ||
'is_accessible_by': self.assertTrue, | ||
'is_editable_by': self.assertFalse, | ||
'is_in_contest': self.assertFalse, | ||
} | ||
self._test_contest_user(self.private_contest, self.users['normal'], methods) | ||
|
||
def _test_contest_list_user(self, user): | ||
# We only care about consistency between Contest.is_accessible_by and Contest.get_visible_contests | ||
contest_keys = [] | ||
for contest in Contest.objects.all(): | ||
if contest.is_accessible_by(user): | ||
contest_keys.append(contest.key) | ||
|
||
self.assertListEqual( | ||
list(Contest.get_visible_contests(user).values_list('key', flat=True)), | ||
contest_keys, | ||
) | ||
|
||
def test_contests_list_superuser_user(self): | ||
self._test_contest_list_user(self.users['superuser']) | ||
|
||
def test_contests_list_staff_contest_1_user(self): | ||
self._test_contest_list_user(self.users['staff_contest_1']) | ||
|
||
def test_contests_list_staff_contest_2_user(self): | ||
self._test_contest_list_user(self.users['staff_contest_2']) | ||
|
||
def test_contests_list_normal_user(self): | ||
self._test_contest_list_user(self.users['normal']) |
Oops, something went wrong.