61e8dc97821d3820441003a6a7f2aa0c17b5ba05
[transportpce.git] / servicehandler / src / test / java / org / opendaylight / transportpce / servicehandler / listeners / ServiceListenerTest.java
1 /*
2  * Copyright © 2021 Orange.  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.servicehandler.listeners;
10
11 import static org.junit.jupiter.api.Assertions.fail;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.anyString;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.never;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
19
20 import java.util.Collection;
21 import java.util.HashSet;
22 import java.util.Map;
23 import java.util.Optional;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.api.extension.ExtendWith;
26 import org.mockito.Mock;
27 import org.mockito.junit.jupiter.MockitoExtension;
28 import org.opendaylight.mdsal.binding.api.DataObjectModification;
29 import org.opendaylight.mdsal.binding.api.DataTreeModification;
30 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
31 import org.opendaylight.transportpce.common.ResponseCodes;
32 import org.opendaylight.transportpce.pce.service.PathComputationService;
33 import org.opendaylight.transportpce.servicehandler.impl.ServicehandlerImpl;
34 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.node.types.rev210528.NodeIdType;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.ConnectionType;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.Restorable;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.configuration.response.common.ConfigurationResponseCommonBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.sdnc.request.header.SdncRequestHeaderBuilder;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.ServiceAEndBuilder;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.ServiceZEndBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirection;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirectionBuilder;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirectionKey;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirection;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirectionBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirectionKey;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.lgx.LgxBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.PortBuilder;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.resiliency.ServiceResiliency;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.resiliency.ServiceResiliencyBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceCreateOutputBuilder;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceDeleteOutputBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRerouteOutputBuilder;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesBuilder;
60 import org.opendaylight.yang.gen.v1.nbi.notifications.rev230726.PublishNotificationAlarmService;
61 import org.opendaylight.yang.gen.v1.nbi.notifications.rev230726.PublishNotificationAlarmServiceBuilder;
62 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
63 import org.opendaylight.yangtools.yang.common.Uint32;
64 import org.opendaylight.yangtools.yang.common.Uint8;
65
66 @ExtendWith(MockitoExtension.class)
67 public class ServiceListenerTest {
68
69     @Mock
70     private ServicehandlerImpl servicehandler;
71     @Mock
72     private ServiceDataStoreOperations serviceDataStoreOperations;
73     @Mock
74     private NotificationPublishService notificationPublishService;
75     @Mock
76     private PathComputationService pathComputationService;
77
78     @Test
79     void testOnDataTreeChangedWhenDeleteService() {
80         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
81                 mock(DataObjectModification.class);
82         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
83         @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
84         changes.add(ch);
85         when(ch.getRootNode()).thenReturn(service);
86
87         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
88         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
89         ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
90                 notificationPublishService);
91         listener.onDataTreeChanged(changes);
92         verify(ch, times(1)).getRootNode();
93         verify(service, times(1)).getModificationType();
94         verify(service, times(2)).getDataBefore();
95         verify(service, never()).getDataAfter();
96         try {
97             verify(notificationPublishService, never()).putNotification(any(PublishNotificationAlarmService.class));
98         } catch (InterruptedException e) {
99             fail("Failed publishing notification");
100         }
101     }
102
103     @Test
104     void testOnDataTreeChangedWhenServiceBecomesOutOfService() {
105         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
106                 mock(DataObjectModification.class);
107         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
108         @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
109         changes.add(ch);
110         when(ch.getRootNode()).thenReturn(service);
111
112         Services serviceDown = buildService(State.OutOfService, AdminStates.InService);
113         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
114         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
115         when(service.getDataAfter()).thenReturn(serviceDown);
116         ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
117                 notificationPublishService);
118         listener.onDataTreeChanged(changes);
119         verify(ch, times(1)).getRootNode();
120         verify(service, times(1)).getModificationType();
121         verify(service, times(3)).getDataBefore();
122         verify(service, times(1)).getDataAfter();
123         try {
124             verify(notificationPublishService, times(1))
125                     .putNotification(buildNotificationAlarmService(serviceDown, "The service is now outOfService"));
126         } catch (InterruptedException e) {
127             fail("Failed publishing notification");
128         }
129     }
130
131     @Test
132     void testOnDataTreeChangedWhenShouldNeverHappen() {
133         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
134                 mock(DataObjectModification.class);
135         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
136         @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
137         changes.add(ch);
138         when(ch.getRootNode()).thenReturn(service);
139
140         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
141         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
142         ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
143                 notificationPublishService);
144         listener.onDataTreeChanged(changes);
145         verify(ch, times(1)).getRootNode();
146         verify(service, times(2)).getModificationType();
147         verify(service, times(2)).getDataBefore();
148         verify(service, never()).getDataAfter();
149         try {
150             verify(notificationPublishService, never()).putNotification(any(PublishNotificationAlarmService.class));
151         } catch (InterruptedException e) {
152             fail("Failed publishing notification");
153         }
154     }
155
156     @Test
157     void testOnDataTreeChangedWhenServiceDegradedShouldBeRerouted() {
158         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
159                 mock(DataObjectModification.class);
160         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
161         @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
162         changes.add(ch);
163         when(ch.getRootNode()).thenReturn(service);
164
165         ServiceResiliency serviceResiliency = new ServiceResiliencyBuilder().setResiliency(Restorable.VALUE).build();
166         Services serviceAfter = new ServicesBuilder(buildService(State.OutOfService, AdminStates.InService))
167                 .setServiceResiliency(serviceResiliency)
168                 .build();
169         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
170         when(service.getDataBefore())
171             .thenReturn(new ServicesBuilder(buildService(State.InService, AdminStates.InService))
172                         .setServiceResiliency(serviceResiliency)
173                         .build());
174         when(service.getDataAfter()).thenReturn(serviceAfter);
175         when(serviceDataStoreOperations.getService(anyString())).thenReturn(Optional.of(serviceAfter));
176         when(servicehandler.serviceDelete(any()))
177             .thenReturn(RpcResultBuilder.success(new ServiceDeleteOutputBuilder()
178                                 .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
179                                                 .setResponseCode(ResponseCodes.RESPONSE_OK)
180                                                 .build())
181                                 .build())
182                         .buildFuture());
183         when(servicehandler.serviceReroute(any()))
184             .thenReturn(RpcResultBuilder.success(new ServiceRerouteOutputBuilder()
185                                 .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
186                                                 .setResponseCode(ResponseCodes.RESPONSE_OK)
187                                                 .build())
188                                 .build())
189                         .buildFuture());
190         when(servicehandler.serviceCreate(any()))
191             .thenReturn(RpcResultBuilder.success(new ServiceCreateOutputBuilder()
192                                 .setConfigurationResponseCommon(new ConfigurationResponseCommonBuilder()
193                                                 .setResponseCode(ResponseCodes.RESPONSE_OK)
194                                                 .build())
195                                 .build())
196                         .buildFuture());
197         ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
198                 notificationPublishService);
199         listener.onDataTreeChanged(changes);
200         verify(ch, times(1)).getRootNode();
201         verify(service, times(1)).getModificationType();
202         verify(service, times(3)).getDataBefore();
203         verify(service, times(1)).getDataAfter();
204         verify(servicehandler, times(1)).serviceDelete(any());
205
206         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
207         listener.onDataTreeChanged(changes);
208         verify(servicehandler, times(1)).serviceCreate(any());
209     }
210
211     @Test
212     void testOnDataTreeChangedWhenServiceDegradedShouldNotBeRerouted() {
213         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
214                 mock(DataObjectModification.class);
215         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
216         @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
217         changes.add(ch);
218         when(ch.getRootNode()).thenReturn(service);
219
220         Services serviceAfter = buildService(State.OutOfService, AdminStates.InService);
221         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
222         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
223         when(service.getDataAfter()).thenReturn(serviceAfter);
224         ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
225                 notificationPublishService);
226         listener.onDataTreeChanged(changes);
227         verify(ch, times(1)).getRootNode();
228         verify(service, times(1)).getModificationType();
229         verify(service, times(3)).getDataBefore();
230         verify(service, times(1)).getDataAfter();
231         verify(servicehandler, times(0)).serviceDelete(any());
232
233         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
234         listener.onDataTreeChanged(changes);
235         verify(servicehandler, times(0)).serviceCreate(any());
236     }
237
238     private Services buildService(State state, AdminStates adminStates) {
239         return new ServicesBuilder()
240                 .setSdncRequestHeader(new SdncRequestHeaderBuilder().build())
241                 .setCommonId("commonId")
242                 .setConnectionType(ConnectionType.Service)
243                 .setCustomer("Customer")
244                 .setServiceName("service 1")
245                 .setServiceAEnd(getServiceAEndBuild().build())
246                 .setServiceZEnd(new ServiceZEndBuilder()
247                         .setClli("clli")
248                         .setServiceFormat(ServiceFormat.Ethernet)
249                         .setServiceRate(Uint32.valueOf(1))
250                         .setNodeId(new NodeIdType("XPONDER-3-2"))
251                         .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
252                         .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()))
253                         .build())
254                 .setOperationalState(state)
255                 .setAdministrativeState(adminStates)
256                 .build();
257     }
258
259     private ServiceAEndBuilder getServiceAEndBuild() {
260         return new ServiceAEndBuilder()
261                 .setClli("clli")
262                 .setServiceFormat(ServiceFormat.Ethernet)
263                 .setServiceRate(Uint32.valueOf(1))
264                 .setNodeId(new NodeIdType("XPONDER-1-2"))
265                 .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
266                 .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()));
267     }
268
269     private TxDirection getTxDirection() {
270         return new TxDirectionBuilder()
271                 .setPort(new PortBuilder()
272                         .setPortDeviceName("device name")
273                         .setPortName("port name")
274                         .setPortRack("port rack")
275                         .setPortShelf("port shelf")
276                         .setPortSlot("port slot")
277                         .setPortSubSlot("port subslot")
278                         .setPortType("port type")
279                         .build())
280                 .setLgx(new LgxBuilder()
281                         .setLgxDeviceName("lgx device name")
282                         .setLgxPortName("lgx port name")
283                         .setLgxPortRack("lgx port rack")
284                         .setLgxPortShelf("lgx port shelf")
285                         .build())
286                 .setIndex(Uint8.ZERO)
287                 .build();
288     }
289
290     private RxDirection getRxDirection() {
291         return new RxDirectionBuilder()
292                 .setPort(new PortBuilder()
293                         .setPortDeviceName("device name")
294                         .setPortName("port name")
295                         .setPortRack("port rack")
296                         .setPortShelf("port shelf")
297                         .setPortSlot("port slot")
298                         .setPortSubSlot("port subslot")
299                         .setPortType("port type")
300                         .build())
301                 .setLgx(new LgxBuilder()
302                         .setLgxDeviceName("lgx device name")
303                         .setLgxPortName("lgx port name")
304                         .setLgxPortRack("lgx port rack")
305                         .setLgxPortShelf("lgx port shelf")
306                         .build())
307                 .setIndex(Uint8.ZERO)
308                 .build();
309     }
310
311     private PublishNotificationAlarmService buildNotificationAlarmService(Services services, String message) {
312         return new PublishNotificationAlarmServiceBuilder()
313                 .setServiceName("service 1")
314                 .setConnectionType(ConnectionType.Service)
315                 .setMessage(message)
316                 .setOperationalState(services.getOperationalState())
317                 .setPublisherName("ServiceListener")
318                 .build();
319     }
320 }