e11cb016d3f41cc3261bc70c831223ff61d7169b
[bgpcep.git] / pcep / topology / topology-provider / src / test / java / org / opendaylight / bgpcep / pcep / topology / provider / TopologyStatsRpcTest.java
1 /*
2  * Copyright (c) 2019 Lumina Networks, 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 package org.opendaylight.bgpcep.pcep.topology.provider;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.Mockito.doNothing;
14 import static org.mockito.Mockito.doReturn;
15
16 import java.util.List;
17 import java.util.Map;
18 import org.junit.After;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.mockito.Mock;
23 import org.mockito.junit.MockitoJUnitRunner;
24 import org.opendaylight.mdsal.binding.api.RpcProviderService;
25 import org.opendaylight.mdsal.binding.api.WriteTransaction;
26 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
27 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.PcepEntityIdRpcAugBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.PcepEntityIdStatsAugBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulCapabilitiesRpcAugBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulCapabilitiesStatsAugBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesRpcAug;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesRpcAugBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesStatsAug;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stateful.stats.rev181109.StatefulMessagesStatsAugBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.error.messages.grouping.ErrorMessages;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.error.messages.grouping.ErrorMessagesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.LocalPref;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.LocalPrefBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.Messages;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.MessagesBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.PeerCapabilities;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.PeerCapabilitiesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.PeerPrefBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionState;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.pcep.session.state.grouping.PcepSessionStateBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.reply.time.grouping.ReplyTime;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.stats.rev171113.reply.time.grouping.ReplyTimeBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsInput;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsInputBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsOutput;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.GetStatsOutputBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.stats.rev181109.PcepTopologyNodeStatsAugBuilder;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
63 import org.opendaylight.yangtools.concepts.Registration;
64 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
65 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
66 import org.opendaylight.yangtools.yang.common.RpcResult;
67 import org.opendaylight.yangtools.yang.common.Uint16;
68 import org.opendaylight.yangtools.yang.common.Uint32;
69 import org.opendaylight.yangtools.yang.common.Uint8;
70
71 @RunWith(MockitoJUnitRunner.StrictStubs.class)
72 public class TopologyStatsRpcTest extends AbstractConcurrentDataBrokerTest {
73     private static final String TOPOLOGY_ID1 = "pcep-topology-1";
74     private static final String TOPOLOGY_ID2 = "pcep-topology-2";
75     private static final String NONEXISTENT_TOPOLOGY = "nonexistent-topology";
76     private static final String NONPCEP_TOPOLOGY = "nonpcep-topology";
77     private static final String NODE_ID1 = "pcc://1.1.1.1";
78     private static final String NODE_ID2 = "pcc://2.2.2.2";
79     private static final String NODE_ID3 = "pcc://3.3.3.3";
80     private static final String NONEXISTENT_NODE = "pcc://4.4.4.4";
81     private static final String NONPCEP_NODE = "nonpcep-node";
82
83     @Mock
84     private RpcProviderService rpcProviderService;
85     @Mock
86     private Registration rpcReg;
87
88     TopologyStatsRpc rpcService;
89
90     @Before
91     public void setUp() throws Exception {
92         doReturn(rpcReg).when(rpcProviderService).registerRpcImplementations(any());
93         doNothing().when(rpcReg).close();
94         rpcService = new TopologyStatsRpc(getDataBroker(), rpcProviderService);
95
96         // PCEP topology with one PCC node
97         final Topology t1 = createTopology(TOPOLOGY_ID1, BindingMap.of(createPcepNode(NODE_ID1)));
98
99         // PCEP topology with two PCC node
100         final Topology t2 =
101                 createTopology(TOPOLOGY_ID2, BindingMap.of(createPcepNode(NODE_ID2), createPcepNode(NODE_ID3)));
102
103         // Non-PCEP topology with one non-PCC node
104         final Topology t3 = createTopology(NONPCEP_TOPOLOGY,
105                 BindingMap.of(new NodeBuilder().setNodeId(new NodeId(NONPCEP_NODE)).build()));
106
107         final WriteTransaction wtx = getDataBroker().newWriteOnlyTransaction();
108         final NetworkTopologyBuilder ntb = new NetworkTopologyBuilder();
109         ntb.setTopology(BindingMap.of(t1, t2, t3));
110         wtx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class).build(),
111                 ntb.build());
112         wtx.commit().get();
113     }
114
115     private static Topology createTopology(final String topologyId, final Map<NodeKey, Node> nodes) {
116         return new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).setNode(nodes).build();
117     }
118
119     private static Node createPcepNode(final String nodeId) {
120         return new NodeBuilder()
121                 .setNodeId(new NodeId(nodeId))
122                 .addAugmentation(new PcepTopologyNodeStatsAugBuilder()
123                     .setPcepSessionState(createTopologySessionState())
124                     .build())
125                 .build();
126     }
127
128     private static PcepSessionState createTopologySessionState() {
129         final ReplyTime replyTime = new ReplyTimeBuilder()
130                 .setAverageTime(Uint32.ONE)
131                 .setMaxTime(Uint32.valueOf(3))
132                 .setMinTime(Uint32.TWO)
133                 .build();
134
135         final ErrorMessages errorMsg = new ErrorMessagesBuilder()
136                 .setReceivedErrorMsgCount(Uint32.ONE)
137                 .setSentErrorMsgCount(Uint32.valueOf(2))
138                 .build();
139
140         final StatefulMessagesStatsAug statefulMsg = new StatefulMessagesStatsAugBuilder()
141                 .setLastReceivedRptMsgTimestamp(Uint32.valueOf(1553183614L))
142                 .setSentUpdMsgCount(Uint32.ONE)
143                 .setReceivedRptMsgCount(Uint32.TWO)
144                 .setSentInitMsgCount(Uint32.valueOf(3))
145                 .build();
146
147         final Messages messages = new MessagesBuilder()
148                 .setLastSentMsgTimestamp(Uint32.valueOf(1553183734L))
149                 .setUnknownMsgReceived(Uint16.ONE)
150                 .setSentMsgCount(Uint32.valueOf(5))
151                 .setReceivedMsgCount(Uint32.valueOf(4))
152                 .setReplyTime(replyTime)
153                 .setErrorMessages(errorMsg)
154                 .addAugmentation(statefulMsg).build();
155
156         final PeerCapabilities capabilities = new PeerCapabilitiesBuilder()
157                 .addAugmentation(new StatefulCapabilitiesStatsAugBuilder()
158                     .setStateful(true)
159                     .setInstantiation(true)
160                     .setActive(true)
161                     .build())
162                 .build();
163
164         final LocalPref localPref = new LocalPrefBuilder()
165                 .setKeepalive(Uint8.valueOf(30))
166                 .setDeadtimer(Uint8.valueOf(120))
167                 .setIpAddress("127.0.0.1")
168                 .setSessionId(Uint16.ZERO)
169                 .addAugmentation(new PcepEntityIdStatsAugBuilder()
170                     .setSpeakerEntityIdValue(new byte[] {0x01, 0x02, 0x03, 0x04})
171                     .build())
172                 .build();
173
174         return new PcepSessionStateBuilder().setSynchronized(true).setSessionDuration("0:00:05:18")
175                 .setDelegatedLspsCount(Uint16.ONE).setLocalPref(localPref)
176                 .setPeerPref(new PeerPrefBuilder(localPref).build())
177                 .setPeerCapabilities(capabilities).setMessages(messages).build();
178     }
179
180     private static PcepSessionState createRpcSessionState() {
181         final ReplyTime replyTime = new ReplyTimeBuilder()
182                 .setAverageTime(Uint32.ONE)
183                 .setMaxTime(Uint32.valueOf(3))
184                 .setMinTime(Uint32.TWO)
185                 .build();
186
187         final ErrorMessages errorMsg = new ErrorMessagesBuilder()
188                 .setReceivedErrorMsgCount(Uint32.ONE).setSentErrorMsgCount(Uint32.TWO).build();
189
190         final StatefulMessagesRpcAug statefulMsg = new StatefulMessagesRpcAugBuilder()
191                 .setLastReceivedRptMsgTimestamp(Uint32.valueOf(1553183614L))
192                 .setSentUpdMsgCount(Uint32.ONE)
193                 .setReceivedRptMsgCount(Uint32.TWO)
194                 .setSentInitMsgCount(Uint32.valueOf(3))
195                 .build();
196
197         final Messages messages = new MessagesBuilder()
198                 .setLastSentMsgTimestamp(Uint32.valueOf(1553183734L))
199                 .setUnknownMsgReceived(Uint16.ONE)
200                 .setSentMsgCount(Uint32.valueOf(5))
201                 .setReceivedMsgCount(Uint32.valueOf(4))
202                 .setReplyTime(replyTime)
203                 .setErrorMessages(errorMsg)
204                 .addAugmentation(statefulMsg).build();
205
206         final PeerCapabilities capabilities = new PeerCapabilitiesBuilder()
207                 .addAugmentation(new StatefulCapabilitiesRpcAugBuilder()
208                         .setStateful(true).setInstantiation(true).setActive(true).build())
209                 .build();
210
211         final LocalPref localPref = new LocalPrefBuilder()
212                 .setKeepalive(Uint8.valueOf(30))
213                 .setDeadtimer(Uint8.valueOf(120))
214                 .setIpAddress("127.0.0.1")
215                 .setSessionId(Uint16.ZERO)
216                 .addAugmentation(new PcepEntityIdRpcAugBuilder()
217                     .setSpeakerEntityIdValue(new byte[] {0x01, 0x02, 0x03, 0x04})
218                     .build())
219                 .build();
220
221         return new PcepSessionStateBuilder().setSynchronized(true).setSessionDuration("0:00:05:18")
222                 .setDelegatedLspsCount(Uint16.ONE).setLocalPref(localPref)
223                 .setPeerPref(new PeerPrefBuilder(localPref).build())
224                 .setPeerCapabilities(capabilities).setMessages(messages)
225                 .build();
226     }
227
228     @Test
229     public void testGetStatsNoMatch() throws Exception {
230         GetStatsInput in;
231         GetStatsOutput out;
232
233         // Non-existing topology
234         in = createGetStatsInput(NONEXISTENT_TOPOLOGY, null);
235         out = createGetStatsOutput(NONEXISTENT_TOPOLOGY, List.of(), null);
236         performTest(in, out);
237
238         // Non-existent node
239         in = createGetStatsInput(TOPOLOGY_ID1, List.of(NONEXISTENT_NODE));
240         out = createGetStatsOutput(TOPOLOGY_ID1, List.of(NONEXISTENT_NODE), null);
241         performTest(in, out);
242
243         // Non-PCEP topology
244         in = createGetStatsInput(NONPCEP_TOPOLOGY, List.of(NONPCEP_NODE));
245         out = createGetStatsOutput(NONPCEP_TOPOLOGY, List.of(NONPCEP_NODE), null);
246         performTest(in, out);
247     }
248
249     @Test
250     public void testGetStatsPartialMatch() throws Exception {
251         GetStatsInput in;
252         GetStatsOutput out;
253
254         // Match one PCEP topology
255         in = createGetStatsInput(TOPOLOGY_ID1, null);
256         out = createGetStatsOutput(TOPOLOGY_ID1, List.of(NODE_ID1), createRpcSessionState());
257         performTest(in, out);
258
259         // Match one PCEP node in one topology
260         in = createGetStatsInput(TOPOLOGY_ID2, List.of(NODE_ID3));
261         out = createGetStatsOutput(TOPOLOGY_ID2, List.of(NODE_ID3), createRpcSessionState());
262         performTest(in, out);
263
264         // Match two PCEP nodes in one topology
265         in = createGetStatsInput(TOPOLOGY_ID2, List.of(NODE_ID2, NODE_ID3));
266         out = createGetStatsOutput(TOPOLOGY_ID2, List.of(NODE_ID2, NODE_ID3), createRpcSessionState());
267         performCountTest(in, out);
268     }
269
270     @Test
271     public void testGetStatsAllMatch() throws Exception {
272         GetStatsInput in;
273
274         final var ot1 = createGetStatsOutput(TOPOLOGY_ID1, List.of(NODE_ID1), createRpcSessionState())
275                 .getTopology().values() .iterator().next();
276         final var ot2 = createGetStatsOutput(TOPOLOGY_ID2, List.of(NODE_ID2, NODE_ID3), createRpcSessionState())
277                 .getTopology().values().iterator().next();
278         final GetStatsOutput out = new GetStatsOutputBuilder().setTopology(BindingMap.of(ot1, ot2)).build();
279
280         // Implicitly match all PCEP topologies and nodes
281         in = createGetStatsInput(null, null);
282         performCountTest(in, out);
283
284         // Explicitly match all PCEP topologies and nodes
285         final var it1 = createGetStatsInput(TOPOLOGY_ID1, List.of(NODE_ID1)).getTopology().values()
286                 .iterator().next();
287         final var it2 = createGetStatsInput(TOPOLOGY_ID2, List.of(NODE_ID2, NODE_ID3)).getTopology().values()
288                 .iterator().next();
289         in = new GetStatsInputBuilder().setTopology(BindingMap.of(it1, it2)).build();
290         performCountTest(in, out);
291     }
292
293     private void performTest(final GetStatsInput in, final GetStatsOutput out) throws Exception {
294         final RpcResult<GetStatsOutput> result = rpcService.getStats(in).get();
295         assertEquals(out, result.getResult());
296         assertTrue(result.isSuccessful());
297         assertTrue(result.getErrors().isEmpty());
298     }
299
300     /*
301      * When topology and/or node list is expected to contain more than one item,
302      * direct comparison will fail due to potential list ordering differences. So
303      * just compare the number of nodes
304      */
305     private void performCountTest(final GetStatsInput in, final GetStatsOutput out) throws Exception {
306         final RpcResult<GetStatsOutput> result = rpcService.getStats(in).get();
307         assertEquals(result.getResult().getTopology().size(), out.getTopology().size());
308         assertTrue(result.isSuccessful());
309         assertEquals(result.getResult().nonnullTopology().values().stream()
310             .flatMap(t -> t.nonnullNode().values().stream()).count(),
311             out.nonnullTopology().values().stream().flatMap(t -> t.nonnullNode().values().stream()).count());
312         assertTrue(result.isSuccessful());
313         assertTrue(result.getErrors().isEmpty());
314     }
315
316     private static GetStatsInput createGetStatsInput(final String topologyId, final List<String> nodeIds) {
317         final Map<
318             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321
319                 .get.stats.input.topology.NodeKey,
320             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321
321                 .get.stats.input.topology.Node> nodes;
322         if (nodeIds != null) {
323             nodes = nodeIds.stream()
324                     .map(nodeId -> new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology
325                         .stats.rpc.rev190321.get.stats.input.topology.NodeBuilder()
326                             .setNodeId(new NodeId(nodeId))
327                             .build())
328                 .collect(BindingMap.toOrderedMap());
329         } else {
330             nodes = null;
331         }
332         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.get
333             .stats.input.Topology topology;
334         if (topologyId != null) {
335             topology = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc
336                     .rev190321.get.stats.input.TopologyBuilder()
337                         .setTopologyId(new TopologyId(topologyId))
338                         .setNode(nodes)
339                         .build();
340         } else {
341             topology = null;
342         }
343         return new GetStatsInputBuilder().setTopology(topology != null ? BindingMap.of(topology) : null).build();
344     }
345
346     private static GetStatsOutput createGetStatsOutput(final String topologyId, final List<String> nodeIds,
347             final PcepSessionState state) {
348         final Map<
349             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321
350                 .get.stats.output.topology.NodeKey,
351             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321
352                     .get.stats.output.topology.Node> nodes;
353         if (nodeIds != null) {
354             nodes = nodeIds.stream()
355                     .map(nodeId -> new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology
356                         .stats.rpc.rev190321.get.stats.output.topology.NodeBuilder()
357                             .setNodeId(new NodeId(nodeId))
358                             .setPcepSessionState(state)
359                             .build())
360                 .collect(BindingMap.toOrderedMap());
361         } else {
362             nodes = null;
363         }
364         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc.rev190321.get
365             .stats.output.Topology topology;
366         if (topologyId != null) {
367             topology = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.topology.stats.rpc
368                     .rev190321.get.stats.output.TopologyBuilder()
369                             .setTopologyId(new TopologyId(topologyId))
370                             .setNode(nodes)
371                             .build();
372         } else {
373             topology = null;
374         }
375         return new GetStatsOutputBuilder().setTopology(topology != null ? BindingMap.of(topology) : null).build();
376     }
377
378     @After
379     public void tearDown() {
380         rpcService.close();
381     }
382 }