""" How large a single upload may be, and who decides. The cap used to be a constant: 4 GB, in `webrtc_server.py`, the same on a Pi with a 32 GB card and on a machine holding a film library. It is the operator's disk that fills, so the number is theirs — `max_upload_gb` under [node] in node.toml, the Node page, and `meshbay-node transfers max-size`, with the constant as the default when they have said nothing. These follow the value along the whole path rather than checking that the field parses, for the reason `test_stream_capacity_config.py` gives: every join in such a path has been wrong at least once, and a ceiling read from the wrong place fails only when somebody sends a large file. """ import textwrap from pathlib import Path import pytest from meshbay_node.config import load_config from meshbay_node.roots import RootSet from meshbay_node.transport.webrtc.upload_handlers import GB_BYTES, MAX_UPLOAD_BYTES from meshbay_node.transport.webrtc_server import WebRTCPeerSession, WebRTCTransport from node_source import daemon_call, webrtc_source def _cfg(tmp_path: Path, body: str): p = tmp_path / "node.toml" p.write_text(textwrap.dedent(body)) return load_config(p) class _FakePC: def on(self, *a, **k): return lambda f: f def _session(gb): t = WebRTCTransport( sk_node=None, hub_pk_pem=b"", gek=b"\0" * 32, roots=RootSet(), index=None, max_upload_gb=gb) return t, WebRTCPeerSession(_FakePC(), t._ctx, peer_id="p") # ── What the operator writes ───────────────────────────────────────────────── def test_the_default_is_eight_gb(): assert MAX_UPLOAD_BYTES == 8 * GB_BYTES def test_the_operator_sets_it(tmp_path): cfg = _cfg(tmp_path, """ [node] max_upload_gb = 20 """) assert cfg.node.max_upload_gb == 20 def test_a_fraction_of_a_gigabyte_is_legitimate(tmp_path): """Not a count, so it does not get `_positive`'s floor of one. A node on a small disk may well want to stop at half a gigabyte, and rounding that to zero would refuse every upload. """ cfg = _cfg(tmp_path, """ [node] max_upload_gb = 0.5 """) assert cfg.node.max_upload_gb == 0.5 _t, s = _session(0.5) assert s._max_upload_bytes() == GB_BYTES // 2 def test_saying_nothing_gets_the_default(tmp_path): cfg = _cfg(tmp_path, """ [node] quic_port = 19010 """) assert cfg.node.max_upload_gb * GB_BYTES == MAX_UPLOAD_BYTES, ( "the config default and the source default disagree, so the ceiling " "depends on whether a node.toml happens to mention it") @pytest.mark.parametrize("value", ["0", "-2", '"lots"', "true"]) def test_a_value_that_would_refuse_every_upload_is_refused(tmp_path, value, caplog): cfg = _cfg(tmp_path, f""" [node] max_upload_gb = {value} """) assert cfg.node.max_upload_gb * GB_BYTES == MAX_UPLOAD_BYTES assert "max_upload_gb" in caplog.text, ( "the value was silently discarded — the operator has no way to learn " "their setting is not in effect") # ── That the number reaches the check it governs ───────────────────────────── @pytest.mark.parametrize("gb,expect", [ (None, MAX_UPLOAD_BYTES), (2, 2 * GB_BYTES), (16, 16 * GB_BYTES), ]) def test_the_configured_size_is_what_the_handler_enforces(gb, expect): _t, s = _session(gb) assert s._max_upload_bytes() == expect def test_the_handler_reads_it_rather_than_the_constant(): """A ceiling captured once is one the operator cannot change. The check runs per chunk, so raising the cap has to reach an upload that is already in flight — which it does only if the handler asks the context each time instead of closing over the constant. """ src = webrtc_source() i = src.index("Upload exceeds size limit") check = src[src.rindex("if state.bytes", 0, i):i] assert "_max_upload_bytes()" in check, ( "the upload check reads the module constant, so node.toml, the Node " "page and the CLI are all read and then ignored") def test_raising_it_reaches_an_upload_already_running(): t, s = _session(2) assert s._max_upload_bytes() == 2 * GB_BYTES t.set_capacity(max_upload_gb=10) assert s._max_upload_bytes() == 10 * GB_BYTES, ( "the session kept the ceiling it started with, so the setting only " "takes effect on a restart" ) def test_zero_is_refused_at_the_transport_too(): t, _s = _session(4) with pytest.raises(ValueError): t.set_capacity(max_upload_gb=0) def test_the_daemon_passes_it(): """The join that syntax checking cannot see.""" call = daemon_call("WebRTCTransport") assert "max_upload_gb=self._config.node.max_upload_gb" in call, ( "the daemon builds the transport without the operator's ceiling, so " "node.toml is read and then ignored")