def setUp(self): super().setUp() setup_models(self) machine_workflow_version = ( self.workflow_versions['machine_workflow_version']) self.step = machine_workflow_version.steps.get(slug='machine_step') self.assertIsNotNone(self.step) self.step.execution_function = { 'path': 'orchestra.tests.helpers.workflow.machine_task_function', } self.step.save() patcher = patch( 'orchestra.tests.helpers.workflow.machine_task_function', return_value={'data': ''}) self.machine_function_mock = patcher.start() self.addCleanup(patcher.stop) self.project = ProjectFactory( workflow_version=machine_workflow_version) create_subsequent_tasks(self.project) self.task = self.project.tasks.first() self.assertIsNotNone(self.task) # Since create_subsequent_tasks will automatically run the machine task # we need to reset the task each time it's called self._reset_task()
def test_message_project_team(self, mock_message_slack_group): project = ProjectFactory(slack_group_id='test-project-1') url = '/orchestra/api/project/message_project_team/' test_message = 'this is a test message' response = self.api_client.post(url, { 'message': test_message, 'project_id': project.id }, format='json') self.assertEqual(response.status_code, 200) self.assertTrue(mock_message_slack_group.called) # No project id provided response = self.api_client.post(url, {'message': test_message}, format='json') self.assertEqual(response.status_code, 400) self.assertEqual( response.json()['message'], ('An object with `message` and `project_id` attributes' ' should be supplied')) # No message provided response = self.api_client.post(url, {'project_id': project.id}, format='json') self.assertEqual(response.status_code, 400) self.assertEqual( response.json()['message'], ('An object with `message` and `project_id` attributes' ' should be supplied')) # Non-existent project_id provided response = self.api_client.post(url, { 'message': 'text', 'project_id': 123456 }, format='json') self.assertEqual(response.status_code, 400) self.assertEqual(response.json()['message'], 'No project for given id')
def setUp(self): super().setUp() self.request_client = APIClient(enforce_csrf_checks=True) self.request_client.force_authenticate(user=SignedUser()) self.workflow_version = WorkflowVersionFactory() self.step = StepFactory(slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory(workflow_version=self.workflow_version)
def setUp(self): super().setUp() setup_models(self) self.workflow_version = WorkflowVersionFactory() self.step = StepFactory( slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory( workflow_version=self.workflow_version)
def test_create_project_slack_group(self): groups = self.slack.data['groups'] num_groups = len(groups) project = ProjectFactory( workflow_version=self.workflow_versions['test_workflow']) self.assertFalse(project.id in groups) group_id = create_project_slack_group(project) self.assertEquals(len(groups), num_groups + 1) self.assertTrue(group_id in groups) project = Project.objects.get(id=project.id) self.assertEquals(group_id, project.slack_group_id)
def setUp(self): super().setUp() self.request_client = APIClient(enforce_csrf_checks=True) self.request_client.force_authenticate(user=SignedUser()) setup_models(self) self.workflow_version = WorkflowVersionFactory() self.step = StepFactory(slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory(workflow_version=self.workflow_version) self.list_url = reverse('orchestra:api:todo-api-list') self.todo = TodoFactory(project=self.project) self.todo_with_step = TodoFactory(project=self.project, step=self.step)
def setUp(self): super().setUp() self.request_client = APIClient(enforce_csrf_checks=True) self.request_client.force_authenticate(user=SignedUser()) self.todolist_template_slug = 'test_todolist_template_slug' self.todolist_template_name = 'test_todolist_template_name' self.todolist_template_description = \ 'test_todolist_template_description' self.workflow_version = WorkflowVersionFactory() self.step = StepFactory(slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory(workflow_version=self.workflow_version)
def setUp(self): super().setUp() setup_models(self) self.worker = Worker.objects.get(user__username='******') self.request_client.login(username=self.worker.user.username, password='******') self.todolist_template_list_url = reverse( 'orchestra:todos:todolist_templates') self.todolist_template_detail_url_name = \ 'orchestra:todos:todolist_template' self.todolist_template_slug = 'test_todolist_template_slug' self.todolist_template_name = 'test_todolist_template_name' self.todolist_template_description = \ 'test_todolist_template_description' self.workflow_version = WorkflowVersionFactory() self.step = StepFactory(slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory(workflow_version=self.workflow_version) self.project2 = ProjectFactory() tasks = Task.objects.filter(assignments__worker=self.worker) self.task = tasks[0] self.task.project = self.project self.task.step = self.step self.task.save()
def setUp(self): super().setUp() setup_models(self) self.worker = Worker.objects.get(user__username='******') self.request_client.login(username=self.worker.user.username, password='******') self.list_create_url = reverse('orchestra:todos:todo_qas') self.worker_task_recent_todo_qas_url = reverse( 'orchestra:todos:worker_task_recent_todo_qas') self.list_details_url_name = 'orchestra:todos:todo_qa' self.project0 = ProjectFactory() self.project1 = ProjectFactory() self.step = StepFactory(slug='some-slug') tasks = Task.objects.filter(assignments__worker=self.worker) self.task_0 = tasks[0] self.task_0.project = self.project0 self.task_0.step = self.step self.task_0.save() self.task_1 = tasks[1] self.task_1.project = self.project1 self.task_1.step = self.step self.task_1.save() self.todo = TodoFactory(project=self.project0, step=self.step) self.comment = 'Test comment'
def test_get_todos(self, mock_request): # This converts `requests.get` into DRF's `APIClient.get` # To make it testable def get(url, *args, **kwargs): return_value = self.request_client.get(url, format='json') return_value.text = json.dumps(return_value.data) return return_value mock_request.get = get step_1 = StepFactory(slug='step_1') step_2 = StepFactory(slug='step_2') project2 = ProjectFactory() # 2 todos have the same project todo1 = TodoFactory(step=step_1, project=self.project) todo2 = TodoFactory(step=step_1, project=self.project) # 1 todo has another project todo3 = TodoFactory(step=step_2, project=project2) todo4 = TodoFactory(step=step_1, project=project2) # Get todo1 and todo2 res = get_todos(self.project.id, step_1.slug) self.assertEqual(len(res), 2) expected_ids = [todo1.id, todo2.id] for r in res: self.assertIn(r['id'], expected_ids) # Get todo3 res = get_todos(project2.id, step_2.slug) self.assertEqual(len(res), 1) self.assertEqual(res[0]['id'], todo3.id) # Filter by project_id res = get_todos(project_id=project2.id) self.assertEqual(len(res), 2) expected_ids = [todo3.id, todo4.id] for r in res: self.assertIn(r['id'], expected_ids) # Test project_id is required msg = 'project_id is required' with self.assertRaisesMessage(OrchestraError, msg): get_todos(None)
def setUp(self): super().setUp() project = ProjectFactory() step = StepFactory() self.old_title = 'Old title' self.new_title = 'New title' self.old_details = 'Old details' self.new_details = 'New details' self.old_todo = TodoFactory(title=self.old_title, details=self.old_details, completed=False, project=project, step=step) self.new_todo = TodoFactory(title=self.new_title, details=self.new_details, completed=True, project=project, step=step) self.sender = UserFactory()
def setUp(self): super().setUp() setup_models(self) self.worker = Worker.objects.get(user__username='******') self.request_client.login(username=self.worker.user.username, password='******') self.list_create_url = reverse('orchestra:todos:todos-list') self.list_details_url_name = 'orchestra:todos:todos-detail' self.workflow_version = WorkflowVersionFactory() self.step = StepFactory(slug='step-slug', workflow_version=self.workflow_version) self.project = ProjectFactory(workflow_version=self.workflow_version) tasks = Task.objects.filter(assignments__worker=self.worker) task = tasks[0] task.project = self.project task.step = self.step task.save() self.todo_title = 'Let us do this' self.deadline = parse('2018-01-16T07:03:00+00:00')
def test_dangerous_sql(self): project = ProjectFactory() TodoFactory(project=project) dangerous_sql = ("if ((select user) = 'sa'" " OR (select user) = 'dbo') select 1 else select 1/0") url_params = build_url_params( project.id, None, **{'additional_data__sql': dangerous_sql}) kwargs = self._get_qs_kwargs(GenericTodoViewset, url_params) # kwargs doesn't contain additional_data__sql field self.assertEqual(kwargs, {'project__id': str(project.id)}) url_params = build_url_params(project.id, None, **{'title': dangerous_sql}) kwargs = self._get_qs_kwargs(GenericTodoViewset, url_params) todos = Todo.objects.filter(**kwargs) self.assertEqual(kwargs, { 'project__id': str(project.id), 'title': dangerous_sql }) self.assertTrue(todos.count, 0)
class MachineTaskTestCase(OrchestraTestCase): def setUp(self): super().setUp() setup_models(self) machine_workflow_version = ( self.workflow_versions['machine_workflow_version']) self.step = machine_workflow_version.steps.get(slug='machine_step') self.assertIsNotNone(self.step) self.step.execution_function = { 'path': 'orchestra.tests.helpers.workflow.machine_task_function', } self.step.save() patcher = patch( 'orchestra.tests.helpers.workflow.machine_task_function', return_value={'data': ''}) self.machine_function_mock = patcher.start() self.addCleanup(patcher.stop) self.project = ProjectFactory( workflow_version=machine_workflow_version) create_subsequent_tasks(self.project) self.task = self.project.tasks.first() self.assertIsNotNone(self.task) # Since create_subsequent_tasks will automatically run the machine task # we need to reset the task each time it's called self._reset_task() def _reset_task(self): self.task.status = Task.Status.AWAITING_PROCESSING self.task.save() self.task.assignments.all().delete() self.machine_function_mock.call_count = 0 def _assert_correct_machine_task_state( self, assignment_status, task_status): self.task.refresh_from_db() assignment = self.task.assignments.first() self.assertEquals(assignment.status, assignment_status) self.assertEquals(self.task.status, task_status) # Check correct iteration state self.assertEquals(assignment.iterations.count(), 1) iteration = assignment.iterations.first() if task_status == Task.Status.COMPLETE: expected_status = Iteration.Status.REQUESTED_REVIEW expected_data = assignment.in_progress_task_data self.assertIsNotNone(iteration.end_datetime) else: expected_status = Iteration.Status.PROCESSING expected_data = {} self.assertIsNone(iteration.end_datetime) self.assertEquals(iteration.status, expected_status) self.assertEquals(iteration.submitted_data, expected_data) # Assert that machine function is called once and there is only one # assignment regardless of state self.assertEquals(self.machine_function_mock.call_count, 1) self.assertEquals(self.task.assignments.count(), 1) def test_new_task(self): self._reset_task() execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.SUBMITTED, Task.Status.COMPLETE) def test_already_processing_task(self): self._reset_task() execute(self.project.id, self.step.slug) # Pretend that the task is still processing self.task.status = Task.Status.PROCESSING self.task.save() assignment = self.task.assignments.first() assignment.status = TaskAssignment.Status.PROCESSING assignment.save() # Reset iteration for assignment assignment.iterations.all().delete() Iteration.objects.create( assignment=assignment, start_datetime=assignment.start_datetime) # Another machine attempts to perform task with self.assertRaises(MachineExecutionError): execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.PROCESSING, Task.Status.PROCESSING) def test_already_completed_task(self): self._reset_task() execute(self.project.id, self.step.slug) with self.assertRaises(MachineExecutionError): execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.SUBMITTED, Task.Status.COMPLETE) @patch('orchestra.machine_tasks.logger') def test_marking_failed_task_assignment(self, mock_logger): self.machine_function_mock.side_effect = Exception('Function failed.') self._reset_task() execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.FAILED, Task.Status.PROCESSING) mock_logger.exception.assert_called_with('Machine task has failed') self.machine_function_mock.side_effect = None def test_reassigning_failed_task_assignment(self): self._reset_task() execute(self.project.id, self.step.slug) # Pretend that the machine task failed self.task.status = Task.Status.PROCESSING self.task.save() assignment = self.task.assignments.first() assignment.status = TaskAssignment.Status.FAILED assignment.save() self.assertEquals(self.machine_function_mock.call_count, 1) self.machine_function_mock.call_count = 0 # New machine picks up the failed task execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.SUBMITTED, Task.Status.COMPLETE) def test_aborted_project(self): self._reset_task() self.project.status = Project.Status.ABORTED self.project.save() self.task.status = Task.Status.PROCESSING self.task.save() execute(self.project.id, self.step.slug) self._assert_correct_machine_task_state( TaskAssignment.Status.SUBMITTED, Task.Status.ABORTED)
def test_todo_qas_create_permissions(self): # Can't make requests for projects in which you're uninvolved. project = ProjectFactory() step = StepFactory() todo = TodoFactory(project=project, step=step) self._verify_todo_qa_creation(todo, False)
def test_todos_list_create_permissions(self): # Can't make requests for projects in which you're uninvolved. project = ProjectFactory() step = StepFactory() self._verify_todos_list(project.id, [], False) self._verify_todo_creation(False, project.id, step)