You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ADN-DMR-Peer-Server/tests/routing/test_obp_announcement_conte...

91 lines
3.6 KiB

# ADN DMR Peer Server - OBP vs server announcement slot contention
#
# Copyright (C) 2026 Rodrigo Pérez, CE5RPY <ce5rpy@qmd.cl>
#
###############################################################################
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
"""OBP ingress blocked while server announcement holds MASTER slot TX row."""
from __future__ import annotations
from tests.harness.deterministic import DeterministicScenario, PacketSpec, patch_routing_wall_time
from tests.harness.scenarios import obp_bridge_scenario
from adn_server.application.server_voice import DEFAULT_SERVER_VOICE_ID
from adn_server.domain import HBPF_SLT_VHEAD, HBPF_SLT_VTERM, bytes_3, bytes_4
def _seed_server_broadcast_slot(scenario: DeterministicScenario, *, ann_tg: int = 91) -> None:
proto = scenario.protocols["MASTER-A"]
t = scenario.clock.time()
proto.STATUS[2] = {
"RX_TYPE": HBPF_SLT_VTERM,
"TX_TYPE": HBPF_SLT_VHEAD,
"TX_TIME": t,
"TX_RFS": bytes_3(DEFAULT_SERVER_VOICE_ID),
"TX_TGID": bytes_3(ann_tg),
"TX_STREAM_ID": bytes_4(0xA0A0A0A0),
}
def test_obp_blocked_while_server_broadcast_holds_master_ts2() -> None:
"""Legacy parity: OBP must not route onto TS2 while announcement holds TX row."""
scenario = obp_bridge_scenario("OBP-CL", tg=7144)
scenario.config["PROXY"] = {"TARGET_SYSTEM": "MASTER-A"}
scenario.config["SYSTEMS"]["MASTER-A"]["PEERS"] = {
bytes_4(730002): {"CONNECTION": "YES", "OPTIONS": b"TS2=7144;"},
}
_seed_server_broadcast_slot(scenario, ann_tg=91)
base = PacketSpec(
peer_id=73010,
rf_src=3340062,
dst_id=7144,
slot=1,
stream_id=0x11111111,
)
with patch_routing_wall_time(scenario.clock):
scenario.inject_obp("OBP-CL", DeterministicScenario.voice_head_spec(base))
assert scenario.capture.for_system("MASTER-A") == []
def test_obp_still_forwards_when_no_server_broadcast_hold() -> None:
"""Inject-only defer remains when the slot is not held by server voice."""
scenario = obp_bridge_scenario("OBP-CL", tg=7144)
scenario.config["PROXY"] = {"TARGET_SYSTEM": "MASTER-A"}
scenario.config["SYSTEMS"]["MASTER-A"]["PEERS"] = {
bytes_4(730002): {"CONNECTION": "YES", "OPTIONS": b"TS2=7144;"},
}
proto = scenario.protocols["MASTER-A"]
t = scenario.clock.time()
proto.STATUS[2] = {
"RX_TYPE": HBPF_SLT_VTERM,
"TX_TYPE": HBPF_SLT_VTERM,
"TX_TIME": t - 60.0,
"TX_RFS": bytes_3(3340062),
"TX_TGID": bytes_3(7144),
}
base = PacketSpec(
peer_id=73010,
rf_src=3340062,
dst_id=7144,
slot=1,
stream_id=0x22222222,
)
with patch_routing_wall_time(scenario.clock):
scenario.inject_obp("OBP-CL", DeterministicScenario.voice_head_spec(base))
assert len(scenario.capture.for_system("MASTER-A")) > 0

Powered by TurnKey Linux.