| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | from datetime import datetime | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  | import re | 
					
						
							|  |  |  | from time import sleep | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from botocore.exceptions import ClientError | 
					
						
							| 
									
										
										
										
											2022-04-20 00:22:49 +02:00
										 |  |  | from dateutil.parser import parse as dtparse | 
					
						
							| 
									
										
										
										
											2015-10-31 21:13:44 +01:00
										 |  |  | from freezegun import freeze_time | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | import pytest | 
					
						
							| 
									
										
										
										
											2015-10-11 14:02:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-18 14:18:57 -01:00
										 |  |  | from moto import mock_swf, settings | 
					
						
							| 
									
										
										
										
											2015-10-11 14:02:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-18 14:18:57 -01:00
										 |  |  | from ..utils import setup_workflow_boto3 | 
					
						
							| 
									
										
										
										
											2015-10-11 14:02:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # PollForDecisionTask endpoint | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-02 14:02:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_when_one_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == ["WorkflowExecutionStarted", "DecisionTaskScheduled"] | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"}, identity="srv01" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ( | 
					
						
							|  |  |  |         resp["events"][-1]["decisionTaskStartedEventAttributes"]["identity"] == "srv01" | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_previous_started_event_id_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert resp["workflowExecution"]["runId"] == client.run_id | 
					
						
							|  |  |  |     assert "previousStartedEventId" not in resp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Require a failing decision, in this case a non-existant activity type | 
					
						
							|  |  |  |     attrs = { | 
					
						
							|  |  |  |         "activityId": "spam", | 
					
						
							|  |  |  |         "activityType": {"name": "test-activity", "version": "v1.42"}, | 
					
						
							|  |  |  |         "taskList": {"name": "eggs"}, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     decision = { | 
					
						
							|  |  |  |         "decisionType": "ScheduleActivityTask", | 
					
						
							|  |  |  |         "scheduleActivityTaskDecisionAttributes": attrs, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     client.respond_decision_task_completed( | 
					
						
							|  |  |  |         taskToken=resp["taskToken"], decisions=[decision] | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert resp["workflowExecution"]["runId"] == client.run_id | 
					
						
							|  |  |  |     assert resp["previousStartedEventId"] == 3 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_ensure_single_started_task(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert "taskToken" in resp | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  |     first_decision_task = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # History should have just the decision task triggered on workflow start | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Schedule another decision task, before first one is completed | 
					
						
							|  |  |  |     client.signal_workflow_execution( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         signalName="my_signal", | 
					
						
							|  |  |  |         workflowId="uid-abcd1234", | 
					
						
							|  |  |  |         input="my_input", | 
					
						
							|  |  |  |         runId=client.run_id, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # Second poll should return no new tasks | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     assert resp["previousStartedEventId"] == 0 | 
					
						
							|  |  |  |     assert resp["startedEventId"] == 0 | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert "taskToken" not in resp | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "WorkflowExecutionSignaled", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=first_decision_task) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert "taskToken" in resp | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "WorkflowExecutionSignaled", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_exclude_completed_executions(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == ["WorkflowExecutionStarted", "DecisionTaskScheduled"] | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     client.terminate_workflow_execution( | 
					
						
							|  |  |  |         domain="test-domain", runId=client.run_id, workflowId="uid-abcd1234" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert "taskToken" not in resp | 
					
						
							| 
									
										
										
										
											2022-11-16 12:36:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_when_none_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.poll_for_decision_task(domain="test-domain", taskList={"name": "queue"}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     # this is the DecisionTask representation you get from the real SWF | 
					
						
							|  |  |  |     # after waiting 60s when there's no decision to be taken | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["previousStartedEventId"] == 0 | 
					
						
							|  |  |  |     assert resp["startedEventId"] == 0 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_on_non_existent_queue_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "non-existent-queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["previousStartedEventId"] == 0 | 
					
						
							|  |  |  |     assert resp["startedEventId"] == 0 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_poll_for_decision_task_with_reverse_order_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"}, reverseOrder=True | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-11 22:14:16 +02:00
										 |  |  | # CountPendingDecisionTasks endpoint | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-02 14:02:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | @mock_swf | 
					
						
							|  |  |  | def test_count_pending_decision_tasks_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     client.poll_for_decision_task(domain="test-domain", taskList={"name": "queue"}) | 
					
						
							|  |  |  |     resp = client.count_pending_decision_tasks( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["count"] == 1 | 
					
						
							|  |  |  |     assert resp["truncated"] is False | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_count_pending_decision_tasks_on_non_existent_task_list_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.count_pending_decision_tasks( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "non-existent"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["count"] == 0 | 
					
						
							|  |  |  |     assert resp["truncated"] is False | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_count_pending_decision_tasks_after_decision_completes_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=resp["taskToken"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.count_pending_decision_tasks( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["count"] == 0 | 
					
						
							|  |  |  |     assert resp["truncated"] is False | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-12 11:08:52 +02:00
										 |  |  | # RespondDecisionTaskCompleted endpoint | 
					
						
							| 
									
										
										
										
											2015-10-31 21:13:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-02 14:02:37 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_no_decision_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.respond_decision_task_completed( | 
					
						
							|  |  |  |         taskToken=task_token, executionContext="free-form context" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     evt = resp["events"][-1] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert evt["decisionTaskCompletedEventAttributes"] == { | 
					
						
							|  |  |  |         "executionContext": "free-form context", | 
					
						
							|  |  |  |         "scheduledEventId": 2, | 
					
						
							|  |  |  |         "startedEventId": 3, | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = client.describe_workflow_execution( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert resp["latestExecutionContext"] == "free-form context" | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_wrong_token_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     client.poll_for_decision_task(domain="test-domain", taskList={"name": "queue"}) | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed(taskToken="not-a-correct-token") | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "ValidationException" | 
					
						
							|  |  |  |     assert ex.value.response["Error"]["Message"] == "Invalid token" | 
					
						
							|  |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_on_close_workflow_execution_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     client.terminate_workflow_execution(domain="test-domain", workflowId="uid-abcd1234") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed(taskToken=task_token) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "UnknownResourceFault" | 
					
						
							|  |  |  |     assert ex.value.response["Error"]["Message"] == ( | 
					
						
							| 
									
										
										
										
											2022-11-17 21:41:08 -01:00
										 |  |  |         f"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId={client.run_id}]" | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_task_already_completed_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed(taskToken=task_token) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "UnknownResourceFault" | 
					
						
							|  |  |  |     assert ex.value.response["Error"]["Message"] == ( | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |         "Unknown decision task, scheduledEventId = 2" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_complete_workflow_execution_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "CompleteWorkflowExecution", | 
					
						
							|  |  |  |             "completeWorkflowExecutionDecisionAttributes": {"result": "foo bar"}, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "WorkflowExecutionCompleted", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert ( | 
					
						
							|  |  |  |         resp["events"][-1]["workflowExecutionCompletedEventAttributes"]["result"] | 
					
						
							|  |  |  |         == "foo bar" | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_close_decision_not_last_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         {"decisionType": "CompleteWorkflowExecution"}, | 
					
						
							|  |  |  |         {"decisionType": "WeDontCare"}, | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed( | 
					
						
							|  |  |  |             taskToken=task_token, decisions=decisions | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "ValidationException" | 
					
						
							|  |  |  |     assert ex.value.response["Error"]["Message"] == ( | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |         "Close must be last decision in list" | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_invalid_decision_type_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         {"decisionType": "BadDecisionType"}, | 
					
						
							|  |  |  |         {"decisionType": "CompleteWorkflowExecution"}, | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed( | 
					
						
							|  |  |  |             taskToken=task_token, decisions=decisions | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "ValidationException" | 
					
						
							|  |  |  |     assert re.search( | 
					
						
							|  |  |  |         "Value 'BadDecisionType' at 'decisions.1.member.decisionType'", | 
					
						
							|  |  |  |         ex.value.response["Error"]["Message"], | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_missing_attributes_totally_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [{"decisionType": "StartTimer"}] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with pytest.raises(ClientError) as ex: | 
					
						
							|  |  |  |         client.respond_decision_task_completed( | 
					
						
							|  |  |  |             taskToken=task_token, decisions=decisions | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["Error"]["Code"] == "ValidationException" | 
					
						
							|  |  |  |     assert re.search( | 
					
						
							|  |  |  |         ( | 
					
						
							|  |  |  |             "Value null at " | 
					
						
							|  |  |  |             "'decisions.1.member.startTimerDecisionAttributes.timerId' " | 
					
						
							|  |  |  |             "failed to satisfy constraint" | 
					
						
							|  |  |  |         ), | 
					
						
							|  |  |  |         ex.value.response["Error"]["Message"], | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400 | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_respond_decision_task_completed_with_fail_workflow_execution_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "FailWorkflowExecution", | 
					
						
							|  |  |  |             "failWorkflowExecutionDecisionAttributes": { | 
					
						
							|  |  |  |                 "reason": "my rules", | 
					
						
							|  |  |  |                 "details": "foo", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "WorkflowExecutionFailed", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     attrs = resp["events"][-1]["workflowExecutionFailedEventAttributes"] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert attrs["reason"] == "my rules" | 
					
						
							|  |  |  |     assert attrs["details"] == "foo" | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							| 
									
										
										
										
											2022-04-20 00:22:49 +02:00
										 |  |  | @freeze_time("2015-01-01 12:00:00 UTC") | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | def test_respond_decision_task_completed_with_schedule_activity_task_boto3(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "ScheduleActivityTask", | 
					
						
							|  |  |  |             "scheduleActivityTaskDecisionAttributes": { | 
					
						
							|  |  |  |                 "activityId": "my-activity-001", | 
					
						
							|  |  |  |                 "activityType": {"name": "test-activity", "version": "v1.1"}, | 
					
						
							|  |  |  |                 "heartbeatTimeout": "60", | 
					
						
							|  |  |  |                 "input": "123", | 
					
						
							|  |  |  |                 "taskList": {"name": "my-task-list"}, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "ActivityTaskScheduled", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert resp["events"][-1]["activityTaskScheduledEventAttributes"] == { | 
					
						
							|  |  |  |         "decisionTaskCompletedEventId": 4, | 
					
						
							|  |  |  |         "activityId": "my-activity-001", | 
					
						
							|  |  |  |         "activityType": {"name": "test-activity", "version": "v1.1"}, | 
					
						
							|  |  |  |         "heartbeatTimeout": "60", | 
					
						
							|  |  |  |         "input": "123", | 
					
						
							|  |  |  |         "taskList": {"name": "my-task-list"}, | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     resp = client.describe_workflow_execution( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert isinstance(resp["latestActivityTaskTimestamp"], datetime) | 
					
						
							| 
									
										
										
										
											2021-09-21 22:00:20 +00:00
										 |  |  |     if not settings.TEST_SERVER_MODE: | 
					
						
							| 
									
										
										
										
											2022-04-20 00:22:49 +02:00
										 |  |  |         ts = resp["latestActivityTaskTimestamp"] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |         assert ts == dtparse("2015-01-01 12:00:00 UTC") | 
					
						
							| 
									
										
										
										
											2021-12-27 19:26:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_record_marker_decision(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "RecordMarker", | 
					
						
							| 
									
										
										
										
											2022-03-10 13:39:59 -01:00
										 |  |  |             "recordMarkerDecisionAttributes": {"markerName": "TheMarker"}, | 
					
						
							| 
									
										
										
										
											2021-12-27 19:26:51 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "MarkerRecorded", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert resp["events"][-1]["markerRecordedEventAttributes"] == { | 
					
						
							|  |  |  |         "decisionTaskCompletedEventId": 4, | 
					
						
							|  |  |  |         "markerName": "TheMarker", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-27 19:26:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_start_and_fire_timer_decision(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "StartTimer", | 
					
						
							|  |  |  |             "startTimerDecisionAttributes": { | 
					
						
							|  |  |  |                 "startToFireTimeout": "1", | 
					
						
							|  |  |  |                 "timerId": "timer1", | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  |     sleep(1.1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "TimerStarted", | 
					
						
							|  |  |  |         "TimerFired", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert resp["events"][-3]["timerStartedEventAttributes"] == { | 
					
						
							|  |  |  |         "decisionTaskCompletedEventId": 4, | 
					
						
							|  |  |  |         "startToFireTimeout": "1", | 
					
						
							|  |  |  |         "timerId": "timer1", | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     assert resp["events"][-2]["timerFiredEventAttributes"] == { | 
					
						
							|  |  |  |         "startedEventId": 5, | 
					
						
							|  |  |  |         "timerId": "timer1", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-27 19:26:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @mock_swf | 
					
						
							|  |  |  | def test_cancel_workflow_decision(): | 
					
						
							|  |  |  |     client = setup_workflow_boto3() | 
					
						
							|  |  |  |     resp = client.poll_for_decision_task( | 
					
						
							|  |  |  |         domain="test-domain", taskList={"name": "queue"} | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     task_token = resp["taskToken"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     decisions = [ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "decisionType": "CancelWorkflowExecution", | 
					
						
							|  |  |  |             "cancelWorkflowExecutionDecisionAttributes": { | 
					
						
							|  |  |  |                 "details": "decide to cancel" | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     client.respond_decision_task_completed(taskToken=task_token, decisions=decisions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     resp = client.get_workflow_execution_history( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     types = [evt["eventType"] for evt in resp["events"]] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert types == [ | 
					
						
							|  |  |  |         "WorkflowExecutionStarted", | 
					
						
							|  |  |  |         "DecisionTaskScheduled", | 
					
						
							|  |  |  |         "DecisionTaskStarted", | 
					
						
							|  |  |  |         "DecisionTaskCompleted", | 
					
						
							|  |  |  |         "WorkflowExecutionCanceled", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     assert resp["events"][-1]["workflowExecutionCanceledEventAttributes"] == { | 
					
						
							|  |  |  |         "decisionTaskCompletedEventId": 4, | 
					
						
							|  |  |  |         "details": "decide to cancel", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-27 19:26:51 +00:00
										 |  |  |     workflow_result = client.describe_workflow_execution( | 
					
						
							|  |  |  |         domain="test-domain", | 
					
						
							|  |  |  |         execution={"runId": client.run_id, "workflowId": "uid-abcd1234"}, | 
					
						
							|  |  |  |     )["executionInfo"] | 
					
						
							| 
									
										
										
										
											2023-08-12 03:59:33 -04:00
										 |  |  |     assert "closeTimestamp" in workflow_result | 
					
						
							|  |  |  |     assert workflow_result["executionStatus"] == "CLOSED" | 
					
						
							|  |  |  |     assert workflow_result["closeStatus"] == "CANCELED" | 
					
						
							|  |  |  |     assert workflow_result["cancelRequested"] is True |