Update cable path tests
Some checks are pending
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run

This commit is contained in:
Jeremy Stretch 2025-11-19 16:20:44 -05:00
parent f49b88ad5e
commit 9dbb9bb51c
3 changed files with 77 additions and 112 deletions

View File

@ -695,7 +695,9 @@ class CablePath(models.Model):
position_stack.append([terminations[0].cable_position]) position_stack.append([terminations[0].cable_position])
# Step 2: Determine the attached links (Cable or WirelessLink), if any # Step 2: Determine the attached links (Cable or WirelessLink), if any
links = [termination.link for termination in terminations if termination.link is not None] links = list(dict.fromkeys(
termination.link for termination in terminations if termination.link is not None
))
if len(links) == 0: if len(links) == 0:
if len(path) == 1: if len(path) == 1:
# If this is the start of the path and no link exists, return None # If this is the start of the path and no link exists, return None
@ -775,83 +777,39 @@ class CablePath(models.Model):
if isinstance(remote_terminations[0], FrontPort): if isinstance(remote_terminations[0], FrontPort):
# Follow FrontPorts to their corresponding RearPorts # Follow FrontPorts to their corresponding RearPorts
if position_stack: if any(rt.positions for rt in remote_terminations):
positions = position_stack.pop()
q_filter = Q() q_filter = Q()
for rt in remote_terminations: for rt in remote_terminations:
position = positions.pop() q_filter |= Q(front_port=rt, front_port_position__in=rt.positions)
q_filter |= Q(front_port=rt, front_port_position=position)
port_assignments = PortAssignment.objects.filter(q_filter) port_assignments = PortAssignment.objects.filter(q_filter)
else: else:
port_assignments = PortAssignment.objects.filter(front_port__in=remote_terminations) port_assignments = PortAssignment.objects.filter(front_port__in=remote_terminations)
if not port_assignments: if not port_assignments:
print(f'No front-to-rear port assignments found for {remote_terminations}')
break break
position_stack.append([assignment.rear_port_position for assignment in port_assignments])
terminations = [assignment.rear_port for assignment in port_assignments] # Compile the list of RearPorts without duplication or altering their ordering
terminations = list(dict.fromkeys(assignment.rear_port for assignment in port_assignments))
# if not(len(terminations) == 1 and terminations[0].positions == 1):
if any(t.positions > 1 for t in terminations):
position_stack.append([assignment.rear_port_position for assignment in port_assignments])
elif isinstance(remote_terminations[0], RearPort): elif isinstance(remote_terminations[0], RearPort):
# Follow RearPorts to their corresponding FrontPorts # Follow RearPorts to their corresponding FrontPorts
if position_stack: if remote_terminations[0].positions > 1 and position_stack:
positions = position_stack.pop() positions = position_stack.pop()
q_filter = Q() q_filter = Q()
for rt in remote_terminations: for rt in remote_terminations:
position = positions.pop() q_filter |= Q(rear_port=rt, rear_port_position__in=positions)
q_filter |= Q(rear_port=rt, rear_port_position=position)
port_assignments = PortAssignment.objects.filter(q_filter) port_assignments = PortAssignment.objects.filter(q_filter)
elif remote_terminations[0].positions > 1:
is_split = True
break
else: else:
port_assignments = PortAssignment.objects.filter(rear_port__in=remote_terminations) port_assignments = PortAssignment.objects.filter(rear_port__in=remote_terminations)
if not port_assignments: if not port_assignments:
print(f'No rear-to-front port assignments found for {remote_terminations}')
break break
position_stack.append([assignment.front_port_position for assignment in port_assignments])
terminations = [assignment.front_port for assignment in port_assignments]
# if len(remote_terminations) == 1 and remote_terminations[0].positions == 1: terminations = [assignment.front_port for assignment in port_assignments]
# front_ports = FrontPort.objects.filter(
# rear_port_id__in=[rp.pk for rp in remote_terminations],
# rear_port_position=1
# )
# # Obtain the individual front ports based on the termination and all positions
# elif len(remote_terminations) > 1 and position_stack:
# positions = position_stack.pop()
#
# # Ensure we have a number of positions equal to the amount of remote terminations
# if len(remote_terminations) != len(positions):
# raise UnsupportedCablePath(
# _("All positions counts within the path on opposite ends of links must match")
# )
#
# # Get our front ports
# q_filter = Q()
# for rt in remote_terminations:
# position = positions.pop()
# q_filter |= Q(rear_port_id=rt.pk, rear_port_position=position)
# if q_filter is Q():
# raise UnsupportedCablePath(_("Remote termination position filter is missing"))
# front_ports = FrontPort.objects.filter(q_filter)
# # Obtain the individual front ports based on the termination and position
# elif position_stack:
# front_ports = FrontPort.objects.filter(
# rear_port_id=remote_terminations[0].pk,
# rear_port_position__in=position_stack.pop()
# )
# # If all rear ports have a single position, we can just get the front ports
# elif all([rp.positions == 1 for rp in remote_terminations]):
# front_ports = FrontPort.objects.filter(rear_port_id__in=[rp.pk for rp in remote_terminations])
#
# if len(front_ports) != len(remote_terminations):
# # Some rear ports does not have a front port
# is_split = True
# break
# else:
# # No position indicated: path has split, so we stop at the RearPorts
# is_split = True
# break
#
# terminations = front_ports
elif isinstance(remote_terminations[0], CircuitTermination): elif isinstance(remote_terminations[0], CircuitTermination):
# Follow a CircuitTermination to its corresponding CircuitTermination (A to Z or vice versa) # Follow a CircuitTermination to its corresponding CircuitTermination (A to Z or vice versa)

View File

@ -1025,8 +1025,6 @@ class LegacyCablePathTests(CablePathTestCase):
b_terminations=[rearport3] b_terminations=[rearport3]
) )
cable4.save() cable4.save()
for path in CablePath.objects.all():
print(path.path_objects)
self.assertPathExists( self.assertPathExists(
( (
interface1, cable1, frontport1_1, rearport1, cable3, frontport2, rearport2, interface1, cable1, frontport1_1, rearport1, cable3, frontport2, rearport2,
@ -1079,7 +1077,7 @@ class LegacyCablePathTests(CablePathTestCase):
interface1 = Interface.objects.create(device=self.device, name='Interface 1') interface1 = Interface.objects.create(device=self.device, name='Interface 1')
interface2 = Interface.objects.create(device=self.device, name='Interface 2') interface2 = Interface.objects.create(device=self.device, name='Interface 2')
interface3 = Interface.objects.create(device=self.device, name='Interface 3') interface3 = Interface.objects.create(device=self.device, name='Interface 3')
rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=2)
frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1') frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2') frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
PortAssignment.objects.bulk_create([ PortAssignment.objects.bulk_create([

View File

@ -1,5 +1,3 @@
from unittest import skipIf
from circuits.models import CircuitTermination from circuits.models import CircuitTermination
from dcim.choices import CableProfileChoices from dcim.choices import CableProfileChoices
from dcim.models import * from dcim.models import *
@ -363,13 +361,13 @@ class CablePathTests(CablePathTestCase):
Interface.objects.create(device=self.device, name='Interface 3'), Interface.objects.create(device=self.device, name='Interface 3'),
Interface.objects.create(device=self.device, name='Interface 4'), Interface.objects.create(device=self.device, name='Interface 4'),
] ]
rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
frontport1 = FrontPort.objects.create( frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
device=self.device, PortAssignment.objects.bulk_create([
name='Front Port 1', PortAssignment(
rear_port=rearport1, front_port=frontport1, front_port_position=None, rear_port=rearport1, rear_port_position=1,
rear_port_position=1 ),
) ])
# Create cables # Create cables
cable1 = Cable( cable1 = Cable(
@ -439,18 +437,24 @@ class CablePathTests(CablePathTestCase):
] ]
rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4) rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=4)
rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4) rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=4)
frontport1_1 = FrontPort.objects.create( frontport1_1 = FrontPort.objects.create(device=self.device, name='Front Port 1:1')
device=self.device, name='Front Port 1:1', rear_port=rearport1, rear_port_position=1 frontport1_2 = FrontPort.objects.create(device=self.device, name='Front Port 1:2')
) frontport2_1 = FrontPort.objects.create(device=self.device, name='Front Port 2:1')
frontport1_2 = FrontPort.objects.create( frontport2_2 = FrontPort.objects.create(device=self.device, name='Front Port 2:2')
device=self.device, name='Front Port 1:2', rear_port=rearport1, rear_port_position=2 PortAssignment.objects.bulk_create([
) PortAssignment(
frontport2_1 = FrontPort.objects.create( front_port=frontport1_1, front_port_position=None, rear_port=rearport1, rear_port_position=1,
device=self.device, name='Front Port 2:1', rear_port=rearport2, rear_port_position=1 ),
) PortAssignment(
frontport2_2 = FrontPort.objects.create( front_port=frontport1_2, front_port_position=None, rear_port=rearport1, rear_port_position=2,
device=self.device, name='Front Port 2:2', rear_port=rearport2, rear_port_position=2 ),
) PortAssignment(
front_port=frontport2_1, front_port_position=None, rear_port=rearport2, rear_port_position=1,
),
PortAssignment(
front_port=frontport2_2, front_port_position=None, rear_port=rearport2, rear_port_position=2,
),
])
# Create cables # Create cables
cable1 = Cable( cable1 = Cable(
@ -654,25 +658,31 @@ class CablePathTests(CablePathTestCase):
Interface.objects.create(device=self.device, name='Interface 2'), Interface.objects.create(device=self.device, name='Interface 2'),
] ]
rear_ports = [ rear_ports = [
RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1), RearPort.objects.create(device=self.device, name='Rear Port 1'),
RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1), RearPort.objects.create(device=self.device, name='Rear Port 2'),
RearPort.objects.create(device=self.device, name='Rear Port 3', positions=1), RearPort.objects.create(device=self.device, name='Rear Port 3'),
RearPort.objects.create(device=self.device, name='Rear Port 4', positions=1), RearPort.objects.create(device=self.device, name='Rear Port 4'),
] ]
front_ports = [ front_ports = [
FrontPort.objects.create( FrontPort.objects.create(device=self.device, name='Front Port 1'),
device=self.device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1 FrontPort.objects.create(device=self.device, name='Front Port 2'),
), FrontPort.objects.create(device=self.device, name='Front Port 3'),
FrontPort.objects.create( FrontPort.objects.create(device=self.device, name='Front Port 4'),
device=self.device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1
),
FrontPort.objects.create(
device=self.device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1
),
FrontPort.objects.create(
device=self.device, name='Front Port 4', rear_port=rear_ports[3], rear_port_position=1
),
] ]
PortAssignment.objects.bulk_create([
PortAssignment(
front_port=front_ports[0], front_port_position=None, rear_port=rear_ports[0], rear_port_position=1,
),
PortAssignment(
front_port=front_ports[1], front_port_position=None, rear_port=rear_ports[1], rear_port_position=1,
),
PortAssignment(
front_port=front_ports[2], front_port_position=None, rear_port=rear_ports[2], rear_port_position=1,
),
PortAssignment(
front_port=front_ports[3], front_port_position=None, rear_port=rear_ports[3], rear_port_position=1,
),
])
# Create cables # Create cables
cable1 = Cable( cable1 = Cable(
@ -723,8 +733,6 @@ class CablePathTests(CablePathTestCase):
# Test SVG generation # Test SVG generation
CableTraceSVG(interfaces[0]).render() CableTraceSVG(interfaces[0]).render()
# TODO: Revisit this test under FR #20564
@skipIf(True, "Waiting for FR #20564")
def test_223_single_path_via_multiple_pass_throughs_with_breakouts(self): def test_223_single_path_via_multiple_pass_throughs_with_breakouts(self):
""" """
[IF1] --C1-- [FP1] [RP1] --C2-- [IF3] [IF1] --C1-- [FP1] [RP1] --C2-- [IF3]
@ -736,14 +744,18 @@ class CablePathTests(CablePathTestCase):
Interface.objects.create(device=self.device, name='Interface 3'), Interface.objects.create(device=self.device, name='Interface 3'),
Interface.objects.create(device=self.device, name='Interface 4'), Interface.objects.create(device=self.device, name='Interface 4'),
] ]
rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1', positions=1) rearport1 = RearPort.objects.create(device=self.device, name='Rear Port 1')
rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2', positions=1) rearport2 = RearPort.objects.create(device=self.device, name='Rear Port 2')
frontport1 = FrontPort.objects.create( frontport1 = FrontPort.objects.create(device=self.device, name='Front Port 1')
device=self.device, name='Front Port 1', rear_port=rearport1, rear_port_position=1 frontport2 = FrontPort.objects.create(device=self.device, name='Front Port 2')
) PortAssignment.objects.bulk_create([
frontport2 = FrontPort.objects.create( PortAssignment(
device=self.device, name='Front Port 2', rear_port=rearport2, rear_port_position=1 front_port=frontport1, front_port_position=None, rear_port=rearport1, rear_port_position=1,
) ),
PortAssignment(
front_port=frontport2, front_port_position=None, rear_port=rearport2, rear_port_position=1,
),
])
# Create cables # Create cables
cable1 = Cable( cable1 = Cable(
@ -761,9 +773,6 @@ class CablePathTests(CablePathTestCase):
cable2.clean() cable2.clean()
cable2.save() cable2.save()
for path in CablePath.objects.all():
print(f'{path}: {path.path_objects}')
# Validate paths # Validate paths
self.assertPathExists( self.assertPathExists(
(interfaces[0], cable1, [frontport1, frontport2], [rearport1, rearport2], cable2, interfaces[2]), (interfaces[0], cable1, [frontport1, frontport2], [rearport1, rearport2], cable2, interfaces[2]),