package org.opendaylight.transportpce.servicehandler.listeners;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.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;
import java.util.Collection;
import java.util.HashSet;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.mdsal.binding.api.DataObjectModification;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
import org.opendaylight.mdsal.binding.api.NotificationPublishService;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.node.types.rev181130.NodeIdType;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.ConnectionType;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.endpoint.RxDirection;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.endpoint.TxDirection;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.lgx.LgxBuilder;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.port.PortBuilder;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev181130.State;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev181130.AdminStates;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.service.format.rev190531.ServiceFormat;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.Services;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev190531.service.list.ServicesBuilder;
-import org.opendaylight.yang.gen.v1.nbi.notifications.rev210628.PublishNotificationAlarmService;
-import org.opendaylight.yang.gen.v1.nbi.notifications.rev210628.PublishNotificationAlarmServiceBuilder;
+import org.opendaylight.transportpce.common.ResponseCodes;
+import org.opendaylight.transportpce.pce.service.PathComputationService;
+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.rev230526.ConnectionType;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.Restorable;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.configuration.response.common.ConfigurationResponseCommonBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.sdnc.request.header.SdncRequestHeaderBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.ServiceAEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.ServiceZEndBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirection;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirectionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.RxDirectionKey;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirection;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirectionBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.endpoint.TxDirectionKey;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.lgx.LgxBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.port.PortBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.service.resiliency.ServiceResiliency;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev230526.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.rev230526.ServiceCreateOutputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceDeleteOutputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.ServiceRerouteOutputBuilder;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.Services;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev230526.service.list.ServicesBuilder;
+import org.opendaylight.yang.gen.v1.nbi.notifications.rev211013.PublishNotificationAlarmService;
+import org.opendaylight.yang.gen.v1.nbi.notifications.rev211013.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)
+@ExtendWith(MockitoExtension.class)
public class ServiceListenerTest {
@Mock
- private DataBroker dataBroker;
+ private ServicehandlerImpl servicehandler;
+ @Mock
+ private ServiceDataStoreOperations serviceDataStoreOperations;
@Mock
private NotificationPublishService notificationPublishService;
+ @Mock
+ private PathComputationService pathComputationService;
@Test
- public void testOnDataTreeChangedWhenDeleteService() {
+ void testOnDataTreeChangedWhenDeleteService() {
@SuppressWarnings("unchecked") final DataObjectModification<Services> service =
mock(DataObjectModification.class);
final Collection<DataTreeModification<Services>> changes = new HashSet<>();
when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
- ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+ ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+ notificationPublishService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(1)).getModificationType();
}
@Test
- public void testOnDataTreeChangedWhenAddService() {
+ void testOnDataTreeChangedWhenServiceBecomesOutOfService() {
@SuppressWarnings("unchecked") final DataObjectModification<Services> service =
mock(DataObjectModification.class);
final Collection<DataTreeModification<Services>> changes = new HashSet<>();
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);
- ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+ 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(2)).getDataAfter();
- PublishNotificationAlarmService publishNotificationAlarmService =
- buildNotificationAlarmService(serviceDown, "The service is now outOfService");
+ verify(service, times(1)).getDataAfter();
try {
verify(notificationPublishService, times(1))
- .putNotification(publishNotificationAlarmService);
+ .putNotification(buildNotificationAlarmService(serviceDown, "The service is now outOfService"));
} catch (InterruptedException e) {
fail("Failed publishing notification");
}
}
@Test
- public void testOnDataTreeChangedWhenShouldNeverHappen() {
+ void testOnDataTreeChangedWhenShouldNeverHappen() {
@SuppressWarnings("unchecked") final DataObjectModification<Services> service =
mock(DataObjectModification.class);
final Collection<DataTreeModification<Services>> changes = new HashSet<>();
when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
when(service.getDataBefore()).thenReturn(buildService(State.InService, AdminStates.InService));
- ServiceListener listener = new ServiceListener(dataBroker, notificationPublishService);
+ ServiceListener listener = new ServiceListener(servicehandler, serviceDataStoreOperations,
+ notificationPublishService);
listener.onDataTreeChanged(changes);
verify(ch, times(1)).getRootNode();
verify(service, times(2)).getModificationType();
}
}
- private Services buildService(State state, AdminStates adminStates) {
- org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceAEnd
- serviceAEnd = getServiceAEndBuild()
- .build();
- org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service
- .ServiceZEnd serviceZEnd = new org.opendaylight.yang.gen.v1
- .http.org.openroadm.common.service.types.rev190531.service.ServiceZEndBuilder()
- .setClli("clli").setServiceFormat(ServiceFormat.OC).setServiceRate(Uint32.valueOf(1))
- .setNodeId(new NodeIdType("XPONDER-3-2"))
- .setTxDirection(getTxDirection())
- .setRxDirection(getRxDirection())
+ @Test
+ 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.VALUE).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.serviceReroute(any()))
+ .thenReturn(RpcResultBuilder.success(new ServiceRerouteOutputBuilder()
+ .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());
- ServicesBuilder builtInput = new ServicesBuilder()
+ when(service.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
+ listener.onDataTreeChanged(changes);
+ verify(servicehandler, times(1)).serviceCreate(any());
+ }
+
+ @Test
+ 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) {
+ return new ServicesBuilder()
+ .setSdncRequestHeader(new SdncRequestHeaderBuilder().build())
.setCommonId("commonId")
.setConnectionType(ConnectionType.Service)
.setCustomer("Customer")
.setServiceName("service 1")
- .setServiceAEnd(serviceAEnd)
- .setServiceZEnd(serviceZEnd)
+ .setServiceAEnd(getServiceAEndBuild().build())
+ .setServiceZEnd(new ServiceZEndBuilder()
+ .setClli("clli")
+ .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())
.setOperationalState(state)
- .setAdministrativeState(adminStates);
-
- return builtInput.build();
+ .setAdministrativeState(adminStates)
+ .build();
}
- private org.opendaylight.yang.gen.v1
- .http.org.openroadm.common.service.types.rev190531.service.ServiceAEndBuilder getServiceAEndBuild() {
- return new org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service
- .ServiceAEndBuilder()
- .setClli("clli").setServiceFormat(ServiceFormat.OC).setServiceRate(Uint32.valueOf(1))
+ private ServiceAEndBuilder getServiceAEndBuild() {
+ return new ServiceAEndBuilder()
+ .setClli("clli")
+ .setServiceFormat(ServiceFormat.Ethernet)
+ .setServiceRate(Uint32.valueOf(1))
.setNodeId(new NodeIdType("XPONDER-1-2"))
- .setTxDirection(getTxDirection())
- .setRxDirection(getRxDirection());
+ .setTxDirection(Map.of(new TxDirectionKey(getTxDirection().key()), getTxDirection()))
+ .setRxDirection(Map.of(new RxDirectionKey(getRxDirection().key()), getRxDirection()));
}
private TxDirection getTxDirection() {
- return new org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service
- .endpoint.TxDirectionBuilder().setPort(new PortBuilder().setPortDeviceName("device name")
- .setPortName("port name").setPortRack("port rack").setPortShelf("port shelf")
- .setPortSlot("port slot").setPortSubSlot("port subslot").setPortType("port type").build())
- .setLgx(new LgxBuilder().setLgxDeviceName("lgx device name").setLgxPortName("lgx port name")
- .setLgxPortRack("lgx port rack").setLgxPortShelf("lgx port shelf").build())
+ return new TxDirectionBuilder()
+ .setPort(new PortBuilder()
+ .setPortDeviceName("device name")
+ .setPortName("port name")
+ .setPortRack("port rack")
+ .setPortShelf("port shelf")
+ .setPortSlot("port slot")
+ .setPortSubSlot("port subslot")
+ .setPortType("port type")
+ .build())
+ .setLgx(new LgxBuilder()
+ .setLgxDeviceName("lgx device name")
+ .setLgxPortName("lgx port name")
+ .setLgxPortRack("lgx port rack")
+ .setLgxPortShelf("lgx port shelf")
+ .build())
+ .setIndex(Uint8.ZERO)
.build();
}
private RxDirection getRxDirection() {
- return new org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service
- .endpoint.RxDirectionBuilder()
- .setPort(new PortBuilder().setPortDeviceName("device name").setPortName("port name")
- .setPortRack("port rack").setPortShelf("port shelf").setPortSlot("port slot")
- .setPortSubSlot("port subslot").setPortType("port type").build())
- .setLgx(new LgxBuilder().setLgxDeviceName("lgx device name")
- .setLgxPortName("lgx port name").setLgxPortRack("lgx port rack")
- .setLgxPortShelf("lgx port shelf").build())
+ return new RxDirectionBuilder()
+ .setPort(new PortBuilder()
+ .setPortDeviceName("device name")
+ .setPortName("port name")
+ .setPortRack("port rack")
+ .setPortShelf("port shelf")
+ .setPortSlot("port slot")
+ .setPortSubSlot("port subslot")
+ .setPortType("port type")
+ .build())
+ .setLgx(new LgxBuilder()
+ .setLgxDeviceName("lgx device name")
+ .setLgxPortName("lgx port name")
+ .setLgxPortRack("lgx port rack")
+ .setLgxPortShelf("lgx port shelf")
+ .build())
+ .setIndex(Uint8.ZERO)
.build();
}
.setConnectionType(ConnectionType.Service)
.setMessage(message)
.setOperationalState(services.getOperationalState())
- .setTopic("ServiceListener")
+ .setPublisherName("ServiceListener")
.build();
}
-}
+}
\ No newline at end of file