summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_memory_ceiling.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_memory_ceiling.py')
-rw-r--r--packages/meshbay-hub/tests/test_memory_ceiling.py53
1 files changed, 51 insertions, 2 deletions
diff --git a/packages/meshbay-hub/tests/test_memory_ceiling.py b/packages/meshbay-hub/tests/test_memory_ceiling.py
index 8430627..d46cae3 100644
--- a/packages/meshbay-hub/tests/test_memory_ceiling.py
+++ b/packages/meshbay-hub/tests/test_memory_ceiling.py
@@ -66,12 +66,16 @@ def target_fn():
def _run(target_fn, tmp_path, *, size, native=False, granted=False,
- streamed=False, picker=False, mode="auto"):
+ streamed=False, picker=False, mode="auto", batched=False):
"""Drive the real function against one browser shape."""
script = tmp_path / "case.mjs"
script.write_text(f"""
// Stubs for everything the lifted function reaches. `formatSize` and `t` only
// build the message; the assertions are about which branch was taken.
+//
+// stdout carries the outcome and nothing else, so the function's own logging
+// goes to stderr -- where it is still shown when a case fails.
+console.info = (...a) => console.error(...a);
const formatSize = (n) => `${{n}} B`;
const t = (key, vars) => key + ' ' + JSON.stringify(vars);
const platform = {{
@@ -107,7 +111,8 @@ if ({json.dumps(picker)}) {{
let outcome;
try {{
- const r = await _openDownloadTarget('film.mkv', {size});
+ const r = await _openDownloadTarget('film.mkv', {size}, {{}}, {size},
+ {{ batched: {json.dumps(batched)} }});
outcome = r === null ? {{ kind: 'memory' }}
: r === false ? {{ kind: 'cancelled' }}
: {{ kind: 'stream', name: r.name }};
@@ -180,6 +185,50 @@ def test_a_browser_with_a_picker_is_offered_one_instead_of_being_refused(
assert out == {"kind": "stream", "name": "p"}
+# ── One dialog per gesture, not one per file ────────────────────────────────
+
+def test_the_first_of_a_batch_still_asks_where_to_save(target_fn, tmp_path):
+ """The preference is not being taken away. Someone who asked to choose the
+ folder chooses it, for the download they actually clicked."""
+ out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True,
+ streamed=True)
+ assert out == {"kind": "stream", "name": "p"}
+
+
+def test_the_rest_of_a_batch_stream_instead_of_asking(target_fn, tmp_path):
+ """A browser grants one picker per user gesture and selecting four files is
+ one gesture. Chrome showed the dialog for the second file anyway and then
+ waited for a human, so the third and fourth sat behind it until they timed
+ out — reported as three downloads frozen.
+
+ There is no gesture left to spend, so nothing is lost by streaming: the file
+ still lands on disk, in the browser's own download folder. Only the choice
+ of folder goes, and it was not on offer.
+ """
+ out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True,
+ streamed=True, batched=True)
+ assert out == {"kind": "stream", "name": "s"}
+
+
+def test_a_batched_download_falls_back_to_the_dialog_rather_than_failing(
+ target_fn, tmp_path):
+ """When the worker does not answer, asking is better than refusing: a
+ dialog that has to be answered is still a download, and the alternative
+ here is losing the file. A preference must not cost a capability, and
+ neither must the fix for one."""
+ out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=True,
+ streamed=False, batched=True)
+ assert out == {"kind": "stream", "name": "p"}
+
+
+def test_batching_never_pushes_a_large_file_into_memory(target_fn, tmp_path):
+ """Firefox shape — no picker at all. Nothing about the batch flag may reach
+ the memory floor above the ceiling."""
+ out = _run(target_fn, tmp_path, size=20 * GB, mode="ask", picker=False,
+ streamed=False, batched=True)
+ assert out["kind"] == "refused", out
+
+
# ── The one that outlives today's branches ──────────────────────────────────
def test_no_unguarded_memory_floor(target_fn):