def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked["typeInfo"]["workflowType"]["name"], version=mocked["typeInfo"]["workflowType"]["version"], status=mocked["typeInfo"]["status"], creation_date=mocked["typeInfo"]["creationDate"], deprecation_date=mocked["typeInfo"]["deprecationDate"], task_list=mocked["configuration"]["defaultTaskList"]["name"], child_policy=mocked["configuration"]["defaultChildPolicy"], execution_timeout=mocked["configuration"][ "defaultExecutionStartToCloseTimeout" ], decision_tasks_timeout=mocked["configuration"][ "defaultTaskStartToCloseTimeout" ], description=mocked["typeInfo"]["description"], ) diffs = workflow_type._diff() self.assertLength(diffs, 0)
def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration'] ['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration'] ['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type._diff() self.assertEqual(len(diffs), 0)
def test___diff_with_different_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type", version="different-version" ) diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertLength(diffs, 6) self.assertTrue(hasattr(diffs[0], "attr")) self.assertTrue(hasattr(diffs[0], "local")) self.assertTrue(hasattr(diffs[0], "upstream"))
def test_is_synced_over_non_existent_workflow_type(self): with patch.object(Layer1, 'describe_workflow_type', mock_describe_workflow_type): workflow_type = WorkflowType(self.domain, "non-existent-workflow-type", version="non-existent-version") self.assertFalse(workflow_type.is_synced)
def test_is_synced_over_non_existent_workflow_execution(self): with patch.object(Layer1, 'describe_workflow_execution', mock_describe_workflow_execution): workflow_execution = WorkflowExecution( self.domain, WorkflowType(self.domain, "NonExistentTestType", "1.0"), "non-existent-id") self.assertFalse(workflow_execution.is_synced)
def test___diff_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType(self.domain, "different-workflow-type", version="different-version") diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream'))
def to_WorkflowType(self, domain, workflow_info, **kwargs): # Not using get_subkey in order for it to explictly # raise when workflowType name doesn't exist for example return WorkflowType(domain, workflow_info['workflowType']['name'], workflow_info['workflowType']['version'], status=workflow_info['status'], **kwargs)
def test_init_with_invalid_child_policy(self): with self.assertRaises(ValueError): WorkflowType( self.domain, "TestType", "1.0", child_policy="FAILING_POLICY" )
def setUp(self): self.domain = Domain("TestDomain") self.wt = WorkflowType(self.domain, "TestType", "1.0") self.we = WorkflowExecution( self.domain, self.wt, "TestType-0.1-TestDomain" )
def test___diff_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type", version="different-version" ) diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream'))
def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration']['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration']['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type._diff() self.assertEqual(len(diffs), 0)
def test_changes_with_different_workflow_execution(self): with patch.object( Layer1, "describe_workflow_execution", mock_describe_workflow_execution, ): workflow_execution = WorkflowExecution( self.domain, WorkflowType(self.domain, "NonExistentTestType", "1.0"), "non-existent-id", ) diffs = workflow_execution.changes self.assertIsNotNone(diffs) self.assertLength(diffs, 7) self.assertTrue(hasattr(diffs[0], "attr")) self.assertTrue(hasattr(diffs[0], "local")) self.assertTrue(hasattr(diffs[0], "upstream"))
def to_WorkflowExecution(self, domain, execution_info, **kwargs): workflow_type = WorkflowType( self.domain, execution_info['workflowType']['name'], execution_info['workflowType']['version'] ) return WorkflowExecution( domain, get_subkey(execution_info, ['execution', 'workflowId']), # workflow_id run_id=get_subkey(execution_info, ['execution', 'runId']), workflow_type=workflow_type, status=execution_info.get('executionStatus'), close_status=execution_info.get('closeStatus'), tag_list=execution_info.get('tagList'), **kwargs )
def test_changes_with_different_workflow_execution(self): with patch.object( Layer1, 'describe_workflow_execution', mock_describe_workflow_execution, ): workflow_execution = WorkflowExecution( self.domain, WorkflowType(self.domain, "NonExistentTestType", "1.0"), "non-existent-id") diffs = workflow_execution.changes self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 7) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream'))
def to_WorkflowExecution(self, domain, execution_info, **kwargs): workflow_type = WorkflowType(self.domain, execution_info['workflowType']['name'], execution_info['workflowType']['version']) return WorkflowExecution( domain, get_subkey(execution_info, ['execution', 'workflowId']), # workflow_id run_id=get_subkey(execution_info, ['execution', 'runId']), workflow_type=workflow_type, status=execution_info.get('executionStatus'), close_status=execution_info.get('closeStatus'), tag_list=execution_info.get('tagList'), start_timestamp=execution_info.get('startTimestamp'), close_timestamp=execution_info.get('closeTimestamp'), cancel_requested=execution_info.get('cancelRequested'), parent=execution_info.get('parent'), **kwargs)
def to_WorkflowExecution(self, domain, execution_info, **kwargs): workflow_type = WorkflowType( self.domain, execution_info["workflowType"]["name"], execution_info["workflowType"]["version"], ) return WorkflowExecution( domain, get_subkey(execution_info, ["execution", "workflowId"]), # workflow_id run_id=get_subkey(execution_info, ["execution", "runId"]), workflow_type=workflow_type, status=execution_info.get("executionStatus"), close_status=execution_info.get("closeStatus"), tag_list=execution_info.get("tagList"), start_timestamp=execution_info.get("startTimestamp"), close_timestamp=execution_info.get("closeTimestamp"), cancel_requested=execution_info.get("cancelRequested"), parent=execution_info.get("parent"), **kwargs )
def poll(self, task_list=None, identity=None, **kwargs): """ Polls a decision task and returns the token and the full history of the workflow's events. :param task_list: task list to poll for decision tasks from. :type task_list: str :param identity: Identity of the decider making the request, which is recorded in the DecisionTaskStarted event in the workflow history. :type identity: str :returns: a Response object with history, token, and execution set :rtype: swf.responses.Response """ logging_context.reset() task_list = task_list or self.task_list task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=format.identity(identity), **kwargs) token = task.get("taskToken") if not token: raise PollTimeout("Decider poll timed out") events = task["events"] logging_context.set("workflow_id", task["workflowExecution"]["workflowId"]) logging_context.set("task_type", "decision") logging_context.set("event_id", task["startedEventId"]) next_page = task.get("nextPageToken") while next_page: try: task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=format.identity(identity), next_page_token=next_page, **kwargs) except boto.exception.SWFResponseError as e: message = self.get_error_message(e) if e.error_code == "UnknownResourceFault": raise DoesNotExistError( "Unable to poll decision task", message, ) raise ResponseError(message) token = task.get("taskToken") if not token: raise PollTimeout("Decider poll timed out") events.extend(task["events"]) next_page = task.get("nextPageToken") history = History.from_event_list(events) workflow_type = WorkflowType( domain=self.domain, name=task["workflowType"]["name"], version=task["workflowType"]["version"], ) execution = WorkflowExecution( domain=self.domain, workflow_id=task["workflowExecution"]["workflowId"], run_id=task["workflowExecution"]["runId"], workflow_type=workflow_type, ) # TODO: move history into execution (needs refactoring on WorkflowExecution.history()) return Response(token=token, history=history, execution=execution)
def setUp(self): self.domain = Domain("TestDomain") self.wt = WorkflowType(self.domain, "TestType", "0.1") self.weq = WorkflowExecutionQuerySet(self.domain)
def create( self, name, version, status=REGISTERED, creation_date=0.0, deprecation_date=0.0, task_list=None, child_policy=CHILD_POLICIES.TERMINATE, execution_timeout="300", decision_tasks_timeout="300", description=None, *args, **kwargs ): """Creates a new remote workflow type and returns the created WorkflowType model instance. :param name: name of the workflow type :type name: String :param version: workflow type version :type version: String :param status: workflow type status :type status: swf.core.ConnectedSWFObject.{REGISTERED, DEPRECATED} :param creation_date: creation date of the current WorkflowType :type creation_date: float (timestamp) :param deprecation_date: deprecation date of WorkflowType :type deprecation_date: float (timestamp) :param task_list: task list to use for scheduling decision tasks for executions of this workflow type :type task_list: String :param child_policy: policy to use for the child workflow executions when a workflow execution of this type is terminated :type child_policy: CHILD_POLICIES.{TERMINATE | REQUEST_CANCEL | ABANDON} :param execution_timeout: maximum duration for executions of this workflow type :type execution_timeout: String :param decision_tasks_timeout: maximum duration of decision tasks for this workflow type :type decision_tasks_timeout: String :param description: Textual description of the workflow type :type description: String """ workflow_type = WorkflowType( self.domain, name, version, status=status, creation_date=creation_date, deprecation_date=deprecation_date, task_list=task_list, child_policy=child_policy, execution_timeout=execution_timeout, decision_tasks_timeout=decision_tasks_timeout, description=description, ) workflow_type.save() return workflow_type
class TestWorkflowType(unittest2.TestCase): def setUp(self): self.domain = Domain("test-domain") self.wt = WorkflowType(self.domain, "TestType", "1.0") def tearDown(self): pass def test_init_with_invalid_child_policy(self): with self.assertRaises(ValueError): WorkflowType( self.domain, "TestType", "1.0", child_policy="FAILING_POLICY" ) def test___diff_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type", version="different-version" ) diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream')) def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration']['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration']['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type._diff() self.assertEqual(len(diffs), 0) def test_exists_with_existing_workflow_type(self): with patch.object(Layer1, 'describe_workflow_type'): self.assertTrue(self.wt.exists) def test_exists_with_non_existent_workflow_type(self): with patch.object(self.wt.connection, 'describe_workflow_type') as mock: mock.side_effect = SWFResponseError( 400, "Bad Request:", {'__type': 'com.amazonaws.swf.base.model#UnknownResourceFault', 'message': 'Unknown type: WorkflowType=[workflowId=blah, runId=test]'}, 'UnknownResourceFault', ) self.assertFalse(self.wt.exists) def test_workflow_type_exists_with_whatever_error(self): with patch.object(self.wt.connection, 'describe_workflow_type') as mock: with self.assertRaises(ResponseError): mock.side_effect = SWFResponseError( 400, "mocking exception", { '__type': 'WhateverError', 'message': 'Whatever' } ) self.domain.exists def test_is_synced_with_unsynced_workflow_type(self): pass def test_is_synced_with_synced_workflow_type(self): pass def test_is_synced_over_non_existent_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type ): workflow_type = WorkflowType( self.domain, "non-existent-workflow-type", version="non-existent-version" ) self.assertFalse(workflow_type.is_synced) def test_changes_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type-type", version="different-workflow-type-type-version" ) diffs = workflow_type.changes self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream')) def test_workflow_type_changes_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration']['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration']['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type.changes self.assertEqual(len(diffs), 0) def test_save_already_existing_type(self): with patch.object(self.wt.connection, 'register_workflow_type') as mock: with self.assertRaises(AlreadyExistsError): mock.side_effect = SWFTypeAlreadyExistsError(400, "mocked exception") self.wt.save() def test_save_with_response_error(self): with patch.object(self.wt.connection, 'register_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", { "__type": "UnknownResourceFault", "message": "Whatever" } ) self.wt.save() def test_delete_non_existent_type(self): with patch.object(self.wt.connection, 'deprecate_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", { "__type": "UnknownResourceFault", "message": "Whatever" } ) self.wt.delete() def test_delete_deprecated_type(self): with patch.object(self.wt.connection, 'deprecate_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", { "__type": "TypeDeprecatedFault", "message": "Whatever" } ) self.wt.delete()
def create(self, name, version, status=REGISTERED, creation_date=0.0, deprecation_date=0.0, task_list=None, child_policy=CHILD_POLICIES.TERMINATE, execution_timeout='300', decision_tasks_timeout='300', description=None, *args, **kwargs): """Creates a new remote workflow type and returns the created WorkflowType model instance. :param name: name of the workflow type :type name: String :param version: workflow type version :type version: String :param status: workflow type status :type status: swf.core.ConnectedSWFObject.{REGISTERED, DEPRECATED} :param creation_date: creation date of the current WorkflowType :type creation_date: float (timestamp) :param deprecation_date: deprecation date of WorkflowType :type deprecation_date: float (timestamp) :param task_list: task list to use for scheduling decision tasks for executions of this workflow type :type task_list: String :param child_policy: policy to use for the child workflow executions when a workflow execution of this type is terminated :type child_policy: CHILD_POLICIES.{TERMINATE | REQUEST_CANCEL | ABANDON} :param execution_timeout: maximum duration for executions of this workflow type :type execution_timeout: String :param decision_tasks_timeout: maximum duration of decision tasks for this workflow type :type decision_tasks_timeout: String :param description: Textual description of the workflow type :type description: String """ workflow_type = WorkflowType( self.domain, name, version, status=status, creation_date=creation_date, deprecation_date=deprecation_date, task_list=task_list, child_policy=child_policy, execution_timeout=execution_timeout, decision_tasks_timeout=decision_tasks_timeout, description=description ) workflow_type.save() return workflow_type
def setUp(self): self.domain = Domain("test-domain") self.wt = WorkflowType(self.domain, "TestType", "1.0")
class TestWorkflowType(unittest.TestCase, CustomAssertions): def setUp(self): self.domain = Domain("test-domain") self.wt = WorkflowType(self.domain, "TestType", "1.0") def tearDown(self): pass def test_init_with_invalid_child_policy(self): with self.assertRaises(ValueError): WorkflowType(self.domain, "TestType", "1.0", child_policy="FAILING_POLICY") def test___diff_with_different_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type", version="different-version" ) diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertLength(diffs, 6) self.assertTrue(hasattr(diffs[0], "attr")) self.assertTrue(hasattr(diffs[0], "local")) self.assertTrue(hasattr(diffs[0], "upstream")) def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked["typeInfo"]["workflowType"]["name"], version=mocked["typeInfo"]["workflowType"]["version"], status=mocked["typeInfo"]["status"], creation_date=mocked["typeInfo"]["creationDate"], deprecation_date=mocked["typeInfo"]["deprecationDate"], task_list=mocked["configuration"]["defaultTaskList"]["name"], child_policy=mocked["configuration"]["defaultChildPolicy"], execution_timeout=mocked["configuration"][ "defaultExecutionStartToCloseTimeout" ], decision_tasks_timeout=mocked["configuration"][ "defaultTaskStartToCloseTimeout" ], description=mocked["typeInfo"]["description"], ) diffs = workflow_type._diff() self.assertLength(diffs, 0) def test_exists_with_existing_workflow_type(self): with patch.object(Layer1, "describe_workflow_type"): self.assertTrue(self.wt.exists) def test_exists_with_non_existent_workflow_type(self): with patch.object(self.wt.connection, "describe_workflow_type") as mock: mock.side_effect = SWFResponseError( 400, "Bad Request:", { "__type": "com.amazonaws.swf.base.model#UnknownResourceFault", "message": "Unknown type: WorkflowType=[workflowId=blah, runId=test]", }, "UnknownResourceFault", ) self.assertFalse(self.wt.exists) # TODO: fix test when no network (probably hits real SWF endpoints) @unittest.skip("Skip it in case there's no network connection.") def test_workflow_type_exists_with_whatever_error(self): with patch.object(self.wt.connection, "describe_workflow_type") as mock: with self.assertRaises(ResponseError): mock.side_effect = SWFResponseError( 400, "mocking exception", {"__type": "WhateverError", "message": "Whatever"}, ) dummy = self.domain.exists def test_is_synced_with_unsynced_workflow_type(self): pass def test_is_synced_with_synced_workflow_type(self): pass def test_is_synced_over_non_existent_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type ): workflow_type = WorkflowType( self.domain, "non-existent-workflow-type", version="non-existent-version", ) self.assertFalse(workflow_type.is_synced) def test_changes_with_different_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type-type", version="different-workflow-type-type-version", ) diffs = workflow_type.changes self.assertIsNotNone(diffs) self.assertLength(diffs, 6) self.assertTrue(hasattr(diffs[0], "attr")) self.assertTrue(hasattr(diffs[0], "local")) self.assertTrue(hasattr(diffs[0], "upstream")) def test_workflow_type_changes_with_identical_workflow_type(self): with patch.object( Layer1, "describe_workflow_type", mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked["typeInfo"]["workflowType"]["name"], version=mocked["typeInfo"]["workflowType"]["version"], status=mocked["typeInfo"]["status"], creation_date=mocked["typeInfo"]["creationDate"], deprecation_date=mocked["typeInfo"]["deprecationDate"], task_list=mocked["configuration"]["defaultTaskList"]["name"], child_policy=mocked["configuration"]["defaultChildPolicy"], execution_timeout=mocked["configuration"][ "defaultExecutionStartToCloseTimeout" ], decision_tasks_timeout=mocked["configuration"][ "defaultTaskStartToCloseTimeout" ], description=mocked["typeInfo"]["description"], ) diffs = workflow_type.changes self.assertLength(diffs, 0) def test_save_already_existing_type(self): with patch.object(self.wt.connection, "register_workflow_type") as mock: with self.assertRaises(AlreadyExistsError): mock.side_effect = SWFTypeAlreadyExistsError(400, "mocked exception") self.wt.save() def test_save_with_response_error(self): with patch.object(self.wt.connection, "register_workflow_type") as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", {"__type": "UnknownResourceFault", "message": "Whatever"}, ) self.wt.save() def test_delete_non_existent_type(self): with patch.object(self.wt.connection, "deprecate_workflow_type") as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", {"__type": "UnknownResourceFault", "message": "Whatever"}, ) self.wt.delete() def test_delete_deprecated_type(self): with patch.object(self.wt.connection, "deprecate_workflow_type") as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError( 400, "mocked exception", {"__type": "TypeDeprecatedFault", "message": "Whatever"}, ) self.wt.delete()
def poll(self, task_list=None, identity=None, **kwargs): """ Polls a decision task and returns the token and the full history of the workflow's events. :param task_list: task list to poll for decision tasks from. :type task_list: str :param identity: Identity of the decider making the request, which is recorded in the DecisionTaskStarted event in the workflow history. :type identity: str :returns: a Response object with history, token, and execution set :rtype: swf.responses.Response """ task_list = task_list or self.task_list task = self.connection.poll_for_decision_task(self.domain.name, task_list=task_list, identity=identity, **kwargs) token = task.get('taskToken') if token is None: raise PollTimeout("Decider poll timed out") events = task['events'] next_page = task.get('nextPageToken') while next_page: try: task = self.connection.poll_for_decision_task( self.domain.name, task_list=task_list, identity=identity, next_page_token=next_page, **kwargs) except boto.exception.SWFResponseError as e: if e.error_code == 'UnknownResourceFault': raise DoesNotExistError( "Unable to poll decision task", e.body['message'], ) raise ResponseError(e.body['message']) token = task.get('taskToken') if token is None: raise PollTimeout("Decider poll timed out") events.extend(task['events']) next_page = task.get('nextPageToken') history = History.from_event_list(events) workflow_type = WorkflowType( domain=self.domain, name=task['workflowType']['name'], version=task['workflowType']['version'], ) execution = WorkflowExecution( domain=self.domain, workflow_id=task['workflowExecution']['workflowId'], run_id=task['workflowExecution']['runId'], workflow_type=workflow_type, ) # TODO: move history into execution (needs refactoring on WorkflowExecution.history()) return Response(token=token, history=history, execution=execution)
class TestWorkflowType(unittest.TestCase): def setUp(self): self.domain = Domain("test-domain") self.wt = WorkflowType(self.domain, "TestType", "1.0") def tearDown(self): pass def test_init_with_invalid_child_policy(self): with self.assertRaises(ValueError): WorkflowType(self.domain, "TestType", "1.0", child_policy="FAILING_POLICY") def test___diff_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType(self.domain, "different-workflow-type", version="different-version") diffs = workflow_type._diff() self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream')) def test_workflow_type__diff_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration'] ['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration'] ['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type._diff() self.assertEqual(len(diffs), 0) def test_exists_with_existing_workflow_type(self): with patch.object(Layer1, 'describe_workflow_type'): self.assertTrue(self.wt.exists) def test_exists_with_non_existent_workflow_type(self): with patch.object(self.wt.connection, 'describe_workflow_type') as mock: mock.side_effect = SWFResponseError( 400, "Bad Request:", { '__type': 'com.amazonaws.swf.base.model#UnknownResourceFault', 'message': 'Unknown type: WorkflowType=[workflowId=blah, runId=test]' }, 'UnknownResourceFault', ) self.assertFalse(self.wt.exists) def test_workflow_type_exists_with_whatever_error(self): with patch.object(self.wt.connection, 'describe_workflow_type') as mock: with self.assertRaises(ResponseError): mock.side_effect = SWFResponseError(400, "mocking exception", { '__type': 'WhateverError', 'message': 'Whatever' }) self.domain.exists def test_is_synced_with_unsynced_workflow_type(self): pass def test_is_synced_with_synced_workflow_type(self): pass def test_is_synced_over_non_existent_workflow_type(self): with patch.object(Layer1, 'describe_workflow_type', mock_describe_workflow_type): workflow_type = WorkflowType(self.domain, "non-existent-workflow-type", version="non-existent-version") self.assertFalse(workflow_type.is_synced) def test_changes_with_different_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): workflow_type = WorkflowType( self.domain, "different-workflow-type-type", version="different-workflow-type-type-version") diffs = workflow_type.changes self.assertIsNotNone(diffs) self.assertEqual(len(diffs), 6) self.assertTrue(hasattr(diffs[0], 'attr')) self.assertTrue(hasattr(diffs[0], 'local')) self.assertTrue(hasattr(diffs[0], 'upstream')) def test_workflow_type_changes_with_identical_workflow_type(self): with patch.object( Layer1, 'describe_workflow_type', mock_describe_workflow_type, ): mocked = mock_describe_workflow_type() workflow_type = WorkflowType( self.domain, name=mocked['typeInfo']['workflowType']['name'], version=mocked['typeInfo']['workflowType']['version'], status=mocked['typeInfo']['status'], creation_date=mocked['typeInfo']['creationDate'], deprecation_date=mocked['typeInfo']['deprecationDate'], task_list=mocked['configuration']['defaultTaskList']['name'], child_policy=mocked['configuration']['defaultChildPolicy'], execution_timeout=mocked['configuration'] ['defaultExecutionStartToCloseTimeout'], decision_tasks_timeout=mocked['configuration'] ['defaultTaskStartToCloseTimeout'], description=mocked['typeInfo']['description'], ) diffs = workflow_type.changes self.assertEqual(len(diffs), 0) def test_save_already_existing_type(self): with patch.object(self.wt.connection, 'register_workflow_type') as mock: with self.assertRaises(AlreadyExistsError): mock.side_effect = SWFTypeAlreadyExistsError( 400, "mocked exception") self.wt.save() def test_save_with_response_error(self): with patch.object(self.wt.connection, 'register_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError(400, "mocked exception", { "__type": "UnknownResourceFault", "message": "Whatever" }) self.wt.save() def test_delete_non_existent_type(self): with patch.object(self.wt.connection, 'deprecate_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError(400, "mocked exception", { "__type": "UnknownResourceFault", "message": "Whatever" }) self.wt.delete() def test_delete_deprecated_type(self): with patch.object(self.wt.connection, 'deprecate_workflow_type') as mock: with self.assertRaises(DoesNotExistError): mock.side_effect = SWFResponseError(400, "mocked exception", { "__type": "TypeDeprecatedFault", "message": "Whatever" }) self.wt.delete()