package org.opendaylight.openflowplugin.impl.connection.listener;
-import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
-import org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl;
-
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.net.InetSocketAddress;
-import java.util.List;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.mdsal.binding.api.NotificationPublishService;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.DeviceConnectionStatusProvider;
import org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl;
+import org.opendaylight.openflowplugin.impl.util.ThreadPoolLoggingExecutor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.common.Uint32;
+import org.opendaylight.yangtools.yang.common.Uint8;
/**
- * Testing basic bahavior of {@link SystemNotificationsListenerImpl}
+ * Testing basic bahavior of {@link SystemNotificationsListenerImpl}.
*/
@RunWith(MockitoJUnitRunner.class)
public class SystemNotificationsListenerImplTest {
- public static final int SAFE_TIMEOUT = 1000;
+ private static final int SAFE_TIMEOUT = 1000;
+ private static final int ECHO_REPLY_TIMEOUT = 2000;
+
@Mock
- private org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter connectionAdapter;
+ private ConnectionAdapter connectionAdapter;
@Mock
private FeaturesReply features;
- private ConnectionContext connectionContext;
- @Captor
- private ArgumentCaptor<ConnectionContext.CONNECTION_STATE> connectionStateArgumentCaptor;
+ @Mock
+ private DeviceConnectionStatusProvider deviceConnectionStatusProvider;
+ @Mock
+ private NotificationPublishService notificationPublishService;
- private SystemNotificationsListenerImpl systemNotificationsListener;
+ private ConnectionContext connectionContext;
private ConnectionContextImpl connectionContextGolem;
+ private SystemNotificationsListenerImpl systemNotificationsListener;
+
+ private static final NodeId NODE_ID =
+ new NodeId("OFP:TEST");
+
+ private final ThreadPoolLoggingExecutor threadPool = new ThreadPoolLoggingExecutor(
+ 0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), "opfpool");
@Before
public void setUp() {
- connectionContextGolem = new ConnectionContextImpl(connectionAdapter);
- connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
+ connectionContextGolem = new ConnectionContextImpl(connectionAdapter, deviceConnectionStatusProvider);
+ connectionContextGolem.changeStateToWorking();
+ connectionContextGolem.setNodeId(NODE_ID);
+ connectionContextGolem.setFeatures(features);
+ connectionContext = Mockito.spy(connectionContextGolem);
Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(
InetSocketAddress.createUnresolved("unit-odl.example.org", 4242));
- connectionContext = Mockito.spy(connectionContextGolem);
- Mockito.when(features.getAuxiliaryId()).thenReturn((short) 0);
-
- Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
- Mockito.when(connectionContext.getFeatures()).thenReturn(features);
- ThreadPoolLoggingExecutor threadPoolLoggingExecutor = new ThreadPoolLoggingExecutor(2000, 2000, 0L, TimeUnit.MILLISECONDS,
- new ArrayBlockingQueue<Runnable>(20), "OFHandshake-test identifier");
+ Mockito.when(features.getAuxiliaryId()).thenReturn(Uint8.ZERO);
- systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext,
- new HandshakeContextImpl(threadPoolLoggingExecutor, null));
+ systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext, ECHO_REPLY_TIMEOUT,
+ threadPool, notificationPublishService);
}
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
Mockito.verifyNoMoreInteractions(connectionContext);
}
/**
- * successful scenario - connection is on and closes without errors
- *
- * @throws Exception
+ * Successful scenario - connection is on and closes without errors.
*/
@Test
- public void testOnDisconnectEvent1() throws Exception {
- Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
- Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.TRUE));
+ public void testOnDisconnectEvent1() {
DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
systemNotificationsListener.onDisconnectEvent(disconnectNotification);
- verifyCommonInvocations();
- Mockito.verify(connectionAdapter).disconnect();
- Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
- Mockito.verify(connectionContext).propagateClosingConnection();
- assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ verifyCommonInvocationsSubSet();
+ Mockito.verify(connectionContext).onConnectionClosed();
+ Mockito.verify(connectionContext).getConnectionAdapter();
+ Mockito.verify(connectionContext, Mockito.atLeastOnce()).getSafeNodeIdForLOG();
}
/**
- * broken scenario - connection is on but fails to close
- *
- * @throws Exception
+ * Broken scenario - connection is on but fails to close.
*/
@Test
- public void testOnDisconnectEvent2() throws Exception {
- Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
- Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.FALSE));
+ public void testOnDisconnectEvent2() {
DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
systemNotificationsListener.onDisconnectEvent(disconnectNotification);
- verifyCommonInvocations();
- Mockito.verify(connectionAdapter).disconnect();
- Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
- Mockito.verify(connectionContext).propagateClosingConnection();
- assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ verifyCommonInvocationsSubSet();
+ Mockito.verify(connectionContext).onConnectionClosed();
+ Mockito.verify(connectionContext).getConnectionAdapter();
+ Mockito.verify(connectionContext, Mockito.atLeastOnce()).getSafeNodeIdForLOG();
}
/**
- * successful scenario - connection is already down
- *
- * @throws Exception
+ * Successful scenario - connection is already down.
*/
@Test
- public void testOnDisconnectEvent3() throws Exception {
- connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
-
- Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
- Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
+ public void testOnDisconnectEvent3() {
+ connectionContextGolem.changeStateToTimeouting();
DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
systemNotificationsListener.onDisconnectEvent(disconnectNotification);
- verifyCommonInvocations();
- Mockito.verify(connectionAdapter).disconnect();
- Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
- Mockito.verify(connectionContext).propagateClosingConnection();
- assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ verifyCommonInvocationsSubSet();
+ Mockito.verify(connectionContext).onConnectionClosed();
+ Mockito.verify(connectionContext).getConnectionAdapter();
+ Mockito.verify(connectionContext, Mockito.atLeastOnce()).getSafeNodeIdForLOG();
}
/**
- * broken scenario - connection is on but throws error on close
- *
- * @throws Exception
+ * Broken scenario - connection is on but throws error on close.
*/
@Test
- public void testOnDisconnectEvent4() throws Exception {
- connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
-
- Mockito.when(connectionAdapter.isAlive()).thenReturn(false);
+ public void testOnDisconnectEvent4() {
+ Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.RIP);
DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
systemNotificationsListener.onDisconnectEvent(disconnectNotification);
- verifyCommonInvocations();
- Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
- Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
- Mockito.verify(connectionContext).propagateClosingConnection();
- assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ verifyCommonInvocationsSubSet();
+ Mockito.verify(connectionContext).onConnectionClosed();
+ Mockito.verify(connectionContext).getConnectionAdapter();
+ Mockito.verify(connectionContext, Mockito.atLeastOnce()).getSafeNodeIdForLOG();
}
/**
- * first encounter of idle event, echo received successfully
- *
- * @throws Exception
+ * First encounter of idle event, echo received successfully.
*/
@Test
public void testOnSwitchIdleEvent1() throws Exception {
- final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
- Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
+ final ListenableFuture<RpcResult<EchoOutput>> echoReply =
+ RpcResultBuilder.success(new EchoOutputBuilder().setXid(Uint32.ZERO).build()).buildFuture();
+
+ Mockito.when(connectionAdapter.echo(any(EchoInput.class))).thenReturn(echoReply);
SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
systemNotificationsListener.onSwitchIdleEvent(notification);
// make sure that the idle notification processing thread started
Thread.sleep(SAFE_TIMEOUT);
- EchoOutput echoReplyVal = new EchoOutputBuilder().build();
- echoReply.set(RpcResultBuilder.success(echoReplyVal).build());
-
- Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
- .setConnectionState(connectionStateArgumentCaptor.capture());
- List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
- Assert.assertEquals(2, allStates.size());
- Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
- Assert.assertEquals(ConnectionContext.CONNECTION_STATE.WORKING, allStates.get(1));
verifyCommonInvocations();
- Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
- Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT)).setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
+ Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(any(EchoInput.class));
Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
- assertFalse(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ Mockito.verify(connectionContext).changeStateToTimeouting();
+ Mockito.verify(connectionContext).changeStateToWorking();
}
/**
- * first encounter of idle event, echo not receive
- *
- * @throws Exception
+ * First encounter of idle event, echo not receive.
*/
@Test
public void testOnSwitchIdleEvent2() throws Exception {
final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
- Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
+ Mockito.when(connectionAdapter.echo(any(EchoInput.class))).thenReturn(echoReply);
Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
- Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
+ Mockito.when(connectionAdapter.disconnect())
+ .thenReturn(Futures.immediateFailedFuture(new Exception("unit exception")));
SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
systemNotificationsListener.onSwitchIdleEvent(notification);
Thread.sleep(SystemNotificationsListenerImpl.MAX_ECHO_REPLY_TIMEOUT + SAFE_TIMEOUT);
verifyCommonInvocations();
- Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
- Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
- .setConnectionState(connectionStateArgumentCaptor.capture());
- List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
- Assert.assertEquals(2, allStates.size());
- Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
- Assert.assertEquals(ConnectionContext.CONNECTION_STATE.RIP, allStates.get(1));
-
+ Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(any(EchoInput.class));
Mockito.verify(connectionAdapter).disconnect();
- Mockito.verify(connectionContext).propagateClosingConnection();
- assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
+ Mockito.verify(connectionContext).changeStateToTimeouting();
+ Mockito.verify(connectionContext).closeConnection(true);
+ Mockito.verify(connectionContext, Mockito.atLeastOnce()).getSafeNodeIdForLOG();
+
}
private void verifyCommonInvocations() {
- Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionState();
+ verifyCommonInvocationsSubSet();
Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getFeatures();
Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionAdapter();
}
-}
\ No newline at end of file
+
+ private void verifyCommonInvocationsSubSet() {
+ Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionState();
+ }
+}