X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin-impl%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fimpl%2Fdevice%2FDeviceManagerImplTest.java;h=2a0a6f3ce31a99477a9a5683c3e8b5e6fbebaedd;hb=b4f4b4b702e2ccd8a7c62fd2a5c184c5b1cbe665;hp=97417436e2cf81591ab6137aa9a6622f0b1b12fa;hpb=77a7d6170ea741d9109dee08e981af9143bc0141;p=openflowplugin.git diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java index 97417436e2..2a0a6f3ce3 100644 --- a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java +++ b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java @@ -8,287 +8,198 @@ package org.opendaylight.openflowplugin.impl.device; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import io.netty.util.HashedWheelTimer; import java.lang.reflect.Field; -import java.math.BigInteger; -import java.util.Collections; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter; -import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue; -import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandler; -import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration; -import org.opendaylight.openflowplugin.api.OFConstants; -import org.opendaylight.openflowplugin.api.openflow.OFPContext; import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext; -import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider; import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext; import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo; -import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager; -import org.opendaylight.openflowplugin.api.openflow.device.DeviceState; -import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator; import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary; -import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler; -import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler; -import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService; -import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey; import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency; +import org.opendaylight.openflowplugin.impl.device.initialization.DeviceInitializerProviderFactory; +import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil; import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager; -import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory; -import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.Capabilities; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.CapabilitiesV10; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader; -import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.features.reply.PhyPortBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint16Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.NonZeroUint32Type; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfigBuilder; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; @RunWith(MockitoJUnitRunner.class) public class DeviceManagerImplTest { - private static final long TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA = 2000l; - private static final int barrierCountLimit = 25600; - private static final int barrierIntervalNanos = 500; - public static final NodeId DUMMY_NODE_ID = new NodeId("dummyNodeId"); + private static final long TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA = 2000L; + private static final int BARRIER_COUNT_LIMIT = 25600; + private static final long BARRIER_INTERVAL_NANOS = 500; + private static final NodeId DUMMY_NODE_ID = new NodeId("dummyNodeId"); + private static final KeyedInstanceIdentifier DUMMY_IDENTIFIER = DeviceStateUtil + .createNodeInstanceIdentifier(DUMMY_NODE_ID); @Mock - CheckedFuture mockedFuture; + private CheckedFuture mockedFuture; @Mock private FeaturesReply mockFeatures; @Mock - private OutboundQueue outboundQueueProvider; - @Mock - private DeviceInitializationPhaseHandler deviceInitPhaseHandler; - @Mock - private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler; - @Mock - private TranslatorLibrary translatorLibrary; - @Mock private ConnectionContext mockConnectionContext; @Mock private ConnectionAdapter mockedConnectionAdapter; @Mock private DeviceContextImpl mockedDeviceContext; @Mock - private NodeId mockedNodeId; - @Mock private MessageIntelligenceAgency messageIntelligenceAgency; @Mock private DeviceInfo deviceInfo; @Mock - private LifecycleService lifecycleService; + private ConvertorExecutor convertorExecutor; @Mock - private ClusterSingletonServiceProvider clusterSingletonServiceProvider; + private DataBroker dataBroker; @Mock - private ConvertorExecutor convertorExecutor; + private WriteTransaction writeTransaction; + @Mock + private BindingTransactionChain transactionChain; + @Mock + private Capabilities capabilities; + @Mock + private CapabilitiesV10 capabilitiesV10; + @Mock + private NotificationPublishService notificationPublishService; + @Mock + private TranslatorLibrary translatorLibrary; + + private DeviceManagerImpl deviceManager; @Before public void setUp() throws Exception { - OpenflowPortsUtil.init(); - - when(mockConnectionContext.getNodeId()).thenReturn(DUMMY_NODE_ID); when(mockConnectionContext.getFeatures()).thenReturn(mockFeatures); when(mockConnectionContext.getConnectionAdapter()).thenReturn(mockedConnectionAdapter); when(mockConnectionContext.getDeviceInfo()).thenReturn(deviceInfo); - when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockConnectionContext); + when(deviceInfo.getNodeInstanceIdentifier()).thenReturn(DUMMY_IDENTIFIER); when(deviceInfo.getNodeId()).thenReturn(DUMMY_NODE_ID); - final Capabilities capabilitiesV13 = mock(Capabilities.class); - final CapabilitiesV10 capabilitiesV10 = mock(CapabilitiesV10.class); - when(mockFeatures.getCapabilities()).thenReturn(capabilitiesV13); - when(mockFeatures.getCapabilitiesV10()).thenReturn(capabilitiesV10); - when(mockFeatures.getDatapathId()).thenReturn(BigInteger.valueOf(21L)); - } - - @Test - public void onDeviceContextLevelUpSuccessTest() throws Exception { - onDeviceContextLevelUp(false); - } - - private DeviceManagerImpl prepareDeviceManager() { - final DataBroker mockedDataBroker = mock(DataBroker.class); - final WriteTransaction mockedWriteTransaction = mock(WriteTransaction.class); - - final BindingTransactionChain mockedTxChain = mock(BindingTransactionChain.class); - final WriteTransaction mockedWTx = mock(WriteTransaction.class); - when(mockedTxChain.newWriteOnlyTransaction()).thenReturn(mockedWTx); - when(mockedDataBroker.createTransactionChain(any(TransactionChainListener.class))).thenReturn - (mockedTxChain); - when(mockedDataBroker.newWriteOnlyTransaction()).thenReturn(mockedWriteTransaction); - - when(mockedWriteTransaction.submit()).thenReturn(mockedFuture); - - final DeviceManagerImpl deviceManager = new DeviceManagerImpl( - mockedDataBroker, - TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA, - false, - barrierIntervalNanos, - barrierCountLimit, + when(mockedFuture.isDone()).thenReturn(true); + when(writeTransaction.submit()).thenReturn(mockedFuture); + when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransaction); + + deviceManager = new DeviceManagerImpl( + new OpenflowProviderConfigBuilder() + .setBarrierCountLimit(new NonZeroUint16Type(BARRIER_COUNT_LIMIT)) + .setBarrierIntervalTimeoutLimit(new NonZeroUint32Type(BARRIER_INTERVAL_NANOS)) + .setGlobalNotificationQuota(TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA) + .setSwitchFeaturesMandatory(false) + .setEnableFlowRemovedNotification(true) + .setSkipTableFeatures(false) + .setUseSingleLayerSerialization(true) + .build(), + dataBroker, messageIntelligenceAgency, - true, - clusterSingletonServiceProvider, - null, + notificationPublishService, new HashedWheelTimer(), - convertorExecutor); + convertorExecutor, + DeviceInitializerProviderFactory.createDefaultProvider()); - deviceManager.setDeviceInitializationPhaseHandler(deviceInitPhaseHandler); - deviceManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler); - - return deviceManager; - } - - public void onDeviceContextLevelUp(final boolean withException) throws Exception { - final DeviceManagerImpl deviceManager = prepareDeviceManager(); - final DeviceState mockedDeviceState = mock(DeviceState.class); - when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState); - - if (withException) { - doThrow(new IllegalStateException("dummy")).when(mockedDeviceContext).initialSubmitTransaction(); - } - deviceManager.addDeviceContextToMap(deviceInfo, mockedDeviceContext); - deviceManager.onDeviceContextLevelUp(deviceInfo, lifecycleService); - if (withException) { - verify(mockedDeviceContext).close(); - } else { - verify(mockedDeviceContext).onPublished(); - } + deviceManager.setTranslatorLibrary(translatorLibrary); + verify(dataBroker).newWriteOnlyTransaction(); + verify(writeTransaction).merge(eq(LogicalDatastoreType.OPERATIONAL), any(), any()); + verify(writeTransaction).submit(); } @Test - public void deviceConnectedTest() throws Exception{ - final DeviceManagerImpl deviceManager = prepareDeviceManager(); - injectMockTranslatorLibrary(deviceManager); - final ConnectionContext mockConnectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3); - - deviceManager.deviceConnected(mockConnectionContext); + public void createContext() throws Exception { + final DeviceContext context = deviceManager.createContext(mockConnectionContext); + assertEquals(deviceInfo, context.getDeviceInfo()); - final InOrder order = inOrder(mockConnectionContext); - order.verify(mockConnectionContext).setOutboundQueueProvider(any(OutboundQueueProvider.class)); - order.verify(mockConnectionContext).setOutboundQueueHandleRegistration( - Mockito.>any()); - verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.any(), Mockito.any()); } @Test - public void deviceConnectedV10Test() throws Exception{ - final DeviceManagerImpl deviceManager = prepareDeviceManager(); - injectMockTranslatorLibrary(deviceManager); - final ConnectionContext mockConnectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_0); + public void removeDeviceFromOperationalDS() throws Exception { + final ListenableFuture future = deviceManager + .removeDeviceFromOperationalDS(DUMMY_IDENTIFIER); - final PhyPortBuilder phyPort = new PhyPortBuilder() - .setPortNo(41L); - when(mockFeatures.getPhyPort()).thenReturn(Collections.singletonList(phyPort.build())); - final MessageTranslator mockedTranslator = mock(MessageTranslator.class); - when(mockedTranslator.translate(Matchers.any(), Matchers.any(), Matchers.any())) - .thenReturn(null); - when(translatorLibrary.lookupTranslator(Matchers.any())).thenReturn(mockedTranslator); - - deviceManager.deviceConnected(mockConnectionContext); - - final InOrder order = inOrder(mockConnectionContext); - order.verify(mockConnectionContext).setOutboundQueueProvider(any(OutboundQueueProvider.class)); - order.verify(mockConnectionContext).setOutboundQueueHandleRegistration( - Mockito.>any()); - verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.any(), Mockito.any()); + future.get(); + assertTrue(future.isDone()); + verify(writeTransaction).delete(LogicalDatastoreType.OPERATIONAL, DUMMY_IDENTIFIER); } - @Test - public void deviceDisconnectedTest() throws Exception { - final DeviceState deviceState = mock(DeviceState.class); - - final DeviceManagerImpl deviceManager = prepareDeviceManager(); - injectMockTranslatorLibrary(deviceManager); - - final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3); - when(connectionContext.getNodeId()).thenReturn(mockedNodeId); - - final DeviceContext deviceContext = mock(DeviceContext.class); - when(deviceContext.shuttingDownDataStoreTransactions()).thenReturn(Futures.immediateCheckedFuture(null)); - when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext); - when(deviceContext.getDeviceState()).thenReturn(deviceState); - when(deviceContext.getState()).thenReturn(OFPContext.CONTEXT_STATE.WORKING); - - final ConcurrentHashMap deviceContexts = getContextsCollection(deviceManager); - deviceContexts.put(deviceInfo, deviceContext); - - deviceManager.onDeviceDisconnected(connectionContext); + @Test(expected = ExecutionException.class) + public void removeDeviceFromOperationalDSException() throws Exception { + final CheckedFuture failedFuture = + Futures.immediateFailedCheckedFuture( + new TransactionCommitFailedException("Test failed transaction")); + Mockito.when(writeTransaction.submit()).thenReturn(failedFuture); + final ListenableFuture future = deviceManager + .removeDeviceFromOperationalDS(DUMMY_IDENTIFIER); + future.get(); + assertTrue(future.isDone()); + verify(writeTransaction).delete(LogicalDatastoreType.OPERATIONAL, DUMMY_IDENTIFIER); } - protected ConnectionContext buildMockConnectionContext(final short ofpVersion) { - when(mockFeatures.getVersion()).thenReturn(ofpVersion); - when(outboundQueueProvider.reserveEntry()).thenReturn(43L); - Mockito.doAnswer(new Answer() { - @Override - public Void answer(final InvocationOnMock invocation) throws Throwable { - final FutureCallback callBack = (FutureCallback) invocation.getArguments()[2]; - callBack.onSuccess(null); - return null; - } - }) - .when(outboundQueueProvider) - .commitEntry(Matchers.anyLong(), Matchers.any(), Matchers.>any()); - - when(mockedConnectionAdapter.registerOutboundQueueHandler(Matchers.any(), Matchers.anyInt(), Matchers.anyLong())) - .thenAnswer(new Answer>() { - @Override - public OutboundQueueHandlerRegistration answer(final InvocationOnMock invocation) throws Throwable { - final OutboundQueueHandler handler = (OutboundQueueHandler) invocation.getArguments()[0]; - handler.onConnectionQueueChanged(outboundQueueProvider); - return null; - } - }); - - when(mockConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueueProvider); - return mockConnectionContext; + @Test + public void sendNodeAddedNotification() throws Exception { + deviceManager.sendNodeAddedNotification(DUMMY_IDENTIFIER); + deviceManager.sendNodeAddedNotification(DUMMY_IDENTIFIER); + verify(notificationPublishService).offerNotification(new NodeUpdatedBuilder() + .setId(DUMMY_NODE_ID) + .setNodeRef(new NodeRef(DUMMY_IDENTIFIER)) + .build()); } - private void injectMockTranslatorLibrary(final DeviceManagerImpl deviceManager) { - deviceManager.setTranslatorLibrary(translatorLibrary); + @Test + public void sendNodeRemovedNotification() throws Exception { + deviceManager.sendNodeAddedNotification(DUMMY_IDENTIFIER); + deviceManager.sendNodeRemovedNotification(DUMMY_IDENTIFIER); + deviceManager.sendNodeRemovedNotification(DUMMY_IDENTIFIER); + verify(notificationPublishService).offerNotification(new NodeRemovedBuilder() + .setNodeRef(new NodeRef(DUMMY_IDENTIFIER)) + .build()); } @Test - public void testClose() throws Exception { + public void close() throws Exception { final DeviceContext deviceContext = mock(DeviceContext.class); - final DeviceManagerImpl deviceManager = prepareDeviceManager(); final ConcurrentHashMap deviceContexts = getContextsCollection(deviceManager); deviceContexts.put(deviceInfo, deviceContext); Assert.assertEquals(1, deviceContexts.size()); - deviceManager.close(); - - verify(deviceContext).shutdownConnection(); - verify(deviceContext, Mockito.never()).close(); + verify(deviceContext).close(); } - private static ConcurrentHashMap getContextsCollection(final DeviceManagerImpl deviceManager) throws NoSuchFieldException, IllegalAccessException { + @SuppressWarnings("unchecked") + private static ConcurrentHashMap getContextsCollection( + final DeviceManagerImpl deviceManager) throws NoSuchFieldException, IllegalAccessException { // HACK: contexts collection for testing shall be accessed in some more civilized way final Field contextsField = DeviceManagerImpl.class.getDeclaredField("deviceContexts"); Assert.assertNotNull(contextsField);