<commit_before># -*- coding: utf8 -*-
# This file is part of PyBossa.
#
# Copyright (C) 2015 SciFabric LTD.
#
# PyBossa is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyBossa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with PyBossa.  If not, see <http://www.gnu.org/licenses/>.
import json
from default import with_context, mock_contributions_guard
from nose.tools import assert_equal
from test_api import TestAPI
from mock import patch
from factories import (ProjectFactory, TaskFactory, TaskRunFactory,
                        AnonymousTaskRunFactory, UserFactory)
from pybossa.repositories import ProjectRepository, TaskRepository
from pybossa.repositories import ResultRepository
from pybossa.core import db

project_repo = ProjectRepository(db)
task_repo = TaskRepository(db)
result_repo = ResultRepository(db)


class TestTaskrunAPI(TestAPI):

    def create_result(self, n_results=1, n_answers=1, owner=None,
                      filter_by=False):
        if owner:
            owner = owner
        else:
            owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        tasks = []
        for i in range(n_results):
            tasks.append(TaskFactory.create(n_answers=n_answers,
                                            project=project))
        for i in range(n_answers):
            for task in tasks:
                TaskRunFactory.create(task=task, project=project)
        if filter_by:
            return result_repo.filter_by(project_id=1)
        else:
            return result_repo.get_by(project_id=1)


    @with_context
    def test_taskrun_query_without_params(self):
        """Test API TaskRun query"""
        owner = UserFactory.create()
        user = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        project_two = ProjectFactory.create()
        TaskRunFactory.create_batch(10, project=project,
                                    info={'answer': 'annakarenina'})
        TaskRunFactory.create_batch(10, project=project_two,
                                    info={'answer': 'annakarenina'})

        project_ids = [project.id, project_two.id]
        # As anon, it sould return everything
        res = self.app.get('/api/taskrun')
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # User context should return 0 taskruns as none of them belong to this
        # user.
        res = self.app.get('/api/taskrun?api_key=' + user.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 0, taskruns

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # User context with all=1 should return everything in the DB, even
        # those task runs that do not belong to the user
        res = self.app.get('/api/taskrun?all=1&api_key=' + user.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # Owner should return all the taskruns that belong to his/her
        # projects
        res = self.app.get('/api/taskrun?api_key=' + owner.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 10, taskruns
        for tr in taskruns:
            assert tr['project_id'] == project.id, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # Owner should return all the taskruns that belong to his/her
        # projects and those that do not belong
        res = self.app.get('/api/taskrun?all=1&api_key=' + owner.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res


    @with_context
    def test_query_taskrun(self):
        """Test API query for taskrun with params works"""
        project = ProjectFactory.create()
        task_runs = TaskRunFactory.create_batch(10, project=project)
        # Test for real field
        res = self.app.get("/api/taskrun?project_id=1")
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        assert data[0]['project_id'] == 1, data

        # Valid field but wrong value
        res = self.app.get("/api/taskrun?project_id=99999999")
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/taskrun?project_id=1&task_id=1')
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['task_id'] == 1, data

        # Limits
        res = self.app.get("/api/taskrun?project_id=1&limit=5")
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data

        # Keyset pagination
        url = "/api/taskrun?project_id=1&limit=5&last_id=%s" % task_runs[4].id
        res = self.app.get(url)
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data
        assert data[0]['id'] == task_runs[5].id, data[0]['id']


    @with_context
    def test_query_taskrun_with_context(self):
        """Test API query for taskrun with params works with context."""
        owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        project_two = ProjectFactory.create()
        task_runs = TaskRunFactory.create_batch(10, project=project)
        task_runs_two = TaskRunFactory.create_batch(10, project=project_two)

        # Test for real field as anon
        res = self.app.get("/api/taskrun?project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project_two.id, tr


        # Test for real field as auth user but not owner
        res = self.app.get("/api/taskrun?api_key=" + owner.api_key + "&project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 0, data

        # Test for real field as auth user but not owner with all=1j
        res = self.app.get("/api/taskrun?all=1&api_key=" + owner.api_key + "&project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project_two.id, tr


        # Test for real field as owner
        res = self.app.get("/api/taskrun?api_key=" + owner.api_key + "&project_id=" + str(project.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project.id, tr

        # Test for real field as owner
        res = self.app.get("/api/taskrun?all=1&api_key=" + owner.api_key + "&project_id=" + str(project.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project.id, tr

        # Valid field but wrong value
        res = self.app.get("/api/taskrun?project_id=99999999")
        data = json.loads(res.data)
        assert len(data) == 0, data

        res = self.app.get("/api/taskrun?project_id=99999999&api_key=" + owner.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        res = self.app.get("/api/taskrun?project_id=99999999&all=1&api_key=" + owner.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # # Multiple fields
        # res = self.app.get('/api/taskrun?project_id=1&task_id=1')
        # data = json.loads(res.data)
        # # One result
        # assert len(data) == 1, data
        # # Correct result
        # assert data[0]['project_id'] == 1, data
        # assert data[0]['task_id'] == 1, data

        # # Limits
        # res = self.app.get("/api/taskrun?project_id=1&limit=5")
        # data = json.loads(res.data)
        # for item in data:
        #     assert item['project_id'] == 1, item
        # assert len(data) == 5, data

        # # Keyset pagination
        # url = "/api/taskrun?project_id=1&limit=5&last_id=%s" % task_runs[4].id
        # res = self.app.get(url)
        # data = json.loads(res.data)
        # for item in data:
        #     assert item['project_id'] == 1, item
        # assert len(data) == 5, data
        # assert data[0]['id'] == task_runs[5].id, data[0]['id']



    @with_context
    @patch('pybossa.api.task_run.request')
    @patch('pybossa.api.task_run.ContributionsGuard')
    def test_taskrun_anonymous_post(self, guard, mock_request):
        """Test API TaskRun creation and auth for anonymous users"""
        guard.return_value = mock_contributions_guard(True)
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        data = dict(
            project_id=project.id,
            task_id=task.id,
            info='my task result')
        mock_request.data = json.dumps(data)

        # With wrong project_id
        mock_request.remote_addr = '127.0.0.0'
        data['project_id'] = 100000000000000000
        datajson = json.dumps(data)<commit_msg>New tests.<commit_after># -*- coding: utf8 -*-
# This file is part of PyBossa.
#
# Copyright (C) 2015 SciFabric LTD.
#
# PyBossa is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyBossa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with PyBossa.  If not, see <http://www.gnu.org/licenses/>.
import json
from default import with_context, mock_contributions_guard
from nose.tools import assert_equal
from test_api import TestAPI
from mock import patch
from factories import (ProjectFactory, TaskFactory, TaskRunFactory,
                        AnonymousTaskRunFactory, UserFactory)
from pybossa.repositories import ProjectRepository, TaskRepository
from pybossa.repositories import ResultRepository
from pybossa.core import db

project_repo = ProjectRepository(db)
task_repo = TaskRepository(db)
result_repo = ResultRepository(db)


class TestTaskrunAPI(TestAPI):

    def create_result(self, n_results=1, n_answers=1, owner=None,
                      filter_by=False):
        if owner:
            owner = owner
        else:
            owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        tasks = []
        for i in range(n_results):
            tasks.append(TaskFactory.create(n_answers=n_answers,
                                            project=project))
        for i in range(n_answers):
            for task in tasks:
                TaskRunFactory.create(task=task, project=project)
        if filter_by:
            return result_repo.filter_by(project_id=1)
        else:
            return result_repo.get_by(project_id=1)


    @with_context
    def test_taskrun_query_without_params(self):
        """Test API TaskRun query"""
        owner = UserFactory.create()
        user = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        project_two = ProjectFactory.create()
        TaskRunFactory.create_batch(10, project=project,
                                    info={'answer': 'annakarenina'})
        TaskRunFactory.create_batch(10, project=project_two,
                                    info={'answer': 'annakarenina'})

        project_ids = [project.id, project_two.id]
        # As anon, it sould return everything
        res = self.app.get('/api/taskrun')
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # User context should return 0 taskruns as none of them belong to this
        # user.
        res = self.app.get('/api/taskrun?api_key=' + user.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 0, taskruns

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # User context with all=1 should return everything in the DB, even
        # those task runs that do not belong to the user
        res = self.app.get('/api/taskrun?all=1&api_key=' + user.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res

        # Owner should return all the taskruns that belong to his/her
        # projects
        res = self.app.get('/api/taskrun?api_key=' + owner.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 10, taskruns
        for tr in taskruns:
            assert tr['project_id'] == project.id, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # Owner should return all the taskruns that belong to his/her
        # projects and those that do not belong
        res = self.app.get('/api/taskrun?all=1&api_key=' + owner.api_key)
        taskruns = json.loads(res.data)
        assert len(taskruns) == 20, taskruns
        for tr in taskruns:
            assert tr['project_id'] in project_ids, tr
            assert tr['info']['answer'] == 'annakarenina', tr

        # The output should have a mime-type: application/json
        assert res.mimetype == 'application/json', res


    @with_context
    def test_query_taskrun(self):
        """Test API query for taskrun with params works"""
        project = ProjectFactory.create()
        task_runs = TaskRunFactory.create_batch(10, project=project)
        # Test for real field
        res = self.app.get("/api/taskrun?project_id=1")
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        assert data[0]['project_id'] == 1, data

        # Valid field but wrong value
        res = self.app.get("/api/taskrun?project_id=99999999")
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/taskrun?project_id=1&task_id=1')
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['task_id'] == 1, data

        # Limits
        res = self.app.get("/api/taskrun?project_id=1&limit=5")
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data

        # Keyset pagination
        url = "/api/taskrun?project_id=1&limit=5&last_id=%s" % task_runs[4].id
        res = self.app.get(url)
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data
        assert data[0]['id'] == task_runs[5].id, data[0]['id']


    @with_context
    def test_query_taskrun_with_context(self):
        """Test API query for taskrun with params works with context."""
        owner = UserFactory.create()
        project = ProjectFactory.create(owner=owner)
        project_two = ProjectFactory.create()
        task_runs = TaskRunFactory.create_batch(10, project=project)
        task_runs_two = TaskRunFactory.create_batch(10, project=project_two)

        # Test for real field as anon
        res = self.app.get("/api/taskrun?project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project_two.id, tr


        # Test for real field as auth user but not owner
        res = self.app.get("/api/taskrun?api_key=" + owner.api_key + "&project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 0, data

        # Test for real field as auth user but not owner with all=1j
        res = self.app.get("/api/taskrun?all=1&api_key=" + owner.api_key + "&project_id=" + str(project_two.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project_two.id, tr


        # Test for real field as owner
        res = self.app.get("/api/taskrun?api_key=" + owner.api_key + "&project_id=" + str(project.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project.id, tr

        # Test for real field as owner
        res = self.app.get("/api/taskrun?all=1&api_key=" + owner.api_key + "&project_id=" + str(project.id))
        data = json.loads(res.data)
        # Should return one result
        assert len(data) == 10, data
        # Correct result
        for tr in data:
            assert tr['project_id'] == project.id, tr

        # Valid field but wrong value
        res = self.app.get("/api/taskrun?project_id=99999999")
        data = json.loads(res.data)
        assert len(data) == 0, data

        res = self.app.get("/api/taskrun?project_id=99999999&api_key=" + owner.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        res = self.app.get("/api/taskrun?project_id=99999999&all=1&api_key=" + owner.api_key)
        data = json.loads(res.data)
        assert len(data) == 0, data

        # Multiple fields
        res = self.app.get('/api/taskrun?project_id=1&task_id=1')
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['task_id'] == 1, data

        res = self.app.get('/api/taskrun?project_id=1&task_id=1&api_key=' + owner.api_key)
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['task_id'] == 1, data

        res = self.app.get('/api/taskrun?project_id=1&task_id=1&all=1&api_key=' + owner.api_key)
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == 1, data
        assert data[0]['task_id'] == 1, data

        url = '/api/taskrun?project_id=%s&task_id=%s&api_key=%s' % (project_two.id,
                                                                    task_runs_two[0].task_id,
                                                                    owner.api_key)
        res = self.app.get(url)
        data = json.loads(res.data)
        # One result
        assert len(data) == 0, data

        url = '/api/taskrun?all=1&project_id=%s&task_id=%s&api_key=%s' % (project_two.id,
                                                                    task_runs_two[0].task_id,
                                                                    owner.api_key)

        res = self.app.get(url)
        data = json.loads(res.data)
        # One result
        assert len(data) == 1, data
        # Correct result
        assert data[0]['project_id'] == project_two.id, data
        assert data[0]['task_id'] == task_runs_two[0].task_id, data


        # Limits
        res = self.app.get("/api/taskrun?project_id=1&limit=5")
        data = json.loads(res.data)
        for item in data:
            assert item['project_id'] == 1, item
        assert len(data) == 5, data

        # # Keyset pagination
        # url = "/api/taskrun?project_id=1&limit=5&last_id=%s" % task_runs[4].id
        # res = self.app.get(url)
        # data = json.loads(res.data)
        # for item in data:
        #     assert item['project_id'] == 1, item
        # assert len(data) == 5, data
        # assert data[0]['id'] == task_runs[5].id, data[0]['id']



    @with_context
    @patch('pybossa.api.task_run.request')
    @patch('pybossa.api.task_run.ContributionsGuard')
    def test_taskrun_anonymous_post(self, guard, mock_request):
        """Test API TaskRun creation and auth for anonymous users"""
        guard.return_value = mock_contributions_guard(True)
        project = ProjectFactory.create()
        task = TaskFactory.create(project=project)
        data = dict(
            project_id=project.id,
            task_id=task.id,
            info='my task result')
        mock_request.data = json.dumps(data)

        # With wrong project_id
        mock_request.remote_addr = '127.0.0.0'
        data['project_id'] = 100000000000000000
        datajson = json.dumps(data)
{'fraction_non_alphanumeric': 0.11293750271067354, 'fraction_numerical': 0.01392201934336644, 'mean_word_length': 2.281810418445773, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 10, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1988380', 'n_tokens_mistral': 7138, 'n_tokens_neox': 6827, 'n_words': 1806}