<commit_before>from django.test import TestCase
from django.conf import settings
from django.contrib.auth.models import User, Permission, ContentType

from common.models import Project, Settings
from testreport.models import TestPlan
from testreport.models import Launch
from testreport.models import PASSED, FAILED, INIT_SCRIPT, ASYNC_CALL, SKIPPED
from testreport.models import STOPPED

from stages.models import Stage

from metrics.models import Metric, MetricValue

from djcelery.models import PeriodicTask, CrontabSchedule

import json
import random
import os
import base64


class AbstractEntityApiTestCase(TestCase):
    allowed_codes = [200, 201, 400, 403, 404, 415, ]

    user_login = 'user'
    user_plain_password = '<PASSWORD>'

    def setUp(self):
        User.objects.create_user(username=self.user_login,
                                 email='<EMAIL>',
                                 password=self.user_plain_password)
        self.client.login(username=self.user_login,
                          password=self.user_plain_password)

    def _create_project(self, name):
        data = {'name': name}
        return self._call_rest('post', 'projects/', data)

    def _call_rest(self, method, url,
                   data=None, content_type='application/json'):
        http_method = getattr(self.client, method)
        url = '/{0}/{1}'.format(settings.CDWS_API_PATH, url)
        request_data = None
        if data is not None:
            if content_type == 'application/json':
                request_data = json.dumps(data)
            else:
                request_data = data

        response = http_method(url,
                               data=request_data,
                               content_type=content_type)

        if response.status_code not in self.allowed_codes:
            raise IndexError('HTTP status code {0} out of range '
                             'of expected values.'.
                             format(response.status_code))

        if content_type == u'application/json':
            return json.loads(response.content.decode('utf-8',
                                                      errors='replace'))
        else:
            return response


class ProjectApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        super(ProjectApiTestCase, self).setUp()

    def _get_projects(self):
        return self._call_rest('get', 'projects/')

    def test_creation(self):
        project = self._create_project('DummyProject')
        projects = self._get_projects()
        self.assertEqual(len(projects['results']), 1)
        self.assertEqual(project, projects['results'][0])

    def test_duplication(self):
        self._create_project('DummyProject')
        self._create_project('DummyProject')
        self.assertEqual(len(Project.objects.all()), 1)

    def test_add_new_setting(self):
        project = Project.objects.create(name='DummyTestProject')
        data = {'key': 'key', 'value': 'value'}
        self._call_rest('post',
                        'projects/{}/settings/'.format(project.id), data)
        setting = Settings.objects.filter(project_id=project.id)
        self.assertEqual(len(setting), 1)
        self.assertEqual(setting[0].key, 'key')
        self.assertEqual(setting[0].value, 'value')

    def test_update_setting(self):
        project = Project.objects.create(name='DummyTestProject')
        Settings.objects.create(key='key', value='value', project=project)
        data = {'key': 'key', 'value': 'new_value'}
        self._call_rest('post',
                        'projects/{}/settings/'.format(project.id), data)
        setting = Settings.objects.filter(project_id=project.id)
        self.assertEqual(len(setting), 1)
        self.assertEqual(setting[0].key, 'key')
        self.assertEqual(setting[0].value, 'new_value')


class TestPlanApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        project = Project.objects.create(name='DummyTestProject')
        TestPlan.objects.create(name='DummyTestPlan',
                                project=project)
        super(TestPlanApiTestCase, self).setUp()

    def _create_testplan(self, name, project_id,
                         hidden=None, description=None):
        if hidden is not None:
            data = {'name': name, 'project': project_id, 'hidden': hidden}
        elif description is not None:
            data = {'name': name, 'project': project_id,
                    'description': description}
        else:
            data = {'name': name, 'project': project_id}
        return self._call_rest('post', 'testplans/', data)

    def _update_testplan(self, testplan_id, name,
                         hidden=None, main=None,
                         statistic_filter=None, description=None):
        data = {'name': name}
        if main is not None:
            data['main'] = main
        if hidden is not None:
            data['hidden'] = hidden
        if statistic_filter is not None:
            data['filter'] = statistic_filter
        if description is not None:
            data['description'] = description
        return self._call_rest('patch',
                               'testplans/{0}/'.format(testplan_id), data)

    def _tp_execute(self, testplan_id, data):
        return self._call_rest('post',
                               'testplans/{0}/execute/'.format(testplan_id),
                               data)

    def _get_testplans(self, filter=None):
        if filter is not None:
            return self._call_rest('get',
                                   'testplans/custom_list/{}'.format(filter))
        else:
            return self._call_rest('get', 'testplans/')

    def _create_launch_item(self, data):
        return self._call_rest('post', 'launch-items/', data)

    def _get_launch(self, launch_id):
        return self._call_rest('get', 'launches/{}/'.format(launch_id))

    def test_duplication(self):
        project = Project.objects.get(name='DummyTestProject')
        self._create_testplan('DummyTestPlan', project.id)
        self._create_testplan('DummyTestPlan', project.id)
        self.assertEqual(len(self._get_testplans()['results']), 1)

    def test_creation(self):
        project = Project.objects.get(name='DummyTestProject')
        self._create_testplan('DummyTestPlan', project.id)
        self._create_testplan('AnotherDummyTestPlan', project.id)
        self.assertEqual(len(self._get_testplans()['results']), 2)

    def test_hidden_flag(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('HiddenByDefaultTrue', project.id)
        self.assertTrue(data['hidden'])
        data = self._create_testplan('Force hidden false', project.id, False)
        self.assertFalse(data['hidden'])

    def test_main_flag(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('HiddenByDefaultTrue', project.id)
        self.assertFalse(data['main'])

    def test_statistic_filter(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertEquals(testplan.filter, '')

    def test_execute_success(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')

        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        count = random.choice([2, 3, 4, 5])
        for x in range(0, count):
            self._create_launch_item({
                'test_plan': test_plan.id,
                'command': 'touch file_'.format(x),
                'type': ASYNC_CALL,
                'timeout': 10,
            })

        output = self._tp_execute(
            test_plan.id, {'options': {'started_by': 'http://2gis.local/'}})
        launch_id = output['launch_id']
        launch = self._get_launch(launch_id)
        self.assertEqual(len(launch['tasks']), count + 1)

    def test_execute_failure(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')

        output = self._tp_execute(
            test_plan.id,
            {'options': {'started_by': 'http://2gis.local/'}})
        self.assertIsNotNone(output.get('message'))

    def test_deploy_script_duplication(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file2',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        output = self._tp_execute(
            test_plan.id, {'options': {'started_by': 'http://2gis.local/'}})
        launch_id = output['launch_id']
        launch = self._get_launch(launch_id)

        self.assertEqual(len(launch['tasks']), 1, launch['tasks'])

    def test_update_main_flag(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertFalse(testplan.main)
        data = self._update_testplan(testplan.id, testplan.name, main=True)
        self.assertTrue(data['main'])
        data = self._update_testplan(testplan.id, testplan.name, main=False)
        self.assertFalse(data['main'])

    def test_update_hidden_flag(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertTrue(testplan.hidden)
        data = self._update_testplan(testplan.id, testplan.name, hidden=False)
        self.assertFalse(data['hidden'])

    def test_update_name(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        data = self._update_testplan(testplan.id, 'NewDummyTestPlan')
        self.assertEquals('NewDummyTestPlan', data['name'])

    def test_update_parameters(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertEquals(testplan.filter, '')
        data = self._update_testplan(testplan.id, testplan.name,
                                     statistic_filter='regression')
        self.assertEquals(data['filter'], 'regression')

    def test_owner(self):
        login = 'user1'
        password = '<PASSWORD>'
        User.objects.create_user(username=login,
                                 email='<EMAIL>',
                                 password=password)
        self.client.login(username=login,
                          password=password)
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('TestplanWithAnotherOwner', project.id)
        user = User.objects.get(username__exact=login)
        self.assertEqual(data['owner'], user.id)

    def test_filter_in(self):
        projects = [self._create_project('Project1'),
                    self._create_project('Project2')]
        testplans = [self._create_testplan('TP1', projects[0]['id']),
                     self._create_testplan('TP1', projects[1]['id'])]
        url = '?project_id__in={0},{1}'.format(projects[0]['id'],
                                               projects[1]['id'])
        data = self._get_testplans(url)
        self.assertEqual(len(data['results']), len(testplans),
                         'Length of results in response not expected. '
                         'Expected "{0}", actual list:"{1}"'.format(
                             len(testplans),
                             json.dumps(data['results'], indent=4)))
        for testplan in testplans:
            self.assertTrue(
                any(tp['name'] == testplan['name'] for tp in data['results']),
                'Testplan "{0}" not found in response "{1}"'.format(
                    json.dumps(testplan['name'], indent=4),
                    json.dumps(data['results'], indent=4)))

    def test_filter_in_empty(self):
        projects = [self._create_project('P1'),
                    self._create_project('P2')]
        testplans = [self._create_testplan('TP1', projects[0]['id']),
                     self._create_testplan('TP1', projects[1]['id'])]

        data = self._get_testplans('?project_id__in=')
        self.assertEqual(len(data['results']), len(testplans) + 1,
                         'Length of results in response not expected. '
                         'Expected "{0}", actual list:"{1}"'.format(
                             len(testplans) + 1,
                             json.dumps(data['results'], indent=4)))

    def test_task(self):
        task = self._call_rest('get', 'tasks/{}/'.format(1))
        self.assertEqual('PENDING', task['status'])
        self.assertEqual(None, task['result'])

    def test_default_description(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('DefaultDescription', project.id)
        self.assertFalse(data['description'])

    def test_description(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan(
            'DefaultDescription', project.id,
            description='Testplan description textfield for DummyTestProject')
        self.assertEqual(data['description'],
                         'Testplan description textfield for DummyTestProject')

    def test_update_description(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertFalse(testplan.description)
        data = self._update_testplan(testplan.id, testplan.name,
                                     description='Update description')
        self.assertEqual(data['description'], 'Update description')
        data = self._update_testplan(testplan.id, testplan.name,
                                     description='')
        self.assertFalse(data['description'])


class LaunchApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        super(LaunchApiTestCase, self).setUp()
        project = Project.objects.create(name='DummyTestProject')
        TestPlan.objects.create(name='DummyTestPlan', project=project)

    def _create_launch_item(self, data):
        return self._call_rest('post', 'launch-items/', data)

    def _create_launch(self, testplan_id):
        data = {
            'test_plan': testplan_id,
            'started_by': 'http://2gis.local/'
        }
        return self._call_rest('post', 'launches/', data)

    def _get_launch(self, launch_id):
        return self._call_rest('get', 'launches/{}/'.format(launch_id))

    def _terminate_launch(self, testplan_id):
        return self._call_rest(
            'get',
            'launches/{}/terminate_tasks/'.format(testplan_id))

    def get_launches(self):
        return self._call_rest('get', 'launches/')

    def test_creation(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)
        self.assertEqual(len(self.get_launches()['results']), 1)
        self.assertEqual(launch['test_plan'], test_plan.id)

    def test_termination(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'sleep 600',
            'type': INIT_SCRIPT,
            'timeout': 1200,
        })
        launch = self._create_launch(test_plan.id)
        output = self._terminate_launch(launch['id'])
        self.assertEqual(output['message'], 'Termination done.')
        actual_launch = self._get_launch(launch['id'])
        self.assertEqual(actual_launch['state'], STOPPED)

    def test_calculate_counts(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)

        data = [{
            'launch': launch['id'],
            'name': 'DummyTestCase',
            'suite': 'DummyTestSuite',
            'state': PASSED,
            'failure_reason': None,
            'duration': 1
        }, {
            'launch': launch['id'],
            'name': 'SecondDummyTestSuite',
            'suite': 'SecondDummyTestSuite',
            'state': FAILED,
            'failure_reason': 'Exception: Clear message about failure',
            'duration': 5
        }, {
            'launch': launch['id'],
            'name': 'SkipDummyTestSuite',
            'suite': 'SkipDummyTestSuite',
            'state': SKIPPED,
            'failure_reason': None,
            'duration': 0
        }]
        self._call_rest('post', 'testresults/', data)

        response = self._call_rest(
            'get', 'launches/{}/calculate_counts/'.format(launch['id']))
        self.assertEqual('Calculation done.', response['message'])
        actual_launch = self._get_launch(launch['id'])
        self.assertFalse(actual_launch['duration'])
        self.assertEqual(3, actual_launch['counts']['total'])

    def update_duration(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)
        self.assertFalse(launch['duration'])
        response = self._call_rest(
            'patch',
            'launches/{0}/'.format(launch['id']), {'duration': 360})
        self.assertEqual(360, response['duration'])


class TestResultApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):<commit_msg>add omitted prefix for test<commit_after>from django.test import TestCase
from django.conf import settings
from django.contrib.auth.models import User, Permission, ContentType

from common.models import Project, Settings
from testreport.models import TestPlan
from testreport.models import Launch
from testreport.models import PASSED, FAILED, INIT_SCRIPT, ASYNC_CALL, SKIPPED
from testreport.models import STOPPED

from stages.models import Stage

from metrics.models import Metric, MetricValue

from djcelery.models import PeriodicTask, CrontabSchedule

import json
import random
import os
import base64


class AbstractEntityApiTestCase(TestCase):
    allowed_codes = [200, 201, 400, 403, 404, 415, ]

    user_login = 'user'
    user_plain_password = '<PASSWORD>'

    def setUp(self):
        User.objects.create_user(username=self.user_login,
                                 email='<EMAIL>',
                                 password=self.user_plain_password)
        self.client.login(username=self.user_login,
                          password=self.user_plain_password)

    def _create_project(self, name):
        data = {'name': name}
        return self._call_rest('post', 'projects/', data)

    def _call_rest(self, method, url,
                   data=None, content_type='application/json'):
        http_method = getattr(self.client, method)
        url = '/{0}/{1}'.format(settings.CDWS_API_PATH, url)
        request_data = None
        if data is not None:
            if content_type == 'application/json':
                request_data = json.dumps(data)
            else:
                request_data = data

        response = http_method(url,
                               data=request_data,
                               content_type=content_type)

        if response.status_code not in self.allowed_codes:
            raise IndexError('HTTP status code {0} out of range '
                             'of expected values.'.
                             format(response.status_code))

        if content_type == u'application/json':
            return json.loads(response.content.decode('utf-8',
                                                      errors='replace'))
        else:
            return response


class ProjectApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        super(ProjectApiTestCase, self).setUp()

    def _get_projects(self):
        return self._call_rest('get', 'projects/')

    def test_creation(self):
        project = self._create_project('DummyProject')
        projects = self._get_projects()
        self.assertEqual(len(projects['results']), 1)
        self.assertEqual(project, projects['results'][0])

    def test_duplication(self):
        self._create_project('DummyProject')
        self._create_project('DummyProject')
        self.assertEqual(len(Project.objects.all()), 1)

    def test_add_new_setting(self):
        project = Project.objects.create(name='DummyTestProject')
        data = {'key': 'key', 'value': 'value'}
        self._call_rest('post',
                        'projects/{}/settings/'.format(project.id), data)
        setting = Settings.objects.filter(project_id=project.id)
        self.assertEqual(len(setting), 1)
        self.assertEqual(setting[0].key, 'key')
        self.assertEqual(setting[0].value, 'value')

    def test_update_setting(self):
        project = Project.objects.create(name='DummyTestProject')
        Settings.objects.create(key='key', value='value', project=project)
        data = {'key': 'key', 'value': 'new_value'}
        self._call_rest('post',
                        'projects/{}/settings/'.format(project.id), data)
        setting = Settings.objects.filter(project_id=project.id)
        self.assertEqual(len(setting), 1)
        self.assertEqual(setting[0].key, 'key')
        self.assertEqual(setting[0].value, 'new_value')


class TestPlanApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        project = Project.objects.create(name='DummyTestProject')
        TestPlan.objects.create(name='DummyTestPlan',
                                project=project)
        super(TestPlanApiTestCase, self).setUp()

    def _create_testplan(self, name, project_id,
                         hidden=None, description=None):
        if hidden is not None:
            data = {'name': name, 'project': project_id, 'hidden': hidden}
        elif description is not None:
            data = {'name': name, 'project': project_id,
                    'description': description}
        else:
            data = {'name': name, 'project': project_id}
        return self._call_rest('post', 'testplans/', data)

    def _update_testplan(self, testplan_id, name,
                         hidden=None, main=None,
                         statistic_filter=None, description=None):
        data = {'name': name}
        if main is not None:
            data['main'] = main
        if hidden is not None:
            data['hidden'] = hidden
        if statistic_filter is not None:
            data['filter'] = statistic_filter
        if description is not None:
            data['description'] = description
        return self._call_rest('patch',
                               'testplans/{0}/'.format(testplan_id), data)

    def _tp_execute(self, testplan_id, data):
        return self._call_rest('post',
                               'testplans/{0}/execute/'.format(testplan_id),
                               data)

    def _get_testplans(self, filter=None):
        if filter is not None:
            return self._call_rest('get',
                                   'testplans/custom_list/{}'.format(filter))
        else:
            return self._call_rest('get', 'testplans/')

    def _create_launch_item(self, data):
        return self._call_rest('post', 'launch-items/', data)

    def _get_launch(self, launch_id):
        return self._call_rest('get', 'launches/{}/'.format(launch_id))

    def test_duplication(self):
        project = Project.objects.get(name='DummyTestProject')
        self._create_testplan('DummyTestPlan', project.id)
        self._create_testplan('DummyTestPlan', project.id)
        self.assertEqual(len(self._get_testplans()['results']), 1)

    def test_creation(self):
        project = Project.objects.get(name='DummyTestProject')
        self._create_testplan('DummyTestPlan', project.id)
        self._create_testplan('AnotherDummyTestPlan', project.id)
        self.assertEqual(len(self._get_testplans()['results']), 2)

    def test_hidden_flag(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('HiddenByDefaultTrue', project.id)
        self.assertTrue(data['hidden'])
        data = self._create_testplan('Force hidden false', project.id, False)
        self.assertFalse(data['hidden'])

    def test_main_flag(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('HiddenByDefaultTrue', project.id)
        self.assertFalse(data['main'])

    def test_statistic_filter(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertEquals(testplan.filter, '')

    def test_execute_success(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')

        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        count = random.choice([2, 3, 4, 5])
        for x in range(0, count):
            self._create_launch_item({
                'test_plan': test_plan.id,
                'command': 'touch file_'.format(x),
                'type': ASYNC_CALL,
                'timeout': 10,
            })

        output = self._tp_execute(
            test_plan.id, {'options': {'started_by': 'http://2gis.local/'}})
        launch_id = output['launch_id']
        launch = self._get_launch(launch_id)
        self.assertEqual(len(launch['tasks']), count + 1)

    def test_execute_failure(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')

        output = self._tp_execute(
            test_plan.id,
            {'options': {'started_by': 'http://2gis.local/'}})
        self.assertIsNotNone(output.get('message'))

    def test_deploy_script_duplication(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'touch init_file2',
            'type': INIT_SCRIPT,
            'timeout': 10,
        })

        output = self._tp_execute(
            test_plan.id, {'options': {'started_by': 'http://2gis.local/'}})
        launch_id = output['launch_id']
        launch = self._get_launch(launch_id)

        self.assertEqual(len(launch['tasks']), 1, launch['tasks'])

    def test_update_main_flag(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertFalse(testplan.main)
        data = self._update_testplan(testplan.id, testplan.name, main=True)
        self.assertTrue(data['main'])
        data = self._update_testplan(testplan.id, testplan.name, main=False)
        self.assertFalse(data['main'])

    def test_update_hidden_flag(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertTrue(testplan.hidden)
        data = self._update_testplan(testplan.id, testplan.name, hidden=False)
        self.assertFalse(data['hidden'])

    def test_update_name(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        data = self._update_testplan(testplan.id, 'NewDummyTestPlan')
        self.assertEquals('NewDummyTestPlan', data['name'])

    def test_update_parameters(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertEquals(testplan.filter, '')
        data = self._update_testplan(testplan.id, testplan.name,
                                     statistic_filter='regression')
        self.assertEquals(data['filter'], 'regression')

    def test_owner(self):
        login = 'user1'
        password = '<PASSWORD>'
        User.objects.create_user(username=login,
                                 email='<EMAIL>',
                                 password=password)
        self.client.login(username=login,
                          password=password)
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('TestplanWithAnotherOwner', project.id)
        user = User.objects.get(username__exact=login)
        self.assertEqual(data['owner'], user.id)

    def test_filter_in(self):
        projects = [self._create_project('Project1'),
                    self._create_project('Project2')]
        testplans = [self._create_testplan('TP1', projects[0]['id']),
                     self._create_testplan('TP1', projects[1]['id'])]
        url = '?project_id__in={0},{1}'.format(projects[0]['id'],
                                               projects[1]['id'])
        data = self._get_testplans(url)
        self.assertEqual(len(data['results']), len(testplans),
                         'Length of results in response not expected. '
                         'Expected "{0}", actual list:"{1}"'.format(
                             len(testplans),
                             json.dumps(data['results'], indent=4)))
        for testplan in testplans:
            self.assertTrue(
                any(tp['name'] == testplan['name'] for tp in data['results']),
                'Testplan "{0}" not found in response "{1}"'.format(
                    json.dumps(testplan['name'], indent=4),
                    json.dumps(data['results'], indent=4)))

    def test_filter_in_empty(self):
        projects = [self._create_project('P1'),
                    self._create_project('P2')]
        testplans = [self._create_testplan('TP1', projects[0]['id']),
                     self._create_testplan('TP1', projects[1]['id'])]

        data = self._get_testplans('?project_id__in=')
        self.assertEqual(len(data['results']), len(testplans) + 1,
                         'Length of results in response not expected. '
                         'Expected "{0}", actual list:"{1}"'.format(
                             len(testplans) + 1,
                             json.dumps(data['results'], indent=4)))

    def test_task(self):
        task = self._call_rest('get', 'tasks/{}/'.format(1))
        self.assertEqual('PENDING', task['status'])
        self.assertEqual(None, task['result'])

    def test_default_description(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan('DefaultDescription', project.id)
        self.assertFalse(data['description'])

    def test_description(self):
        project = Project.objects.get(name='DummyTestProject')
        data = self._create_testplan(
            'DefaultDescription', project.id,
            description='Testplan description textfield for DummyTestProject')
        self.assertEqual(data['description'],
                         'Testplan description textfield for DummyTestProject')

    def test_update_description(self):
        testplan = TestPlan.objects.get(name='DummyTestPlan')
        self.assertFalse(testplan.description)
        data = self._update_testplan(testplan.id, testplan.name,
                                     description='Update description')
        self.assertEqual(data['description'], 'Update description')
        data = self._update_testplan(testplan.id, testplan.name,
                                     description='')
        self.assertFalse(data['description'])


class LaunchApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
        super(LaunchApiTestCase, self).setUp()
        project = Project.objects.create(name='DummyTestProject')
        TestPlan.objects.create(name='DummyTestPlan', project=project)

    def _create_launch_item(self, data):
        return self._call_rest('post', 'launch-items/', data)

    def _create_launch(self, testplan_id):
        data = {
            'test_plan': testplan_id,
            'started_by': 'http://2gis.local/'
        }
        return self._call_rest('post', 'launches/', data)

    def _get_launch(self, launch_id):
        return self._call_rest('get', 'launches/{}/'.format(launch_id))

    def _terminate_launch(self, testplan_id):
        return self._call_rest(
            'get',
            'launches/{}/terminate_tasks/'.format(testplan_id))

    def get_launches(self):
        return self._call_rest('get', 'launches/')

    def test_creation(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)
        self.assertEqual(len(self.get_launches()['results']), 1)
        self.assertEqual(launch['test_plan'], test_plan.id)

    def test_termination(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        self._create_launch_item({
            'test_plan': test_plan.id,
            'command': 'sleep 600',
            'type': INIT_SCRIPT,
            'timeout': 1200,
        })
        launch = self._create_launch(test_plan.id)
        output = self._terminate_launch(launch['id'])
        self.assertEqual(output['message'], 'Termination done.')
        actual_launch = self._get_launch(launch['id'])
        self.assertEqual(actual_launch['state'], STOPPED)

    def test_calculate_counts(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)

        data = [{
            'launch': launch['id'],
            'name': 'DummyTestCase',
            'suite': 'DummyTestSuite',
            'state': PASSED,
            'failure_reason': None,
            'duration': 1
        }, {
            'launch': launch['id'],
            'name': 'SecondDummyTestSuite',
            'suite': 'SecondDummyTestSuite',
            'state': FAILED,
            'failure_reason': 'Exception: Clear message about failure',
            'duration': 5
        }, {
            'launch': launch['id'],
            'name': 'SkipDummyTestSuite',
            'suite': 'SkipDummyTestSuite',
            'state': SKIPPED,
            'failure_reason': None,
            'duration': 0
        }]
        self._call_rest('post', 'testresults/', data)

        response = self._call_rest(
            'get', 'launches/{}/calculate_counts/'.format(launch['id']))
        self.assertEqual('Calculation done.', response['message'])
        actual_launch = self._get_launch(launch['id'])
        self.assertFalse(actual_launch['duration'])
        self.assertEqual(3, actual_launch['counts']['total'])

    def test_update_duration(self):
        test_plan = TestPlan.objects.get(name='DummyTestPlan')
        launch = self._create_launch(test_plan.id)
        self.assertFalse(launch['duration'])
        response = self._call_rest(
            'patch',
            'launches/{0}/'.format(launch['id']), {'duration': 360})
        self.assertEqual(360, response['duration'])


class TestResultApiTestCase(AbstractEntityApiTestCase):
    def setUp(self):
{'fraction_non_alphanumeric': 0.1270920351433098, 'fraction_numerical': 0.0061068702290076335, 'mean_word_length': 2.3721223895094705, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1020915', 'n_tokens_mistral': 9996, 'n_tokens_neox': 9622, 'n_words': 1713}