Merge "Determine preferred node/port from PCRI"
[transportpce.git] / pce / src / test / java / org / opendaylight / transportpce / pce / graph / PceGraphTest.java
1 /*
2  * Copyright © 2020 Orange, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.transportpce.pce.graph;
10
11
12 import static org.junit.jupiter.api.Assertions.assertEquals;
13 import static org.junit.jupiter.api.Assertions.assertThrows;
14 import static org.junit.jupiter.api.Assertions.fail;
15
16 import com.google.common.collect.ImmutableMap;
17 import com.google.gson.stream.JsonReader;
18 import java.io.FileReader;
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.nio.charset.StandardCharsets;
22 import java.util.Map;
23 import java.util.Optional;
24 import java.util.Set;
25 import java.util.concurrent.ExecutionException;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.mockito.MockitoAnnotations;
30 import org.opendaylight.mdsal.binding.api.DataBroker;
31 import org.opendaylight.mdsal.binding.api.MountPoint;
32 import org.opendaylight.mdsal.binding.api.MountPointService;
33 import org.opendaylight.mdsal.binding.api.WriteTransaction;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.transportpce.common.NetworkUtils;
36 import org.opendaylight.transportpce.common.StringConstants;
37 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
38 import org.opendaylight.transportpce.common.device.DeviceTransactionManagerImpl;
39 import org.opendaylight.transportpce.common.mapping.PortMapping;
40 import org.opendaylight.transportpce.common.mapping.PortMappingImpl;
41 import org.opendaylight.transportpce.common.mapping.PortMappingVersion121;
42 import org.opendaylight.transportpce.common.mapping.PortMappingVersion221;
43 import org.opendaylight.transportpce.common.mapping.PortMappingVersion710;
44 import org.opendaylight.transportpce.common.network.NetworkTransactionImpl;
45 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
46 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
47 import org.opendaylight.transportpce.pce.networkanalyzer.PceCalculation;
48 import org.opendaylight.transportpce.pce.networkanalyzer.PceLink;
49 import org.opendaylight.transportpce.pce.networkanalyzer.PceNode;
50 import org.opendaylight.transportpce.pce.networkanalyzer.PceOtnNode;
51 import org.opendaylight.transportpce.pce.networkanalyzer.PceResult;
52 import org.opendaylight.transportpce.pce.utils.JsonUtil;
53 import org.opendaylight.transportpce.pce.utils.NodeUtils;
54 import org.opendaylight.transportpce.test.AbstractTest;
55 import org.opendaylight.transportpce.test.converter.DataObjectConverter;
56 import org.opendaylight.transportpce.test.converter.JSONDataObjectConverter;
57 import org.opendaylight.transportpce.test.stub.MountPointServiceStub;
58 import org.opendaylight.transportpce.test.stub.MountPointStub;
59 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInput;
60 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PathComputationRequestInputBuilder;
61 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.PceConstraintMode;
62 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.request.input.ServiceAEndBuilder;
63 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev240205.path.computation.request.input.ServiceZEndBuilder;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.PortBuilder;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev230526.OpenroadmVersionType;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev230526.Node1Builder;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.TerminationPoint1Builder;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.networks.network.node.termination.point.XpdrNetworkAttributesBuilder;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType;
71 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmTpType;
72 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.constraints.CoRoutingBuilder;
73 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.constraints.co.routing.ServiceIdentifierListBuilder;
74 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.HardConstraintsBuilder;
75 import org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209.routing.constraints.SoftConstraintsBuilder;
76 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
77 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.OperationalModeCatalog;
78 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.PceMetric;
79 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.RxDirectionBuilder;
80 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.endpoint.sp.TxDirectionBuilder;
81 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.service.handler.header.ServiceHandlerHeaderBuilder;
82 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
83 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
84 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
85 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeBuilder;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.NodeKey;
90 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNode;
91 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeBuilder;
92 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNodeKey;
93 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
94 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.TpId;
95 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
96 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
97 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointBuilder;
98 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPointKey;
99 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
100 import org.opendaylight.yangtools.yang.common.Uint32;
101 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
102 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
103 import org.slf4j.Logger;
104 import org.slf4j.LoggerFactory;
105
106 public class PceGraphTest extends AbstractTest {
107     private static final Logger LOG = LoggerFactory.getLogger(PceGraphTest.class);
108     private Link link1 = null;
109     private Node node = null;
110     private PceLink pceLink1 = null;
111     private PceGraph pceGraph = null;
112     private PceConstraints pceHardConstraints = null;
113     private PceResult rc = null;
114     private Map<NodeId, PceNode> allPceNodes = null;
115     private Map<LinkId, PceLink> allPceLinks = null;
116     private static final String CATALOG_FILE = "src/test/resources/apidocCatalog12_0-OptSpecV5_1.json";
117     private static final String MAPPING_FILE = "src/test/resources/topologyData/portMapping2.json";
118     private static OperationalModeCatalog omCatalog;
119     private static org.opendaylight.yang.gen.v1.http.org.opendaylight
120             .transportpce.portmapping.rev231221.Network networkNode;
121     private DataBroker dataBroker;
122     private MountPoint mountPoint;
123     private MountPointService mountPointService;
124     private DeviceTransactionManager deviceTransactionManager;
125     private PortMappingVersion710 portMappingVersion710;
126     private PortMappingVersion221 portMappingVersion22;
127     private PortMappingVersion121 portMappingVersion121;
128     private PortMapping portMapping;
129     private NetworkTransactionService netTransServ;
130
131     // Test of integration for PceGraph
132
133     @BeforeEach
134     void setUp() throws InterruptedException, ExecutionException {
135         // PortMapping is instantiated to create the mapping of the different nodes in the topology
136         this.dataBroker =  getNewDataBroker();
137         this.mountPoint = new MountPointStub(dataBroker);
138         this.mountPointService = new MountPointServiceStub(mountPoint);
139         this.deviceTransactionManager = new DeviceTransactionManagerImpl(mountPointService, 3000);
140         this.portMappingVersion22 = new PortMappingVersion221(dataBroker, deviceTransactionManager);
141         this.portMappingVersion121 = new PortMappingVersion121(dataBroker, deviceTransactionManager);
142         this.portMappingVersion710 = new PortMappingVersion710(dataBroker, deviceTransactionManager);
143         this.portMapping = new PortMappingImpl(dataBroker, this.portMappingVersion710,
144             this.portMappingVersion22, this.portMappingVersion121);
145         //  The catalog of operational mode needs to be loaded so that Ctalog primitives (CatlogUtils)
146         // can retrieve physical parameters of the nodes of the path
147         DataObjectConverter dataObjectConverter = JSONDataObjectConverter
148             .createWithDataStoreUtil(getDataStoreContextUtil());
149         try (Reader reader = new FileReader(CATALOG_FILE, StandardCharsets.UTF_8)) {
150             NormalizedNode normalizedNode = dataObjectConverter
151                 .transformIntoNormalizedNode(reader)
152                 .orElseThrow();
153             omCatalog = (OperationalModeCatalog) getDataStoreContextUtil()
154                 .getBindingDOMCodecServices()
155                 .fromNormalizedNode(
156                     YangInstanceIdentifier.of(OperationalModeCatalog.QNAME), normalizedNode)
157                 .getValue();
158             @NonNull
159             WriteTransaction newWriteOnlyTransaction = dataBroker.newWriteOnlyTransaction();
160             newWriteOnlyTransaction
161                 .put(LogicalDatastoreType.CONFIGURATION,
162                     InstanceIdentifier.create(OperationalModeCatalog.class),
163                     omCatalog);
164             newWriteOnlyTransaction.commit().get();
165         } catch (IOException e) {
166             LOG.error("Cannot load OpenROADM part of Operational Mode Catalog ", e);
167             fail("Cannot load openROADM operational modes ");
168         }
169         // The mapping corresponding to the topology is directly populated from a file in the Dta Store
170         try (Reader reader = new FileReader(MAPPING_FILE, StandardCharsets.UTF_8)) {
171             NormalizedNode normalizedNode = dataObjectConverter.transformIntoNormalizedNode(reader).orElseThrow();
172             networkNode = (org.opendaylight.yang.gen.v1.http.org.opendaylight
173                     .transportpce.portmapping.rev231221.Network) getDataStoreContextUtil()
174                 .getBindingDOMCodecServices()
175                 .fromNormalizedNode(
176                     YangInstanceIdentifier.of(org.opendaylight.yang.gen.v1.http.org.opendaylight
177                         .transportpce.portmapping.rev231221.Network.QNAME), normalizedNode)
178                 .getValue();
179             @NonNull
180             WriteTransaction newWriteOnlyTransaction = dataBroker.newWriteOnlyTransaction();
181             newWriteOnlyTransaction
182                 .put(LogicalDatastoreType.CONFIGURATION,
183                     InstanceIdentifier.create(org.opendaylight.yang.gen.v1.http.org.opendaylight
184                         .transportpce.portmapping.rev231221.Network.class),
185                     networkNode);
186             newWriteOnlyTransaction.commit().get();
187         } catch (IOException e) {
188             LOG.error("Cannot load OpenROADM part of Operational Mode Catalog ", e);
189             fail("Cannot load openROADM operational modes ");
190         }
191
192         MockitoAnnotations.openMocks(this);
193         // The topology (openROADM-Network and openROADM-topology layers) is loaded from a file
194         JsonReader networkReader = null;
195         JsonReader topoReader = null;
196         try {
197             // load openroadm-network
198             Reader gnpyNetwork = new FileReader("src/test/resources/gnpy/gnpy_network.json", StandardCharsets.UTF_8);
199             networkReader = new JsonReader(gnpyNetwork);
200             Networks networks = (Networks) JsonUtil.getInstance().getDataObjectFromJson(networkReader, Networks.QNAME);
201             saveOpenRoadmNetwork(networks.getNetwork().values().iterator().next(), NetworkUtils.UNDERLAY_NETWORK_ID);
202             // load openroadm-topology
203             Reader gnpyTopo = new FileReader("src/test/resources/topologyData/or-base-topology.json",
204                     StandardCharsets.UTF_8);
205             topoReader = new JsonReader(gnpyTopo);
206             networks = (Networks) JsonUtil.getInstance().getDataObjectFromJson(topoReader, Networks.QNAME);
207             saveOpenRoadmNetwork(networks.getNetwork().values().iterator().next(), NetworkUtils.OVERLAY_NETWORK_ID);
208         } catch (IOException | InterruptedException | ExecutionException e) {
209             LOG.error("Cannot init test ", e);
210             fail("Cannot init test ");
211         } finally {
212             try {
213                 if (networkReader != null) {
214                     networkReader.close();
215                 }
216                 if (topoReader != null) {
217                     topoReader.close();
218                 }
219             } catch (IOException e) {
220                 LOG.warn("Cannot close reader ", e);
221             }
222         }
223         // init PceHardContraints
224         pceHardConstraints = new PceConstraints();
225         this.rc = new PceResult();
226         this.netTransServ = new NetworkTransactionImpl(dataBroker);
227         LOG.info("The value of the mapping is {}", portMapping);
228     }
229
230 //                       TOPOLOGY ON WHICH TEST ARE BASED
231 //           _____                      _____                       _____
232 //          |     | 20dB, 100km,PMD 2  |     | 20dB,100km, PMD 2   |     |
233 //          |  1  |____________________|  2  |_____________________|  5  |
234 //          |     |                    |     |                     |     |
235 //          |_____|                    |_____|                     |_____|
236 //              |___________      10km    |   20dB,100km,PMD32    /   |  100 km
237 //                          |      5dB    |   _________|_________/    |  25 dB
238 //                          |     PMD32 __|__/                      __|__PMD 2.0
239 //        28dB, 100km,PMD 0 |          |     | 25dB,100km, PMD 2   |     |
240 //                          |__________|  3  |_____________________|  4  |
241 //                                     |     |                     |     |
242 //                                     |_____|                     |_____|
243 //
244     @Test
245     void clacPath100GE() {
246         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(100), ServiceFormat.Ethernet,
247             "XPONDER-1", "Node1", "Client-1", "XPONDER-3", "Node3", "Client-1"),
248             netTransServ, pceHardConstraints, null, rc, portMapping);
249         pceCalc.retrievePceNetwork();
250         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
251             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
252             rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose);
253         assertEquals(pceGraph.calcPath(), true);
254         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(3.0919881995992924));
255     }
256
257     @Test
258     void clacPathOTUC2() {
259         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(200), ServiceFormat.Ethernet,
260             "XPONDER-1", "Node1", "XPDR-NW1-TX", "XPONDER-4", "Node4", "XPDR-NW1-RX"),
261             netTransServ, pceHardConstraints, null, rc, portMapping);
262         pceCalc.retrievePceNetwork();
263         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
264             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
265             rc, StringConstants.SERVICE_TYPE_OTUC2, netTransServ, PceConstraintMode.Loose);
266         assertEquals(pceGraph.calcPath(), true);
267         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.1559963686478447));
268     }
269
270     @Test
271     void clacPathOTUC3() {
272         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(300), ServiceFormat.Ethernet,
273             "XPONDER-1", "Node1", "XPDR-NW1-TX", "XPONDER-3", "Node3", "XPDR-NW1-RX"),
274             netTransServ, pceHardConstraints, null, rc, portMapping);
275         pceCalc.retrievePceNetwork();
276         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
277             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
278             rc, StringConstants.SERVICE_TYPE_OTUC3, netTransServ, PceConstraintMode.Loose);
279         assertEquals(pceGraph.calcPath(), true);
280         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.3351048800367167));
281     }
282
283     @Test
284     void clacUnfeasiblePath400GE() {
285         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(400), ServiceFormat.Ethernet,
286             "XPONDER-1", "Node1", "Client-1", "XPONDER-3", "Node3", "Client-1"),
287             netTransServ, pceHardConstraints, null, rc, portMapping);
288         pceCalc.retrievePceNetwork();
289         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
290             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
291             rc, StringConstants.SERVICE_TYPE_400GE, netTransServ, PceConstraintMode.Loose);
292         assertEquals(pceGraph.calcPath(), false);
293         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.0));
294     }
295
296     @Test
297     void clacPath400GE() {
298         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(400), ServiceFormat.Ethernet,
299             "XPONDER-1", "Node1", "Client-1", "XPONDER-5", "Node5", "Client-1"),
300             netTransServ, pceHardConstraints, null, rc, portMapping);
301         pceCalc.retrievePceNetwork();
302         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
303             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
304             rc, StringConstants.SERVICE_TYPE_400GE, netTransServ, PceConstraintMode.Loose);
305         assertEquals(pceGraph.calcPath(), true);
306         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.4432381874659086));
307     }
308
309     @Test
310     void clacPathOTUC4() {
311         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(400), ServiceFormat.Ethernet,
312             "XPONDER-1", "Node1", "XPDR-NW1-TX", "XPONDER-5", "Node5", "XPDR-NW1-RX"),
313             netTransServ, pceHardConstraints, null, rc, portMapping);
314         pceCalc.retrievePceNetwork();
315         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
316             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
317             rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ, PceConstraintMode.Loose);
318         assertEquals(pceGraph.calcPath(), true);
319         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(1.4432381874659086));
320     }
321
322     @Test
323     void clacOpticalTunnelOTUC4() {
324         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(400), ServiceFormat.OC,
325             "OpenROADM-1", "Node1", "DEG1-PP-TX", "OpenROADM-5", "Node5", "DEG3-PP-TX"),
326             netTransServ, pceHardConstraints, null, rc, portMapping);
327         pceCalc.retrievePceNetwork();
328         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
329             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
330             rc, StringConstants.SERVICE_TYPE_OTUC4, netTransServ, PceConstraintMode.Loose);
331         assertEquals(pceGraph.calcPath(), true);
332         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(0.0));
333     }
334
335     @Test
336     void clacPath100GEnoPort() {
337         PceCalculation pceCalc = new PceCalculation(getPCE2Request(Uint32.valueOf(100), ServiceFormat.Ethernet,
338             "XPONDER-1", "Node1", "Client-1", "XPONDER-3", "Node3", "Client-1"),
339             netTransServ, pceHardConstraints, null, rc, portMapping);
340         pceCalc.retrievePceNetwork();
341         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
342             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
343             rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose);
344         assertEquals(pceGraph.calcPath(), true);
345         assertEquals(Optional.ofNullable(pceGraph.getmargin()), Optional.ofNullable(3.0919881995992924));
346     }
347
348     @Test
349     void clacPathPropagationDelay() {
350         PceCalculation pceCalc = new PceCalculation(getPCE1Request(Uint32.valueOf(100), ServiceFormat.Ethernet,
351             "XPONDER-1", "Node1", "Client-1", "XPONDER-3", "Node3", "Client-1"),
352             netTransServ, pceHardConstraints, null, rc, portMapping);
353         pceCalc.retrievePceNetwork();
354         pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay);
355         pceGraph = new PceGraph(pceCalc.getaendPceNode(), pceCalc.getzendPceNode(),
356             pceCalc.getAllPceNodes(), pceCalc.getAllPceLinks(), pceHardConstraints,
357             rc, StringConstants.SERVICE_TYPE_100GE_T, netTransServ, PceConstraintMode.Loose);
358         pceGraph.setConstrains(pceHardConstraints);
359
360         assertEquals(pceGraph.calcPath(), true);
361         assertEquals(Optional.ofNullable(pceGraph.getPathAtoZ().get(2).getLatency()),
362             Optional.ofNullable(1.0));
363         assertEquals(pceGraph.getReturnStructure().getRate(), 100);
364     }
365
366     //FIXME: Review this test. Getting NPE is never normal!
367     @Test
368     void clacPath10GE2() {
369         assertThrows(NullPointerException.class, () -> {
370             getOtnPceGraph(StringConstants.SERVICE_TYPE_10GE);
371         });
372 //        assertEquals(pceGraph.calcPath(), false);
373     }
374
375     //FIXME: Review this test. Getting NPE is never normal!
376     @Test
377     void clacPath1GE() {
378         assertThrows(NullPointerException.class, () -> {
379             getOtnPceGraph(StringConstants.SERVICE_TYPE_1GE);
380         });
381 //        assertEquals(pceGraph.calcPath(), false);
382     }
383
384     private PceGraph getOtnPceGraph(String type) {
385         // Build Link
386         link1 = NodeUtils.createRoadmToRoadm("optical", "optical2", "DEG1-TTP-TX", "DEG1-TTP-RX").build();
387
388         node = NodeUtils.getOTNNodeBuilder(NodeUtils.geSupportingNodes(), OpenroadmTpType.XPONDERNETWORK).build();
389
390         PceOtnNode pceOtnNode = new PceOtnNode(node, OpenroadmNodeType.MUXPDR,
391             new NodeId("optical"), ServiceFormat.OTU.getName(), "serviceType", null);
392         pceOtnNode.validateXponder("optical", "sl");
393         pceOtnNode.validateXponder("not optical", "sl");
394         pceOtnNode.initXndrTps("AZ");
395         pceOtnNode.checkAvailableTribPort();
396         pceOtnNode.checkAvailableTribSlot();
397
398         PceOtnNode pceOtnNode2 = new PceOtnNode(node, OpenroadmNodeType.MUXPDR,
399             new NodeId("optical2"), ServiceFormat.OTU.getName(), "serviceType", null);
400         pceOtnNode2.validateXponder("optical", "sl");
401         pceOtnNode2.validateXponder("not optical", "sl");
402         pceOtnNode2.initXndrTps("AZ");
403         pceOtnNode2.initXndrTps("mode");
404         pceOtnNode2.checkAvailableTribPort();
405         pceOtnNode2.checkAvailableTribSlot();
406
407         pceLink1 = new PceLink(link1, pceOtnNode, pceOtnNode2);
408         pceLink1.setClientA("XPONDER-CLIENT");
409
410         pceLink1.getDestId();
411         pceOtnNode.addOutgoingLink(pceLink1);
412
413         // init PceHardContraints
414         pceHardConstraints = new PceConstraints();
415         // pceHardConstraints.setp
416         allPceNodes = Map.of(
417             new NodeId("optical"), pceOtnNode,
418             new NodeId("optical2"), pceOtnNode2);
419         return new PceGraph(pceOtnNode, pceOtnNode2, allPceNodes, allPceLinks, pceHardConstraints,
420                 new PceResult(), type, null, PceConstraintMode.Loose);
421     }
422
423     private void saveOpenRoadmNetwork(Network network, String networkId)
424             throws InterruptedException, ExecutionException {
425         InstanceIdentifier<Network> nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
426             .child(Network.class, new NetworkKey(new NetworkId(networkId))).build();
427         WriteTransaction dataWriteTransaction = dataBroker.newWriteOnlyTransaction();
428         dataWriteTransaction.put(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier, network);
429         dataWriteTransaction.commit().get();
430     }
431
432     public static Node createNetworkNode(String nodeId, OpenroadmNodeType nodeType) {
433         SupportingNode supportingNode = new SupportingNodeBuilder()
434             .setNetworkRef(new NetworkId(NetworkUtils.CLLI_NETWORK_ID))
435             .setNodeRef(new NodeId("node1"))
436             .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.CLLI_NETWORK_ID),
437                 new NodeId("node1")))
438             .build();
439         return new NodeBuilder()
440             .setNodeId(new NodeId(nodeId))
441             .withKey(new NodeKey(new NodeId(nodeId)))
442             .setSupportingNode(ImmutableMap.of(supportingNode.key(), supportingNode))
443             .addAugmentation(
444                 new Node1Builder().setOpenroadmVersion(OpenroadmVersionType._221).build())
445             .addAugmentation(
446                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1Builder()
447                     .setNodeType(nodeType).build())
448             .build();
449     }
450
451     public static TerminationPoint createNetworkTp(String nodeId, String tpId) {
452         var nwTpId = new TpId(tpId);
453         return new TerminationPointBuilder()
454             .setTpId(nwTpId)
455             .withKey(new TerminationPointKey(nwTpId))
456             .addAugmentation(new TerminationPoint1Builder()
457                 .setXpdrNetworkAttributes(new XpdrNetworkAttributesBuilder().setState(State.InService).build())
458                 .build())
459             .build();
460     }
461
462     public static Node createTopologyNode(String nodeId, OpenroadmNodeType nodeType) {
463         SupportingNode supportingNode = new SupportingNodeBuilder()
464             .setNetworkRef(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))
465             .setNodeRef(new NodeId("node1"))
466             .withKey(new SupportingNodeKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID),
467                 new NodeId("node1")))
468             .build();
469         return new NodeBuilder()
470             .setNodeId(new NodeId(nodeId))
471             .withKey(new NodeKey(new NodeId(nodeId)))
472             .setSupportingNode(ImmutableMap.of(supportingNode.key(), supportingNode))
473             .addAugmentation(
474                 new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev230526.Node1Builder()
475                     .setXpdrAttributes(null).build())
476             .addAugmentation(
477                 new org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1Builder()
478                     .setNodeType(nodeType).build())
479             .build();
480     }
481
482     public static PathComputationRequestInput getPCE1Request(Uint32 rate, ServiceFormat serviceFormat, String aaNodeId,
483             String aaClliId, String aaPortName, String zzNodeId, String zzClliId, String zzPortName) {
484         return new PathComputationRequestInputBuilder()
485             .setServiceName("service1")
486             .setResourceReserve(true)
487             .setPceRoutingMetric(PceMetric.HopCount)
488             .setServiceHandlerHeader(new ServiceHandlerHeaderBuilder()
489                 .setRequestId("request1")
490                 .build())
491             .setServiceAEnd(new ServiceAEndBuilder()
492                 .setServiceFormat(serviceFormat)
493                 .setServiceRate(Uint32.valueOf(100))
494                 .setClli(aaClliId)
495                 .setNodeId(aaNodeId)
496                 .setTxDirection(new TxDirectionBuilder()
497                     .setPort(new PortBuilder()
498                         .setPortDeviceName(aaNodeId)
499                         .setPortType("fixed")
500                         .setPortName(aaPortName)
501                         .setPortRack("Some port-rack")
502                         .setPortShelf("Some port-shelf")
503                         .setPortSlot("Some port-slot")
504                         .setPortSubSlot("Some port-sub-slot")
505                         .build())
506                     .build())
507                 .setRxDirection(new RxDirectionBuilder()
508                     .setPort(new PortBuilder()
509                         .setPortDeviceName(aaNodeId)
510                         .setPortType("fixed")
511                         .setPortName(aaPortName)
512                         .setPortRack("Some port-rack")
513                         .setPortShelf("Some port-shelf")
514                         .setPortSlot("Some port-slot")
515                         .setPortSubSlot("Some port-sub-slot")
516                         .build())
517                     .build())
518                 .build())
519             .setServiceZEnd(new ServiceZEndBuilder()
520                 .setServiceFormat(serviceFormat)
521                 .setServiceRate(Uint32.valueOf(0))
522                 .setClli(zzClliId)
523                 .setNodeId(zzNodeId)
524                 .setTxDirection(new TxDirectionBuilder()
525                     .setPort(new PortBuilder()
526                         .setPortDeviceName(zzNodeId)
527                         .setPortType("fixed")
528                         .setPortName(zzPortName)
529                         .setPortRack("Some port-rack")
530                         .setPortShelf("Some port-shelf")
531                         .setPortSlot("Some port-slot")
532                         .setPortSubSlot("Some port-sub-slot")
533                         .build())
534                     .build())
535                 .setRxDirection(new RxDirectionBuilder()
536                     .setPort(new PortBuilder()
537                         .setPortDeviceName(zzNodeId)
538                         .setPortType("fixed")
539                         .setPortName(zzPortName)
540                         .setPortRack("Some port-rack")
541                         .setPortShelf("Some port-shelf")
542                         .setPortSlot("Some port-slot")
543                         .setPortSubSlot("Some port-sub-slot")
544                         .build())
545                     .build())
546                 .build())
547             .setHardConstraints(new HardConstraintsBuilder()
548                 .setCustomerCode(Set.of("Some customer-code"))
549                 .setCoRouting(new CoRoutingBuilder()
550                     .setServiceIdentifierList(Map.of(
551                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
552                                 .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
553                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service").build()))
554                     .build())
555                 .build())
556             .setSoftConstraints(new SoftConstraintsBuilder()
557                 .setCustomerCode(Set.of("Some customer-code"))
558                 .setCoRouting(new CoRoutingBuilder()
559                     .setServiceIdentifierList(Map.of(
560                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
561                                 .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
562                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service").build()))
563                     .build())
564                 .build())
565             .build();
566     }
567
568     public static PathComputationRequestInput getPCE2Request(Uint32 rate, ServiceFormat serviceFormat, String aaNodeId,
569             String aaClliId, String aaPortName, String zzNodeId, String zzClliId, String zzPortName) {
570         return new PathComputationRequestInputBuilder()
571             .setServiceName("service1")
572             .setResourceReserve(true)
573             .setPceRoutingMetric(PceMetric.HopCount)
574             .setServiceHandlerHeader(new ServiceHandlerHeaderBuilder()
575                 .setRequestId("request1")
576                 .build())
577             .setServiceAEnd(new ServiceAEndBuilder()
578                 .setServiceFormat(serviceFormat)
579                 .setServiceRate(Uint32.valueOf(100))
580                 .setClli(aaClliId)
581                 .setNodeId(aaNodeId)
582                 .setTxDirection(new TxDirectionBuilder()
583                   .build())
584                 .setRxDirection(new RxDirectionBuilder()
585                     .build())
586                 .build())
587             .setServiceZEnd(new ServiceZEndBuilder()
588                 .setServiceFormat(serviceFormat)
589                 .setServiceRate(Uint32.valueOf(0))
590                 .setClli(zzClliId)
591                 .setNodeId(zzNodeId)
592                 .setTxDirection(new TxDirectionBuilder()
593                     .build())
594                 .setRxDirection(new RxDirectionBuilder()
595                     .build())
596                 .build())
597             .setHardConstraints(new HardConstraintsBuilder()
598                 .setCustomerCode(Set.of("Some customer-code"))
599                 .setCoRouting(new CoRoutingBuilder()
600                     .setServiceIdentifierList(Map.of(
601                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
602                                 .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
603                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service").build()))
604                     .build())
605                 .build())
606             .setSoftConstraints(new SoftConstraintsBuilder()
607                 .setCustomerCode(Set.of("Some customer-code"))
608                 .setCoRouting(new CoRoutingBuilder()
609                     .setServiceIdentifierList(Map.of(
610                         new org.opendaylight.yang.gen.v1.http.org.openroadm.routing.constraints.rev221209
611                                 .constraints.co.routing.ServiceIdentifierListKey("Some existing-service"),
612                         new ServiceIdentifierListBuilder().setServiceIdentifier("Some existing-service").build()))
613                     .build())
614                 .build())
615                     .build();
616     }
617 }