"""Smoke tests для cuframes Python bindings. В Phase 0 (skeleton) проверяем что: - модуль импортируется - версия читается - error классы существуют и являются нормальной иерархией Subscriber / DLPack тесты появятся в следующих фазах (см. issue gx/cuframes#6, tasks #198+). """ import cuframes def test_version_format(): v = cuframes.version_string() assert isinstance(v, str) parts = v.split(".") assert len(parts) >= 3 assert all(p.isdigit() for p in parts[:3]) def test_protocol_version_is_uint(): pv = cuframes.protocol_version() assert isinstance(pv, int) assert pv >= 0 def test_pixel_format_enum_members(): assert cuframes.PixelFormat.NV12.value == 0 assert cuframes.PixelFormat.YUV420P.value == 1 def test_subscriber_mode_enum_members(): assert cuframes.SubscriberMode.NEWEST_ONLY.value == 0 assert cuframes.SubscriberMode.STRICT_ORDER.value == 1 def test_error_hierarchy(): """Все subtype'ы наследуются от CuframesError.""" for sub in [ cuframes.CuframesPublisherGone, cuframes.CuframesFrameTimeout, cuframes.CuframesDeviceLost, cuframes.CuframesShmError, cuframes.CuframesProtocolMismatch, cuframes.CuframesInvalidArgument, cuframes.CuframesOutOfMemory, cuframes.CuframesInternal, ]: assert issubclass(sub, cuframes.CuframesError) def test_subscriber_class_exposed(): """CuframesSubscriber/CuframesFrame exposed как public classes.""" assert hasattr(cuframes, "CuframesSubscriber") assert hasattr(cuframes, "CuframesFrame") assert hasattr(cuframes, "subscribe") def test_subscribe_to_missing_publisher_raises(): """Subscribe к несуществующему publisher → CuframesError (subclass) после connect_timeout_ms. Этот тест работает на любом хосте (без живого cuframes-pub) — мы верифицируем что error path работает и маппит CUFRAMES_ERR_* в правильный Python exception. """ import pytest with pytest.raises(cuframes.CuframesError): cuframes.subscribe( "definitely-not-existing-publisher-xyz", connect_timeout_ms=100, ) def test_subscriber_repr_when_unable_to_connect(): """Лёгкий тест что repr не падает и close idempotent.""" import pytest try: sub = cuframes.subscribe("nope-xyz", connect_timeout_ms=100) except cuframes.CuframesError: return # ожидаемо pytest.fail("subscribe должно было выкинуть exception") def test_subscribe_accepts_consumer_stream_param(): """consumer_stream — uintptr (cudaStream_t). Проверяем что параметр accepted; реальное использование требует cuda-python / torch.cuda.Stream — это в integration тестах yolo-world-detector'а. """ import pytest with pytest.raises(cuframes.CuframesError): cuframes.subscribe( "nope-xyz", connect_timeout_ms=100, consumer_stream=0, # 0 = default stream ) def test_subscribe_kwargs_signature(): """Проверяем что у subscribe правильный набор kwargs.""" import inspect # Pybind11-обёртки не дают inspect.signature, но help_doc отражает их. doc = cuframes.subscribe.__doc__ assert "consumer_name" in doc assert "mode" in doc assert "cuda_device" in doc assert "connect_timeout_ms" in doc assert "consumer_stream" in doc