From 4418312b0b4ec74a13bc00d6f22a3226ca6e1e6b Mon Sep 17 00:00:00 2001 From: Matysh Date: Tue, 28 Jul 2026 16:11:48 +0300 Subject: [PATCH] test: config cap under aiohttp's 4 MB frame; own marker id for the upload test A 4 MB cap could never be reported: the frame limit rejects the message first and the socket closes with 1009, so the user gets a dropped connection instead of 'too_large'. 2 MB is ~30x a real three-floor configuration (70 KB measured). The upload test listed a folder test_ha_upload.py also writes into. --- custom_components/houseplan/validation.py | 10 ++++++---- tests_backend/test_ha_websocket.py | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/custom_components/houseplan/validation.py b/custom_components/houseplan/validation.py index 8a8da0b..b2b1d80 100644 --- a/custom_components/houseplan/validation.py +++ b/custom_components/houseplan/validation.py @@ -81,10 +81,12 @@ MAX_KNOWN_DEVICES = 20000 MAX_TEXT = 500 # names, models, ids MAX_DESCRIPTION = 4000 MAX_URL = 2000 -# Below the WebSocket frame limit on purpose: a payload larger than that never -# reaches the handler at all — the socket closes with 1009 and the user sees a -# dropped connection instead of an error they can act on. -MAX_CONFIG_BYTES = 4 * 1024 * 1024 +# Comfortably below the WebSocket frame limit (aiohttp's default is 4 MB): a +# payload larger than the frame never reaches the handler at all — the socket +# closes with 1009 and the user sees a dropped connection instead of an error +# they can act on. For scale, a real three-floor home with ~200 devices stores +# about 70 KB, so this is ~30x headroom. +MAX_CONFIG_BYTES = 2 * 1024 * 1024 _TEXT = vol.All(str, vol.Length(max=MAX_TEXT)) _TEXT_OR_NONE = vol.Any(None, _TEXT) diff --git a/tests_backend/test_ha_websocket.py b/tests_backend/test_ha_websocket.py index afa43ef..bc25272 100644 --- a/tests_backend/test_ha_websocket.py +++ b/tests_backend/test_ha_websocket.py @@ -681,12 +681,12 @@ async def test_upload_never_overwrites_an_existing_attachment( assert resp.status == 200, await resp.text() return (await resp.json())["url"] - first = await upload("m1", "manual.pdf", b"ONE") - second = await upload("m1", "manual.pdf", b"TWO") + first = await upload("m9", "manual.pdf", b"ONE") + second = await upload("m9", "manual.pdf", b"TWO") assert first != second, "the second upload must not take the first name" - folder = os.path.join(hass.config.path(FILES_DIR), "m1") - # the HA test config dir is shared across the module — look only at ours + folder = os.path.join(hass.config.path(FILES_DIR), "m9") + # the HA test config dir is shared across the module — hence our own marker id names = sorted( n for n in await hass.async_add_executor_job(os.listdir, folder) if n.startswith("manual") )