Fix statistics race condition on big flows
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / device / DeviceContextImplTest.java
index f6298433c6b7afbd7aab4c60a029c3acee5c8237..95e454a98001f6ade7afd1aa346a28c2363d84a5 100644 (file)
@@ -29,10 +29,12 @@ import io.netty.util.Timeout;
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
 import java.util.concurrent.atomic.AtomicLong;
+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.runners.MockitoJUnitRunner;
@@ -51,13 +53,13 @@ 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.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
@@ -66,14 +68,13 @@ import org.opendaylight.openflowplugin.api.openflow.registry.group.DeviceGroupRe
 import org.opendaylight.openflowplugin.api.openflow.registry.meter.DeviceMeterRegistry;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.extension.api.ConvertorMessageFromOFJava;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowDescriptorFactory;
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
-import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
+import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.experimenter.message.service.rev151020.ExperimenterMessageFromDev;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -109,6 +110,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Pa
 import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -149,8 +151,6 @@ public class DeviceContextImplTest {
     @Mock
     HashedWheelTimer timer;
     @Mock
-    MessageIntelligenceAgency messageIntelligenceAgency;
-    @Mock
     OutboundQueueProvider outboundQueueProvider;
     @Mock
     ConnectionAdapter connectionAdapter;
@@ -167,9 +167,13 @@ public class DeviceContextImplTest {
     @Mock
     private MessageTranslator<Object, Object> messageTranslatorFlowRemoved;
     @Mock
-    private LifecycleConductor lifecycleConductor;
-    @Mock
     private DeviceInfo deviceInfo;
+    @Mock
+    private DeviceManager deviceManager;
+    @Mock
+    private ConvertorExecutor convertorExecutor;
+    @Mock
+    private MessageSpy messageSpy;
 
     private InOrder inOrderDevState;
 
@@ -218,37 +222,33 @@ public class DeviceContextImplTest {
         Mockito.when(translatorLibrary.lookupTranslator(eq(new TranslatorKey(OFConstants.OFP_VERSION_1_3,
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved.class.getName()))))
                 .thenReturn(messageTranslatorFlowRemoved);
-        Mockito.when(lifecycleConductor.getMessageIntelligenceAgency()).thenReturn(messageIntelligenceAgency);
 
-        deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary);
+        deviceContext = new DeviceContextImpl(
+                connectionContext,
+                dataBroker,
+                messageSpy,
+                translatorLibrary,
+                deviceManager,
+                convertorExecutor,
+                false, timer, deviceManager);
         deviceContextSpy = Mockito.spy(deviceContext);
 
         xid = new Xid(atomicLong.incrementAndGet());
         xidMulti = new Xid(atomicLong.incrementAndGet());
+        ((DeviceContextImpl) deviceContext).lazyTransactionManagerInitialization();
 
         Mockito.doNothing().when(deviceContextSpy).writeToTransaction(Mockito.<LogicalDatastoreType>any(), Mockito.<InstanceIdentifier>any(), any());
-    }
 
-    @Test(expected = NullPointerException.class)
-    public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
-        new DeviceContextImpl(connectionContext, deviceState, null, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
     }
 
     @Test(expected = NullPointerException.class)
-    public void testDeviceContextImplConstructorNullDeviceState() throws Exception {
-        new DeviceContextImpl(connectionContext, null, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
+    public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
+        new DeviceContextImpl(connectionContext, null, null, translatorLibrary, deviceManager, convertorExecutor,false, timer, deviceManager).close();
     }
 
     @Test(expected = NullPointerException.class)
     public void testDeviceContextImplConstructorNullTimer() throws Exception {
-        new DeviceContextImpl(null, deviceState, dataBroker, lifecycleConductor, outboundQueueProvider, translatorLibrary).close();
-    }
-
-    @Test
-    public void testGetDeviceState() {
-        final DeviceState deviceSt = deviceContext.getDeviceState();
-        assertNotNull(deviceSt);
-        assertEquals(deviceState, deviceSt);
+        new DeviceContextImpl(null, dataBroker, null, translatorLibrary, deviceManager,convertorExecutor,false, timer, deviceManager).close();
     }
 
     @Test
@@ -268,20 +268,14 @@ public class DeviceContextImplTest {
         ((DeviceContextImpl) deviceContext).getTransactionChainManager().activateTransactionManager() ;
         ((DeviceContextImpl) deviceContext).getTransactionChainManager().enableSubmit();
         deviceContext.addDeleteToTxChain(LogicalDatastoreType.CONFIGURATION, dummyII);
-        ((DeviceContextImpl) deviceContext).initialSubmitTransaction();
+        deviceContext.initialSubmitTransaction();
         verify(wTx).submit();
     }
 
-    @Test
-    public void testGetReservedXid() {
-        deviceContext.reserveXidForDeviceMessage();
-        verify(outboundQueueProvider).reserveEntry();
-    }
-
     @Test
     public void testAuxiliaryConnectionContext() {
         final ConnectionContext mockedConnectionContext = addDummyAuxiliaryConnectionContext();
-        final ConnectionContext pickedConnectiobContexts = deviceContext.getAuxiliaryConnectiobContexts(DUMMY_COOKIE);
+        final ConnectionContext pickedConnectiobContexts = deviceContext.getAuxiliaryConnectionContexts(DUMMY_COOKIE);
         assertEquals(mockedConnectionContext, pickedConnectiobContexts);
     }
     @Test
@@ -291,9 +285,9 @@ public class DeviceContextImplTest {
         final ConnectionAdapter mockedAuxConnectionAdapter = mock(ConnectionAdapter.class);
         when(mockedConnectionContext.getConnectionAdapter()).thenReturn(mockedAuxConnectionAdapter);
 
-        assertNotNull(deviceContext.getAuxiliaryConnectiobContexts(DUMMY_COOKIE));
+        assertNotNull(deviceContext.getAuxiliaryConnectionContexts(DUMMY_COOKIE));
         deviceContext.removeAuxiliaryConnectionContext(mockedConnectionContext);
-        assertNull(deviceContext.getAuxiliaryConnectiobContexts(DUMMY_COOKIE));
+        assertNull(deviceContext.getAuxiliaryConnectionContexts(DUMMY_COOKIE));
     }
 
     private ConnectionContext addDummyAuxiliaryConnectionContext() {
@@ -360,10 +354,10 @@ public class DeviceContextImplTest {
     public void testProcessReply() {
         final Error mockedError = mock(Error.class);
         deviceContext.processReply(mockedError);
-        verify(messageIntelligenceAgency).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE));
         final OfHeader mockedOfHeader = mock(OfHeader.class);
         deviceContext.processReply(mockedOfHeader);
-        verify(messageIntelligenceAgency).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
     }
 
     @Test
@@ -371,7 +365,7 @@ public class DeviceContextImplTest {
         final MultipartReply mockedMultipartReply = mock(MultipartReply.class);
         final Xid dummyXid = new Xid(DUMMY_XID);
         deviceContext.processReply(dummyXid, Lists.newArrayList(mockedMultipartReply));
-        verify(messageIntelligenceAgency).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_FAILURE));
     }
 
     @Test
@@ -383,7 +377,7 @@ public class DeviceContextImplTest {
         when(mockedNotificationPublishService.offerNotification(any(PacketReceived.class))).thenReturn(stringListenableFuture);
         deviceContext.setNotificationPublishService(mockedNotificationPublishService);
         deviceContext.processPacketInMessage(mockedPacketInMessage);
-        verify(messageIntelligenceAgency).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_PUBLISHED_SUCCESS));
     }
 
     @Test
@@ -395,7 +389,7 @@ public class DeviceContextImplTest {
         when(mockedNotificationPublishService.offerNotification(any(PacketReceived.class))).thenReturn(dummyFuture);
         deviceContext.setNotificationPublishService(mockedNotificationPublishService);
         deviceContext.processPacketInMessage(mockedPacketInMessage);
-        verify(messageIntelligenceAgency).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_NOTIFICATION_REJECTED));
+        verify(messageSpy).spyMessage(any(Class.class), eq(MessageSpy.STATISTIC_GROUP.FROM_SWITCH_NOTIFICATION_REJECTED));
     }
 
     @Test
@@ -416,8 +410,6 @@ public class DeviceContextImplTest {
 
         final ConnectionContext mockedAuxiliaryConnectionContext = prepareConnectionContext();
         deviceContext.addAuxiliaryConnectionContext(mockedAuxiliaryConnectionContext);
-        final DeviceTerminationPhaseHandler mockedDeviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
-        when(deviceState.isValid()).thenReturn(true);
         deviceContext.shutdownConnection();
         verify(connectionContext).closeConnection(true);
     }
@@ -433,7 +425,7 @@ public class DeviceContextImplTest {
     @Test
     public void testGetMessageSpy() {
         final MessageSpy pickedMessageSpy = deviceContext.getMessageSpy();
-        assertEquals(messageIntelligenceAgency, pickedMessageSpy);
+        assertEquals(messageSpy, pickedMessageSpy);
     }
 
     @Test
@@ -465,7 +457,6 @@ public class DeviceContextImplTest {
         when(mockedPortStatusMessage.getReason()).thenReturn(PortReason.OFPPRADD);
         when(mockedPortStatusMessage.getPortNo()).thenReturn(42L);
 
-        OpenflowPortsUtil.init();
         deviceContextSpy.processPortStatusMessage(mockedPortStatusMessage);
         verify(deviceContextSpy).writeToTransaction(Mockito.<LogicalDatastoreType>any(), Mockito.<InstanceIdentifier>any(), any());
         verify(deviceContextSpy).submitTransaction();
@@ -485,9 +476,9 @@ public class DeviceContextImplTest {
                 .thenReturn(flowRemovedMdsalBld.build());
 
         // insert flow+flowId into local registry
-        final FlowRegistryKey flowRegKey = FlowRegistryKeyFactory.create(flowRemovedMdsalBld.build());
+        final FlowRegistryKey flowRegKey = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowRemovedMdsalBld.build());
         final FlowDescriptor flowDescriptor = FlowDescriptorFactory.create((short) 0, new FlowId("ut-ofp:f456"));
-        deviceContext.getDeviceFlowRegistry().store(flowRegKey, flowDescriptor);
+        deviceContext.getDeviceFlowRegistry().storeDescriptor(flowRegKey, flowDescriptor);
 
         // plug in lifecycleListener
         final ItemLifecycleListener itemLifecycleListener = Mockito.mock(ItemLifecycleListener.class);
@@ -504,9 +495,17 @@ public class DeviceContextImplTest {
                 .child(Table.class, new TableKey((short) 0))
                 .child(Flow.class, new FlowKey(new FlowId("ut-ofp:f456")));
 
+        Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(true);
+
         deviceContext.setNotificationPublishService(mockedNotificationPublishService);
         deviceContext.processFlowRemovedMessage(flowRemovedBld.build());
+
         Mockito.verify(itemLifecycleListener).onRemoved(flowToBeRemovedPath);
+
+        Mockito.when(deviceManager.isFlowRemovedNotificationOn()).thenReturn(false);
+        deviceContext.processFlowRemovedMessage(flowRemovedBld.build());
+
+        Mockito.verify(mockedNotificationPublishService).offerNotification(Matchers.any(Notification.class));
     }
 
     @Test
@@ -532,9 +531,22 @@ public class DeviceContextImplTest {
     public void testOnDeviceDisconnected() throws Exception {
         final DeviceTerminationPhaseHandler deviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
 
-        assertEquals(0, deviceContext.getDeviceFlowRegistry().getAllFlowDescriptors().size());
-        assertEquals(0, deviceContext.getDeviceGroupRegistry().getAllGroupIds().size());
-        assertEquals(0, deviceContext.getDeviceMeterRegistry().getAllMeterIds().size());
+        assertEquals(0, deviceContext.getDeviceFlowRegistry().size());
+        assertEquals(0, deviceContext.getDeviceGroupRegistry().size());
+        assertEquals(0, deviceContext.getDeviceMeterRegistry().size());
 
     }
+
+    @Test
+    public void replaceConnectionContext() throws Exception {
+
+        final ConnectionContext connectionContext1 = mock(ConnectionContext.class);
+        Assert.assertEquals(deviceContext.getPrimaryConnectionContext(), connectionContext);
+        Mockito.when(connectionContext1.getConnectionAdapter()).thenReturn(connectionAdapter);
+        Mockito.doNothing().when(connectionAdapter).setPacketInFiltering(Mockito.anyBoolean());
+        deviceContext.replaceConnectionContext(connectionContext1);
+        Assert.assertEquals(deviceContext.getPrimaryConnectionContext(), connectionContext1);
+
+    }
+
 }