Skip to content

Commit a1c97c0

Browse files
committed
test: add tests for cache eviction and narrowed exception handling
- test_cache_evicts_oldest_when_full: verifies FIFO eviction at _MAX_CACHE_SIZE - test_export_cloudformation_stack_unexpected_exception_propagates: verifies unexpected exceptions (TypeError etc.) are not silently swallowed - Updated existing expansion_failure test to use InvalidSamDocumentException
1 parent eaaf811 commit a1c97c0

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

tests/unit/lib/cfn_language_extensions/test_sam_integration.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ def test_frozen(self):
785785

786786
from samcli.lib.cfn_language_extensions.sam_integration import (
787787
_expansion_cache,
788+
_MAX_CACHE_SIZE,
788789
clear_expansion_cache,
789790
)
790791

@@ -973,3 +974,38 @@ def test_non_language_ext_template_cached(self):
973974
assert len(_expansion_cache) == 1
974975
# Ensure independence
975976
assert result1.expanded_template is not result2.expanded_template
977+
978+
def test_cache_evicts_oldest_when_full(self):
979+
"""Cache should evict the oldest entry when _MAX_CACHE_SIZE is reached."""
980+
clear_expansion_cache()
981+
template = {
982+
"Transform": "AWS::LanguageExtensions",
983+
"Resources": {
984+
"Fn::ForEach::Loop": [
985+
"Item",
986+
["A"],
987+
{"Res${Item}": {"Type": "AWS::SNS::Topic"}},
988+
]
989+
},
990+
}
991+
992+
with tempfile.TemporaryDirectory() as tmp:
993+
paths = []
994+
for i in range(_MAX_CACHE_SIZE + 1):
995+
path = os.path.join(tmp, f"template_{i}.yaml")
996+
with open(path, "w") as f:
997+
f.write("AWSTemplateFormatVersion: '2010-09-09'\n")
998+
paths.append(path)
999+
1000+
# Fill the cache to capacity
1001+
for i in range(_MAX_CACHE_SIZE):
1002+
expand_language_extensions(template, template_path=paths[i])
1003+
1004+
assert len(_expansion_cache) == _MAX_CACHE_SIZE
1005+
first_key = next(iter(_expansion_cache))
1006+
1007+
# One more should evict the oldest
1008+
expand_language_extensions(template, template_path=paths[_MAX_CACHE_SIZE])
1009+
1010+
assert len(_expansion_cache) == _MAX_CACHE_SIZE
1011+
assert first_key not in _expansion_cache

tests/unit/lib/package/test_artifact_exporter.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from samcli.commands._utils.experimental import ExperimentalFlag
1616
from samcli.commands.package import exceptions
1717
from samcli.commands.package.exceptions import ExportFailedError
18+
from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
1819
from samcli.lib.package.artifact_exporter import (
1920
is_local_folder,
2021
make_abs_path,
@@ -2515,7 +2516,7 @@ def test_export_cloudformation_stack_language_extensions_expansion_failure(self,
25152516

25162517
with patch(
25172518
"samcli.lib.cfn_language_extensions.sam_integration.expand_language_extensions",
2518-
side_effect=Exception("expansion failed"),
2519+
side_effect=InvalidSamDocumentException("expansion failed"),
25192520
):
25202521
stack_resource.export(resource_id, resource_dict, parent_dir)
25212522

@@ -2526,3 +2527,32 @@ def test_export_cloudformation_stack_language_extensions_expansion_failure(self,
25262527
self.assertNotIn("template_str", call_kwargs.kwargs)
25272528
finally:
25282529
os.remove(template_path)
2530+
2531+
@patch("samcli.lib.package.artifact_exporter.Template")
2532+
def test_export_cloudformation_stack_unexpected_exception_propagates(self, TemplateMock):
2533+
"""
2534+
When expand_language_extensions raises an unexpected exception (not InvalidSamDocumentException),
2535+
it should propagate instead of being silently swallowed.
2536+
"""
2537+
stack_resource = CloudFormationStackResource(self.uploaders_mock, self.code_signer_mock)
2538+
2539+
resource_id = "NestedStack"
2540+
property_name = stack_resource.PROPERTY_NAME
2541+
2542+
handle = tempfile.NamedTemporaryFile(suffix=".yaml", mode="w", delete=False)
2543+
try:
2544+
handle.write("Resources: {}")
2545+
handle.flush()
2546+
template_path = handle.name
2547+
handle.close()
2548+
resource_dict = {property_name: template_path}
2549+
parent_dir = tempfile.gettempdir()
2550+
2551+
with patch(
2552+
"samcli.lib.cfn_language_extensions.sam_integration.expand_language_extensions",
2553+
side_effect=TypeError("unexpected bug"),
2554+
):
2555+
with self.assertRaises(ExportFailedError):
2556+
stack_resource.export(resource_id, resource_dict, parent_dir)
2557+
finally:
2558+
os.remove(template_path)

0 commit comments

Comments
 (0)