Merge "Statistics collection fix"
[openflowplugin.git] / openflowplugin-impl / src / test / java / org / opendaylight / openflowplugin / impl / connection / listener / SystemNotificationsListenerImplTest.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.impl.connection.listener;
10
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.SettableFuture;
13 import java.net.InetSocketAddress;
14 import org.junit.After;
15 import org.junit.Before;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 import org.mockito.Matchers;
19 import org.mockito.Mock;
20 import org.mockito.Mockito;
21 import org.mockito.runners.MockitoJUnitRunner;
22 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
23 import org.opendaylight.openflowplugin.impl.connection.ConnectionContextImpl;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutputBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEventBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder;
33 import org.opendaylight.yangtools.yang.common.RpcResult;
34 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
35
36 /**
37  * Testing basic bahavior of {@link SystemNotificationsListenerImpl}
38  */
39 @RunWith(MockitoJUnitRunner.class)
40 public class SystemNotificationsListenerImplTest {
41
42     public static final int SAFE_TIMEOUT = 1000;
43     @Mock
44     private org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter connectionAdapter;
45     @Mock
46     private FeaturesReply features;
47     private ConnectionContext connectionContext;
48
49     private SystemNotificationsListenerImpl systemNotificationsListener;
50     private ConnectionContextImpl connectionContextGolem;
51     private static final NodeId nodeId = new NodeId("OFP:TEST");
52
53     @Before
54     public void setUp() {
55         connectionContextGolem = new ConnectionContextImpl(connectionAdapter);
56         connectionContextGolem.changeStateToWorking();
57         connectionContextGolem.setNodeId(nodeId);
58
59         Mockito.when(connectionAdapter.getRemoteAddress()).thenReturn(
60                 InetSocketAddress.createUnresolved("unit-odl.example.org", 4242));
61         connectionContext = Mockito.spy(connectionContextGolem);
62         Mockito.when(features.getAuxiliaryId()).thenReturn((short) 0);
63
64         Mockito.when(connectionContext.getConnectionAdapter()).thenReturn(connectionAdapter);
65         Mockito.when(connectionContext.getFeatures()).thenReturn(features);
66
67         systemNotificationsListener = new SystemNotificationsListenerImpl(connectionContext);
68     }
69
70     @After
71     public void tearDown() throws Exception {
72         Mockito.verifyNoMoreInteractions(connectionContext);
73     }
74
75     /**
76      * successful scenario - connection is on and closes without errors
77      *
78      * @throws Exception
79      */
80     @Test
81     public void testOnDisconnectEvent1() throws Exception {
82         Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
83         Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.TRUE));
84
85         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
86         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
87
88         verifyCommonInvocationsSubSet();
89         Mockito.verify(connectionContext).onConnectionClosed();
90     }
91
92     /**
93      * broken scenario - connection is on but fails to close
94      *
95      * @throws Exception
96      */
97     @Test
98     public void testOnDisconnectEvent2() throws Exception {
99         Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
100         Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.immediateFuture(Boolean.FALSE));
101
102         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
103         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
104
105         verifyCommonInvocationsSubSet();
106         Mockito.verify(connectionContext).onConnectionClosed();
107     }
108
109     /**
110      * successful scenario - connection is already down
111      *
112      * @throws Exception
113      */
114     @Test
115     public void testOnDisconnectEvent3() throws Exception {
116         connectionContextGolem.changeStateToTimeouting();
117
118         Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
119         Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
120
121         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
122         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
123
124         verifyCommonInvocationsSubSet();
125         Mockito.verify(connectionContext).onConnectionClosed();
126     }
127
128     /**
129      * broken scenario - connection is on but throws error on close
130      *
131      * @throws Exception
132      */
133     @Test
134     public void testOnDisconnectEvent4() throws Exception {
135         Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.RIP);
136         Mockito.when(connectionAdapter.isAlive()).thenReturn(false);
137
138         DisconnectEvent disconnectNotification = new DisconnectEventBuilder().setInfo("testing disconnect").build();
139         systemNotificationsListener.onDisconnectEvent(disconnectNotification);
140
141         verifyCommonInvocationsSubSet();
142         Mockito.verify(connectionContext).onConnectionClosed();
143     }
144
145     /**
146      * first encounter of idle event, echo received successfully
147      *
148      * @throws Exception
149      */
150     @Test
151     public void testOnSwitchIdleEvent1() throws Exception {
152         final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
153         Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
154
155         SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
156         systemNotificationsListener.onSwitchIdleEvent(notification);
157
158         // make sure that the idle notification processing thread started
159         Thread.sleep(SAFE_TIMEOUT);
160         EchoOutput echoReplyVal = new EchoOutputBuilder().build();
161         echoReply.set(RpcResultBuilder.success(echoReplyVal).build());
162
163         verifyCommonInvocations();
164         Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
165         Mockito.verify(connectionAdapter, Mockito.never()).disconnect();
166         Mockito.verify(connectionContext).changeStateToTimeouting();
167         Mockito.verify(connectionContext).changeStateToWorking();
168     }
169
170     /**
171      * first encounter of idle event, echo not receive
172      *
173      * @throws Exception
174      */
175     @Test
176     public void testOnSwitchIdleEvent2() throws Exception {
177         final SettableFuture<RpcResult<EchoOutput>> echoReply = SettableFuture.create();
178         Mockito.when(connectionAdapter.echo(Matchers.any(EchoInput.class))).thenReturn(echoReply);
179         Mockito.when(connectionAdapter.isAlive()).thenReturn(true);
180         Mockito.when(connectionAdapter.disconnect()).thenReturn(Futures.<Boolean>immediateFailedFuture(new Exception("unit exception")));
181
182         SwitchIdleEvent notification = new SwitchIdleEventBuilder().setInfo("wake up, device sleeps").build();
183         systemNotificationsListener.onSwitchIdleEvent(notification);
184
185         Thread.sleep(SystemNotificationsListenerImpl.MAX_ECHO_REPLY_TIMEOUT + SAFE_TIMEOUT);
186
187         verifyCommonInvocations();
188         Mockito.verify(connectionAdapter, Mockito.timeout(SAFE_TIMEOUT)).echo(Matchers.any(EchoInput.class));
189         Mockito.verify(connectionAdapter).disconnect();
190         Mockito.verify(connectionContext).changeStateToTimeouting();
191         Mockito.verify(connectionContext).closeConnection(true);
192     }
193
194     private void verifyCommonInvocations() {
195         verifyCommonInvocationsSubSet();
196         Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionAdapter();
197     }
198
199     private void verifyCommonInvocationsSubSet() {
200         Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getConnectionState();
201         Mockito.verify(connectionContext, Mockito.timeout(SAFE_TIMEOUT).atLeastOnce()).getFeatures();
202     }
203 }