Skip to content
This repository was archived by the owner on Mar 23, 2026. It is now read-only.

Commit a17c007

Browse files
authored
feat(stepfunctions): Add support for variables as TestState parameter (#13827)
1 parent aa8af99 commit a17c007

11 files changed

Lines changed: 383 additions & 49 deletions

File tree

localstack-core/localstack/services/stepfunctions/asl/component/test_state/state/common.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ class MockedCommonState(MockedBaseState[CommonStateField]):
2020
def add_inspection_data(self, env: TestStateEnvironment):
2121
state = self._wrapped
2222

23+
if state._is_language_query_jsonpath():
24+
self._add_jsonpath_inspection_data(env)
25+
26+
def _add_jsonpath_inspection_data(self, env: TestStateEnvironment):
27+
28+
state = self._wrapped
29+
2330
if not isinstance(state, StatePass):
2431
if not self.is_single_state:
2532
return

localstack-core/localstack/services/stepfunctions/asl/eval/test_state/environment.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
ProgramRetriable,
2222
)
2323
from localstack.services.stepfunctions.asl.eval.variable_store import VariableStore
24+
from localstack.services.stepfunctions.asl.utils.encoding import to_json_str
2425
from localstack.services.stepfunctions.backend.activity import Activity
2526
from localstack.services.stepfunctions.backend.test_state.test_state_mock import TestStateMock
2627

@@ -50,6 +51,9 @@ def __init__(
5051
variable_store=variable_store,
5152
)
5253
self.inspection_data = InspectionData()
54+
variables = variable_store.to_dict()
55+
if variables:
56+
self.inspection_data["variables"] = to_json_str(variables)
5357
self.mock = mock
5458

5559
def is_test_state_mocked_mode(self) -> bool:

localstack-core/localstack/services/stepfunctions/asl/eval/variable_store.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,17 @@ class VariableStore:
5454
_outer_variable_declaration_cache: VariableDeclarations | None
5555
_variable_declarations_cache: VariableDeclarations | None
5656

57-
def __init__(self):
57+
def __init__(self, variables: dict | None = None):
5858
self._outer_scope = {}
5959
self._inner_scope = {}
6060
self._declaration_tracing = set()
6161
self._outer_variable_declaration_cache = None
6262
self._variable_declarations_cache = None
6363

64+
if variables:
65+
for key, value in variables.items():
66+
self.set(key, value)
67+
6468
@classmethod
6569
def as_inner_scope_of(cls, outer_variable_store: VariableStore) -> VariableStore:
6670
inner_variable_store = cls()
@@ -85,6 +89,14 @@ def get_assigned_variables(self) -> dict[str, str]:
8589
assigned_variables[traced_declaration_identifier] = traced_declaration_value_json_str
8690
return assigned_variables
8791

92+
def to_dict(self) -> dict[str, str]:
93+
assigned_variables: dict[str, str] = {}
94+
for traced_declaration_identifier in self._declaration_tracing:
95+
assigned_variables[traced_declaration_identifier] = self.get(
96+
traced_declaration_identifier
97+
)
98+
return assigned_variables
99+
88100
def get(self, variable_identifier: VariableIdentifier) -> VariableValue:
89101
if variable_identifier in self._inner_scope:
90102
return self._inner_scope[variable_identifier]

localstack-core/localstack/services/stepfunctions/backend/test_state/execution.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
TestStateOutput,
1313
Timestamp,
1414
)
15-
from localstack.services.stepfunctions.asl.eval.evaluation_details import EvaluationDetails
15+
from localstack.services.stepfunctions.asl.eval.evaluation_details import (
16+
EvaluationDetails,
17+
)
1618
from localstack.services.stepfunctions.asl.eval.program_state import (
1719
ProgramEnded,
1820
ProgramError,
@@ -43,6 +45,7 @@ class TestStateExecution(Execution):
4345
next_state: str | None
4446
state_name: str | None
4547
mock: TestStateMock | None
48+
variables: dict | None
4649

4750
class TestCaseExecutionWorkerCommunication(BaseExecutionWorkerCommunication):
4851
_execution: TestStateExecution
@@ -79,6 +82,7 @@ def __init__(
7982
state_name: str | None = None,
8083
input_data: dict | None = None,
8184
mock: TestStateMock | None = None,
85+
variables: dict | None = None,
8286
):
8387
super().__init__(
8488
name=name,
@@ -98,6 +102,7 @@ def __init__(
98102
self.next_state = None
99103
self.state_name = state_name
100104
self.mock = mock
105+
self.variables = variables
101106

102107
def _get_start_execution_worker_comm(self) -> BaseExecutionWorkerCommunication:
103108
return self.TestCaseExecutionWorkerCommunication(self)
@@ -114,6 +119,7 @@ def _get_start_execution_worker(self) -> TestStateExecutionWorker:
114119
activity_store=self._activity_store,
115120
state_name=self.state_name,
116121
mock=self.mock,
122+
variables=self.variables,
117123
)
118124

119125
def publish_execution_status_change_event(self):

localstack-core/localstack/services/stepfunctions/backend/test_state/execution_worker.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
StateMachineData,
1515
)
1616
from localstack.services.stepfunctions.asl.eval.test_state.environment import TestStateEnvironment
17+
from localstack.services.stepfunctions.asl.eval.variable_store import VariableStore
1718
from localstack.services.stepfunctions.asl.parse.test_state.asl_parser import (
1819
TestStateAmazonStateLanguageParser,
1920
)
@@ -29,6 +30,7 @@ class TestStateExecutionWorker(SyncExecutionWorker):
2930
env: TestStateEnvironment | None
3031
state_name: str | None = None
3132
mock: TestStateMock | None
33+
variables: dict | None
3234

3335
def __init__(
3436
self,
@@ -38,6 +40,7 @@ def __init__(
3840
activity_store: dict[Arn, Activity],
3941
state_name: StateName | None = None,
4042
mock: TestStateMock | None = None,
43+
variables: dict | None = None,
4144
):
4245
super().__init__(
4346
evaluation_details,
@@ -48,6 +51,7 @@ def __init__(
4851
)
4952
self.state_name = state_name
5053
self.mock = mock
54+
self.variables = variables
5155

5256
def _get_evaluation_entrypoint(self) -> EvalComponent:
5357
return TestStateAmazonStateLanguageParser.parse(
@@ -74,5 +78,6 @@ def _get_evaluation_environment(self) -> Environment:
7478
event_history_context=EventHistoryContext.of_program_start(),
7579
cloud_watch_logging_session=self._cloud_watch_logging_session,
7680
activity_store=self._activity_store,
81+
variable_store=VariableStore(self.variables),
7782
mock=self.mock,
7883
)

localstack-core/localstack/services/stepfunctions/provider.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,9 @@ def test_state(
15661566
if input_json := request.get("input", {}):
15671567
input_json = json.loads(input_json)
15681568

1569+
if variables_json := request.get("variables"):
1570+
variables_json = json.loads(variables_json)
1571+
15691572
execution = TestStateExecution(
15701573
name=exec_name,
15711574
role_arn=role_arn,
@@ -1578,6 +1581,7 @@ def test_state(
15781581
state_name=state_name,
15791582
activity_store=self.get_store(context).activities,
15801583
mock=state_mock,
1584+
variables=variables_json,
15811585
)
15821586
execution.start()
15831587

tests/aws/services/stepfunctions/v2/outputdecl/test_output.snapshot.json

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_cases[BASE_EMPTY]": {
3-
"recorded-date": "04-11-2024, 13:15:46",
3+
"recorded-date": "19-02-2026, 14:47:34",
44
"recorded-content": {
55
"get_execution_history": {
66
"events": [
@@ -78,7 +78,7 @@
7878
}
7979
},
8080
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_cases[BASE_LITERALS]": {
81-
"recorded-date": "04-11-2024, 13:16:06",
81+
"recorded-date": "19-02-2026, 14:47:49",
8282
"recorded-content": {
8383
"get_execution_history": {
8484
"events": [
@@ -266,7 +266,7 @@
266266
}
267267
},
268268
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_cases[BASE_EXPR]": {
269-
"recorded-date": "04-11-2024, 13:16:22",
269+
"recorded-date": "19-02-2026, 14:48:04",
270270
"recorded-content": {
271271
"get_execution_history": {
272272
"events": [
@@ -463,7 +463,7 @@
463463
}
464464
},
465465
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_cases[BASE_DIRECT_EXPR]": {
466-
"recorded-date": "04-11-2024, 13:16:38",
466+
"recorded-date": "19-02-2026, 14:48:17",
467467
"recorded-content": {
468468
"get_execution_history": {
469469
"events": [
@@ -587,7 +587,7 @@
587587
}
588588
},
589589
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_lambda[BASE_LAMBDA]": {
590-
"recorded-date": "04-11-2024, 14:01:00",
590+
"recorded-date": "19-02-2026, 14:48:36",
591591
"recorded-content": {
592592
"get_execution_history": {
593593
"events": [
@@ -813,7 +813,7 @@
813813
}
814814
},
815815
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_task_lambda[BASE_TASK_LAMBDA]": {
816-
"recorded-date": "04-11-2024, 14:15:19",
816+
"recorded-date": "19-02-2026, 14:48:54",
817817
"recorded-content": {
818818
"get_execution_history": {
819819
"events": [
@@ -920,9 +920,7 @@
920920
"Connection": [
921921
"keep-alive"
922922
],
923-
"x-amzn-RequestId": [
924-
"<uuid:1>"
925-
],
923+
"x-amzn-RequestId": "x-amzn-RequestId",
926924
"Content-Length": [
927925
"60"
928926
],
@@ -939,13 +937,13 @@
939937
"Date": "date",
940938
"X-Amz-Executed-Version": "$LATEST",
941939
"x-amzn-Remapped-Content-Length": "0",
942-
"x-amzn-RequestId": "<uuid:1>",
940+
"x-amzn-RequestId": "x-amzn-RequestId",
943941
"X-Amzn-Trace-Id": "X-Amzn-Trace-Id"
944942
},
945943
"HttpStatusCode": 200
946944
},
947945
"SdkResponseMetadata": {
948-
"RequestId": "<uuid:1>"
946+
"RequestId": "RequestId"
949947
},
950948
"StatusCode": 200
951949
},
@@ -996,9 +994,7 @@
996994
"Connection": [
997995
"keep-alive"
998996
],
999-
"x-amzn-RequestId": [
1000-
"<uuid:1>"
1001-
],
997+
"x-amzn-RequestId": "x-amzn-RequestId",
1002998
"Content-Length": [
1003999
"60"
10041000
],
@@ -1015,13 +1011,13 @@
10151011
"Date": "date",
10161012
"X-Amz-Executed-Version": "$LATEST",
10171013
"x-amzn-Remapped-Content-Length": "0",
1018-
"x-amzn-RequestId": "<uuid:1>",
1014+
"x-amzn-RequestId": "x-amzn-RequestId",
10191015
"X-Amzn-Trace-Id": "X-Amzn-Trace-Id"
10201016
},
10211017
"HttpStatusCode": 200
10221018
},
10231019
"SdkResponseMetadata": {
1024-
"RequestId": "<uuid:1>"
1020+
"RequestId": "RequestId"
10251021
},
10261022
"StatusCode": 200
10271023
}
@@ -1068,9 +1064,7 @@
10681064
"Connection": [
10691065
"keep-alive"
10701066
],
1071-
"x-amzn-RequestId": [
1072-
"<uuid:1>"
1073-
],
1067+
"x-amzn-RequestId": "x-amzn-RequestId",
10741068
"Content-Length": [
10751069
"60"
10761070
],
@@ -1087,13 +1081,13 @@
10871081
"Date": "date",
10881082
"X-Amz-Executed-Version": "$LATEST",
10891083
"x-amzn-Remapped-Content-Length": "0",
1090-
"x-amzn-RequestId": "<uuid:1>",
1084+
"x-amzn-RequestId": "x-amzn-RequestId",
10911085
"X-Amzn-Trace-Id": "X-Amzn-Trace-Id"
10921086
},
10931087
"HttpStatusCode": 200
10941088
},
10951089
"SdkResponseMetadata": {
1096-
"RequestId": "<uuid:1>"
1090+
"RequestId": "RequestId"
10971091
},
10981092
"StatusCode": 200
10991093
}
@@ -1116,7 +1110,7 @@
11161110
}
11171111
},
11181112
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[NULL]": {
1119-
"recorded-date": "20-11-2024, 18:24:00",
1113+
"recorded-date": "19-02-2026, 14:49:08",
11201114
"recorded-content": {
11211115
"get_execution_history": {
11221116
"events": [
@@ -1184,7 +1178,7 @@
11841178
}
11851179
},
11861180
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[INT]": {
1187-
"recorded-date": "20-11-2024, 18:24:15",
1181+
"recorded-date": "19-02-2026, 14:49:23",
11881182
"recorded-content": {
11891183
"get_execution_history": {
11901184
"events": [
@@ -1252,7 +1246,7 @@
12521246
}
12531247
},
12541248
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[FLOAT]": {
1255-
"recorded-date": "20-11-2024, 18:24:31",
1249+
"recorded-date": "19-02-2026, 14:49:37",
12561250
"recorded-content": {
12571251
"get_execution_history": {
12581252
"events": [
@@ -1320,7 +1314,7 @@
13201314
}
13211315
},
13221316
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[BOOL]": {
1323-
"recorded-date": "20-11-2024, 18:24:46",
1317+
"recorded-date": "19-02-2026, 14:49:51",
13241318
"recorded-content": {
13251319
"get_execution_history": {
13261320
"events": [
@@ -1388,7 +1382,7 @@
13881382
}
13891383
},
13901384
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[STR_LIT]": {
1391-
"recorded-date": "20-11-2024, 18:25:01",
1385+
"recorded-date": "19-02-2026, 14:50:05",
13921386
"recorded-content": {
13931387
"get_execution_history": {
13941388
"events": [
@@ -1456,7 +1450,7 @@
14561450
}
14571451
},
14581452
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[JSONATA_EXPR]": {
1459-
"recorded-date": "20-11-2024, 18:25:16",
1453+
"recorded-date": "19-02-2026, 14:50:20",
14601454
"recorded-content": {
14611455
"get_execution_history": {
14621456
"events": [
@@ -1528,7 +1522,7 @@
15281522
}
15291523
},
15301524
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[LIST_EMPY]": {
1531-
"recorded-date": "20-11-2024, 18:25:31",
1525+
"recorded-date": "19-02-2026, 14:50:35",
15321526
"recorded-content": {
15331527
"get_execution_history": {
15341528
"events": [
@@ -1596,7 +1590,7 @@
15961590
}
15971591
},
15981592
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_base_output_any_non_dict[LIST_RICH]": {
1599-
"recorded-date": "20-11-2024, 18:25:47",
1593+
"recorded-date": "19-02-2026, 14:50:49",
16001594
"recorded-content": {
16011595
"get_execution_history": {
16021596
"events": [
@@ -1664,7 +1658,7 @@
16641658
}
16651659
},
16661660
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_output_in_choice[CONDITION_TRUE]": {
1667-
"recorded-date": "27-12-2024, 14:50:09",
1661+
"recorded-date": "19-02-2026, 14:51:09",
16681662
"recorded-content": {
16691663
"get_execution_history": {
16701664
"events": [
@@ -1758,7 +1752,7 @@
17581752
}
17591753
},
17601754
"tests/aws/services/stepfunctions/v2/outputdecl/test_output.py::TestArgumentsBase::test_output_in_choice[CONDITION_FALSE]": {
1761-
"recorded-date": "27-12-2024, 14:50:24",
1755+
"recorded-date": "19-02-2026, 14:51:23",
17621756
"recorded-content": {
17631757
"get_execution_history": {
17641758
"events": [

0 commit comments

Comments
 (0)