From 0ff30a6562e1d6fd8aa31a7b795ca5ecb398d7b0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Joakim=20T=C3=B6rnqvist?= Date: Thu, 7 Dec 2023 14:13:13 +0000 Subject: [PATCH] Determine preferred node/port from PCRI MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Package intended to be used to determine preferred SRG port usage when setting up optical services between ROADMs. Use an instance of PathComputationRequestInput, e.g. API input and provides a method for checking if a specific SRG port is among the ports in the client request. Package org.opendaylight.transportpce.pce.networkanalyzer.port: * Preference - Interface defining one method capable of determining if a node/port is 'preferred' by the client. * ClientPreference - Implements Preference. Contains information about actual client port preference. * NoPreference - Implements Preference. Typically used when the client has no preference regarding port. * Factory - Interface defining methods needed in order to convert a PathComputationRequestInput to an implementation of Preferenc. * PreferenceFactory - Implements Factory. The method 'portPreference' should typically be used implementing the feature in the application. The method portPreference either returns an instance of 'ClientPreference' or 'NoPreference'. Example: public void someMethod(PathComputationRequestInput input) { Factory portPreferenceFactory = new PreferenceFactory(); Preference preference = portPreferenceFactory.portPreference(input); if (preference.preferredPort("ROADM-A-SRG1", "SRG1-PP1-TXRX")) { System.out.println("The port 'SRG1-PP1-TXRX' on 'ROADM-A-SRG1' " +"is preferred by the client."); } } JIRA: TRNSPRTPCE-176 Change-Id: Iba7e7886678deb6d965391633f819995635caa06 Signed-off-by: Joakim Törnqvist --- .../port/ClientPreference.java | 33 ++ .../pce/networkanalyzer/port/Factory.java | 32 ++ .../networkanalyzer/port/NoPreference.java | 26 ++ .../pce/networkanalyzer/port/Preference.java | 18 + .../port/PreferenceFactory.java | 140 ++++++++ .../port/ClientPreferenceTest.java | 63 ++++ .../port/PreferenceFactoryTest.java | 312 ++++++++++++++++++ 7 files changed, 624 insertions(+) create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreference.java create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Factory.java create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/NoPreference.java create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Preference.java create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactory.java create mode 100644 pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreferenceTest.java create mode 100644 pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactoryTest.java diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreference.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreference.java new file mode 100644 index 000000000..d3749c382 --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreference.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +import java.util.Map; +import java.util.Set; + +public class ClientPreference implements Preference { + + Map> nodePortPreference; + + public ClientPreference(Map> nodePortPreference) { + this.nodePortPreference = nodePortPreference; + } + + @Override + public boolean isPreferredPort(String node, String portName) { + + //If there is no preferred port registered for the node, it means + //the client has no preference regarding the node. + //Therefore, we'll treat the node as it was preferred to + //prevent it from NOT being used. + return !nodePortPreference.containsKey(node) || nodePortPreference.get(node).contains(portName); + + } + +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Factory.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Factory.java new file mode 100644 index 000000000..11721f520 --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Factory.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput; + +public interface Factory { + + /** + * Extracting preferred ports from pathComputationRequestInput. + * + *

+ * This is the recommended method of determining if a node/port combination + * is preferred by the client. + * + *

+ * Pseudocode example: + *

+     *     Factory.portPreference(PCRI).preferredPort("ROADM-B-SRG1", "SRG1-PP1-TXRX");
+     * 
+ * + * @return Client port preference + */ + Preference portPreference(PathComputationRequestInput pathComputationRequestInput); + +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/NoPreference.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/NoPreference.java new file mode 100644 index 000000000..5b96ca09a --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/NoPreference.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +/** + * This class represents a state where the client has no port preference. + * In essence, all ports on all nodes will therefore be treated as 'preferred' + * when queried. + * + *

+ * Usage of this class is of sorts the 'backwards compatible' approach. Meaning, + * intended to offer a path for the application to behave as it did + * prior to implementing client port preference. + */ +public class NoPreference implements Preference { + @Override + public boolean isPreferredPort(String node, String portName) { + return true; + } +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Preference.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Preference.java new file mode 100644 index 000000000..3d1acb86d --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/Preference.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +public interface Preference { + + /** + * Return true if the portName is among the ports preferred by the client. + */ + boolean isPreferredPort(String node, String portName); + +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactory.java b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactory.java new file mode 100644 index 000000000..6d36d8212 --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactory.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceAEnd; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceZEnd; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.Port; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.RxDirection; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.TxDirection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PreferenceFactory implements Factory { + + private static final Logger LOG = LoggerFactory.getLogger(PreferenceFactory.class); + + private final String portNamePattern = "(?i)SRG\\d+-PP\\d+-(TXRX|TX|RX)"; + + @Override + public Preference portPreference(PathComputationRequestInput pathComputationRequestInput) { + + Map> map = nodePortMap(pathComputationRequestInput); + + if (map.isEmpty()) { + LOG.debug("No port preference found in path computation request."); + return new NoPreference(); + } + + LOG.debug("Port preference in path computation request: {}." , map); + return new ClientPreference(map); + } + + /** + * Create a key value mapper from PCRI where key is the node and the value is + * a unique list of port names. + * + * @return Client port preference map + */ + Map> nodePortMap(PathComputationRequestInput pathComputationRequestInput) { + + Map> mapper = new HashMap<>(); + + ServiceAEnd serviceAEnd = pathComputationRequestInput.getServiceAEnd(); + if (serviceAEnd != null) { + + RxDirection rxAzDirection = serviceAEnd.getRxDirection(); + if (rxAzDirection != null) { + + Port rxAZport = rxAzDirection.getPort(); + if (rxAZport != null) { + add(rxAZport.getPortDeviceName(), rxAZport.getPortName(), mapper); + } + } + + TxDirection txAzDirection = serviceAEnd.getTxDirection(); + if (txAzDirection != null) { + + Port txAZport = txAzDirection.getPort(); + if (txAZport != null) { + add(txAZport.getPortDeviceName(), txAZport.getPortName(), mapper); + } + } + } + + ServiceZEnd serviceZEnd = pathComputationRequestInput.getServiceZEnd(); + if (serviceZEnd != null) { + + RxDirection rxZaDirection = serviceZEnd.getRxDirection(); + if (rxZaDirection != null) { + + Port rxZAport = rxZaDirection.getPort(); + if (rxZAport != null) { + add(rxZAport.getPortDeviceName(), rxZAport.getPortName(), mapper); + } + } + + TxDirection txZaDirection = serviceZEnd.getTxDirection(); + if (txZaDirection != null) { + + Port txZAport = txZaDirection.getPort(); + if (txZAport != null) { + add(txZAport.getPortDeviceName(), txZAport.getPortName(), mapper); + } + } + } + + return mapper; + } + + /** + * Add node/port name to key value map. Mutable method, modifies the argument nodePortMap. + */ + boolean add(String node, String port, Map> nodePortMap) { + + if (node == null || port == null) { + return false; + } + + String nodeTrimmed = node.trim(); + String portTrimmed = port.trim(); + + if (nodeTrimmed.isEmpty() || portTrimmed.isEmpty()) { + return false; + } + + if (!portTrimmed.matches(portNamePattern)) { + LOG.warn("Preferred port name '{}' on node {} doesn't match pattern '{}'", + portTrimmed, + nodeTrimmed, + portNamePattern + ); + } + + if (nodePortMap.containsKey(nodeTrimmed)) { + boolean added = nodePortMap.get(nodeTrimmed).add(portTrimmed); + if (added) { + LOG.debug("Preferred port '{}' for node '{}' registered.", portTrimmed, nodeTrimmed); + } else { + LOG.debug("Failed registering port '{}' for node '{}'.", portTrimmed, nodeTrimmed); + } + return added; + } + + nodePortMap.put(nodeTrimmed, new HashSet<>(Arrays.asList(portTrimmed))); + + return true; + } +} diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreferenceTest.java b/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreferenceTest.java new file mode 100644 index 000000000..24662213b --- /dev/null +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/ClientPreferenceTest.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ClientPreferenceTest { + + @Test + void preferredPort_returnTrue() { + + Map> nodePortPreference = new HashMap<>(); + nodePortPreference.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + + Preference clientPreference = new ClientPreference(nodePortPreference); + + Assertions.assertTrue(clientPreference.isPreferredPort("ROADM-B-SRG1", "SRG1-PP1-TXRX")); + } + + /** + * The client prefer to use SRG1-PP1-TXRX on ROADM-B-SRG1. + * Therefore, preferredPort returns false on SRG1-PP2-TXRX. + */ + @Test + void nonPreferredPort_returnFalse() { + + Map> nodePortPreference = new HashMap<>(); + nodePortPreference.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + + Preference clientPreference = new ClientPreference(nodePortPreference); + + Assertions.assertFalse(clientPreference.isPreferredPort("ROADM-B-SRG1", "SRG1-PP2-TXRX")); + } + + /** + * In this scenario ROADM-A-SRG1 is missing from the client preferred list. + * We treat this as the client has no opinion on what port + * to use on ROADM-A-SRG1. Meaning, as far as the client goes, all + * ports on ROADM-A-SRG1 are fine. + */ + @Test + void nodeMissingInPreferredList_returnTrue() { + + Map> nodePortPreference = new HashMap<>(); + nodePortPreference.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + + Preference clientPreference = new ClientPreference(nodePortPreference); + + Assertions.assertTrue(clientPreference.isPreferredPort("ROADM-A-SRG1", "SRG1-PP2-TXRX")); + + } +} \ No newline at end of file diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactoryTest.java b/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactoryTest.java new file mode 100644 index 000000000..34ebb5cae --- /dev/null +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/networkanalyzer/port/PreferenceFactoryTest.java @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2024 Smartoptics and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.pce.networkanalyzer.port; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.PathComputationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceAEnd; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev230925.path.computation.request.input.ServiceZEnd; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.PortBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.RxDirection; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.TxDirection; + +class PreferenceFactoryTest { + + @Test + void emptyPathComputationRequest_returnEmptyHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Map> expected = new HashMap<>(); + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceAEndRxDirectionWithoutDeviceAndPort_returnEmptyHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceAEnd serviceAEnd = Mockito.mock(ServiceAEnd.class); + RxDirection rxDirection = Mockito.mock(RxDirection.class); + + Mockito.when(rxDirection.getPort()).thenReturn(new PortBuilder().build()); + Mockito.when(serviceAEnd.getRxDirection()).thenReturn(rxDirection); + Mockito.when(pathComputationRequestInput.getServiceAEnd()).thenReturn(serviceAEnd); + + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Map> expected = new HashMap<>(); + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceAEndRxDirectionWithoutPort_returnEmptyHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceAEnd serviceAEnd = Mockito.mock(ServiceAEnd.class); + RxDirection rxDirection = Mockito.mock(RxDirection.class); + + Mockito.when(rxDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .build() + ); + Mockito.when(serviceAEnd.getRxDirection()).thenReturn(rxDirection); + Mockito.when(pathComputationRequestInput.getServiceAEnd()).thenReturn(serviceAEnd); + + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Map> expected = new HashMap<>(); + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceAEndRxDirectionTxRx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceAEnd serviceAEnd = Mockito.mock(ServiceAEnd.class); + RxDirection rxDirection = Mockito.mock(RxDirection.class); + + Mockito.when(rxDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-TXRX") + .build() + ); + Mockito.when(serviceAEnd.getRxDirection()).thenReturn(rxDirection); + Mockito.when(pathComputationRequestInput.getServiceAEnd()).thenReturn(serviceAEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceAEndRxDirectionTx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceAEnd serviceAEnd = Mockito.mock(ServiceAEnd.class); + RxDirection rxDirection = Mockito.mock(RxDirection.class); + + Mockito.when(rxDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-TX") + .build() + ); + Mockito.when(serviceAEnd.getRxDirection()).thenReturn(rxDirection); + Mockito.when(pathComputationRequestInput.getServiceAEnd()).thenReturn(serviceAEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceAEndRxDirectionRx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceAEnd serviceAEnd = Mockito.mock(ServiceAEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-RX") + .build() + ); + Mockito.when(serviceAEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceAEnd()).thenReturn(serviceAEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-RX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceZEndRx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + RxDirection rxDirection = Mockito.mock(RxDirection.class); + + Mockito.when(rxDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-TXRX") + .build() + ); + Mockito.when(serviceZEnd.getRxDirection()).thenReturn(rxDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceZEndTxDirectionTxRx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-TXRX") + .build() + ); + Mockito.when(serviceZEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TXRX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceZEndTxDirectionTx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-TX") + .build() + ); + Mockito.when(serviceZEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-TX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathComputationRequestServiceZEndTxDirectionRx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("SRG1-PP1-RX") + .build() + ); + Mockito.when(serviceZEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("SRG1-PP1-RX")); + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathEmptyComputationRequestServiceZEndTx_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName(" ") + .build() + ); + Mockito.when(serviceZEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void pathUnexpectedPortName_returnHashmap() { + + PathComputationRequestInput pathComputationRequestInput = Mockito.mock(PathComputationRequestInput.class); + ServiceZEnd serviceZEnd = Mockito.mock(ServiceZEnd.class); + TxDirection txDirection = Mockito.mock(TxDirection.class); + + Mockito.when(txDirection.getPort()).thenReturn( + new PortBuilder() + .setPortDeviceName("ROADM-B-SRG1") + .setPortName("FUBAR") + .build() + ); + Mockito.when(serviceZEnd.getTxDirection()).thenReturn(txDirection); + Mockito.when(pathComputationRequestInput.getServiceZEnd()).thenReturn(serviceZEnd); + + Map> expected = new HashMap<>(); + expected.put("ROADM-B-SRG1", Set.of("FUBAR")); + + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + Assertions.assertEquals(expected, portPreferenceFactory.nodePortMap(pathComputationRequestInput)); + + } + + @Test + void addingMultiplePort() { + + PreferenceFactory portPreferenceFactory = new PreferenceFactory(); + Map> mapper = new HashMap<>(); + + //New ports + Assertions.assertTrue(portPreferenceFactory.add("ROADM-B-SRG1", "SRG1-PP1-TXRX", mapper)); + Assertions.assertTrue(portPreferenceFactory.add("ROADM-B-SRG1", "SRG1-PP2-TXRX", mapper)); + Assertions.assertTrue(portPreferenceFactory.add("ROADM-B-SRG1", "SRG1-PP3-RX", mapper)); + Assertions.assertTrue(portPreferenceFactory.add("ROADM-B-SRG1", "SRG1-PP3-TX", mapper)); + + //This port already exists, should return false. + Assertions.assertFalse(portPreferenceFactory.add("ROADM-B-SRG1", "SRG1-PP2-TXRX", mapper)); + + Assertions.assertEquals( + Set.of("SRG1-PP1-TXRX", "SRG1-PP2-TXRX", "SRG1-PP3-RX", "SRG1-PP3-TX"), + mapper.get("ROADM-B-SRG1") + ); + } +} \ No newline at end of file -- 2.36.6