Files
sps_skel/tests/test_tro_link.py
T
Samer AyadiandClaude Opus 5.5 77c5aac343 tro_flow.link_tros: Uebergang durch eine Weiche zwischen zwei Kreiseln
Der Weichenknoten-TRO leitet ueber jede seiner Weichen auf den
Partnerkreisel um; dort faehrt der Traeger zum naechsten Halt nach der
Weiche. Ohne diese Kante fehlte z. B. in der Testanlage test_system
TRO(0011) -> TRO(0010), der Ausgang war vom Eingang aus unerreichbar.
Test tests/test_tro_link.py mit Fixture test_system_sep22_export.csv;
ID-Datei cfg/export_tro_ids.ini der Testanlage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 16:16:21 +02:00

75 lines
2.6 KiB
Python

# -*- coding: utf-8 -*-
"""Tests fuer tro_flow.link_tros - Uebergang durch eine Kreisel-Kreisel-Weiche.
Fixture: Testanlage test_system (dxfmakros results/export.csv) mit einem
zusaetzlichen Separator 0022 auf Kreisel 0007. Kreisel 0009 hat nur einen
eigenen Separator (0010 vor Weiche 0024 zu Kreisel 0001 mit der Entladung);
in Kreisel 0009 gelangt man nur ueber Weiche 0023, die Separator 0011 auf
Kreisel 0008 steuert. Die Kreiselketten kennen Weichen nicht als Glied - ohne
eigene Weichenkante fehlte TRO(0011) -> TRO(0010), der Ausgang war vom
Eingang aus unerreichbar und stattdessen zeigte TRO(0010) rueckwaerts auf
TRO(0011).
TROs werden ueber ihre Separatoren angesprochen, nicht ueber die IDs (die
haengen an der ID-Datei der Anlage).
"""
from __future__ import annotations
from pathlib import Path
import pytest
from material_flow import build_graph, read_elements
from tro_flow import BOUNDARY_ENTRY, BOUNDARY_EXIT, analyse_tros
FIXTURES = Path(__file__).parent / "fixtures"
def _analyse(name: str):
path = FIXTURES / name
elements = read_elements(path, [])
graph = build_graph(elements, path.name, [])
return analyse_tros(graph, elements)
@pytest.fixture(scope="module")
def analysis():
return _analyse("test_system_sep22_export.csv")
def _tro_mit_sep(analysis, sep_id: str) -> str:
return next(t.tro_id for t in analysis.tros if sep_id in t.separators)
def _erreichbar(edges, start: str) -> set[str]:
nach: dict[str, list[str]] = {}
for a, b in edges:
nach.setdefault(a, []).append(b)
seen, stack = {start}, [start]
while stack:
for nxt in nach.get(stack.pop(), []):
if nxt not in seen:
seen.add(nxt)
stack.append(nxt)
return seen
def test_weiche_fuehrt_auf_partnerkreisel(analysis):
von, nach = _tro_mit_sep(analysis, "0011"), _tro_mit_sep(analysis, "0010")
assert (von, nach) in analysis.edges
def test_keine_rueckwaertskante_ueber_die_weiche(analysis):
von, nach = _tro_mit_sep(analysis, "0010"), _tro_mit_sep(analysis, "0011")
assert (von, nach) not in analysis.edges
def test_ausgang_vom_eingang_erreichbar(analysis):
# Nicht fuer test_system_export.csv: dort fehlt auf Kreisel 0007 der
# Separator vor der Weiche zu Kreisel 0008 (erst 0022 hier steuert sie) -
# die Anlage ist dort physisch nicht durchgaengig.
eingang = next(b.tro_id for b in analysis.boundaries if b.type_name == BOUNDARY_ENTRY)
ausgang = next(b.tro_id for b in analysis.boundaries if b.type_name == BOUNDARY_EXIT)
assert ausgang in _erreichbar(analysis.edges, eingang)