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.ServiceAEnd;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceAEndBuilder;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceZEnd;
-import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev190531.service.ServiceZEndBuilder;
-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.RxDirectionBuilder;
-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.endpoint.TxDirectionBuilder;
-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.rev210813.PublishNotificationAlarmService;
-import org.opendaylight.yang.gen.v1.nbi.notifications.rev210813.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();
}
}
+ @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());
+
+ 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) {
- ServiceAEnd serviceAEnd = getServiceAEndBuild().build();
- ServiceZEnd serviceZEnd = new ServiceZEndBuilder()
- .setClli("clli")
- .setServiceFormat(ServiceFormat.OC)
- .setServiceRate(Uint32.valueOf(1))
- .setNodeId(new NodeIdType("XPONDER-3-2"))
- .setTxDirection(getTxDirection())
- .setRxDirection(getRxDirection())
- .build();
- ServicesBuilder builtInput = new ServicesBuilder()
+ 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 ServiceAEndBuilder getServiceAEndBuild() {
return new ServiceAEndBuilder()
.setClli("clli")
- .setServiceFormat(ServiceFormat.OC)
+ .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() {
.setLgxPortRack("lgx port rack")
.setLgxPortShelf("lgx port shelf")
.build())
+ .setIndex(Uint8.ZERO)
.build();
}
.setLgxPortRack("lgx port rack")
.setLgxPortShelf("lgx port shelf")
.build())
+ .setIndex(Uint8.ZERO)
.build();
}
.setPublisherName("ServiceListener")
.build();
}
-}
+}
\ No newline at end of file