Skip to content

Commit 53dbfac

Browse files
fluffy314cursoragent
authored andcommitted
test(ci): cover decode integration branches
Exercise worker snapshot imports, proxy appends, cancellation, concurrency, and memory-drain paths so the platform-neutral gate remains deterministic at 100% coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent f19a718 commit 53dbfac

3 files changed

Lines changed: 322 additions & 0 deletions

File tree

tests/inference_engine/distributed/test_mlx_ring.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ def test_probe_never_raises_and_is_structured():
3737
assert env.world_size == 0
3838

3939

40+
def test_probe_reports_import_failure_on_every_platform(monkeypatch):
41+
def fail_import(_name):
42+
raise ImportError("synthetic missing mlx")
43+
44+
monkeypatch.setattr(
45+
"inference_engine.distributed.mlx_ring.importlib.import_module",
46+
fail_import,
47+
)
48+
env = probe_ring_environment()
49+
assert not env.is_available
50+
assert env.backend == ""
51+
assert env.rank == 0
52+
assert env.world_size == 0
53+
assert env.failure_reason == (
54+
"mlx.core.distributed import failed: "
55+
"ImportError: synthetic missing mlx"
56+
)
57+
58+
4059
@pytest.mark.skipif(
4160
platform.machine() == "arm64",
4261
reason="Linux-gate branch: asserts the mlx-absent probe result",

tests/inference_engine/distributed/test_prefill_cache_runtime_fallback.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,82 @@ def test_successful_local_import_suffix_and_on_reuse(monkeypatch):
283283
hook.close()
284284

285285

286+
def test_worker_proxy_import_uses_returned_snapshot_state():
287+
compatibility = CacheCompatibility(model_id="m", block_size_tokens=2)
288+
hook = DistributedPrefillCacheHook(
289+
PrefixCacheStore(
290+
compatibility,
291+
max_bytes=1024,
292+
node_id="head",
293+
),
294+
compression=CompressionCodec.NONE,
295+
)
296+
block_hash = chained_block_hashes([1, 2], compatibility)[0]
297+
298+
class WorkerProxy(_Verifier):
299+
def import_snapshot(self, payload, imported_compatibility):
300+
assert payload == b"worker-snapshot"
301+
assert imported_compatibility == compatibility
302+
return {
303+
"next_global_position": 2,
304+
"cached_token_ids": [1, 2],
305+
"block_hash": block_hash.hex(),
306+
}
307+
308+
verifier = WorkerProxy()
309+
reused = hook._try_import(
310+
verifier,
311+
[1, 2],
312+
_Hit(
313+
"local",
314+
"lease",
315+
1,
316+
2,
317+
len(b"worker-snapshot"),
318+
b"worker-snapshot",
319+
block_hash=block_hash,
320+
),
321+
)
322+
assert reused == 2
323+
assert verifier.cached_token_sequence == [1, 2]
324+
assert verifier.next_global_position == 2
325+
assert hook.stats.local_hits == 1
326+
hook.close()
327+
328+
329+
def test_worker_proxy_append_path_skips_snapshot_publication(monkeypatch):
330+
compatibility = CacheCompatibility(model_id="m", block_size_tokens=2)
331+
hook = DistributedPrefillCacheHook(
332+
PrefixCacheStore(
333+
compatibility,
334+
max_bytes=1024,
335+
node_id="head",
336+
),
337+
)
338+
published = []
339+
monkeypatch.setattr(
340+
hook,
341+
"_publish_boundary",
342+
lambda *args: published.append(args),
343+
)
344+
345+
class WorkerProxy(_Verifier):
346+
is_decode_worker_proxy = True
347+
348+
def append_accepted_tokens(self, tokens):
349+
self.cached_token_sequence.extend(tokens)
350+
self.next_global_position += len(tokens)
351+
352+
verifier = WorkerProxy()
353+
verifier.prefill([1, 2])
354+
hashes = chained_block_hashes([1, 2, 3, 4], compatibility)
355+
hook._compute_and_publish(verifier, [1, 2, 3, 4], hashes, reused=2)
356+
assert verifier.cached_token_sequence == [1, 2, 3, 4]
357+
assert hook.stats.tokens_computed == 2
358+
assert published == []
359+
hook.close()
360+
361+
286362
def test_import_budget_and_remote_worker_failures(monkeypatch):
287363
compatibility = CacheCompatibility(model_id="m", block_size_tokens=2)
288364
store = PrefixCacheStore(compatibility, max_bytes=1024, node_id="head")

tests/inference_engine/server/test_grpc_app.py

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
DEFAULT_BIND_ADDRESS,
3232
GrpcServerConfig,
3333
RuntimeServiceServicer,
34+
_ThreadedEventStream,
3435
create_grpc_server,
3536
)
3637
from inference_engine.server.proto_gen.kakeya.v1 import (
@@ -883,6 +884,232 @@ def generate(self, session_id, *, max_tokens, **kw):
883884
await server.stop(grace=0.1)
884885

885886

887+
async def test_threaded_event_stream_stops_putting_after_cancel():
888+
cancel_event = threading.Event()
889+
stream = _ThreadedEventStream((), cancel_event)
890+
stream._queue.put(("occupied", None))
891+
cancel_event.set()
892+
stream._put(("ignored", None))
893+
assert stream._queue.get_nowait() == ("occupied", None)
894+
assert stream._queue.empty()
895+
896+
897+
async def test_threaded_event_stream_breaks_after_cancelled_event():
898+
cancel_event = threading.Event()
899+
900+
class CancelOnFirst:
901+
def __iter__(self):
902+
return self
903+
904+
def __next__(self):
905+
cancel_event.set()
906+
return "first"
907+
908+
stream = _ThreadedEventStream(CancelOnFirst(), cancel_event)
909+
stream._run()
910+
assert stream._queue.get_nowait() == ("first", None)
911+
912+
913+
class _DirectAbort(Exception):
914+
pass
915+
916+
917+
class _DirectContext:
918+
def __init__(self):
919+
self.code = None
920+
self.detail = ""
921+
self.callback = None
922+
923+
async def abort(self, code, detail):
924+
self.code = code
925+
self.detail = detail
926+
raise _DirectAbort
927+
928+
def cancelled(self):
929+
return False
930+
931+
def add_done_callback(self, callback):
932+
self.callback = callback
933+
934+
935+
async def test_watch_context_removes_cancelled_session():
936+
store = SessionStore(capacity=1)
937+
session = store.create_session()
938+
servicer = RuntimeServiceServicer(store)
939+
context = _DirectContext()
940+
cancel_event = threading.Event()
941+
servicer._watch_context(context, cancel_event, session.session_id)
942+
assert context.callback is not None
943+
context.callback(type("Done", (), {"cancelled": lambda self: True})())
944+
assert cancel_event.is_set()
945+
assert store.active_count == 0
946+
947+
948+
async def test_create_session_rejects_memory_drain():
949+
store = SessionStore(capacity=1)
950+
governor = type("Governor", (), {"draining": True})()
951+
servicer = RuntimeServiceServicer(store, memory_governor=governor)
952+
context = _DirectContext()
953+
with pytest.raises(_DirectAbort):
954+
await servicer.CreateSession(runtime_pb2.CreateSessionRequest(), context)
955+
assert context.code == grpc.StatusCode.RESOURCE_EXHAUSTED
956+
assert store.active_count == 0
957+
958+
959+
async def test_append_rejects_concurrent_operation():
960+
store = SessionStore(capacity=1)
961+
session = store.create_session()
962+
coordinator = type(
963+
"Coordinator",
964+
(),
965+
{"append_tokens": lambda self, session_id, token_ids: 0},
966+
)()
967+
servicer = RuntimeServiceServicer(store, append_coordinator=coordinator)
968+
assert servicer._acquire_operation(session.session_id)
969+
context = _DirectContext()
970+
with pytest.raises(_DirectAbort):
971+
await servicer.AppendTokens(
972+
runtime_pb2.AppendTokensRequest(
973+
session_id=session.session_id,
974+
token_ids=[1],
975+
),
976+
context,
977+
)
978+
assert context.code == grpc.StatusCode.ABORTED
979+
servicer._release_operation(session.session_id)
980+
981+
982+
async def test_append_passes_cancel_event_and_resets_liveness():
983+
observed = {}
984+
985+
class Coordinator:
986+
def append_tokens(self, session_id, token_ids, cancel_event):
987+
observed["session_id"] = session_id
988+
observed["tokens"] = token_ids
989+
observed["cancel_event"] = cancel_event
990+
return len(token_ids)
991+
992+
class Liveness:
993+
def update(self, phase):
994+
observed["phase"] = phase
995+
996+
store = SessionStore(capacity=1)
997+
session = store.create_session()
998+
servicer = RuntimeServiceServicer(
999+
store,
1000+
append_coordinator=Coordinator(),
1001+
liveness=Liveness(),
1002+
)
1003+
response = await servicer.AppendTokens(
1004+
runtime_pb2.AppendTokensRequest(
1005+
session_id=session.session_id,
1006+
token_ids=[4, 5],
1007+
),
1008+
_DirectContext(),
1009+
)
1010+
assert response.history_length == 2
1011+
assert observed["session_id"] == session.session_id
1012+
assert observed["tokens"] == [4, 5]
1013+
assert isinstance(observed["cancel_event"], threading.Event)
1014+
assert observed["phase"] == "idle"
1015+
1016+
1017+
async def test_append_asyncio_cancellation_removes_session():
1018+
class Coordinator:
1019+
def append_tokens(self, session_id, token_ids):
1020+
raise asyncio.CancelledError
1021+
1022+
store = SessionStore(capacity=1)
1023+
session = store.create_session()
1024+
servicer = RuntimeServiceServicer(store, append_coordinator=Coordinator())
1025+
with pytest.raises(asyncio.CancelledError):
1026+
await servicer.AppendTokens(
1027+
runtime_pb2.AppendTokensRequest(
1028+
session_id=session.session_id,
1029+
token_ids=[1],
1030+
),
1031+
_DirectContext(),
1032+
)
1033+
assert store.active_count == 0
1034+
1035+
1036+
async def test_append_worker_cancellation_maps_cancelled():
1037+
from inference_engine.session import OperationCancelledError
1038+
1039+
class Coordinator:
1040+
def append_tokens(self, session_id, token_ids):
1041+
raise OperationCancelledError("worker cancelled")
1042+
1043+
store = SessionStore(capacity=1)
1044+
session = store.create_session()
1045+
servicer = RuntimeServiceServicer(store, append_coordinator=Coordinator())
1046+
context = _DirectContext()
1047+
with pytest.raises(_DirectAbort):
1048+
await servicer.AppendTokens(
1049+
runtime_pb2.AppendTokensRequest(
1050+
session_id=session.session_id,
1051+
token_ids=[1],
1052+
),
1053+
context,
1054+
)
1055+
assert context.code == grpc.StatusCode.CANCELLED
1056+
assert store.active_count == 0
1057+
1058+
1059+
async def test_generate_rejects_concurrent_operation():
1060+
class Coordinator:
1061+
def generate(self, session_id, **kwargs):
1062+
return iter(())
1063+
1064+
store = SessionStore(capacity=1)
1065+
session = store.create_session()
1066+
servicer = RuntimeServiceServicer(
1067+
store,
1068+
generation_coordinator=Coordinator(),
1069+
)
1070+
assert servicer._acquire_operation(session.session_id)
1071+
context = _DirectContext()
1072+
with pytest.raises(_DirectAbort):
1073+
async for _ in servicer.Generate(
1074+
runtime_pb2.GenerateRequest(
1075+
session_id=session.session_id,
1076+
max_tokens=1,
1077+
),
1078+
context,
1079+
):
1080+
pass
1081+
assert context.code == grpc.StatusCode.ABORTED
1082+
servicer._release_operation(session.session_id)
1083+
1084+
1085+
async def test_generate_busy_error_maps_aborted():
1086+
from inference_engine.session import SessionGenerationBusyError
1087+
1088+
class Coordinator:
1089+
def generate(self, session_id, **kwargs):
1090+
if False:
1091+
yield
1092+
raise SessionGenerationBusyError(session_id)
1093+
1094+
store = SessionStore(capacity=1)
1095+
session = store.create_session()
1096+
servicer = RuntimeServiceServicer(
1097+
store,
1098+
generation_coordinator=Coordinator(),
1099+
)
1100+
context = _DirectContext()
1101+
with pytest.raises(_DirectAbort):
1102+
async for _ in servicer.Generate(
1103+
runtime_pb2.GenerateRequest(
1104+
session_id=session.session_id,
1105+
max_tokens=1,
1106+
),
1107+
context,
1108+
):
1109+
pass
1110+
assert context.code == grpc.StatusCode.ABORTED
1111+
1112+
8861113
async def test_factory_wires_prefill_cache_service():
8871114
from inference_engine.distributed.capability import CacheCompatibility
8881115
from inference_engine.distributed.prefill_cache import PrefixCacheStore

0 commit comments

Comments
 (0)