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