firegex/tests/unit/test_zstd_compat.py
Domingo Dirutigliano 70373eb4f6
minor adjustments
2026-09-24 09:19:00 +02:00

111 lines
4.6 KiB
Python

"""The two zstd backends have to answer the same thing, on the same bytes.
`compression.zstd` is Python 3.14 and later; `zstandard` fills the gap below it. They are
not interchangeable by import alone — `zstandard.decompress()` refuses a frame whose
header carries no content size, which is exactly what a server produces when it
compresses a response body on the fly — so the shim normalises them. A filter that reads
a body on one Python and gets nothing on another is the same class of lie as a tester
that disagrees with the engine, which is why this is pinned rather than assumed.
Both backends are exercised in one run wherever `zstandard` is installed: the fallback is
loaded a second time with `compression` hidden, so the agreement is checked rather than
inferred from whichever Python happens to be running the suite.
"""
import builtins
import importlib.util
import io
import os
import pytest
zstandard = pytest.importorskip("zstandard")
SHIM = os.path.abspath(os.path.join(
os.path.dirname(__file__), "..", "..", "fgex-lib",
"firegex", "pyfilters", "internals", "zstd_compat.py"))
def _load(hide_stdlib: bool):
"""Load the shim, optionally with `compression` unavailable."""
real_import = builtins.__import__
def blocked(name, *args, **kwargs):
if hide_stdlib and name.startswith("compression"):
raise ImportError("hidden for this test")
return real_import(name, *args, **kwargs)
spec = importlib.util.spec_from_file_location("zstd_compat_probe", SHIM)
module = importlib.util.module_from_spec(spec)
builtins.__import__ = blocked
try:
spec.loader.exec_module(module)
finally:
builtins.__import__ = real_import
return module
def _corpus():
"""The shapes an HTTP body actually arrives in."""
compressor = zstandard.ZstdCompressor()
for name, data in (("small", b"hello"),
("empty", b""),
("large", bytes(range(256)) * 400)):
# A body whose length was known before compressing.
yield f"{name}, content size in the header", compressor.compress(data), data
# And one compressed on the fly, which carries no length at all. This is the
# case a bare `zstandard.decompress()` refuses.
buf = io.BytesIO()
with compressor.stream_writer(buf, closefd=False) as writer:
writer.write(data)
yield f"{name}, streamed", buf.getvalue(), data
# An encoder that flushed mid-response produces a concatenation of frames, and the
# standard library reads it as one body.
yield ("two frames concatenated",
compressor.compress(b"first") + compressor.compress(b"second"),
b"firstsecond")
BACKENDS = [
pytest.param(False, id="whatever-this-python-has"),
pytest.param(True, id="zstandard-fallback"),
]
@pytest.mark.parametrize("hide_stdlib", BACKENDS)
@pytest.mark.parametrize("label,blob,expected",
[pytest.param(n, b, e, id=n) for n, b, e in _corpus()])
def test_both_backends_decompress_the_same_bytes(hide_stdlib, label, blob, expected):
assert _load(hide_stdlib).decompress(blob) == expected
def test_the_fallback_is_reachable_at_all():
"""Guards the test above from passing vacuously.
If hiding `compression` did not actually select the other backend, every case would
be checking one implementation twice and the disagreement this exists to catch would
sail straight through.
"""
fallback = _load(hide_stdlib=True)
# The stdlib path is a module-level `from compression.zstd import decompress`, so its
# function belongs to the standard library; the fallback's is a plain `def` in the
# shim itself. That is what tells the two apart.
assert fallback._decompress.__module__ == "zstd_compat_probe", \
"hiding `compression` did not select the zstandard fallback"
@pytest.mark.parametrize("hide_stdlib", BACKENDS)
@pytest.mark.parametrize("label,blob,expected",
[pytest.param(n, b, e, id=n) for n, b, e in _corpus()])
def test_both_backends_stop_where_they_are_told_to(hide_stdlib, label, blob, expected):
"""A bounded read, so a body can be decoded only as far as a filter may hold it."""
shim = _load(hide_stdlib)
assert shim.decompress(blob, max_length=7) == expected[:7]
assert shim.decompress(blob, max_length=len(expected) + 1) == expected
@pytest.mark.parametrize("hide_stdlib", BACKENDS)
def test_a_frame_declaring_far_more_is_not_decoded_whole(hide_stdlib):
blob = zstandard.ZstdCompressor().compress(b"\0" * (64 * 1024 * 1024))
assert len(_load(hide_stdlib).decompress(blob, max_length=1024)) == 1024