from __future__ import annotations
import time
import pytest
import zerodds
from zerodds import _core
pytestmark = pytest.mark.skipif(
not getattr(zerodds, "_CORE_AVAILABLE", False),
reason="zerodds._core not compiled — maturin develop needed",
)
_DOM = [40]
def _domain() -> int:
_DOM[0] += 1
return _DOM[0]
def _drain_info(reader, timeout=3.0):
out = []
deadline = time.time() + timeout
while time.time() < deadline:
try:
reader.wait_for_data(0.3)
except Exception:
pass
batch = reader.take_with_info()
if batch:
out.extend(batch)
elif out:
break
return out
def test_bytes_take_with_info_returns_sample_info():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_bytes_topic("InfoT")
w = p.create_publisher().create_bytes_writer(t)
r = p.create_subscriber().create_bytes_reader(t)
w.wait_for_matched_subscription(1, 5.0)
r.wait_for_matched_publication(1, 5.0)
w.write(b"hello")
got = _drain_info(r, timeout=3.0)
assert len(got) >= 1
data, info = got[0]
assert data == b"hello"
assert info.instance_state == "Alive"
assert info.valid_data is True
assert info.sample_state in ("Read", "NotRead")
assert info.view_state in ("New", "NotNew")
def test_sample_info_exposed_in_module():
assert hasattr(_core, "SampleInfo")
def test_keyed_dispose_observed_as_not_alive_disposed():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_keyed_topic("KeyT")
w = p.create_publisher().create_keyed_writer(t)
r = p.create_subscriber().create_keyed_reader(t)
w.wait_for_matched_subscription(1, 5.0)
r.wait_for_matched_publication(1, 5.0)
w.write(_core.KeyedReading(id=1, seq=0, value=1.0))
w.write(_core.KeyedReading(id=2, seq=0, value=2.0))
alive = _drain_info(r, timeout=3.0)
handles = {s.id: info.instance_handle for (s, info) in alive if info.valid_data}
states = {s.id: info.instance_state for (s, info) in alive if info.valid_data}
assert states.get(1) == "Alive"
assert states.get(2) == "Alive"
assert len(set(handles.values())) == 2
w.dispose(_core.KeyedReading(id=1))
disp = _drain_info(r, timeout=3.0)
disposed = [(s, info) for (s, info) in disp if info.instance_state == "NotAliveDisposed"]
assert disposed, "expected a NotAliveDisposed marker after dispose(id=1)"
assert all(info.valid_data is False for (_s, info) in disposed)
assert 1 in {s.id for (s, _info) in disposed}
def test_keyed_register_instance_returns_real_handle():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_keyed_topic("KeyRegT")
w = p.create_publisher().create_keyed_writer(t)
h1 = w.register_instance(_core.KeyedReading(id=5))
h2 = w.register_instance(_core.KeyedReading(id=5))
h3 = w.register_instance(_core.KeyedReading(id=6))
assert h1 != 0
assert h1 == h2 assert h1 != h3
def test_reader_liveliness_changed_status_getter():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_bytes_topic("LiveStatusT")
r = p.create_subscriber().create_bytes_reader(t)
st = r.liveliness_changed_status()
assert isinstance(st, tuple) and len(st) == 3
assert isinstance(st[0], bool)
assert isinstance(st[1], int) and isinstance(st[2], int)
def test_content_filtered_topic_filters_samples():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_bytes_topic("CftT")
def keep(raw: bytes) -> bool:
return len(raw) > 0 and raw[0] % 2 == 0
cft = p.create_bytes_contentfilteredtopic("CftEven", t, keep)
assert cft.related_topic_name == "CftT"
w = p.create_publisher().create_bytes_writer(t)
r = p.create_subscriber().create_bytes_reader_cft(cft)
w.wait_for_matched_subscription(1, 5.0)
r.wait_for_matched_publication(1, 5.0)
for i in range(10):
w.write(bytes([i]))
out = []
deadline = time.time() + 4.0
while len(out) < 5 and time.time() < deadline:
try:
r.wait_for_data(0.3)
except Exception:
pass
out.extend(r.take())
assert out, "expected some samples through the CFT"
assert all(b[0] % 2 == 0 for b in out)
def test_cft_empty_name_rejected():
p = _core.DomainParticipantFactory.instance().create_participant(_domain())
t = p.create_bytes_topic("CftBadT")
with pytest.raises(Exception):
p.create_bytes_contentfilteredtopic("", t, lambda b: True)
def test_bytes_writer_lifecycle_methods_present():
p = _core.DomainParticipantFactory.instance().create_participant_offline(_domain())
t = p.create_bytes_topic("ByteLifeT")
w = p.create_publisher().create_bytes_writer(t)
for m in ("register_instance", "dispose", "unregister_instance", "lookup_instance"):
assert hasattr(w, m), f"BytesWriter missing {m}"
assert w.lookup_instance(b"x") == 0
assert w.register_instance(b"x") == 0