2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.connection.listener;
11 import static org.junit.Assert.*;
13 import org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl;
15 import java.util.concurrent.ArrayBlockingQueue;
16 import java.util.concurrent.TimeUnit;
17 import org.opendaylight.openflowplugin.openflow.md.core.ThreadPoolLoggingExecutor;
18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.SettableFuture;
20 import java.net.InetSocketAddress;
21 import java.util.List;
22 import org.junit.After;
23 import org.junit.Assert;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.mockito.ArgumentCaptor;
28 import org.mockito.Captor;
29 import org.mockito.Matchers;
30 import org.mockito.Mock;
31 import org.mockito.Mockito;
32 import org.mockito.runners.MockitoJUnitRunner;
33 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
34 import org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEventBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder;
43 import org.opendaylight.yangtools.yang.common.RpcResult;
44 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47 * Testing basic bahavior of {@link SystemNotificationsListenerImpl}
49 @RunWith(MockitoJUnitRunner.class)
50 public class SystemNotificationsListenerImplTest {
52 public static final int SAFE_TIMEOUT = 1000;
54 private org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter connectionAdapter;
56 private FeaturesReply features;
57 private ConnectionContext connectionContext;
59 private ArgumentCaptor<ConnectionContext.CONNECTION_STATE> connectionStateArgumentCaptor;
61 private SystemNotificationsListenerImpl systemNotificationsListener;
62 private ConnectionContextImpl connectionContextGolem;
66 connectionContextGolem = new ConnectionContextImpl(connectionAdapter);
67 connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
69 Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(
70 InetSocketAddress.createUnresolved("unit-odl.example.org", 4242));
71 connectionContext = Mockito.spy(connectionContextGolem);
72 Mockito.when(features.getAuxiliaryId()).thenReturn((short) 0);
74 Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
75 Mockito.when(connectionContext.getFeatures()).thenReturn(features);
77 ThreadPoolLoggingExecutor threadPoolLoggingExecutor = new ThreadPoolLoggingExecutor(2000, 2000, 0L, TimeUnit.MILLISECONDS,
78 new ArrayBlockingQueue<Runnable>(20), "OFHandshake-test identifier");
80 systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext,
81 new HandshakeContextImpl(threadPoolLoggingExecutor, null));
85 public void tearDown() throws Exception {
86 Mockito.verifyNoMoreInteractions(connectionContext);
90 * successful scenario - connection is on and closes without errors
95 public void testOnDisconnectEvent1() throws Exception {
96 Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
97 Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.TRUE));
99 DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
100 systemNotificationsListener.onDisconnectEvent(disconnectNotification);
102 verifyCommonInvocations();
103 Mockito.verify(connectionAdapter).disconnect();
104 Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
105 Mockito.verify(connectionContext).propagateClosingConnection();
106 assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
110 * broken scenario - connection is on but fails to close
115 public void testOnDisconnectEvent2() throws Exception {
116 Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
117 Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.FALSE));
119 DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
120 systemNotificationsListener.onDisconnectEvent(disconnectNotification);
122 verifyCommonInvocations();
123 Mockito.verify(connectionAdapter).disconnect();
124 Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
125 Mockito.verify(connectionContext).propagateClosingConnection();
126 assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
130 * successful scenario - connection is already down
135 public void testOnDisconnectEvent3() throws Exception {
136 connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
138 Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
139 Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
141 DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
142 systemNotificationsListener.onDisconnectEvent(disconnectNotification);
144 verifyCommonInvocations();
145 Mockito.verify(connectionAdapter).disconnect();
146 Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
147 Mockito.verify(connectionContext).propagateClosingConnection();
148 assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
152 * broken scenario - connection is on but throws error on close
157 public void testOnDisconnectEvent4() throws Exception {
158 connectionContextGolem.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
160 Mockito.when(connectionAdapter.isAlive()).thenReturn(false);
162 DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
163 systemNotificationsListener.onDisconnectEvent(disconnectNotification);
165 verifyCommonInvocations();
166 Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
167 Mockito.verify(connectionContext).setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
168 Mockito.verify(connectionContext).propagateClosingConnection();
169 assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
173 * first encounter of idle event, echo received successfully
178 public void testOnSwitchIdleEvent1() throws Exception {
179 final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
180 Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
182 SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
183 systemNotificationsListener.onSwitchIdleEvent(notification);
185 // make sure that the idle notification processing thread started
186 Thread.sleep(SAFE_TIMEOUT);
187 EchoOutput echoReplyVal = new EchoOutputBuilder().build();
188 echoReply.set(RpcResultBuilder.success(echoReplyVal).build());
190 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
191 .setConnectionState(connectionStateArgumentCaptor.capture());
192 List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
193 Assert.assertEquals(2, allStates.size());
194 Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
195 Assert.assertEquals(ConnectionContext.CONNECTION_STATE.WORKING, allStates.get(1));
197 verifyCommonInvocations();
198 Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
199 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT)).setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
200 Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
201 assertFalse(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
205 * first encounter of idle event, echo not receive
210 public void testOnSwitchIdleEvent2() throws Exception {
211 final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
212 Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
213 Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
214 Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
216 SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
217 systemNotificationsListener.onSwitchIdleEvent(notification);
219 Thread.sleep(SystemNotificationsListenerImpl.MAX_ECHO_REPLY_TIMEOUT + SAFE_TIMEOUT);
221 verifyCommonInvocations();
222 Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
223 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).times(2))
224 .setConnectionState(connectionStateArgumentCaptor.capture());
225 List<ConnectionContext.CONNECTION_STATE> allStates = connectionStateArgumentCaptor.getAllValues();
226 Assert.assertEquals(2, allStates.size());
227 Assert.assertEquals(ConnectionContext.CONNECTION_STATE.TIMEOUTING, allStates.get(0));
228 Assert.assertEquals(ConnectionContext.CONNECTION_STATE.RIP, allStates.get(1));
230 Mockito.verify(connectionAdapter).disconnect();
231 Mockito.verify(connectionContext).propagateClosingConnection();
232 assertTrue(systemNotificationsListener.handshakeContext.getHandshakePool().isTerminated());
235 private void verifyCommonInvocations() {
236 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionState();
237 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getFeatures();
238 Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionAdapter();