test(security): cover GRAPHIFY_MAX_GRAPH_BYTES parsing; clarify unit docstring

_max_graph_file_bytes() resolves the graph-load memory-bomb cap and parses the
GRAPHIFY_MAX_GRAPH_BYTES env var (plain bytes, MB/GB suffix, fallbacks), but had
no behavioral tests — only the default constant was asserted.

- Add tests for: unset/blank -> default, plain integer, MB/GB suffix (binary),
  case-insensitive and space-tolerant suffixes, unparseable -> default, and
  non-positive -> default.
- Fix the docstring, which described the suffix as "decimal multipliers of 1024"
  (self-contradictory). MB/GB are treated as binary (MiB/GiB); the tests lock
  that behavior in.

No behavior change.
This commit is contained in:
kaanrumin
2026-07-08 01:03:28 +01:00
committed by safishamsi
parent 0ce8ea00e7
commit 6c33e3aad7
2 changed files with 54 additions and 1 deletions
+2 -1
View File
@@ -38,7 +38,8 @@ def _max_graph_file_bytes() -> int:
Honors the ``GRAPHIFY_MAX_GRAPH_BYTES`` environment variable so users with
large codebases can raise the limit without editing source. The value may
be plain bytes (``671088640``) or carry an ``MB`` / ``GB`` suffix
(``640MB``, ``2GB`` — case-insensitive, decimal multipliers of 1024).
(``640MB``, ``2GB`` — case-insensitive, binary multipliers: ``MB`` is
1024*1024 and ``GB`` is 1024*1024*1024, i.e. MiB / GiB).
Falls back to ``_MAX_GRAPH_FILE_BYTES`` (512 MiB) when the env var is unset,
blank, or unparseable.
+52
View File
@@ -20,6 +20,7 @@ from graphify.security import (
_MAX_FETCH_BYTES,
_MAX_GRAPH_FILE_BYTES,
_MAX_TEXT_BYTES,
_max_graph_file_bytes,
_METADATA_MAX_LIST_ITEMS,
_METADATA_MAX_VALUE_LEN,
_sanitize_metadata_string,
@@ -227,6 +228,57 @@ def test_graph_size_cap_default_is_512_mib():
assert _MAX_GRAPH_FILE_BYTES == 512 * 1024 * 1024
# ---------------------------------------------------------------------------
# _max_graph_file_bytes — GRAPHIFY_MAX_GRAPH_BYTES env-var parsing
# ---------------------------------------------------------------------------
def test_max_graph_bytes_default_when_unset(monkeypatch):
monkeypatch.delenv("GRAPHIFY_MAX_GRAPH_BYTES", raising=False)
assert _max_graph_file_bytes() == _MAX_GRAPH_FILE_BYTES
def test_max_graph_bytes_default_when_blank(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", " ")
assert _max_graph_file_bytes() == _MAX_GRAPH_FILE_BYTES
def test_max_graph_bytes_plain_integer(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", "671088640")
assert _max_graph_file_bytes() == 671088640
def test_max_graph_bytes_mb_suffix_is_binary(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", "640MB")
assert _max_graph_file_bytes() == 640 * 1024 * 1024
def test_max_graph_bytes_gb_suffix_is_binary(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", "2GB")
assert _max_graph_file_bytes() == 2 * 1024 * 1024 * 1024
def test_max_graph_bytes_suffix_is_case_insensitive(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", "3gb")
assert _max_graph_file_bytes() == 3 * 1024 * 1024 * 1024
def test_max_graph_bytes_tolerates_space_before_suffix(monkeypatch):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", "5 GB")
assert _max_graph_file_bytes() == 5 * 1024 * 1024 * 1024
@pytest.mark.parametrize("bad", ["not-a-number", "1.5GB", "0x10", "640KB"])
def test_max_graph_bytes_unparseable_falls_back(monkeypatch, bad):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", bad)
assert _max_graph_file_bytes() == _MAX_GRAPH_FILE_BYTES
@pytest.mark.parametrize("nonpositive", ["0", "-1", "-4GB"])
def test_max_graph_bytes_nonpositive_falls_back(monkeypatch, nonpositive):
monkeypatch.setenv("GRAPHIFY_MAX_GRAPH_BYTES", nonpositive)
assert _max_graph_file_bytes() == _MAX_GRAPH_FILE_BYTES
def test_graph_size_cap_under_limit_returns_none(tmp_path):
p = tmp_path / "graph.json"
p.write_text('{"nodes": [], "links": []}', encoding="utf-8")