summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/tests
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/tests')
-rw-r--r--packages/meshbay-node/tests/test_stream_subtitle_tracks.py55
1 files changed, 54 insertions, 1 deletions
diff --git a/packages/meshbay-node/tests/test_stream_subtitle_tracks.py b/packages/meshbay-node/tests/test_stream_subtitle_tracks.py
index 9a09edb..d3bcc8b 100644
--- a/packages/meshbay-node/tests/test_stream_subtitle_tracks.py
+++ b/packages/meshbay-node/tests/test_stream_subtitle_tracks.py
@@ -38,7 +38,11 @@ from meshbay_common.crypto import generate_gek
from meshbay_common.webcrypto import chunk_key_aes, decrypt_chunk_aes
from meshbay_node.indexer.group_index import GroupIndex
from meshbay_node.media_probe import TEXT_SUBTITLE_CODECS
-from meshbay_node.transport.webrtc_server import WebRTCPeerSession, _probe_video
+from meshbay_node.transport.webrtc_server import (
+ WebRTCPeerSession,
+ _probe_video,
+ _subtitle_timeout_for,
+)
from conftest import needs_subprocess, one_root
@@ -356,3 +360,52 @@ async def test_the_result_is_fetched_through_the_ordinary_chunk_path(tmp_path):
plain = decrypt_chunk_aes(key, chunk["nonce"], chunk["ct"])
assert plain.decode("utf-8").startswith("WEBVTT")
assert _CUE_WORD[2] in plain.decode("utf-8")
+
+
+def test_the_budget_grows_with_the_file_not_with_the_subtitle():
+ """Extraction demuxes the whole container, so the file sets the cost.
+
+ Measured on a library held on an external disk: 9.8 s per GB — 36 s for a
+ 3.9 GB title and 71 s for a 7.3 GB one. A flat 60 s therefore worked on
+ most of a library and failed on the big films, which is indistinguishable
+ from a broken feature to whoever is watching one. The allowance is three
+ times the measured rate, so a slower disk still finishes.
+ """
+ assert _subtitle_timeout_for(500_000_000) == 60 # small file, the floor
+ assert _subtitle_timeout_for(7_310_000_000) > 71 * 2 # the film that timed out
+ assert _subtitle_timeout_for(3_900_000_000) > 36 * 2
+ # Bounded: a pathological container must not pin a transcode slot for ever.
+ assert _subtitle_timeout_for(500_000_000_000) == 900
+ # Monotonic, or a bigger file could be given less time than a smaller one.
+ budgets = [_subtitle_timeout_for(int(gb * 1e9)) for gb in (1, 4, 8, 20, 100)]
+ assert budgets == sorted(budgets)
+
+
+@pytest.mark.asyncio
+async def test_two_requests_for_one_track_extract_once(tmp_path):
+ """Two clicks seconds apart used to run two whole extractions.
+
+ The cache is consulted on the way in, so the second request missed it
+ while the first was still running: seen in the log as two identical
+ extractions of one 4.3 GB file overlapping, each holding a transcode slot
+ and reading the file end to end. The latecomer waits for the answer the
+ first is already producing, and both are answered.
+ """
+ clip = tmp_path / "clip.mp4"
+ _make_subtitled_clip(clip)
+ gek = generate_gek()
+ session, file_id = _session(clip, gek)
+
+ import asyncio
+ await asyncio.gather(
+ session._do_subtitle_request({"file_id": file_id, "track": 1}),
+ session._do_subtitle_request({"file_id": file_id, "track": 1}),
+ )
+
+ replies = [m for m in session.sent if m.get("type") == "subtitle_resp"]
+ assert len(replies) == 2, f"both callers must be answered: {session.sent}"
+ assert replies[0]["hash"] == replies[1]["hash"]
+ assert session._ctx["media_cache"].puts == 1, (
+ "the second request ran its own extraction instead of joining the first")
+ assert not session._ctx["_subtitle_inflight"], (
+ "the in-flight entry outlived the extraction and would block the next one")