mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-09-06 18:17:03 +03:00
fix: normalize marker.match event tag to int to match the REST schema
The WS event carried the tag as str (verbatim from the MARK signal) when present and as int when falling back to the registry, so one tag reached consumers as two different values. Parse the signal's decimal (the exact value we installed via 'mark <bpf> tag <id>') and keep the registered int on malformed input; None only when neither side carries one.
This commit is contained in:
parent
b72b8b44b4
commit
9262dcfaef
@ -114,13 +114,24 @@ class MarkerListener(asyncio.DatagramProtocol):
|
||||
# signals that carry no `link=`.
|
||||
signal_link = link if link and link != "-" else None
|
||||
|
||||
# Normalize the tag to int so the event matches the REST schema
|
||||
# (MarkerCreate.tag is Optional[int]): the signal merely echoes the
|
||||
# decimal we installed via `mark <bpf> tag <id>`, so parsing cannot
|
||||
# fail for well-formed signals; a malformed value keeps the registered
|
||||
# int, and the tag is None only when neither side carries one.
|
||||
event_tag = registered_tag
|
||||
if tag and tag != "-":
|
||||
try:
|
||||
event_tag = int(tag)
|
||||
except ValueError:
|
||||
pass # malformed signal tag: keep the registered value
|
||||
|
||||
event = {
|
||||
"project_id": project_id,
|
||||
"node_id": node_id,
|
||||
"link_id": signal_link or link_id,
|
||||
"filter": filter_name,
|
||||
# Prefer the value carried in the signal; fall back to the one we registered.
|
||||
"tag": tag if tag and tag != "-" else registered_tag,
|
||||
"tag": event_tag,
|
||||
"ts": ts,
|
||||
"len": int(length) if length and length.isdigit() else 0,
|
||||
# Travel direction relative to the capture node (node_id above);
|
||||
|
||||
@ -121,7 +121,11 @@ class TestMarkerListener:
|
||||
assert ev["node_id"] == "n1"
|
||||
assert ev["link_id"] == "l1"
|
||||
assert ev["filter"] == "f1"
|
||||
assert ev["tag"] == "7"
|
||||
# The event tag is normalized to int to match the REST schema — the
|
||||
# signal echoes the decimal we installed, so str and int variants of
|
||||
# the same tag must never reach consumers as different keys.
|
||||
assert ev["tag"] == 7
|
||||
assert isinstance(ev["tag"], int)
|
||||
assert ev["ts"] == pytest.approx(1700000000.123456)
|
||||
assert ev["len"] == 98
|
||||
# No dir= in the signal (legacy uBridge) → undirected.
|
||||
@ -163,6 +167,24 @@ class TestMarkerListener:
|
||||
lis.datagram_received(b"MARK 2.0 node=n filter=f tag=- len=20\n", None)
|
||||
assert fmgr.events[0][1]["tag"] == 42
|
||||
|
||||
def test_non_numeric_signal_tag_falls_back_to_registered(self):
|
||||
# A corrupt/unknown signal value must not leak a str tag into the
|
||||
# event stream — the registry's int wins.
|
||||
fmgr = FakeMarkerManager()
|
||||
fmgr.register("p", "n", "f", "l", tag=42)
|
||||
lis = MarkerListener(fmgr)
|
||||
lis.connection_made(None)
|
||||
lis.datagram_received(b"MARK 2.0 node=n filter=f tag=oops len=20\n", None)
|
||||
assert fmgr.events[0][1]["tag"] == 42
|
||||
|
||||
def test_no_tag_anywhere_is_none(self):
|
||||
fmgr = FakeMarkerManager()
|
||||
fmgr.register("p", "n", "f", "l", tag=None)
|
||||
lis = MarkerListener(fmgr)
|
||||
lis.connection_made(None)
|
||||
lis.datagram_received(b"MARK 2.0 node=n filter=f tag=- len=20\n", None)
|
||||
assert fmgr.events[0][1]["tag"] is None
|
||||
|
||||
def test_link_in_signal_overrides_registry_link(self):
|
||||
# Per-link attribution (contract §3.2/§3.3): the signal's `link=` is
|
||||
# authoritative and must disambiguate links sharing a node+filter —
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user