Files
govoplan-templates/tests/test_render_limits.py
T

53 lines
2.9 KiB
Python

from __future__ import annotations
import unittest
from types import SimpleNamespace
from unittest.mock import patch
from govoplan_core.core.templates import TemplateRenderError
from govoplan_templates.backend import rendering
class TemplateRenderLimitTests(unittest.TestCase):
def test_many_items_stop_before_rendering_the_entire_oversized_bundle(self):
with patch.object(rendering, "MAX_OUTPUT_BYTES", 128), patch.object(rendering, "_substitute", wraps=rendering._substitute) as substitute:
with self.assertRaisesRegex(TemplateRenderError, "bounded-download limit"):
rendering._render_items("x" * 64, {}, [{}] * 5000, html=False)
self.assertEqual(3, substitute.call_count)
def test_repeated_token_expansion_stops_before_allocating_the_whole_row(self):
with patch.object(rendering, "MAX_OUTPUT_BYTES", 128), patch.object(rendering, "_display_value", wraps=rendering._display_value) as display:
with self.assertRaisesRegex(TemplateRenderError, "bounded-download limit"):
rendering._substitute("{{value}}" * 5000, {"value": "x" * 64}, html=False)
self.assertEqual(3, display.call_count)
def test_utf8_byte_limit_is_not_a_character_limit(self):
with patch.object(rendering, "MAX_OUTPUT_BYTES", 4):
self.assertEqual("üü", rendering._substitute("{{value}}", {"value": "üü"}, html=False))
with self.assertRaises(TemplateRenderError):
rendering._substitute("{{value}}", {"value": "üüü"}, html=False)
def test_html_escaping_counts_expanded_bytes_and_preserves_valid_output(self):
with patch.object(rendering, "MAX_OUTPUT_BYTES", 9):
self.assertEqual("&lt;&amp;", rendering._substitute("{{value}}", {"value": "<&"}, html=True))
with self.assertRaises(TemplateRenderError):
rendering._substitute("{{value}}!", {"value": "<&"}, html=True)
def test_text_separator_is_part_of_the_same_budget(self):
with patch.object(rendering, "MAX_OUTPUT_BYTES", 5):
self.assertEqual(["ab", "cd"], rendering._render_items("{{value}}", {}, [{"value": "ab"}, {"value": "cd"}], html=False, separator="\n"))
with self.assertRaises(TemplateRenderError):
rendering._render_items("{{value}}", {}, [{"value": "ab"}, {"value": "cd"}], html=False, separator="\n\n")
def test_html_wrapper_is_also_subject_to_output_limit(self):
definition = SimpleNamespace(name="Example")
revision = SimpleNamespace(content_html="<p>Ada</p>", content_text=None, template_type="list_layout", layout={}, output_profiles=[])
request = SimpleNamespace(output_format="html", parameters={})
with patch.object(rendering, "MAX_OUTPUT_BYTES", 32):
with self.assertRaises(TemplateRenderError):
rendering._render_payload(definition, revision, request=request, items=[{}])
if __name__ == "__main__":
unittest.main()