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)
        }
Exemplo n.º 3
0
 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
Exemplo n.º 6
0
 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()
Exemplo n.º 8
0
    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()
Exemplo n.º 9
0
    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')
Exemplo n.º 10
0
    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'])
Exemplo n.º 11
0
 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,
     )
Exemplo n.º 12
0
 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()
Exemplo n.º 13
0
    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"]
Exemplo n.º 14
0
    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))
Exemplo n.º 15
0
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))
Exemplo n.º 16
0
 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)
Exemplo n.º 17
0
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
Exemplo n.º 18
0
 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)
Exemplo n.º 21
0
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