Add tests for autonomous service rerouting
[transportpce.git] / servicehandler / src / test / java / org / opendaylight / transportpce / servicehandler / listeners / ServiceListenerTest.java
index a18f8da39a6beed57664d7ed06224e532ed4059d..368009f6daf1538c5ad81bc294b32124431dc5f1 100755 (executable)
@@ -10,6 +10,7 @@ package org.opendaylight.transportpce.servicehandler.listeners;
 
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -19,6 +20,7 @@ import static org.mockito.Mockito.when;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Optional;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -26,10 +28,14 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.transportpce.common.ResponseCodes;
 import org.opendaylight.transportpce.servicehandler.impl.ServicehandlerImpl;
 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.node.types.rev210528.NodeIdType;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.ConnectionType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.Restorable;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.configuration.response.common.ConfigurationResponseCommonBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.sdnc.request.header.SdncRequestHeaderBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEnd;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEndBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceZEnd;
@@ -42,17 +48,22 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev2
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.endpoint.TxDirectionKey;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.lgx.LgxBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.port.PortBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.ServiceResiliency;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.resiliency.ServiceResiliencyBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev191129.ServiceFormat;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceCreateOutputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.ServiceDeleteOutputBuilder;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.list.Services;
 import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev211210.service.list.ServicesBuilder;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev210813.PublishNotificationAlarmService;
 import org.opendaylight.yang.gen.v1.nbi.notifications.rev210813.PublishNotificationAlarmServiceBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.Uint32;
 import org.opendaylight.yangtools.yang.common.Uint8;
 
-@RunWith(MockitoJUnitRunner.StrictStubs.class)
+@RunWith(MockitoJUnitRunner.class)
 public class ServiceListenerTest {
 
     @Mock
@@ -88,7 +99,7 @@ public class ServiceListenerTest {
     }
 
     @Test
-    public void testOnDataTreeChangedWhenAddService() {
+    public void testOnDataTreeChangedWhenServiceBecomesOutOfService() {
         @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
                 mock(DataObjectModification.class);
         final Collection<DataTreeModification<Services>> changes = new HashSet<>();
@@ -96,7 +107,7 @@ public class ServiceListenerTest {
         changes.add(ch);
         when(ch.getRootNode()).thenReturn(service);
 
-        Services serviceDown = buildService(State.OutOfService, AdminStates.OutOfService);
+        Services serviceDown = buildService(State.OutOfService, AdminStates.InService);
         when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
         when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
         when(service.getDataAfter()).thenReturn(serviceDown);
@@ -107,11 +118,9 @@ public class ServiceListenerTest {
         verify(service, times(1)).getModificationType();
         verify(service, times(3)).getDataBefore();
         verify(service, times(1)).getDataAfter();
-        PublishNotificationAlarmService publishNotificationAlarmService =
-                buildNotificationAlarmService(serviceDown, "The service is now outOfService");
         try {
             verify(notificationPublishService, times(1))
-                    .putNotification(publishNotificationAlarmService);
+                    .putNotification(buildNotificationAlarmService(serviceDown, "The service is now outOfService"));
         } catch (InterruptedException e) {
             fail("Failed publishing notification");
         }
@@ -142,17 +151,97 @@ public class ServiceListenerTest {
         }
     }
 
+    @Test
+    public void testOnDataTreeChangedWhenServiceDegradedShouldBeRerouted() {
+        @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
+                mock(DataObjectModification.class);
+        final Collection<DataTreeModification<Services>> changes = new HashSet<>();
+        @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
+        changes.add(ch);
+        when(ch.getRootNode()).thenReturn(service);
+
+        ServiceResiliency serviceResiliency = new ServiceResiliencyBuilder().setResiliency(Restorable.class).build();
+        Services serviceAfter = new ServicesBuilder(buildService(State.OutOfService, AdminStates.InService))
+                .setServiceResiliency(serviceResiliency)
+                .build();
+        when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+        when(service.getDataBefore()).thenReturn(
+                new ServicesBuilder(buildService(State.InService, AdminStates.InService))
+                        .setServiceResiliency(serviceResiliency)
+                        .build());
+        when(service.getDataAfter()).thenReturn(serviceAfter);
+        when(serviceDataStoreOperations.getService(anyString())).thenReturn(Optional.of(serviceAfter));
+        when(servicehandler.serviceDelete(any())).thenReturn(
+                RpcResultBuilder.success(
+                        new ServiceDeleteOutputBuilder()
+                                .setConfigurationResponseCommon(
+                                        new ConfigurationResponseCommonBuilder()
+                                                .setResponseCode(ResponseCodes.RESPONSE_OK)
+                                                .build())
+                                .build())
+                        .buildFuture());
+        when(servicehandler.serviceCreate(any())).thenReturn(
+                RpcResultBuilder.success(
+                        new ServiceCreateOutputBuilder()
+                                .setConfigurationResponseCommon(
+                                        new ConfigurationResponseCommonBuilder()
+                                                .setResponseCode(ResponseCodes.RESPONSE_OK)
+                                                .build())
+                                .build())
+                        .buildFuture());
+        ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                notificationPublishService);
+        listener.onDataTreeChanged(changes);
+        verify(ch, times(1)).getRootNode();
+        verify(service, times(1)).getModificationType();
+        verify(service, times(3)).getDataBefore();
+        verify(service, times(1)).getDataAfter();
+        verify(servicehandler, times(1)).serviceDelete(any());
+
+        when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+        listener.onDataTreeChanged(changes);
+        verify(servicehandler, times(1)).serviceCreate(any());
+    }
+
+    @Test
+    public void testOnDataTreeChangedWhenServiceDegradedShouldNotBeRerouted() {
+        @SuppressWarnings("unchecked") final DataObjectModification<Services> service =
+                mock(DataObjectModification.class);
+        final Collection<DataTreeModification<Services>> changes = new HashSet<>();
+        @SuppressWarnings("unchecked") final DataTreeModification<Services> ch = mock(DataTreeModification.class);
+        changes.add(ch);
+        when(ch.getRootNode()).thenReturn(service);
+
+        Services serviceAfter = buildService(State.OutOfService, AdminStates.InService);
+        when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
+        when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
+        when(service.getDataAfter()).thenReturn(serviceAfter);
+        ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+                notificationPublishService);
+        listener.onDataTreeChanged(changes);
+        verify(ch, times(1)).getRootNode();
+        verify(service, times(1)).getModificationType();
+        verify(service, times(3)).getDataBefore();
+        verify(service, times(1)).getDataAfter();
+        verify(servicehandler, times(0)).serviceDelete(any());
+
+        when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+        listener.onDataTreeChanged(changes);
+        verify(servicehandler, times(0)).serviceCreate(any());
+    }
+
     private Services buildService(State state, AdminStates adminStates) {
         ServiceAEnd serviceAEnd = getServiceAEndBuild().build();
         ServiceZEnd serviceZEnd = new ServiceZEndBuilder()
                 .setClli("clli")
-                .setServiceFormat(ServiceFormat.OC)
+                .setServiceFormat(ServiceFormat.Ethernet)
                 .setServiceRate(Uint32.valueOf(1))
                 .setNodeId(new NodeIdType("XPONDER-3-2"))
                 .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
                 .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()))
                 .build();
         ServicesBuilder builtInput = new ServicesBuilder()
+                .setSdncRequestHeader(new SdncRequestHeaderBuilder().build())
                 .setCommonId("commonId")
                 .setConnectionType(ConnectionType.Service)
                 .setCustomer("Customer")
@@ -168,7 +257,7 @@ public class ServiceListenerTest {
     private ServiceAEndBuilder getServiceAEndBuild() {
         return new ServiceAEndBuilder()
                 .setClli("clli")
-                .setServiceFormat(ServiceFormat.OC)
+                .setServiceFormat(ServiceFormat.Ethernet)
                 .setServiceRate(Uint32.valueOf(1))
                 .setNodeId(new NodeIdType("XPONDER-1-2"))
                 .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))