Files
wehub-resource-sync 59a0a3844c
PR Test AMD / cancel-on-close (push) Has been skipped
PR Test NVIDIA ARM / scan (push) Has been skipped
PR Test NVIDIA / cancel-on-close (push) Has been skipped
PR Test AMD / scan (push) Has been skipped
PR Test NVIDIA ARM / cancel-on-close (push) Has been skipped
PR Test NVIDIA / scan (push) Has been skipped
Release Docker Images / build (cu129-torch-2.11.0) (push) Has been skipped
Release Docker Images / build (cu130-torch-2.11.0) (push) Has been skipped
Release PyPI / publish (push) Has been skipped
Scheduler Python Test / test (push) Successful in 27m19s
Docs / build (push) Successful in 28m8s
Scheduler C++ Test / test (push) Successful in 28m19s
Scheduler C++ Test / test-flat (push) Successful in 28m18s
Docs / deploy (push) Has been cancelled
PR Test AMD / finish (push) Has been cancelled
PR Test NVIDIA / finish (push) Has been cancelled
PR Test NVIDIA ARM / finish (push) Has been cancelled
PR Test NVIDIA ARM / ${{ matrix.name }} (${{ matrix.runner }}) (push) Has been cancelled
PR Test AMD / ${{ matrix.name }} (${{ matrix.runner }}) (push) Has been cancelled
PR Test NVIDIA / ${{ matrix.name }} (${{ matrix.runner }}) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:31 +08:00

139 lines
3.9 KiB
Python

from types import SimpleNamespace
import msgspec
import pytest
from tokenspeed.runtime.pd.kv_events import (
BlockRemoved,
BlockStored,
EventPublisherFactory,
KVEventBatch,
KVEventsConfig,
NullEventPublisher,
drain_scheduler_kv_events,
scheduler_kv_event_to_wire_event,
)
class _FakePublisher(NullEventPublisher):
def __init__(self, attn_dp_rank: int = 0, **kwargs):
super().__init__(attn_dp_rank=attn_dp_rank)
self.kwargs = kwargs
def test_vllm_style_enable_kv_cache_events_config_is_accepted() -> None:
config = KVEventsConfig.from_cli(
'{"publisher":"zmq","endpoint":"tcp://*:5557","enable_kv_cache_events":true}'
)
assert config.enable_kv_cache_events is True
assert EventPublisherFactory.is_enabled(
'{"publisher":"zmq","endpoint":"tcp://*:5557","enable_kv_cache_events":true}'
)
def test_factory_returns_null_publisher_when_events_are_disabled() -> None:
publisher = EventPublisherFactory.create(
'{"publisher":"zmq","endpoint":"tcp://*:5557","enable_kv_cache_events":false}',
attn_dp_rank=3,
)
assert isinstance(publisher, NullEventPublisher)
def test_enable_only_config_defaults_to_zmq_publisher() -> None:
original = EventPublisherFactory._registry["zmq"]
EventPublisherFactory._registry["zmq"] = _FakePublisher
try:
publisher = EventPublisherFactory.create(
'{"enable_kv_cache_events":true}',
attn_dp_rank=4,
)
finally:
EventPublisherFactory._registry["zmq"] = original
assert isinstance(publisher, _FakePublisher)
def test_scheduler_block_stored_translation() -> None:
event = SimpleNamespace(
kind="BlockStored",
block_hashes=[123],
parent_block_hash=None,
token_ids=[1, 2, 3, 4],
block_size=4,
)
wire_event = scheduler_kv_event_to_wire_event(event)
assert wire_event == BlockStored(
block_hashes=[123],
parent_block_hash=None,
token_ids=[1, 2, 3, 4],
block_size=4,
)
def test_scheduler_block_removed_translation() -> None:
event = SimpleNamespace(kind="BlockRemoved", block_hashes=[123, 456])
wire_event = scheduler_kv_event_to_wire_event(event)
assert wire_event == BlockRemoved(block_hashes=[123, 456])
def test_scheduler_translation_uses_event_kind_not_shape() -> None:
event = SimpleNamespace(
kind="FutureSchedulerEvent",
block_hashes=[123],
token_ids=[1, 2],
)
with pytest.raises(TypeError, match="FutureSchedulerEvent"):
scheduler_kv_event_to_wire_event(event)
def test_drain_scheduler_kv_events_skips_binding_when_disabled() -> None:
assert drain_scheduler_kv_events(object(), enabled=False) == []
def test_drain_scheduler_kv_events_errors_clearly_when_binding_is_missing() -> None:
with pytest.raises(RuntimeError, match="Scheduler.drain_kv_events"):
drain_scheduler_kv_events(object(), enabled=True)
def test_drain_scheduler_kv_events_returns_scheduler_events() -> None:
event = SimpleNamespace(block_hashes=[123])
scheduler = SimpleNamespace(drain_kv_events=lambda: [event])
assert drain_scheduler_kv_events(scheduler, enabled=True) == [event]
def test_kv_event_batch_msgpack_shape_is_dynamo_compatible() -> None:
payload = msgspec.msgpack.encode(
KVEventBatch(
ts=1.5,
events=[
BlockStored(
block_hashes=[123],
parent_block_hash=None,
token_ids=[1, 2],
block_size=2,
),
BlockRemoved(block_hashes=[123]),
],
attn_dp_rank=2,
)
)
decoded = msgspec.msgpack.decode(payload)
assert decoded == [
1.5,
[
["BlockStored", [123], None, [1, 2], 2],
["BlockRemoved", [123]],
],
2,
]