diff --git a/graphify/security.py b/graphify/security.py index d371e53..2dbe5bd 100644 --- a/graphify/security.py +++ b/graphify/security.py @@ -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. diff --git a/tests/test_security.py b/tests/test_security.py index d2e08c0..2f69be6 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -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")