Rewrite deprecated SWF tests (#3891)
This commit is contained in:
parent
f7ce1c73fe
commit
5b10671af4
@ -1,14 +1,20 @@
|
||||
from boto.swf.exceptions import SWFResponseError
|
||||
from botocore.exceptions import ClientError
|
||||
from freezegun import freeze_time
|
||||
from unittest import SkipTest
|
||||
import pytest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
from moto import mock_swf, mock_swf_deprecated
|
||||
from moto import settings
|
||||
from moto.swf import swf_backend
|
||||
|
||||
from ..utils import setup_workflow, SCHEDULE_ACTIVITY_TASK_DECISION
|
||||
from ..utils import setup_workflow_boto3
|
||||
|
||||
|
||||
# PollForActivityTask endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_activity_task_when_one():
|
||||
conn = setup_workflow()
|
||||
@ -31,6 +37,34 @@ def test_poll_for_activity_task_when_one():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_poll_for_activity_task_when_one_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
resp = client.poll_for_activity_task(
|
||||
domain="test-domain",
|
||||
taskList={"name": "activity-task-list"},
|
||||
identity="surprise",
|
||||
)
|
||||
resp["activityId"].should.equal("my-activity-001")
|
||||
resp["taskToken"].should_not.be.none
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["events"][-1]["eventType"].should.equal("ActivityTaskStarted")
|
||||
resp["events"][-1]["activityTaskStartedEventAttributes"].should.equal(
|
||||
{"identity": "surprise", "scheduledEventId": 5}
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_activity_task_when_none():
|
||||
conn = setup_workflow()
|
||||
@ -38,6 +72,7 @@ def test_poll_for_activity_task_when_none():
|
||||
resp.should.equal({"startedEventId": 0})
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_activity_task_on_non_existent_queue():
|
||||
conn = setup_workflow()
|
||||
@ -45,7 +80,20 @@ def test_poll_for_activity_task_on_non_existent_queue():
|
||||
resp.should.equal({"startedEventId": 0})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("task_name", ["activity-task-list", "non-existent-queue"])
|
||||
@mock_swf
|
||||
def test_poll_for_activity_task_when_none_boto3(task_name):
|
||||
client = setup_workflow_boto3()
|
||||
resp = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": task_name}
|
||||
)
|
||||
resp.shouldnt.have.key("taskToken")
|
||||
resp.should.have.key("startedEventId").equal(0)
|
||||
resp.should.have.key("previousStartedEventId").equal(0)
|
||||
|
||||
|
||||
# CountPendingActivityTasks endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_count_pending_activity_tasks():
|
||||
conn = setup_workflow()
|
||||
@ -58,6 +106,7 @@ def test_count_pending_activity_tasks():
|
||||
resp.should.equal({"count": 1, "truncated": False})
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_count_pending_decision_tasks_on_non_existent_task_list():
|
||||
conn = setup_workflow()
|
||||
@ -65,7 +114,28 @@ def test_count_pending_decision_tasks_on_non_existent_task_list():
|
||||
resp.should.equal({"count": 0, "truncated": False})
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"task_name,cnt", [("activity-task-list", 1), ("non-existent", 0)]
|
||||
)
|
||||
@mock_swf
|
||||
def test_count_pending_activity_tasks_boto3(task_name, cnt):
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
|
||||
resp = client.count_pending_activity_tasks(
|
||||
domain="test-domain", taskList={"name": task_name}
|
||||
)
|
||||
resp.should.have.key("count").equal(cnt)
|
||||
resp.should.have.key("truncated").equal(False)
|
||||
|
||||
|
||||
# RespondActivityTaskCompleted endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_activity_task_completed():
|
||||
conn = setup_workflow()
|
||||
@ -91,6 +161,34 @@ def test_respond_activity_task_completed():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_respond_activity_task_completed_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
client.respond_activity_task_completed(
|
||||
taskToken=activity_token, result="result of the task"
|
||||
)
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["events"][-2]["eventType"].should.equal("ActivityTaskCompleted")
|
||||
resp["events"][-2]["activityTaskCompletedEventAttributes"].should.equal(
|
||||
{"result": "result of the task", "scheduledEventId": 5, "startedEventId": 6}
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_activity_task_completed_on_closed_workflow_execution():
|
||||
conn = setup_workflow()
|
||||
@ -113,6 +211,33 @@ def test_respond_activity_task_completed_on_closed_workflow_execution():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_respond_activity_task_completed_on_closed_workflow_execution_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
client.terminate_workflow_execution(domain="test-domain", workflowId="uid-abcd1234")
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.respond_activity_task_completed(taskToken=activity_token)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId={}]".format(
|
||||
client.run_id
|
||||
)
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_activity_task_completed_with_task_already_completed():
|
||||
conn = setup_workflow()
|
||||
@ -131,7 +256,32 @@ def test_respond_activity_task_completed_with_task_already_completed():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_respond_activity_task_completed_with_task_already_completed_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
client.respond_activity_task_completed(taskToken=activity_token)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.respond_activity_task_completed(taskToken=activity_token)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown activity, scheduledEventId = 5"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# RespondActivityTaskFailed endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_activity_task_failed():
|
||||
conn = setup_workflow()
|
||||
@ -162,6 +312,39 @@ def test_respond_activity_task_failed():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_respond_activity_task_failed_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
client.respond_activity_task_failed(
|
||||
taskToken=activity_token, reason="short reason", details="long details"
|
||||
)
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["events"][-2]["eventType"].should.equal("ActivityTaskFailed")
|
||||
resp["events"][-2]["activityTaskFailedEventAttributes"].should.equal(
|
||||
{
|
||||
"reason": "short reason",
|
||||
"details": "long details",
|
||||
"scheduledEventId": 5,
|
||||
"startedEventId": 6,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_activity_task_completed_with_wrong_token():
|
||||
# NB: we just test ONE failure case for RespondActivityTaskFailed
|
||||
@ -178,7 +361,31 @@ def test_respond_activity_task_completed_with_wrong_token():
|
||||
).should.throw(SWFResponseError, "Invalid token")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_respond_activity_task_completed_with_wrong_token_boto3():
|
||||
# NB: we just test ONE failure case for RespondActivityTaskFailed
|
||||
# because the safeguards are shared with RespondActivityTaskCompleted, so
|
||||
# no need to retest everything end-to-end.
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.respond_activity_task_failed(taskToken="not-a-correct-token")
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.equal("Invalid token")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# RecordActivityTaskHeartbeat endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_record_activity_task_heartbeat():
|
||||
conn = setup_workflow()
|
||||
@ -194,6 +401,24 @@ def test_record_activity_task_heartbeat():
|
||||
resp.should.equal({"cancelRequested": False})
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_record_activity_task_heartbeat_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
resp = client.record_activity_task_heartbeat(taskToken=activity_token)
|
||||
resp.should.have.key("cancelRequested").equal(False)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_record_activity_task_heartbeat_with_wrong_token():
|
||||
conn = setup_workflow()
|
||||
@ -208,6 +433,27 @@ def test_record_activity_task_heartbeat_with_wrong_token():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_record_activity_task_heartbeat_with_wrong_token_boto3():
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.record_activity_task_heartbeat(taskToken="bad-token")
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.equal("Invalid token")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_record_activity_task_heartbeat_sets_details_in_case_of_timeout():
|
||||
conn = setup_workflow()
|
||||
@ -231,3 +477,34 @@ def test_record_activity_task_heartbeat_sets_details_in_case_of_timeout():
|
||||
resp["events"][-2]["eventType"].should.equal("ActivityTaskTimedOut")
|
||||
attrs = resp["events"][-2]["activityTaskTimedOutEventAttributes"]
|
||||
attrs["details"].should.equal("some progress details")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_record_activity_task_heartbeat_sets_details_in_case_of_timeout_boto3():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Unable to manipulate time in ServerMode")
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
|
||||
with freeze_time("2015-01-01 12:00:00"):
|
||||
activity_token = client.poll_for_activity_task(
|
||||
domain="test-domain", taskList={"name": "activity-task-list"}
|
||||
)["taskToken"]
|
||||
client.record_activity_task_heartbeat(
|
||||
taskToken=activity_token, details="some progress details"
|
||||
)
|
||||
|
||||
with freeze_time("2015-01-01 12:05:30"):
|
||||
# => Activity Task Heartbeat timeout reached!!
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["events"][-2]["eventType"].should.equal("ActivityTaskTimedOut")
|
||||
attrs = resp["events"][-2]["activityTaskTimedOutEventAttributes"]
|
||||
attrs["details"].should.equal("some progress details")
|
||||
|
@ -2,6 +2,7 @@ import boto
|
||||
from boto.swf.exceptions import SWFResponseError
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
import pytest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
@ -9,6 +10,7 @@ from moto import mock_swf
|
||||
|
||||
|
||||
# RegisterActivityType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -21,6 +23,26 @@ def test_register_activity_type():
|
||||
actype["activityType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_register_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.0"
|
||||
)
|
||||
|
||||
types = client.list_activity_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED"
|
||||
)["typeInfos"]
|
||||
types.should.have.length_of(1)
|
||||
actype = types[0]
|
||||
actype["activityType"]["name"].should.equal("test-activity")
|
||||
actype["activityType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_already_existing_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -32,6 +54,28 @@ def test_register_already_existing_activity_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_register_already_existing_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.0"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.0"
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("TypeAlreadyExistsFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"ActivityType=[name=test-activity, version=v1.0]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_with_wrong_parameter_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -43,6 +87,7 @@ def test_register_with_wrong_parameter_type():
|
||||
|
||||
|
||||
# ListActivityTypes endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_activity_types():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -59,6 +104,33 @@ def test_list_activity_types():
|
||||
names.should.equal(["a-test-activity", "b-test-activity", "c-test-activity"])
|
||||
|
||||
|
||||
# ListActivityTypes endpoint
|
||||
@mock_swf
|
||||
def test_list_activity_types_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="b-test-activity", version="v1.0"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="a-test-activity", version="v1.0"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="c-test-activity", version="v1.0"
|
||||
)
|
||||
|
||||
types = client.list_activity_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED"
|
||||
)
|
||||
names = [
|
||||
activity_type["activityType"]["name"] for activity_type in types["typeInfos"]
|
||||
]
|
||||
names.should.equal(["a-test-activity", "b-test-activity", "c-test-activity"])
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_activity_types_reverse_order():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -77,7 +149,34 @@ def test_list_activity_types_reverse_order():
|
||||
names.should.equal(["c-test-activity", "b-test-activity", "a-test-activity"])
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_list_activity_types_reverse_order_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="b-test-activity", version="v1.0"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="a-test-activity", version="v1.0"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="c-test-activity", version="v1.0"
|
||||
)
|
||||
|
||||
types = client.list_activity_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED", reverseOrder=True
|
||||
)
|
||||
|
||||
names = [
|
||||
activity_type["activityType"]["name"] for activity_type in types["typeInfos"]
|
||||
]
|
||||
names.should.equal(["c-test-activity", "b-test-activity", "a-test-activity"])
|
||||
|
||||
|
||||
# DeprecateActivityType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -91,6 +190,30 @@ def test_deprecate_activity_type():
|
||||
actype["activityType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# DeprecateActivityType endpoint
|
||||
@mock_swf
|
||||
def test_deprecate_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.0"
|
||||
)
|
||||
client.deprecate_activity_type(
|
||||
domain="test-domain", activityType={"name": "test-activity", "version": "v1.0"}
|
||||
)
|
||||
|
||||
types = client.list_activity_types(
|
||||
domain="test-domain", registrationStatus="DEPRECATED"
|
||||
)
|
||||
types.should.have.key("typeInfos").being.length_of(1)
|
||||
actype = types["typeInfos"][0]
|
||||
actype["activityType"]["name"].should.equal("test-activity")
|
||||
actype["activityType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_already_deprecated_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -103,6 +226,32 @@ def test_deprecate_already_deprecated_activity_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_already_deprecated_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.0"
|
||||
)
|
||||
client.deprecate_activity_type(
|
||||
domain="test-domain", activityType={"name": "test-activity", "version": "v1.0"}
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_activity_type(
|
||||
domain="test-domain",
|
||||
activityType={"name": "test-activity", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("TypeDeprecatedFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"ActivityType=[name=test-activity, version=v1.0]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_non_existent_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -113,6 +262,25 @@ def test_deprecate_non_existent_activity_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_non_existent_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-2")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_activity_type(
|
||||
domain="test-domain",
|
||||
activityType={"name": "test-activity", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown type: ActivityType=[name=test-activity, version=v1.0]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# DeprecateActivityType endpoint
|
||||
@mock_swf
|
||||
def test_undeprecate_activity_type():
|
||||
@ -185,6 +353,7 @@ def test_undeprecate_non_existent_activity_type():
|
||||
|
||||
|
||||
# DescribeActivityType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -205,6 +374,31 @@ def test_describe_activity_type():
|
||||
infos["status"].should.equal("REGISTERED")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain",
|
||||
name="test-activity",
|
||||
version="v1.0",
|
||||
defaultTaskList={"name": "foo"},
|
||||
defaultTaskHeartbeatTimeout="32",
|
||||
)
|
||||
|
||||
actype = client.describe_activity_type(
|
||||
domain="test-domain", activityType={"name": "test-activity", "version": "v1.0"}
|
||||
)
|
||||
actype["configuration"]["defaultTaskList"]["name"].should.equal("foo")
|
||||
infos = actype["typeInfo"]
|
||||
infos["activityType"]["name"].should.equal("test-activity")
|
||||
infos["activityType"]["version"].should.equal("v1.0")
|
||||
infos["status"].should.equal("REGISTERED")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_non_existent_activity_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -213,3 +407,22 @@ def test_describe_non_existent_activity_type():
|
||||
conn.describe_activity_type.when.called_with(
|
||||
"test-domain", "non-existent", "v1.0"
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_non_existent_activity_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.describe_activity_type(
|
||||
domain="test-domain",
|
||||
activityType={"name": "test-activity", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown type: ActivityType=[name=test-activity, version=v1.0]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
@ -1,14 +1,18 @@
|
||||
from boto.swf.exceptions import SWFResponseError
|
||||
from botocore.exceptions import ClientError
|
||||
from datetime import datetime
|
||||
from freezegun import freeze_time
|
||||
import pytest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
from moto import mock_swf_deprecated, mock_swf, settings
|
||||
from moto.swf import swf_backend
|
||||
|
||||
from ..utils import setup_workflow
|
||||
from ..utils import setup_workflow, setup_workflow_boto3
|
||||
|
||||
|
||||
# PollForDecisionTask endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_decision_task_when_one():
|
||||
conn = setup_workflow()
|
||||
@ -30,6 +34,31 @@ def test_poll_for_decision_task_when_one():
|
||||
)
|
||||
|
||||
|
||||
@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"]]
|
||||
types.should.equal(["WorkflowExecutionStarted", "DecisionTaskScheduled"])
|
||||
|
||||
resp = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}, identity="srv01"
|
||||
)
|
||||
types = [evt["eventType"] for evt in resp["events"]]
|
||||
types.should.equal(
|
||||
["WorkflowExecutionStarted", "DecisionTaskScheduled", "DecisionTaskStarted"]
|
||||
)
|
||||
|
||||
resp["events"][-1]["decisionTaskStartedEventAttributes"]["identity"].should.equal(
|
||||
"srv01"
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_decision_task_previous_started_event_id():
|
||||
conn = setup_workflow()
|
||||
@ -54,6 +83,37 @@ def test_poll_for_decision_task_previous_started_event_id():
|
||||
assert resp["previousStartedEventId"] == 3
|
||||
|
||||
|
||||
@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
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_decision_task_when_none():
|
||||
conn = setup_workflow()
|
||||
@ -65,6 +125,22 @@ def test_poll_for_decision_task_when_none():
|
||||
resp.should.equal({"previousStartedEventId": 0, "startedEventId": 0})
|
||||
|
||||
|
||||
@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
|
||||
resp.should.have.key("previousStartedEventId").equal(0)
|
||||
resp.should.have.key("startedEventId").equal(0)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_decision_task_on_non_existent_queue():
|
||||
conn = setup_workflow()
|
||||
@ -72,6 +148,17 @@ def test_poll_for_decision_task_on_non_existent_queue():
|
||||
resp.should.equal({"previousStartedEventId": 0, "startedEventId": 0})
|
||||
|
||||
|
||||
@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"}
|
||||
)
|
||||
resp.should.have.key("previousStartedEventId").equal(0)
|
||||
resp.should.have.key("startedEventId").equal(0)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_poll_for_decision_task_with_reverse_order():
|
||||
conn = setup_workflow()
|
||||
@ -82,7 +169,20 @@ def test_poll_for_decision_task_with_reverse_order():
|
||||
)
|
||||
|
||||
|
||||
@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"]]
|
||||
types.should.equal(
|
||||
["DecisionTaskStarted", "DecisionTaskScheduled", "WorkflowExecutionStarted"]
|
||||
)
|
||||
|
||||
|
||||
# CountPendingDecisionTasks endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_count_pending_decision_tasks():
|
||||
conn = setup_workflow()
|
||||
@ -91,6 +191,18 @@ def test_count_pending_decision_tasks():
|
||||
resp.should.equal({"count": 1, "truncated": False})
|
||||
|
||||
|
||||
@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"}
|
||||
)
|
||||
resp.should.have.key("count").equal(1)
|
||||
resp.should.have.key("truncated").equal(False)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_count_pending_decision_tasks_on_non_existent_task_list():
|
||||
conn = setup_workflow()
|
||||
@ -98,6 +210,17 @@ def test_count_pending_decision_tasks_on_non_existent_task_list():
|
||||
resp.should.equal({"count": 0, "truncated": False})
|
||||
|
||||
|
||||
@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"}
|
||||
)
|
||||
resp.should.have.key("count").equal(0)
|
||||
resp.should.have.key("truncated").equal(False)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_count_pending_decision_tasks_after_decision_completes():
|
||||
conn = setup_workflow()
|
||||
@ -108,7 +231,23 @@ def test_count_pending_decision_tasks_after_decision_completes():
|
||||
resp.should.equal({"count": 0, "truncated": False})
|
||||
|
||||
|
||||
@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"}
|
||||
)
|
||||
resp.should.have.key("count").equal(0)
|
||||
resp.should.have.key("truncated").equal(False)
|
||||
|
||||
|
||||
# RespondDecisionTaskCompleted endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_no_decision():
|
||||
conn = setup_workflow()
|
||||
@ -146,6 +285,48 @@ def test_respond_decision_task_completed_with_no_decision():
|
||||
resp["latestExecutionContext"].should.equal("free-form context")
|
||||
|
||||
|
||||
@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"]]
|
||||
types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"DecisionTaskStarted",
|
||||
"DecisionTaskCompleted",
|
||||
]
|
||||
)
|
||||
evt = resp["events"][-1]
|
||||
evt["decisionTaskCompletedEventAttributes"].should.equal(
|
||||
{
|
||||
"executionContext": "free-form context",
|
||||
"scheduledEventId": 2,
|
||||
"startedEventId": 3,
|
||||
}
|
||||
)
|
||||
|
||||
resp = client.describe_workflow_execution(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["latestExecutionContext"].should.equal("free-form context")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_wrong_token():
|
||||
conn = setup_workflow()
|
||||
@ -155,6 +336,18 @@ def test_respond_decision_task_completed_with_wrong_token():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@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")
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.equal("Invalid token")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_on_close_workflow_execution():
|
||||
conn = setup_workflow()
|
||||
@ -172,6 +365,28 @@ def test_respond_decision_task_completed_on_close_workflow_execution():
|
||||
)
|
||||
|
||||
|
||||
@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)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId={}]".format(
|
||||
client.run_id
|
||||
)
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_task_already_completed():
|
||||
conn = setup_workflow()
|
||||
@ -184,6 +399,25 @@ def test_respond_decision_task_completed_with_task_already_completed():
|
||||
)
|
||||
|
||||
|
||||
@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)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown decision task, scheduledEventId = 2"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_complete_workflow_execution():
|
||||
conn = setup_workflow()
|
||||
@ -217,6 +451,42 @@ def test_respond_decision_task_completed_with_complete_workflow_execution():
|
||||
].should.equal("foo bar")
|
||||
|
||||
|
||||
@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"]]
|
||||
types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"DecisionTaskStarted",
|
||||
"DecisionTaskCompleted",
|
||||
"WorkflowExecutionCompleted",
|
||||
]
|
||||
)
|
||||
resp["events"][-1]["workflowExecutionCompletedEventAttributes"][
|
||||
"result"
|
||||
].should.equal("foo bar")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_close_decision_not_last():
|
||||
conn = setup_workflow()
|
||||
@ -233,6 +503,31 @@ def test_respond_decision_task_completed_with_close_decision_not_last():
|
||||
).should.throw(SWFResponseError, r"Close must be last decision in list")
|
||||
|
||||
|
||||
@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
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Close must be last decision in list"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_invalid_decision_type():
|
||||
conn = setup_workflow()
|
||||
@ -252,6 +547,31 @@ def test_respond_decision_task_completed_with_invalid_decision_type():
|
||||
)
|
||||
|
||||
|
||||
@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
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.match(
|
||||
"Value 'BadDecisionType' at 'decisions.1.member.decisionType'"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_missing_attributes():
|
||||
conn = setup_workflow()
|
||||
@ -274,6 +594,7 @@ def test_respond_decision_task_completed_with_missing_attributes():
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_missing_attributes_totally():
|
||||
conn = setup_workflow()
|
||||
@ -291,6 +612,28 @@ def test_respond_decision_task_completed_with_missing_attributes_totally():
|
||||
)
|
||||
|
||||
|
||||
@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
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("ValidationException")
|
||||
ex.value.response["Error"]["Message"].should.match(
|
||||
"Value null at 'decisions.1.member.startTimerDecisionAttributes.timerId' failed to satisfy constraint"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_respond_decision_task_completed_with_fail_workflow_execution():
|
||||
conn = setup_workflow()
|
||||
@ -327,6 +670,45 @@ def test_respond_decision_task_completed_with_fail_workflow_execution():
|
||||
attrs["details"].should.equal("foo")
|
||||
|
||||
|
||||
@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"]]
|
||||
types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"DecisionTaskStarted",
|
||||
"DecisionTaskCompleted",
|
||||
"WorkflowExecutionFailed",
|
||||
]
|
||||
)
|
||||
attrs = resp["events"][-1]["workflowExecutionFailedEventAttributes"]
|
||||
attrs["reason"].should.equal("my rules")
|
||||
attrs["details"].should.equal("foo")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
@freeze_time("2015-01-01 12:00:00")
|
||||
def test_respond_decision_task_completed_with_schedule_activity_task():
|
||||
@ -375,3 +757,61 @@ def test_respond_decision_task_completed_with_schedule_activity_task():
|
||||
|
||||
resp = conn.describe_workflow_execution("test-domain", conn.run_id, "uid-abcd1234")
|
||||
resp["latestActivityTaskTimestamp"].should.equal(1420113600.0)
|
||||
|
||||
|
||||
@mock_swf
|
||||
@freeze_time("2015-01-01 12: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"]]
|
||||
types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"DecisionTaskStarted",
|
||||
"DecisionTaskCompleted",
|
||||
"ActivityTaskScheduled",
|
||||
]
|
||||
)
|
||||
resp["events"][-1]["activityTaskScheduledEventAttributes"].should.equal(
|
||||
{
|
||||
"decisionTaskCompletedEventId": 4,
|
||||
"activityId": "my-activity-001",
|
||||
"activityType": {"name": "test-activity", "version": "v1.1"},
|
||||
"heartbeatTimeout": "60",
|
||||
"input": "123",
|
||||
"taskList": {"name": "my-task-list"},
|
||||
}
|
||||
)
|
||||
|
||||
resp = client.describe_workflow_execution(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["latestActivityTaskTimestamp"].should.be.a(datetime)
|
||||
if not settings.TEST_SERVER_MODE:
|
||||
ts = resp["latestActivityTaskTimestamp"].strftime("%Y-%m-%d %H:%M:%S")
|
||||
ts.should.equal("2015-01-01 12:00:00")
|
||||
|
@ -2,6 +2,7 @@ import boto
|
||||
from boto.swf.exceptions import SWFResponseError
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
import pytest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
@ -10,6 +11,7 @@ from moto.core import ACCOUNT_ID
|
||||
|
||||
|
||||
# RegisterDomain endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -26,6 +28,28 @@ def test_register_domain():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_register_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
|
||||
all_domains = client.list_domains(registrationStatus="REGISTERED")
|
||||
all_domains.should.have.key("domainInfos").being.length_of(1)
|
||||
domain = all_domains["domainInfos"][0]
|
||||
|
||||
domain["name"].should.equal("test-domain")
|
||||
domain["status"].should.equal("REGISTERED")
|
||||
domain["description"].should.equal("A test domain")
|
||||
domain["arn"].should.equal(
|
||||
"arn:aws:swf:us-west-1:{0}:/domain/test-domain".format(ACCOUNT_ID)
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_already_existing_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -36,6 +60,27 @@ def test_register_already_existing_domain():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_register_already_existing_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("DomainAlreadyExistsFault")
|
||||
ex.value.response["Error"]["Message"].should.equal("test-domain")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_with_wrong_parameter_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -46,6 +91,7 @@ def test_register_with_wrong_parameter_type():
|
||||
|
||||
|
||||
# ListDomains endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_domains_order():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -58,6 +104,27 @@ def test_list_domains_order():
|
||||
names.should.equal(["a-test-domain", "b-test-domain", "c-test-domain"])
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_list_domains_order_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="b-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_domain(
|
||||
name="a-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_domain(
|
||||
name="c-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
|
||||
all_domains = client.list_domains(registrationStatus="REGISTERED")
|
||||
all_domains.should.have.key("domainInfos").being.length_of(3)
|
||||
|
||||
names = [domain["name"] for domain in all_domains["domainInfos"]]
|
||||
names.should.equal(["a-test-domain", "b-test-domain", "c-test-domain"])
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_domains_reverse_order():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -70,7 +137,30 @@ def test_list_domains_reverse_order():
|
||||
names.should.equal(["c-test-domain", "b-test-domain", "a-test-domain"])
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_list_domains_reverse_order_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="b-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_domain(
|
||||
name="a-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.register_domain(
|
||||
name="c-test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
|
||||
all_domains = client.list_domains(
|
||||
registrationStatus="REGISTERED", reverseOrder=True
|
||||
)
|
||||
all_domains.should.have.key("domainInfos").being.length_of(3)
|
||||
|
||||
names = [domain["name"] for domain in all_domains["domainInfos"]]
|
||||
names.should.equal(["c-test-domain", "b-test-domain", "a-test-domain"])
|
||||
|
||||
|
||||
# DeprecateDomain endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -83,6 +173,25 @@ def test_deprecate_domain():
|
||||
domain["name"].should.equal("test-domain")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.deprecate_domain(name="test-domain")
|
||||
|
||||
all_domains = client.list_domains(registrationStatus="REGISTERED")
|
||||
all_domains.should.have.key("domainInfos").being.length_of(0)
|
||||
|
||||
all_domains = client.list_domains(registrationStatus="DEPRECATED")
|
||||
all_domains.should.have.key("domainInfos").being.length_of(1)
|
||||
|
||||
domain = all_domains["domainInfos"][0]
|
||||
domain["name"].should.equal("test-domain")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_already_deprecated_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -92,6 +201,22 @@ def test_deprecate_already_deprecated_domain():
|
||||
conn.deprecate_domain.when.called_with("test-domain").should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_already_deprecated_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60"
|
||||
)
|
||||
client.deprecate_domain(name="test-domain")
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_domain(name="test-domain")
|
||||
ex.value.response["Error"]["Code"].should.equal("DomainDeprecatedFault")
|
||||
ex.value.response["Error"]["Message"].should.equal("test-domain")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_non_existent_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -101,6 +226,17 @@ def test_deprecate_non_existent_domain():
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_non_existent_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_domain(name="non-existent")
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal("Unknown domain: non-existent")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# UndeprecateDomain endpoint
|
||||
@mock_swf
|
||||
def test_undeprecate_domain():
|
||||
@ -152,6 +288,7 @@ def test_undeprecate_non_existent_domain():
|
||||
|
||||
|
||||
# DescribeDomain endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -164,8 +301,36 @@ def test_describe_domain():
|
||||
domain["domainInfo"]["status"].should.equal("REGISTERED")
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
|
||||
domain = client.describe_domain(name="test-domain")
|
||||
domain["configuration"]["workflowExecutionRetentionPeriodInDays"].should.equal("60")
|
||||
domain["domainInfo"]["description"].should.equal("A test domain")
|
||||
domain["domainInfo"]["name"].should.equal("test-domain")
|
||||
domain["domainInfo"]["status"].should.equal("REGISTERED")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_non_existent_domain():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
|
||||
conn.describe_domain.when.called_with("non-existent").should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_non_existent_domain_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.describe_domain(name="non-existent")
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal("Unknown domain: non-existent")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
@ -1,13 +1,17 @@
|
||||
from datetime import datetime
|
||||
from freezegun import freeze_time
|
||||
from unittest import SkipTest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
from moto import mock_swf_deprecated, mock_swf, settings
|
||||
|
||||
from ..utils import setup_workflow, SCHEDULE_ACTIVITY_TASK_DECISION
|
||||
from ..utils import setup_workflow_boto3
|
||||
|
||||
|
||||
# Activity Task Heartbeat timeout
|
||||
# Default value in workflow helpers: 5 mins
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_activity_task_heartbeat_timeout():
|
||||
with freeze_time("2015-01-01 12:00:00"):
|
||||
@ -43,8 +47,52 @@ def test_activity_task_heartbeat_timeout():
|
||||
resp["events"][-1]["eventType"].should.equal("DecisionTaskScheduled")
|
||||
|
||||
|
||||
# Activity Task Heartbeat timeout
|
||||
# Default value in workflow helpers: 5 mins
|
||||
@mock_swf
|
||||
def test_activity_task_heartbeat_timeout_boto3():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Unable to manipulate time in ServerMode")
|
||||
with freeze_time("2015-01-01 12:00:00"):
|
||||
client = setup_workflow_boto3()
|
||||
decision_token = client.poll_for_decision_task(
|
||||
domain="test-domain", taskList={"name": "queue"}
|
||||
)["taskToken"]
|
||||
client.respond_decision_task_completed(
|
||||
taskToken=decision_token, decisions=[SCHEDULE_ACTIVITY_TASK_DECISION]
|
||||
)
|
||||
client.poll_for_activity_task(
|
||||
domain="test-domain",
|
||||
taskList={"name": "activity-task-list"},
|
||||
identity="surprise",
|
||||
)
|
||||
|
||||
with freeze_time("2015-01-01 12:04:30"):
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
resp["events"][-1]["eventType"].should.equal("ActivityTaskStarted")
|
||||
|
||||
with freeze_time("2015-01-01 12:05:30"):
|
||||
# => Activity Task Heartbeat timeout reached!!
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
|
||||
resp["events"][-2]["eventType"].should.equal("ActivityTaskTimedOut")
|
||||
attrs = resp["events"][-2]["activityTaskTimedOutEventAttributes"]
|
||||
attrs["timeoutType"].should.equal("HEARTBEAT")
|
||||
# checks that event has been emitted at 12:05:00, not 12:05:30
|
||||
resp["events"][-2]["eventTimestamp"].should.be.a(datetime)
|
||||
ts = resp["events"][-2]["eventTimestamp"].strftime("%Y-%m-%d %H:%M:%S")
|
||||
ts.should.equal("2015-01-01 12:05:00")
|
||||
|
||||
|
||||
# Decision Task Start to Close timeout
|
||||
# Default value in workflow helpers: 5 mins
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_decision_task_start_to_close_timeout():
|
||||
pass
|
||||
@ -90,8 +138,62 @@ def test_decision_task_start_to_close_timeout():
|
||||
resp["events"][-2]["eventTimestamp"].should.equal(1420113900.0)
|
||||
|
||||
|
||||
# Decision Task Start to Close timeout
|
||||
# Default value in workflow helpers: 5 mins
|
||||
@mock_swf
|
||||
def test_decision_task_start_to_close_timeout_boto3():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Unable to manipulate time in ServerMode")
|
||||
|
||||
with freeze_time("2015-01-01 12:00:00"):
|
||||
client = setup_workflow_boto3()
|
||||
client.poll_for_decision_task(domain="test-domain", taskList={"name": "queue"})
|
||||
|
||||
with freeze_time("2015-01-01 12:04:30"):
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
|
||||
event_types = [evt["eventType"] for evt in resp["events"]]
|
||||
event_types.should.equal(
|
||||
["WorkflowExecutionStarted", "DecisionTaskScheduled", "DecisionTaskStarted"]
|
||||
)
|
||||
|
||||
with freeze_time("2015-01-01 12:05:30"):
|
||||
# => Decision Task Start to Close timeout reached!!
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
|
||||
event_types = [evt["eventType"] for evt in resp["events"]]
|
||||
event_types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"DecisionTaskStarted",
|
||||
"DecisionTaskTimedOut",
|
||||
"DecisionTaskScheduled",
|
||||
]
|
||||
)
|
||||
attrs = resp["events"][-2]["decisionTaskTimedOutEventAttributes"]
|
||||
attrs.should.equal(
|
||||
{
|
||||
"scheduledEventId": 2,
|
||||
"startedEventId": 3,
|
||||
"timeoutType": "START_TO_CLOSE",
|
||||
}
|
||||
)
|
||||
# checks that event has been emitted at 12:05:00, not 12:05:30
|
||||
resp["events"][-2]["eventTimestamp"].should.be.a(datetime)
|
||||
ts = resp["events"][-2]["eventTimestamp"].strftime("%Y-%m-%d %H:%M:%S")
|
||||
ts.should.equal("2015-01-01 12:05:00")
|
||||
|
||||
|
||||
# Workflow Execution Start to Close timeout
|
||||
# Default value in workflow helpers: 2 hours
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_workflow_execution_start_to_close_timeout():
|
||||
pass
|
||||
@ -124,3 +226,44 @@ def test_workflow_execution_start_to_close_timeout():
|
||||
attrs.should.equal({"childPolicy": "ABANDON", "timeoutType": "START_TO_CLOSE"})
|
||||
# checks that event has been emitted at 14:00:00, not 14:00:30
|
||||
resp["events"][-1]["eventTimestamp"].should.equal(1420120800.0)
|
||||
|
||||
|
||||
# Workflow Execution Start to Close timeout
|
||||
# Default value in workflow helpers: 2 hours
|
||||
@mock_swf
|
||||
def test_workflow_execution_start_to_close_timeout_boto3():
|
||||
if settings.TEST_SERVER_MODE:
|
||||
raise SkipTest("Unable to manipulate time in ServerMode")
|
||||
with freeze_time("2015-01-01 12:00:00"):
|
||||
client = setup_workflow_boto3()
|
||||
|
||||
with freeze_time("2015-01-01 13:59:30"):
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
|
||||
event_types = [evt["eventType"] for evt in resp["events"]]
|
||||
event_types.should.equal(["WorkflowExecutionStarted", "DecisionTaskScheduled"])
|
||||
|
||||
with freeze_time("2015-01-01 14:00:30"):
|
||||
# => Workflow Execution Start to Close timeout reached!!
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": client.run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
|
||||
event_types = [evt["eventType"] for evt in resp["events"]]
|
||||
event_types.should.equal(
|
||||
[
|
||||
"WorkflowExecutionStarted",
|
||||
"DecisionTaskScheduled",
|
||||
"WorkflowExecutionTimedOut",
|
||||
]
|
||||
)
|
||||
attrs = resp["events"][-1]["workflowExecutionTimedOutEventAttributes"]
|
||||
attrs.should.equal({"childPolicy": "ABANDON", "timeoutType": "START_TO_CLOSE"})
|
||||
# checks that event has been emitted at 14:00:00, not 14:00:30
|
||||
resp["events"][-1]["eventTimestamp"].should.be.a(datetime)
|
||||
ts = resp["events"][-1]["eventTimestamp"].strftime("%Y-%m-%d %H:%M:%S")
|
||||
ts.should.equal("2015-01-01 14:00:00")
|
||||
|
@ -1,10 +1,13 @@
|
||||
import boto
|
||||
import boto3
|
||||
from boto.swf.exceptions import SWFResponseError
|
||||
from botocore.exceptions import ClientError
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
import sure # noqa
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
from moto import mock_swf_deprecated, mock_swf
|
||||
from moto.core.utils import unix_time
|
||||
|
||||
|
||||
@ -26,7 +29,30 @@ def setup_swf_environment():
|
||||
return conn
|
||||
|
||||
|
||||
def setup_swf_environment_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain",
|
||||
name="test-workflow",
|
||||
version="v1.0",
|
||||
defaultTaskList={"name": "queue"},
|
||||
defaultChildPolicy="TERMINATE",
|
||||
defaultTaskStartToCloseTimeout="300",
|
||||
defaultExecutionStartToCloseTimeout="300",
|
||||
)
|
||||
client.register_activity_type(
|
||||
domain="test-domain", name="test-activity", version="v1.1"
|
||||
)
|
||||
return client
|
||||
|
||||
|
||||
# StartWorkflowExecution endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_start_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -37,6 +63,20 @@ def test_start_workflow_execution():
|
||||
wf.should.contain("runId")
|
||||
|
||||
|
||||
# StartWorkflowExecution endpoint
|
||||
@mock_swf
|
||||
def test_start_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
|
||||
wf = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
wf.should.have.key("runId")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_signal_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -54,6 +94,32 @@ def test_signal_workflow_execution():
|
||||
wfe["openCounts"]["openDecisionTasks"].should.equal(2)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_signal_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
hsh = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
run_id = hsh["runId"]
|
||||
|
||||
wfe = client.signal_workflow_execution(
|
||||
domain="test-domain",
|
||||
signalName="my_signal",
|
||||
workflowId="uid-abcd1234",
|
||||
input="my_input",
|
||||
runId=run_id,
|
||||
)
|
||||
|
||||
wfe = client.describe_workflow_execution(
|
||||
domain="test-domain", execution={"runId": run_id, "workflowId": "uid-abcd1234"}
|
||||
)
|
||||
|
||||
wfe["openCounts"]["openDecisionTasks"].should.equal(2)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_start_already_started_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -66,6 +132,29 @@ def test_start_already_started_workflow_execution():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_start_already_started_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal(
|
||||
"WorkflowExecutionAlreadyStartedFault"
|
||||
)
|
||||
ex.value.response["Error"]["Message"].should.equal("Already Started")
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_start_workflow_execution_on_deprecated_type():
|
||||
conn = setup_swf_environment()
|
||||
@ -76,7 +165,28 @@ def test_start_workflow_execution_on_deprecated_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_start_workflow_execution_on_deprecated_type_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
client.deprecate_workflow_type(
|
||||
domain="test-domain", workflowType={"name": "test-workflow", "version": "v1.0"}
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("TypeDeprecatedFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"WorkflowType=[name=test-workflow, version=v1.0]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# DescribeWorkflowExecution endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -90,6 +200,25 @@ def test_describe_workflow_execution():
|
||||
wfe["executionInfo"]["executionStatus"].should.equal("OPEN")
|
||||
|
||||
|
||||
# DescribeWorkflowExecution endpoint
|
||||
@mock_swf
|
||||
def test_describe_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
hsh = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
run_id = hsh["runId"]
|
||||
|
||||
wfe = client.describe_workflow_execution(
|
||||
domain="test-domain", execution={"runId": run_id, "workflowId": "uid-abcd1234"}
|
||||
)
|
||||
wfe["executionInfo"]["execution"]["workflowId"].should.equal("uid-abcd1234")
|
||||
wfe["executionInfo"]["executionStatus"].should.equal("OPEN")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_non_existent_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -99,7 +228,24 @@ def test_describe_non_existent_workflow_execution():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_non_existent_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.describe_workflow_execution(
|
||||
domain="test-domain",
|
||||
execution={"runId": "wrong-run-id", "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId=wrong-run-id]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# GetWorkflowExecutionHistory endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_get_workflow_execution_history():
|
||||
conn = setup_swf_environment()
|
||||
@ -113,6 +259,25 @@ def test_get_workflow_execution_history():
|
||||
types.should.equal(["WorkflowExecutionStarted", "DecisionTaskScheduled"])
|
||||
|
||||
|
||||
# GetWorkflowExecutionHistory endpoint
|
||||
@mock_swf
|
||||
def test_get_workflow_execution_history_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
hsh = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
run_id = hsh["runId"]
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain", execution={"runId": run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
types = [evt["eventType"] for evt in resp["events"]]
|
||||
types.should.equal(["WorkflowExecutionStarted", "DecisionTaskScheduled"])
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_get_workflow_execution_history_with_reverse_order():
|
||||
conn = setup_swf_environment()
|
||||
@ -128,6 +293,26 @@ def test_get_workflow_execution_history_with_reverse_order():
|
||||
types.should.equal(["DecisionTaskScheduled", "WorkflowExecutionStarted"])
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_get_workflow_execution_history_with_reverse_order_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
hsh = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
run_id = hsh["runId"]
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": run_id, "workflowId": "uid-abcd1234"},
|
||||
reverseOrder=True,
|
||||
)
|
||||
types = [evt["eventType"] for evt in resp["events"]]
|
||||
types.should.equal(["DecisionTaskScheduled", "WorkflowExecutionStarted"])
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_get_workflow_execution_history_on_non_existent_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -137,7 +322,24 @@ def test_get_workflow_execution_history_on_non_existent_workflow_execution():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_get_workflow_execution_history_on_non_existent_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.get_workflow_execution_history(
|
||||
domain="test-domain",
|
||||
execution={"runId": "wrong-run-id", "workflowId": "wrong-workflow-id"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=wrong-workflow-id, runId=wrong-run-id]"
|
||||
)
|
||||
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
||||
|
||||
# ListOpenWorkflowExecutions endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_open_workflow_executions():
|
||||
conn = setup_swf_environment()
|
||||
@ -175,7 +377,52 @@ def test_list_open_workflow_executions():
|
||||
open_workflow["executionStatus"].should.equal("OPEN")
|
||||
|
||||
|
||||
# ListOpenWorkflowExecutions endpoint
|
||||
@mock_swf
|
||||
def test_list_open_workflow_executions_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
# One open workflow execution
|
||||
client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
# One closed workflow execution to make sure it isn't displayed
|
||||
run_id = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd12345",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)["runId"]
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd12345",
|
||||
details="some details",
|
||||
reason="a more complete reason",
|
||||
runId=run_id,
|
||||
)
|
||||
|
||||
yesterday = datetime.utcnow() - timedelta(days=1)
|
||||
oldest_date = unix_time(yesterday)
|
||||
response = client.list_open_workflow_executions(
|
||||
domain="test-domain",
|
||||
startTimeFilter={"oldestDate": oldest_date},
|
||||
executionFilter={"workflowId": "test-workflow"},
|
||||
)
|
||||
execution_infos = response["executionInfos"]
|
||||
len(execution_infos).should.equal(1)
|
||||
open_workflow = execution_infos[0]
|
||||
open_workflow["workflowType"].should.equal(
|
||||
{"version": "v1.0", "name": "test-workflow"}
|
||||
)
|
||||
open_workflow.should.contain("startTimestamp")
|
||||
open_workflow["execution"]["workflowId"].should.equal("uid-abcd1234")
|
||||
open_workflow["execution"].should.contain("runId")
|
||||
open_workflow["cancelRequested"].should.be(False)
|
||||
open_workflow["executionStatus"].should.equal("OPEN")
|
||||
|
||||
|
||||
# ListClosedWorkflowExecutions endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_closed_workflow_executions():
|
||||
conn = setup_swf_environment()
|
||||
@ -213,7 +460,52 @@ def test_list_closed_workflow_executions():
|
||||
open_workflow["executionStatus"].should.equal("CLOSED")
|
||||
|
||||
|
||||
# ListClosedWorkflowExecutions endpoint
|
||||
@mock_swf
|
||||
def test_list_closed_workflow_executions_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
# Leave one workflow execution open to make sure it isn't displayed
|
||||
client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
# One closed workflow execution
|
||||
run_id = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd12345",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)["runId"]
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd12345",
|
||||
details="some details",
|
||||
reason="a more complete reason",
|
||||
runId=run_id,
|
||||
)
|
||||
|
||||
yesterday = datetime.utcnow() - timedelta(days=1)
|
||||
oldest_date = unix_time(yesterday)
|
||||
response = client.list_closed_workflow_executions(
|
||||
domain="test-domain",
|
||||
startTimeFilter={"oldestDate": oldest_date},
|
||||
executionFilter={"workflowId": "test-workflow"},
|
||||
)
|
||||
execution_infos = response["executionInfos"]
|
||||
len(execution_infos).should.equal(1)
|
||||
open_workflow = execution_infos[0]
|
||||
open_workflow["workflowType"].should.equal(
|
||||
{"version": "v1.0", "name": "test-workflow"}
|
||||
)
|
||||
open_workflow.should.contain("startTimestamp")
|
||||
open_workflow["execution"]["workflowId"].should.equal("uid-abcd12345")
|
||||
open_workflow["execution"].should.contain("runId")
|
||||
open_workflow["cancelRequested"].should.be(False)
|
||||
open_workflow["executionStatus"].should.equal("CLOSED")
|
||||
|
||||
|
||||
# TerminateWorkflowExecution endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_terminate_workflow_execution():
|
||||
conn = setup_swf_environment()
|
||||
@ -239,6 +531,36 @@ def test_terminate_workflow_execution():
|
||||
attrs["cause"].should.equal("OPERATOR_INITIATED")
|
||||
|
||||
|
||||
# TerminateWorkflowExecution endpoint
|
||||
@mock_swf
|
||||
def test_terminate_workflow_execution_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
run_id = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)["runId"]
|
||||
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
details="some details",
|
||||
reason="a more complete reason",
|
||||
runId=run_id,
|
||||
)
|
||||
|
||||
resp = client.get_workflow_execution_history(
|
||||
domain="test-domain", execution={"runId": run_id, "workflowId": "uid-abcd1234"},
|
||||
)
|
||||
evt = resp["events"][-1]
|
||||
evt["eventType"].should.equal("WorkflowExecutionTerminated")
|
||||
attrs = evt["workflowExecutionTerminatedEventAttributes"]
|
||||
attrs["details"].should.equal("some details")
|
||||
attrs["reason"].should.equal("a more complete reason")
|
||||
attrs["cause"].should.equal("OPERATOR_INITIATED")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_terminate_workflow_execution_with_wrong_workflow_or_run_id():
|
||||
conn = setup_swf_environment()
|
||||
@ -272,3 +594,58 @@ def test_terminate_workflow_execution_with_wrong_workflow_or_run_id():
|
||||
).should.throw(
|
||||
SWFResponseError, "WorkflowExecution=[workflowId=uid-abcd1234, runId="
|
||||
)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_terminate_workflow_execution_with_wrong_workflow_or_run_id_boto3():
|
||||
client = setup_swf_environment_boto3()
|
||||
run_id = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)["runId"]
|
||||
|
||||
# terminate workflow execution
|
||||
client.terminate_workflow_execution(domain="test-domain", workflowId="uid-abcd1234")
|
||||
|
||||
# already closed, with run_id
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain", workflowId="uid-abcd1234", runId=run_id
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId={}]".format(
|
||||
run_id
|
||||
)
|
||||
)
|
||||
|
||||
# already closed, without run_id
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain", workflowId="uid-abcd1234"
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution, workflowId = uid-abcd1234"
|
||||
)
|
||||
|
||||
# wrong workflow id
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain", workflowId="uid-non-existent"
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution, workflowId = uid-non-existent"
|
||||
)
|
||||
|
||||
# wrong run_id
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.terminate_workflow_execution(
|
||||
domain="test-domain", workflowId="uid-abcd1234", runId="foo"
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown execution: WorkflowExecution=[workflowId=uid-abcd1234, runId=foo]"
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import sure
|
||||
import boto
|
||||
import boto3
|
||||
import pytest
|
||||
|
||||
from moto import mock_swf_deprecated
|
||||
from moto import mock_swf
|
||||
@ -9,6 +10,7 @@ from botocore.exceptions import ClientError
|
||||
|
||||
|
||||
# RegisterWorkflowType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -21,6 +23,26 @@ def test_register_workflow_type():
|
||||
actype["workflowType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# RegisterWorkflowType endpoint
|
||||
@mock_swf
|
||||
def test_register_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="test-workflow", version="v1.0"
|
||||
)
|
||||
|
||||
types = client.list_workflow_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED"
|
||||
)
|
||||
actype = types["typeInfos"][0]
|
||||
actype["workflowType"]["name"].should.equal("test-workflow")
|
||||
actype["workflowType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_already_existing_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -32,6 +54,27 @@ def test_register_already_existing_workflow_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_register_already_existing_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="test-workflow", version="v1.0"
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="test-workflow", version="v1.0"
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("TypeAlreadyExistsFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"WorkflowType=[name=test-workflow, version=v1.0]"
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_register_with_wrong_parameter_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -43,6 +86,7 @@ def test_register_with_wrong_parameter_type():
|
||||
|
||||
|
||||
# ListWorkflowTypes endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_workflow_types():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -59,6 +103,34 @@ def test_list_workflow_types():
|
||||
names.should.equal(["a-test-workflow", "b-test-workflow", "c-test-workflow"])
|
||||
|
||||
|
||||
# ListWorkflowTypes endpoint
|
||||
@mock_swf
|
||||
def test_list_workflow_types_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="b-test-workflow", version="v1.0"
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="a-test-workflow", version="v1.0"
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="c-test-workflow", version="v1.0"
|
||||
)
|
||||
|
||||
all_workflow_types = client.list_workflow_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED"
|
||||
)
|
||||
names = [
|
||||
activity_type["workflowType"]["name"]
|
||||
for activity_type in all_workflow_types["typeInfos"]
|
||||
]
|
||||
names.should.equal(["a-test-workflow", "b-test-workflow", "c-test-workflow"])
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_list_workflow_types_reverse_order():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -77,7 +149,35 @@ def test_list_workflow_types_reverse_order():
|
||||
names.should.equal(["c-test-workflow", "b-test-workflow", "a-test-workflow"])
|
||||
|
||||
|
||||
# ListWorkflowTypes endpoint
|
||||
@mock_swf
|
||||
def test_list_workflow_types_reverse_order_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="b-test-workflow", version="v1.0"
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="a-test-workflow", version="v1.0"
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="c-test-workflow", version="v1.0"
|
||||
)
|
||||
|
||||
all_workflow_types = client.list_workflow_types(
|
||||
domain="test-domain", registrationStatus="REGISTERED", reverseOrder=True
|
||||
)
|
||||
names = [
|
||||
activity_type["workflowType"]["name"]
|
||||
for activity_type in all_workflow_types["typeInfos"]
|
||||
]
|
||||
names.should.equal(["c-test-workflow", "b-test-workflow", "a-test-workflow"])
|
||||
|
||||
|
||||
# DeprecateWorkflowType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -91,6 +191,29 @@ def test_deprecate_workflow_type():
|
||||
actype["workflowType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# DeprecateWorkflowType endpoint
|
||||
@mock_swf
|
||||
def test_deprecate_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="test-workflow", version="v1.0"
|
||||
)
|
||||
client.deprecate_workflow_type(
|
||||
domain="test-domain", workflowType={"name": "test-workflow", "version": "v1.0"}
|
||||
)
|
||||
|
||||
actypes = client.list_workflow_types(
|
||||
domain="test-domain", registrationStatus="DEPRECATED"
|
||||
)
|
||||
actype = actypes["typeInfos"][0]
|
||||
actype["workflowType"]["name"].should.equal("test-workflow")
|
||||
actype["workflowType"]["version"].should.equal("v1.0")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_already_deprecated_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -103,6 +226,31 @@ def test_deprecate_already_deprecated_workflow_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_already_deprecated_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
client.register_workflow_type(
|
||||
domain="test-domain", name="test-workflow", version="v1.0"
|
||||
)
|
||||
client.deprecate_workflow_type(
|
||||
domain="test-domain", workflowType={"name": "test-workflow", "version": "v1.0"}
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_workflow_type(
|
||||
domain="test-domain",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("TypeDeprecatedFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"WorkflowType=[name=test-workflow, version=v1.0]"
|
||||
)
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_deprecate_non_existent_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -113,6 +261,24 @@ def test_deprecate_non_existent_workflow_type():
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_deprecate_non_existent_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.deprecate_workflow_type(
|
||||
domain="test-domain",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown type: WorkflowType=[name=test-workflow, version=v1.0]"
|
||||
)
|
||||
|
||||
|
||||
# UndeprecateWorkflowType endpoint
|
||||
@mock_swf
|
||||
def test_undeprecate_workflow_type():
|
||||
@ -185,6 +351,7 @@ def test_undeprecate_non_existent_workflow_type():
|
||||
|
||||
|
||||
# DescribeWorkflowType endpoint
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -242,6 +409,7 @@ def test_describe_workflow_type_full_boto3():
|
||||
resp["configuration"]["defaultLambdaRole"].should.equal("arn:bar")
|
||||
|
||||
|
||||
# Has boto3 equivalent
|
||||
@mock_swf_deprecated
|
||||
def test_describe_non_existent_workflow_type():
|
||||
conn = boto.connect_swf("the_key", "the_secret")
|
||||
@ -250,3 +418,21 @@ def test_describe_non_existent_workflow_type():
|
||||
conn.describe_workflow_type.when.called_with(
|
||||
"test-domain", "non-existent", "v1.0"
|
||||
).should.throw(SWFResponseError)
|
||||
|
||||
|
||||
@mock_swf
|
||||
def test_describe_non_existent_workflow_type_boto3():
|
||||
client = boto3.client("swf", region_name="us-east-1")
|
||||
client.register_domain(
|
||||
name="test-domain", workflowExecutionRetentionPeriodInDays="60",
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as ex:
|
||||
client.describe_workflow_type(
|
||||
domain="test-domain",
|
||||
workflowType={"name": "non-existent", "version": "v1.0"},
|
||||
)
|
||||
ex.value.response["Error"]["Code"].should.equal("UnknownResourceFault")
|
||||
ex.value.response["Error"]["Message"].should.equal(
|
||||
"Unknown type: WorkflowType=[name=non-existent, version=v1.0]"
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import boto
|
||||
import boto3
|
||||
|
||||
from moto.swf.models import ActivityType, Domain, WorkflowType, WorkflowExecution
|
||||
|
||||
@ -47,6 +48,17 @@ def _generic_workflow_type_attributes():
|
||||
)
|
||||
|
||||
|
||||
def _generic_workflow_type_attributes_boto3():
|
||||
return {
|
||||
"name": "test-workflow",
|
||||
"version": "v1.0",
|
||||
"defaultTaskList": {"name": "queue"},
|
||||
"defaultChildPolicy": "ABANDON",
|
||||
"defaultExecutionStartToCloseTimeout": "7200",
|
||||
"defaultTaskStartToCloseTimeout": "300",
|
||||
}
|
||||
|
||||
|
||||
def get_basic_workflow_type():
|
||||
args, kwargs = _generic_workflow_type_attributes()
|
||||
return WorkflowType(*args, **kwargs)
|
||||
@ -58,6 +70,12 @@ def mock_basic_workflow_type(domain_name, conn):
|
||||
return conn
|
||||
|
||||
|
||||
def mock_basic_workflow_type_boto3(domain_name, client):
|
||||
kwargs = _generic_workflow_type_attributes_boto3()
|
||||
client.register_workflow_type(domain=domain_name, **kwargs)
|
||||
return client
|
||||
|
||||
|
||||
# A test WorkflowExecution
|
||||
def make_workflow_execution(**kwargs):
|
||||
domain = get_basic_domain()
|
||||
@ -93,6 +111,33 @@ def setup_workflow():
|
||||
return conn
|
||||
|
||||
|
||||
# Setup a complete example workflow and return the connection object
|
||||
def setup_workflow_boto3():
|
||||
client = boto3.client("swf", region_name="us-west-1")
|
||||
client.register_domain(
|
||||
name="test-domain",
|
||||
workflowExecutionRetentionPeriodInDays="60",
|
||||
description="A test domain",
|
||||
)
|
||||
mock_basic_workflow_type_boto3("test-domain", client)
|
||||
client.register_activity_type(
|
||||
domain="test-domain",
|
||||
name="test-activity",
|
||||
version="v1.1",
|
||||
defaultTaskHeartbeatTimeout="600",
|
||||
defaultTaskScheduleToCloseTimeout="600",
|
||||
defaultTaskScheduleToStartTimeout="600",
|
||||
defaultTaskStartToCloseTimeout="600",
|
||||
)
|
||||
wfe = client.start_workflow_execution(
|
||||
domain="test-domain",
|
||||
workflowId="uid-abcd1234",
|
||||
workflowType={"name": "test-workflow", "version": "v1.0"},
|
||||
)
|
||||
client.run_id = wfe["runId"]
|
||||
return client
|
||||
|
||||
|
||||
# A helper for processing the first timeout on a given object
|
||||
def process_first_timeout(obj):
|
||||
_timeout = obj.first_timeout()
|
||||
|
Loading…
x
Reference in New Issue
Block a user