• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

localstack / localstack / 21891233725

10 Feb 2026 10:59PM UTC coverage: 86.883% (+0.01%) from 86.871%
21891233725

push

github

web-flow
SFN: Fix Local mock iterations for states without retry (#13693)

Co-authored-by: Hernan <hernaner28@gmail.com>

The Step Functions Local mock configuration was using RetryCount to index numbered mock responses. In case of successful invocations or states without retry configuration this caused all invocations to return the same response ("0") instead of iterating through the sequence ("0", "1", "2", etc.).

RetryCount only increments on actual retry attempts (failures), not on successful invocations. This made the mock iteration feature unusable for testing state transition scenarios with multiple invocations of the same state.

- Added next_local_mock_invocation_number dict to execution environment to track mock invocations.
- Modified get_current_local_mocked_response() to use next_local_mock_invocation_number instead of retry_count.
- Shared next_local_mock_invocation_number between parent and child frames to maintain consistent counting across execution context

An existing `aws.services.stepfunctions.v2.local_mocking.test_base_scenarios.TestBaseScenarios.test_map_state_lambda test` was giving a false positive. It used a mock response with only one mocked invocation and should have failed when 2 invocations were done. Effectively, it started to fail after the fix and mocked response has been adjusted.

Also, adds `test_numbered_mock_responses_multiple_success_invocations` that tests multiple success invocations in a regular top-level state, outside of map configuration.

7 of 7 new or added lines in 1 file covered. (100.0%)

255 existing lines in 12 files now uncovered.

69977 of 80542 relevant lines covered (86.88%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.1
/localstack-core/localstack/runtime/analytics.py
1
import logging
1✔
2
import os
1✔
3
import platform
1✔
4

5
from localstack import config
1✔
6
from localstack.runtime import hooks
1✔
7
from localstack.utils.analytics import log
1✔
8

9
LOG = logging.getLogger(__name__)
1✔
10

11
# Config options for which both usage and values are reported in analytics.
12
# Important: This list must only contain options whose values do not contain PII or sensitive data.
13
TRACKED_ENV_VAR = [
1✔
14
    "ACTIVATE_PRO",
15
    "ALLOW_NONSTANDARD_REGIONS",
16
    "BEDROCK_PREWARM",
17
    "CFN_IGNORE_UNSUPPORTED_TYPE_CREATE",
18
    "CFN_IGNORE_UNSUPPORTED_TYPE_UPDATE",
19
    "CFN_IGNORE_UNSUPPORTED_RESOURCE_TYPES",
20
    "CLOUDFRONT_LAMBDA_EDGE",
21
    "CONTAINER_RUNTIME",
22
    "DEBUG",
23
    "DEFAULT_REGION",  # Not functional; deprecated in 0.12.7, removed in 3.0.0
24
    "DEFAULT_BEDROCK_MODEL",
25
    "DISABLE_CORS_CHECK",
26
    "DISABLE_CORS_HEADERS",
27
    "DMS_SERVERLESS_DEPROVISIONING_DELAY",
28
    "DMS_SERVERLESS_STATUS_CHANGE_WAITING_TIME",
29
    "DNS_ADDRESS",
30
    "DYNAMODB_ERROR_PROBABILITY",
31
    "DYNAMODB_IN_MEMORY",
32
    "DYNAMODB_REMOVE_EXPIRED_ITEMS",
33
    "EAGER_SERVICE_LOADING",
34
    "EC2_DOCKER_INIT",
35
    "EC2_VM_MANAGER",
36
    "ECS_TASK_EXECUTOR",
37
    "EDGE_PORT",
38
    "EKS_K8S_PROVIDER",
39
    "EKS_PERSIST_CLUSTER_CONTENTS",
40
    "ENABLE_REPLICATOR",
41
    "ENFORCE_IAM",
42
    "ES_CUSTOM_BACKEND",  # deprecated in 0.14.0, removed in 3.0.0
43
    "ES_MULTI_CLUSTER",  # deprecated in 0.14.0, removed in 3.0.0
44
    "ES_ENDPOINT_STRATEGY",  # deprecated in 0.14.0, removed in 3.0.0
45
    "EVENT_RULE_ENGINE",
46
    "IAM_SOFT_MODE",
47
    "KINESIS_PROVIDER",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
48
    "KINESIS_ERROR_PROBABILITY",
49
    "KMS_PROVIDER",  # defunct since 1.4.0
50
    "LAMBDA_DEBUG_MODE",
51
    "LAMBDA_DOWNLOAD_AWS_LAYERS",
52
    "LAMBDA_EXECUTOR",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
53
    "LAMBDA_STAY_OPEN_MODE",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
54
    "LAMBDA_REMOTE_DOCKER",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
55
    "LAMBDA_CODE_EXTRACT_TIME",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
56
    "LAMBDA_CONTAINER_REGISTRY",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
57
    "LAMBDA_FALLBACK_URL",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
58
    "LAMBDA_FORWARD_URL",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
59
    "LAMBDA_XRAY_INIT",  # Not functional; deprecated in 2.0.0, removed in 3.0.0
60
    "LAMBDA_PREBUILD_IMAGES",
61
    "LAMBDA_RUNTIME_EXECUTOR",
62
    "LAMBDA_RUNTIME_ENVIRONMENT_TIMEOUT",
63
    "LEGACY_EDGE_PROXY",  # Not functional; deprecated in 1.0.0, removed in 2.0.0
64
    "LS_LOG",
65
    "LOCALSTACK_K8S_DEPLOYMENT_METHOD",
66
    "MOCK_UNIMPLEMENTED",  # Not functional; deprecated in 1.3.0, removed in 3.0.0
67
    "OPENSEARCH_ENDPOINT_STRATEGY",
68
    "PERSISTENCE",
69
    "PERSISTENCE_SINGLE_FILE",
70
    "PERSIST_ALL",  # defunct since 2.3.2
71
    "PORT_WEB_UI",
72
    "RDS_MYSQL_DOCKER",
73
    "REQUIRE_PRO",
74
    "SERVICES",
75
    "STRICT_SERVICE_LOADING",
76
    "SKIP_INFRA_DOWNLOADS",
77
    "SQS_ENDPOINT_STRATEGY",
78
    "USE_SINGLE_REGION",  # Not functional; deprecated in 0.12.7, removed in 3.0.0
79
    "USE_SSL",
80
]
81

82
# Config options for which only the usage is reported in analytics.
83
# Use this for options which may hold sensitive data or PII.
84
PRESENCE_ENV_VAR = [
1✔
85
    "DATA_DIR",
86
    "EDGE_FORWARD_URL",  # Not functional; deprecated in 1.4.0, removed in 3.0.0
87
    "EC2_HYPERVISOR_URI",
88
    "EC2_REFERENCE_DOMAIN",
89
    "EC2_LIBVIRT_NETWORK",
90
    "EC2_LIBVIRT_POOL",
91
    "GATEWAY_LISTEN",
92
    "HOSTNAME",
93
    "HOSTNAME_EXTERNAL",
94
    "HOSTNAME_FROM_LAMBDA",
95
    "HOST_TMP_FOLDER",  # Not functional; deprecated in 1.0.0, removed in 2.0.0
96
    "INIT_SCRIPTS_PATH",  # Not functional; deprecated in 1.1.0, removed in 2.0.0
97
    "KUBERNETES_SERVICE_HOST",
98
    "LAMBDA_DEBUG_MODE_CONFIG_PATH",
99
    "LEGACY_DIRECTORIES",  # Not functional; deprecated in 1.1.0, removed in 2.0.0
100
    "LEGACY_INIT_DIR",  # Not functional; deprecated in 1.1.0, removed in 2.0.0
101
    "LOCALSTACK_HOST",
102
    "LOCALSTACK_HOSTNAME",
103
    "OUTBOUND_HTTP_PROXY",
104
    "OUTBOUND_HTTPS_PROXY",
105
    "S3_DIR",
106
    "SFN_MOCK_CONFIG",
107
    "TMPDIR",
108
]
109

110

111
@hooks.on_infra_start()
1✔
112
def _publish_config_as_analytics_event():
1✔
113
    env_vars = list(TRACKED_ENV_VAR)
1✔
114

115
    for key, value in os.environ.items():
1✔
116
        if key.startswith("PROVIDER_OVERRIDE_"):
1✔
117
            env_vars.append(key)
1✔
118
        elif key.startswith("SYNCHRONOUS_") and key.endswith("_EVENTS"):
1✔
119
            # these config variables have been removed with 3.0.0
UNCOV
120
            env_vars.append(key)
×
121

122
    env_vars = {key: os.getenv(key) for key in env_vars}
1✔
123
    present_env_vars = {env_var: 1 for env_var in PRESENCE_ENV_VAR if os.getenv(env_var)}
1✔
124

125
    log.event("config", env_vars=env_vars, set_vars=present_env_vars)
1✔
126

127

128
class LocalstackContainerInfo:
1✔
129
    def get_image_variant(self) -> str:
1✔
130
        for f in os.listdir("/usr/lib/localstack"):
1✔
131
            if f.startswith(".") and f.endswith("-version"):
1✔
132
                return f[1:-8]
1✔
UNCOV
133
        return "unknown"
×
134

135
    def has_docker_socket(self) -> bool:
1✔
136
        return os.path.exists("/run/docker.sock")
1✔
137

138
    def uname(self) -> dict:
1✔
139
        result = platform.uname()
1✔
140
        return {
1✔
141
            "uname_system": result.system,
142
            "uname_release": result.release,
143
            "uname_version": result.version,
144
            "uname_machine": result.machine,
145
        }
146

147
    def to_dict(self):
1✔
148
        return {
1✔
149
            "variant": self.get_image_variant(),
150
            "has_docker_socket": self.has_docker_socket(),
151
            "container_runtime": config.CONTAINER_RUNTIME,
152
            **self.uname(),
153
        }
154

155

156
@hooks.on_infra_start()
1✔
157
def _publish_container_info():
1✔
158
    if not config.is_in_docker:
1✔
159
        return
1✔
160

161
    try:
1✔
162
        log.event("container_info", payload=LocalstackContainerInfo().to_dict())
1✔
163
    except Exception as e:
×
UNCOV
164
        if config.DEBUG_ANALYTICS:
×
UNCOV
165
            LOG.debug("error gathering container information: %s", e)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc