pyws plugin P2: live sim resource
- Sim facade (bound as `sim`): start(tag) arms the sim, dispatching 14a/15693 by tag type; stop(), push(tag) -> tag.sync(), frames -> decoded trace - SimResource: opens SimSession on load, closes on exit; a missing device is non-fatal - one connection mode per workspace (reader OR sim) — the second is refused (serial contention) - sim.push added to the write effect patterns (withheld on autoreplay) Arming stays explicit. Hardware-free tests via injected sessions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
"""Tests for the pm3py pyws plugin (P1: reader resource + namespace + effects). Hardware-free."""
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
from pyws import ResourceStatus, WorkspacePlugin
|
||||
|
||||
from pm3py.pyws_plugin import Pm3pyPlugin, ReaderResource
|
||||
from pm3py.pyws_plugin import Pm3pyPlugin, ReaderResource, Sim, SimResource
|
||||
|
||||
|
||||
def _run(coro):
|
||||
@@ -80,6 +80,56 @@ def test_reader_resource_no_device_is_nonfatal(monkeypatch):
|
||||
assert r.obj is None
|
||||
|
||||
|
||||
def test_create_resource_builds_reader():
|
||||
def test_create_resource_builds_reader_and_sim():
|
||||
# fresh plugin instances → each mode is available
|
||||
assert isinstance(Pm3pyPlugin().create_resource("reader", {}, session=None), ReaderResource)
|
||||
assert Pm3pyPlugin().create_resource("sim", {}, session=None) is None # P2
|
||||
assert isinstance(Pm3pyPlugin().create_resource("sim", {}, session=None), SimResource)
|
||||
|
||||
|
||||
def test_one_mode_per_workspace():
|
||||
plug = Pm3pyPlugin()
|
||||
assert isinstance(plug.create_resource("reader", {}, None), ReaderResource)
|
||||
# a second, different-mode connection resource is refused (serial contention)
|
||||
assert plug.create_resource("sim", {}, None) is None
|
||||
|
||||
|
||||
def test_sim_resource_opens_and_closes():
|
||||
fake = MagicMock()
|
||||
r = SimResource("sim", session=fake)
|
||||
_run(r.start())
|
||||
assert r.status is ResourceStatus.CONNECTED
|
||||
assert isinstance(r.obj, Sim) and r.obj.session is fake
|
||||
_run(r.stop())
|
||||
fake.close.assert_called_once()
|
||||
|
||||
|
||||
def test_sim_resource_no_device_is_nonfatal():
|
||||
r = SimResource("sim", config={"port": "/dev/pyws-no-such-device"})
|
||||
_run(r.start())
|
||||
assert r.status is ResourceStatus.DISCONNECTED
|
||||
assert r.obj is None
|
||||
|
||||
|
||||
def test_sim_start_dispatches_by_protocol():
|
||||
from pm3py.sim import NTAG213, Tag15693
|
||||
|
||||
sess = MagicMock()
|
||||
sim = Sim(sess)
|
||||
sim.start(NTAG213()) # ISO 14443-A
|
||||
sess.start_14a.assert_called_once()
|
||||
sess.start_15693.assert_not_called()
|
||||
sim.start(Tag15693()) # ISO 15693
|
||||
sess.start_15693.assert_called_once()
|
||||
|
||||
|
||||
def test_sim_push_calls_tag_sync():
|
||||
sim = Sim(MagicMock())
|
||||
tag = MagicMock()
|
||||
sim.push(tag)
|
||||
tag.sync.assert_called_once()
|
||||
|
||||
|
||||
def test_sim_effect_patterns():
|
||||
eff = Pm3pyPlugin.effects
|
||||
assert "sim.start" in eff["sim"] and "sim.stop" in eff["sim"]
|
||||
assert "sim.push" in eff["write"]
|
||||
|
||||
Reference in New Issue
Block a user