Add method to register listener for unknown msg
[openflowjava.git] / openflow-protocol-impl / src / test / java / org / opendaylight / openflowjava / protocol / impl / core / TcpHandlerTest.java
1 /*
2  * Copyright (c) 2014 Brocade Communications 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.openflowjava.protocol.impl.core;
10
11 import static org.junit.Assert.assertEquals;
12 import io.netty.channel.ChannelHandlerContext;
13
14 import java.io.IOException;
15 import java.net.BindException;
16 import java.net.InetAddress;
17 import java.net.InetSocketAddress;
18 import java.net.Socket;
19 import java.util.concurrent.ExecutionException;
20
21 import io.netty.channel.unix.Errors;
22 import org.junit.Assert;
23 import org.junit.Test;
24 import org.mockito.Mock;
25 import org.mockito.MockitoAnnotations;
26 import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
27 import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
28 import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
29
30 import com.google.common.util.concurrent.ListenableFuture;
31
32 /**
33  *
34  * @author jameshall
35  */
36 public class TcpHandlerTest {
37
38     private InetAddress serverAddress = InetAddress.getLoopbackAddress() ;
39     @Mock ChannelHandlerContext mockChHndlrCtx ;
40     @Mock TcpChannelInitializer mockChannelInitializer;
41     @Mock SwitchConnectionHandler mockSwitchConnHndler ;
42     @Mock SerializationFactory mockSerializationFactory ;
43     @Mock DeserializationFactory mockDeserializationFactory ;
44
45     TcpHandler tcpHandler ;
46
47     /**
48      * Initialize mocks
49      */
50     public TcpHandlerTest() {
51         MockitoAnnotations.initMocks(this);
52     }
53
54     /**
55      * Test run with null address set
56      * @throws IOException
57      * @throws InterruptedException
58      * @throws ExecutionException
59      */
60     @Test
61     public void testRunWithNullAddress() throws IOException, InterruptedException, ExecutionException  {
62
63         tcpHandler = new TcpHandler(null, 0);
64         tcpHandler.setChannelInitializer(mockChannelInitializer);
65
66         assertEquals("failed to start server", true, startupServer(false)) ;
67         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
68         shutdownServer();
69     }
70
71     /**
72      * Test run with null address set on Epoll native transport
73      * @throws IOException
74      * @throws InterruptedException
75      * @throws ExecutionException
76      */
77     @Test
78     public void testRunWithNullAddressOnEpoll() throws IOException, InterruptedException, ExecutionException  {
79
80         tcpHandler = new TcpHandler(null, 0);
81         tcpHandler.setChannelInitializer(mockChannelInitializer);
82
83         //Use Epoll native transport
84         assertEquals("failed to start server", true, startupServer(true)) ;
85         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
86         shutdownServer();
87     }
88
89     /**
90      * Test run with address set
91      * @throws IOException
92      * @throws InterruptedException
93      * @throws ExecutionException
94      */
95     @Test
96     public void testRunWithAddress() throws IOException, InterruptedException, ExecutionException  {
97
98         tcpHandler = new TcpHandler(serverAddress, 0);
99         tcpHandler.setChannelInitializer(mockChannelInitializer);
100
101         assertEquals("failed to start server", true, startupServer(false)) ;
102         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
103         shutdownServer();
104     }
105
106     /**
107      * Test run with address set on Epoll native transport
108      * @throws IOException
109      * @throws InterruptedException
110      * @throws ExecutionException
111      */
112     @Test
113     public void testRunWithAddressOnEpoll() throws IOException, InterruptedException, ExecutionException  {
114
115         tcpHandler = new TcpHandler(serverAddress, 0);
116         tcpHandler.setChannelInitializer(mockChannelInitializer);
117
118         //Use Epoll native transport
119         assertEquals("failed to start server", true, startupServer(true));
120         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
121         shutdownServer();
122     }
123
124     /**
125      * Test run with encryption
126      * @throws InterruptedException
127      * @throws IOException
128      * @throws ExecutionException
129      */
130     @Test
131     public void testRunWithEncryption() throws InterruptedException, IOException, ExecutionException {
132         int serverPort = 28001;
133         tcpHandler = new TcpHandler(serverAddress, serverPort);
134         tcpHandler.setChannelInitializer(mockChannelInitializer);
135
136         assertEquals( "failed to start server", true, startupServer(false));
137         assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections());
138         assertEquals( "wrong port", serverPort, tcpHandler.getPort());
139         assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
140
141         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
142
143         shutdownServer();
144     }
145
146     /**
147      * Test run with encryption on Epoll native transport
148      * @throws InterruptedException
149      * @throws IOException
150      * @throws ExecutionException
151      */
152     @Test
153     public void testRunWithEncryptionOnEpoll() throws InterruptedException, IOException, ExecutionException {
154         int serverPort = 28001;
155         tcpHandler = new TcpHandler(serverAddress, serverPort);
156         tcpHandler.setChannelInitializer(mockChannelInitializer);
157
158         //Use Epoll native transport
159         assertEquals( "failed to start server", true, startupServer(true));
160         assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections());
161         assertEquals( "wrong port", serverPort, tcpHandler.getPort());
162         assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
163
164         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
165
166         shutdownServer();
167     }
168
169     /**
170      * Test run on already used port
171      * @throws IOException
172      */
173     @Test
174     public void testSocketAlreadyInUse() throws IOException {
175         int serverPort = 28001;
176         Socket firstBinder = new Socket();
177         boolean exceptionThrown = false;
178         try {
179             firstBinder.bind(new InetSocketAddress(serverAddress, serverPort));
180         } catch (Exception e) {
181             Assert.fail("Test precondition failed - not able to bind socket to port " + serverPort);
182         }
183         try {
184             tcpHandler = new TcpHandler(serverAddress, serverPort);
185             tcpHandler.setChannelInitializer(mockChannelInitializer);
186             tcpHandler.initiateEventLoopGroups(null, false);
187             tcpHandler.run();
188         } catch (Exception e) {
189             if (e instanceof BindException) {
190                 exceptionThrown = true;
191             }
192         }
193         firstBinder.close();
194         Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true);
195     }
196
197     /**
198      * Test run on already used port
199      * @throws IOException
200      */
201     @Test
202     public void testSocketAlreadyInUseOnEpoll() throws IOException {
203         int serverPort = 28001;
204         Socket firstBinder = new Socket();
205         boolean exceptionThrown = false;
206         try {
207             firstBinder.bind(new InetSocketAddress(serverAddress, serverPort));
208         } catch (Exception e) {
209             Assert.fail("Test precondition failed - not able to bind socket to port " + serverPort);
210         }
211         try {
212             tcpHandler = new TcpHandler(serverAddress, serverPort);
213             tcpHandler.setChannelInitializer(mockChannelInitializer);
214             //Use Epoll native transport
215             tcpHandler.initiateEventLoopGroups(null, true);
216             tcpHandler.run();
217         } catch (Exception e) {
218             if (e instanceof BindException || e instanceof Errors.NativeIoException) {
219                 exceptionThrown = true;
220             }
221         }
222         firstBinder.close();
223         Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true);
224     }
225
226     /**
227      * Trigger the server shutdown and wait 2 seconds for completion
228      */
229     private void shutdownServer() throws InterruptedException, ExecutionException {
230         ListenableFuture<Boolean> shutdownRet = tcpHandler.shutdown() ;
231         while ( shutdownRet.isDone() != true )
232             Thread.sleep(100) ;
233         assertEquals("shutdown failed", true, shutdownRet.get());
234     }
235
236     /**
237      * @throws InterruptedException
238      * @throws IOException
239      * @throws ExecutionException
240      */
241     private Boolean startupServer(boolean isEpollEnabled) throws InterruptedException, IOException, ExecutionException {
242         ListenableFuture<Boolean> online = tcpHandler.getIsOnlineFuture();
243         /**
244          * Test EPoll based native transport if isEpollEnabled is true.
245          * Else use Nio based transport.
246          */
247         tcpHandler.initiateEventLoopGroups(null, isEpollEnabled);
248             (new Thread(tcpHandler)).start();
249             int retry = 0;
250             while (online.isDone() != true && retry++ < 20) {
251                 Thread.sleep(100);
252             }
253         return online.isDone() ;
254     }
255     /**
256      * @throws IOException
257      */
258     private static Boolean clientConnection(int port) throws IOException {
259         // Connect, and disconnect
260         Socket socket = new Socket(InetAddress.getLoopbackAddress(), port );
261         Boolean result = socket.isConnected();
262         socket.close() ;
263         return result ;
264     }
265 }