def setUp(self): self.owner = UserFactory(username='******', super_user=True) self.normal_user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.owner, title="Competition One") self.competition_participant = CompetitionParticipantFactory( user=self.normal_user, competition=self.competition) self.phase1 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=False, start=twenty_five_minutes_ago, end=twenty_minutes_ago, index=0, name='Phase1', status=Phase.CURRENT) self.phase2 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=True, start=five_minutes_ago, end=twenty_minutes_from_now, index=1, name='Phase2', status=Phase.NEXT) self.phase3 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=False, start=twenty_minutes_from_now, index=2, name='Phase3', status=Phase.FINAL) for _ in range(4): self.make_submission()
def setUp(self): self.user = UserFactory() self.comp = CompetitionFactory(created_by=self.user) self.tasks = [TaskFactory(created_by=self.user)] self.base = {'competition': self.comp, 'tasks': self.tasks} self.phase1 = PhaseFactory.create(**self.base) self.phase2 = PhaseFactory.create(**self.base) self.phase3 = PhaseFactory.create(**self.base) self.before_previous = { 'start': now() - timedelta(minutes=20), 'end': now() - timedelta(minutes=15) } self.previous = { 'start': now() - timedelta(minutes=10), 'end': now() - timedelta(minutes=5) } self.current = { 'start': now() - timedelta(minutes=1), 'end': now() + timedelta(minutes=5) } self.next = { 'start': now() + timedelta(minutes=10), 'end': now() + timedelta(minutes=15) } self.after_next = { 'start': now() + timedelta(minutes=20), 'end': now() + timedelta(minutes=25) }
def setUp(self): self.creator = UserFactory(username='******', password='******') self.other_user = UserFactory(username='******', password='******') self.comp = CompetitionFactory(created_by=self.creator) self.phase_1 = PhaseFactory(competition=self.comp, index=0) self.phase_2 = PhaseFactory(competition=self.comp, index=1) self.leaderboard = LeaderboardFactory(competition=self.comp) ColumnFactory(leaderboard=self.leaderboard)
def test_making_submission_to_phase_with_one_task_does_not_create_parents_or_children( self): self.single_phase = PhaseFactory(competition=self.comp) self.sub = self.make_submission(phase=self.single_phase) resp = self.mock_run_submission(self.sub) assert resp.call_count == 1 sub = Submission.objects.get(id=self.sub.id) assert not sub.has_children
def test_five_phases_updated_correctly(self): self.phase4 = PhaseFactory.create(**self.base) self.phase5 = PhaseFactory.create(**self.base) self.set_start_end(self.phase1, **self.before_previous) self.set_start_end(self.phase2, **self.previous) self.set_start_end(self.phase3, **self.current) self.set_start_end(self.phase4, **self.next) self.set_start_end(self.phase5, **self.after_next) do_phase_migrations() assert Phase.objects.get(id=self.phase1.id).status is None assert Phase.objects.get(id=self.phase2.id).status == Phase.PREVIOUS assert Phase.objects.get(id=self.phase3.id).status == Phase.CURRENT assert Phase.objects.get(id=self.phase4.id).status == Phase.NEXT assert Phase.objects.get(id=self.phase5.id).status is None
def setUp(self): self.creator = UserFactory(username='******', password='******') self.bot_user = UserFactory(username='******', password='******', is_bot=True) self.non_bot_user = UserFactory(username='******', password='******') self.bot_comp = CompetitionFactory(created_by=self.creator, allow_robot_submissions=True) self.bot_phase = PhaseFactory(competition=self.bot_comp) self.bot_phase_day_limited = PhaseFactory(competition=self.bot_comp, has_max_submissions=True, max_submissions_per_day=1) self.bot_phase_person_limited = PhaseFactory( competition=self.bot_comp, has_max_submissions=True, max_submissions_per_person=1) CompetitionParticipant(user=self.non_bot_user, competition=self.bot_comp, status=CompetitionParticipant.APPROVED).save()
def setUp(self): self.user = UserFactory(username='******') self.admin = UserFactory(username='******', super_user=True) self.collab = UserFactory(username='******') self.normal_user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.user) self.competition.collaborators.add(self.collab) self.phase = PhaseFactory(competition=self.competition) self.leaderboard = LeaderboardFactory(competition=self.competition) self.column = ColumnFactory(leaderboard=self.leaderboard, key='test') self.submission = self.make_submission()
def setUp(self): self.user = UserFactory(username='******') self.admin = UserFactory(username='******', super_user=True) self.collab = UserFactory(username='******') self.normal_user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.user) self.competition.collaborators.add(self.collab) self.phase = PhaseFactory(competition=self.competition) for _ in range(4): self.make_submission()
def setUp(self): self.superuser = UserFactory(is_superuser=True, is_staff=True) # Competition and creator self.creator = UserFactory(username='******', password='******') self.collaborator = UserFactory(username='******', password='******') self.comp = CompetitionFactory(created_by=self.creator, collaborators=[self.collaborator]) self.phase = PhaseFactory(competition=self.comp) # Extra dummy user to test permissions, they shouldn't have access to many things self.other_user = UserFactory(username='******', password='******') # Make a participant and submission into competition self.participant = UserFactory(username='******', password='******') CompetitionParticipantFactory(user=self.participant, competition=self.comp) self.existing_submission = SubmissionFactory( phase=self.phase, owner=self.participant, status=Submission.SUBMITTED, secret='7df3600c-1234-5678-bbc8-bbe91f42d875')
def setUp(self): # Competition and creator self.creator = UserFactory(username='******', password='******') self.comp = CompetitionFactory(created_by=self.creator) self.phase = PhaseFactory(competition=self.comp) for _ in range(2): self.phase.tasks.add(TaskFactory.create()) # Extra phase for testing tasks can't be run on the wrong phase self.other_phase = PhaseFactory(competition=self.comp) # URL and data for making submissions self.submission_url = reverse('submission-list') self.submission_data = { 'phase': self.phase.id, 'data': Data.objects.create(created_by=self.creator, type=Data.SUBMISSION).key, 'tasks': random.sample( list(self.phase.tasks.all().values_list('id', flat=True)), 2) } self.sorted_tasks = sorted(self.submission_data['tasks'])
def setUp(self): self.user = UserFactory() self.comp = CompetitionFactory(published=True) self.participant = CompetitionParticipantFactory(user=self.user, competition=self.comp) self.phase = PhaseFactory(competition=self.comp) self.data = DataFactory() # Calling this after initial setup so we don't turn on FORCE_CHAHUB and try and send all our setup objects super().setUp() self.submission = SubmissionFactory.build( owner=self.user, phase=self.phase, data=self.data, participant=self.participant, status='Finished', is_public=True, )
def setUp(self): for _ in range(5): user = UserFactory(chahub_needs_retry=True) comp = CompetitionFactory(chahub_needs_retry=True, published=True) participant = CompetitionParticipantFactory(competition=comp, user=user, status='approved') phase = PhaseFactory(competition=comp) DataFactory(chahub_needs_retry=True, is_public=True, upload_completed_successfully=True) SubmissionFactory(chahub_needs_retry=True, status="Finished", phase=phase, is_public=True, participant=participant) super().setUp()
def test_task_shown_as_validated_properly(self): user = UserFactory(username='******') solution = SolutionFactory(md5="12345") task = TaskFactory(created_by=user, solutions=[solution]) competition = CompetitionFactory(created_by=user) phase = PhaseFactory(competition=competition, tasks=[task]) submission = SubmissionFactory(md5="12345", phase=phase, status=Submission.FINISHED) url = reverse('task-detail', kwargs={'pk': task.id}) self.client.login(username=user.username, password='******') # task should be validated because we have a successful submission matching # our solution resp = self.client.get(url) assert resp.status_code == 200 assert resp.data["validated"] # make submission anything but Submission.FINISHED, task -> invalidated submission.status = Submission.FAILED submission.save() resp = self.client.get(url) assert resp.status_code == 200 assert not resp.data["validated"] # make submission Submission.Finished, task -> re-validated submission.status = Submission.FINISHED submission.save() resp = self.client.get(url) assert resp.status_code == 200 assert resp.data["validated"] # delete submission, task -> re-invalidated submission.delete() resp = self.client.get(url) assert resp.status_code == 200 assert not resp.data["validated"] # make submission with different Sha -> still invalid SubmissionFactory(md5="different", phase=phase, status=Submission.FINISHED) resp = self.client.get(url) assert resp.status_code == 200 assert not resp.data["validated"]
def handle(self, *args, **kwargs): size = kwargs.get('size') or 3 no_admin = kwargs.get('no_admin') print( f'Creating data of size {size} {"without an admin account." if no_admin else "with an admin account." }' ) users = [] for i in range(size): if i == 0 and not no_admin: try: user = UserFactory(username='******', password='******', super_user=True) except IntegrityError: # admin user already exists user = User.objects.get(username='******') else: user = UserFactory() users.append(user) for user in users: for _ in range(size): comp = CompetitionFactory(created_by=user) for u in users: try: CompetitionParticipantFactory(competition=comp, user=u, status='approved') except IntegrityError: # User already a participant in the competition pass for i in range(size): phase = PhaseFactory(competition=comp, index=i, tasks=[TaskFactory(created_by=user)]) for _ in range(size): SubmissionFactory(phase=phase, owner=random.choice(users))
class CompetitionPhaseMigrationValidation(TestCase): def setUp(self): self.user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.user, id=1) self.phase = PhaseFactory(competition=self.competition) self.leaderboard = LeaderboardFactory(competition=self.competition) def serialize_and_validate_data(self): serializer = CompetitionSerializer(self.competition) data = serializer.data with pytest.raises(ValidationError) as exception: serializer = CompetitionSerializer(data=data) serializer.is_valid(raise_exception=True) return exception def test_phase_is_valid(self): self.phase.auto_migrate_to_this_phase = False self.phase.save() exception = self.serialize_and_validate_data() assert ("'phase:'" not in str(exception.value)) def test_phase_serializer_auto_migrate_on_first_phase(self): self.phase.auto_migrate_to_this_phase = True self.phase.save() exception = self.serialize_and_validate_data() errors = [ "You cannot auto migrate in a competition with one phase", "You cannot auto migrate to the first phase of a competition" ] assert any(error in str(exception.value) for error in errors) def test_phase_serializer_no_phases(self): self.phase.competition = None self.phase.save() exception = self.serialize_and_validate_data() assert ("Competitions must have at least one phase" in str(exception.value))
def setUp(self): self.user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.user, id=1) self.phase = PhaseFactory(competition=self.competition) self.leaderboard = LeaderboardFactory(competition=self.competition)
class PhaseToPhaseMigrationTests(TestCase): def setUp(self): self.owner = UserFactory(username='******', super_user=True) self.normal_user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.owner, title="Competition One") self.competition_participant = CompetitionParticipantFactory( user=self.normal_user, competition=self.competition) self.phase1 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=False, start=twenty_five_minutes_ago, end=twenty_minutes_ago, index=0, name='Phase1', status=Phase.CURRENT) self.phase2 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=True, start=five_minutes_ago, end=twenty_minutes_from_now, index=1, name='Phase2', status=Phase.NEXT) self.phase3 = PhaseFactory(competition=self.competition, auto_migrate_to_this_phase=False, start=twenty_minutes_from_now, index=2, name='Phase3', status=Phase.FINAL) for _ in range(4): self.make_submission() def make_submission(self, **kwargs): kwargs.setdefault('owner', self.owner) kwargs.setdefault('participant', self.competition_participant) kwargs.setdefault('phase', self.phase1) kwargs.setdefault('status', Submission.FINISHED) sub = SubmissionFactory(**kwargs) return sub def mock_migration(self): with mock.patch( 'competitions.models.Submission.start') as submission_start: do_phase_migrations() return submission_start def test_migrate_submissions(self): assert not self.phase2.submissions.exists() mock_start = self.mock_migration() assert mock_start.call_count == self.phase1.submissions.count() assert self.phase1.submissions.count( ) == self.phase2.submissions.count() def test_currently_migrating_competitions_dont_migrate(self): self.mock_migration() assert Competition.objects.get(id=self.competition.id).is_migrating mock_start = self.mock_migration() assert not mock_start.called def test_competitions_with_scoring_submissions_dont_migrate(self): self.make_submission(status=Submission.SCORING, participant=self.competition_participant) self.mock_migration() assert self.phase1.submissions.count( ) != self.phase2.submissions.count() def test_submission_ran_after_migration_complete(self): self.mock_migration() assert not self.phase2.submissions.filter(status='None').exists() def test_has_been_migrated_competitions_arent_migrated(self): self.phase2.has_been_migrated = True self.phase2.save() assert not self.phase2.submissions.exists() self.mock_migration() assert self.phase1.submissions.count( ) != self.phase2.submissions.count() def test_prevent_migration_to_auto_migrate_to_the_phase_is_false(self): assert not self.phase2.submissions.exists() assert not self.phase3.submissions.exists() self.mock_migration() assert self.phase1.submissions.count( ) == self.phase2.submissions.count() assert self.phase1.submissions.count( ) != self.phase3.submissions.count() assert self.phase2.submissions.count( ) != self.phase3.submissions.count() def test_all_submissions_migrated_before_changing_phase_status(self): self.mock_migration() assert Phase.objects.get(id=self.phase1.id).status == Phase.PREVIOUS assert Competition.objects.get(id=self.competition.id).is_migrating phase2 = Phase.objects.get(id=self.phase2.id) assert phase2.has_been_migrated assert phase2.status == Phase.CURRENT self.mock_migration() assert Competition.objects.get(id=self.competition.id).is_migrating self.phase2.submissions.update(status='Finished') self.mock_migration() assert not Competition.objects.get( id=self.phase1.competition.id).is_migrating mock_start = self.mock_migration() assert mock_start.call_count == 0 def test_only_parent_submissions_migrated(self): self.parent_submission = self.make_submission() self.phase1.submissions.exclude(id=self.parent_submission.id).update( parent=self.parent_submission) assert Submission.objects.get( id=self.parent_submission.id).children.exists() assert Submission.objects.get( id=self.parent_submission.id).children.count() > 0 mock_sub_start = self.mock_migration() assert mock_sub_start.call_count == 1
def setUp(self): self.comp = CompetitionFactory(published=False) PhaseFactory(competition=self.comp) super().setUp()
def setUp(self): self.user = UserFactory(username='******') self.competition = CompetitionFactory(created_by=self.user) self.phase = PhaseFactory(competition=self.competition)
def setUp(self): self.user = UserFactory() self.comp = CompetitionFactory() self.tasks = [TaskFactory() for _ in range(2)] self.phase = PhaseFactory(competition=self.comp, tasks=self.tasks)
class SubmissionAPITests(APITestCase): def setUp(self): self.superuser = UserFactory(is_superuser=True, is_staff=True) # Competition and creator self.creator = UserFactory(username='******', password='******') self.collaborator = UserFactory(username='******', password='******') self.comp = CompetitionFactory(created_by=self.creator, collaborators=[self.collaborator]) self.phase = PhaseFactory(competition=self.comp) # Extra dummy user to test permissions, they shouldn't have access to many things self.other_user = UserFactory(username='******', password='******') # Make a participant and submission into competition self.participant = UserFactory(username='******', password='******') CompetitionParticipantFactory(user=self.participant, competition=self.comp) self.existing_submission = SubmissionFactory( phase=self.phase, owner=self.participant, status=Submission.SUBMITTED, secret='7df3600c-1234-5678-bbc8-bbe91f42d875') def test_can_make_submission_checks_if_you_are_participant(self): # You should get a message back if you aren't registered in this competition self.client.login(username="******", password="******") resp = self.client.get( reverse("can_make_submission", args=(self.phase.pk, ))) assert resp.status_code == 200 assert not resp.data["can"] assert resp.data[ "reason"] == "User not approved to participate in this competition" self.client.logout() # If you are in the competition (the creator), should be good-to-go self.client.login(username="******", password="******") resp = self.client.get( reverse("can_make_submission", args=(self.phase.pk, ))) assert resp.status_code == 200 assert resp.data["can"] def test_making_a_submission_checks_if_you_are_a_participant(self): # You should get a message back if you aren't registered in this competition self.client.login(username="******", password="******") resp = self.client.post(reverse("submission-list"), {"phase": self.phase.pk}) assert resp.status_code == 403 assert "You do not have access to this competition to make a submission" in resp.data[ "detail"] def test_trying_to_change_submission_without_secret_raises_permission_denied( self): url = reverse('submission-detail', args=(self.existing_submission.pk, )) # As anonymous user resp = self.client.patch(url, {"status": Submission.FINISHED}) assert resp.status_code == 400 assert "Secret: (None) not a valid UUID" in str(resp.content) assert Submission.objects.filter(pk=self.existing_submission.pk, status=Submission.SUBMITTED) # As superuser (bad secret) self.client.force_login(self.creator) resp = self.client.patch( url, { "status": Submission.FINISHED, "secret": '7df3600c-aa6d-41c5-bbc8-bbe91f42d875' }) assert resp.status_code == 403 assert resp.data["detail"] == "Submission secrets do not match" assert Submission.objects.filter(pk=self.existing_submission.pk, status=Submission.SUBMITTED) # As anonymous user with secret self.client.logout() resp = self.client.patch( url, { "status": Submission.FINISHED, "secret": self.existing_submission.secret }) assert resp.status_code == 200 assert Submission.objects.filter(pk=self.existing_submission.pk, status=Submission.FINISHED) def test_cannot_delete_submission_you_didnt_create(self): url = reverse('submission-detail', args=(self.existing_submission.pk, )) # As anonymous user resp = self.client.delete(url) assert resp.status_code == 403 assert resp.data[ "detail"] == "Cannot interact with submission you did not make" # As regular user self.client.force_login(self.other_user) resp = self.client.delete(url) assert resp.status_code == 403 assert resp.data[ "detail"] == "Cannot interact with submission you did not make" # As user who made submission self.client.force_login(self.participant) resp = self.client.delete(url) assert resp.status_code == 204 assert not Submission.objects.filter( pk=self.existing_submission.pk).exists() # As superuser (re-making submission since it has been destroyed) self.existing_submission = SubmissionFactory( phase=self.phase, owner=self.participant, status=Submission.SUBMITTED, secret='7df3600c-1234-5678-90c8-bbe91f42d875') url = reverse('submission-detail', args=(self.existing_submission.pk, )) self.client.force_login(self.superuser) resp = self.client.delete(url) assert resp.status_code == 204 assert not Submission.objects.filter( pk=self.existing_submission.pk).exists() def test_cannot_get_details_of_submission_unless_creator_collab_or_superuser( self): url = reverse('submission-get-details', args=(self.existing_submission.pk, )) # Non logged in user can't even see this resp = self.client.get(url) assert resp.status_code == 404 # Regular user can't see this self.client.force_login(self.other_user) resp = self.client.get(url) assert resp.status_code == 404 # Actual user can see download details self.client.force_login(self.participant) resp = self.client.get(url) assert resp.status_code == 200 # Competition creator can see download details self.client.force_login(self.creator) resp = self.client.get(url) assert resp.status_code == 200 # Collaborator can see download details self.client.force_login(self.collaborator) resp = self.client.get(url) assert resp.status_code == 200 # Superuser can see download details self.client.force_login(self.superuser) resp = self.client.get(url) assert resp.status_code == 200 def test_hidden_details_actually_stops_submission_creator_from_seeing_output( self): self.phase.hide_output = True self.phase.save() url = reverse('submission-get-details', args=(self.existing_submission.pk, )) # Non logged in user can't even see this resp = self.client.get(url) assert resp.status_code == 404 # Regular user can't see this self.client.force_login(self.other_user) resp = self.client.get(url) assert resp.status_code == 404 # Actual user cannot see their submission details self.client.force_login(self.participant) resp = self.client.get(url) assert resp.status_code == 403 assert resp.data[ "detail"] == "Cannot access submission details while phase marked to hide output." # Competition creator can see download details self.client.force_login(self.creator) resp = self.client.get(url) assert resp.status_code == 200 # Collaborator can see download details self.client.force_login(self.collaborator) resp = self.client.get(url) assert resp.status_code == 200 # Superuser can see download details self.client.force_login(self.superuser) resp = self.client.get(url) assert resp.status_code == 200