9d3f1cee64fc7d57f0a3895013aa7c8e23670bc9
[openflowplugin.git] / openflowjava / 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 package org.opendaylight.openflowjava.protocol.impl.core;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNull;
12 import static org.junit.Assert.fail;
13
14 import io.netty.channel.ChannelHandlerContext;
15 import io.netty.channel.unix.Errors;
16 import java.io.IOException;
17 import java.net.BindException;
18 import java.net.InetAddress;
19 import java.net.InetSocketAddress;
20 import java.net.Socket;
21 import java.util.concurrent.ExecutionException;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.junit.MockitoJUnitRunner;
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 /**
31  * Unit tests for TcpHandler.
32  *
33  * @author jameshall
34  */
35 @RunWith(MockitoJUnitRunner.class)
36 public class TcpHandlerTest {
37     private final InetAddress serverAddress = InetAddress.getLoopbackAddress();
38
39     @Mock
40     ChannelHandlerContext mockChHndlrCtx;
41     @Mock
42     TcpChannelInitializer mockChannelInitializer;
43     @Mock
44     SwitchConnectionHandler mockSwitchConnHndler;
45     @Mock
46     SerializationFactory mockSerializationFactory;
47     @Mock
48     DeserializationFactory mockDeserializationFactory;
49
50     TcpHandler tcpHandler;
51
52     /**
53      * Test run with null address set.
54      */
55     @Test
56     public void testRunWithNullAddress() throws IOException, InterruptedException, ExecutionException  {
57         tcpHandler = new TcpHandler(null, 0, () -> { });
58         tcpHandler.setChannelInitializer(mockChannelInitializer);
59
60         assertEquals("failed to start server", true, startupServer(false)) ;
61         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
62         shutdownServer();
63     }
64
65     /**
66      * Test run with null address set on Epoll native transport.
67      */
68     @Test
69     public void testRunWithNullAddressOnEpoll() throws IOException, InterruptedException, ExecutionException  {
70         tcpHandler = new TcpHandler(null, 0, () -> { });
71         tcpHandler.setChannelInitializer(mockChannelInitializer);
72
73         //Use Epoll native transport
74         assertEquals("failed to start server", true, startupServer(true)) ;
75         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
76         shutdownServer();
77     }
78
79     /**
80      * Test run with address set.
81      */
82     @Test
83     public void testRunWithAddress() throws IOException, InterruptedException, ExecutionException  {
84         tcpHandler = new TcpHandler(serverAddress, 0, () -> { });
85         tcpHandler.setChannelInitializer(mockChannelInitializer);
86
87         assertEquals("failed to start server", true, startupServer(false)) ;
88         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
89         shutdownServer();
90     }
91
92     /**
93      * Test run with address set on Epoll native transport.
94      */
95     @Test
96     public void testRunWithAddressOnEpoll() throws IOException, InterruptedException, ExecutionException  {
97         tcpHandler = new TcpHandler(serverAddress, 0, () -> { });
98         tcpHandler.setChannelInitializer(mockChannelInitializer);
99
100         //Use Epoll native transport
101         assertEquals("failed to start server", true, startupServer(true));
102         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
103         shutdownServer();
104     }
105
106     /**
107      * Test run with encryption.
108      */
109     @Test
110     public void testRunWithEncryption() throws InterruptedException, IOException, ExecutionException {
111         int serverPort = 28001;
112         tcpHandler = new TcpHandler(serverAddress, serverPort, () -> { });
113         tcpHandler.setChannelInitializer(mockChannelInitializer);
114
115         assertEquals("failed to start server", true, startupServer(false));
116         assertEquals("wrong connection count", 0, tcpHandler.getNumberOfConnections());
117         assertEquals("wrong port", serverPort, tcpHandler.getPort());
118         assertEquals("wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
119
120         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
121
122         shutdownServer();
123     }
124
125     /**
126      * Test run with encryption on Epoll native transport.
127      */
128     @Test
129     public void testRunWithEncryptionOnEpoll() throws InterruptedException, IOException, ExecutionException {
130         int serverPort = 28001;
131         tcpHandler = new TcpHandler(serverAddress, serverPort, () -> { });
132         tcpHandler.setChannelInitializer(mockChannelInitializer);
133
134         //Use Epoll native transport
135         assertEquals("failed to start server", true, startupServer(true));
136         assertEquals("wrong connection count", 0, tcpHandler.getNumberOfConnections());
137         assertEquals("wrong port", serverPort, tcpHandler.getPort());
138         assertEquals("wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
139
140         assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
141
142         shutdownServer();
143     }
144
145     /**
146      * Test run on already used port.
147      */
148     @Test(expected = BindException.class)
149     public void testSocketAlreadyInUse() throws IOException {
150         int serverPort = 28001;
151         Socket firstBinder = new Socket();
152
153         try (firstBinder) {
154             firstBinder.bind(new InetSocketAddress(serverAddress, serverPort));
155             tcpHandler = new TcpHandler(serverAddress, serverPort, () -> { });
156             tcpHandler.setChannelInitializer(mockChannelInitializer);
157             tcpHandler.initiateEventLoopGroups(null, false);
158             tcpHandler.run();
159         }
160     }
161
162     /**
163      * Test run on already used port.
164      */
165     @Test
166     public void testSocketAlreadyInUseOnEpoll() throws IOException {
167         int serverPort = 28001;
168         Socket firstBinder = new Socket();
169
170         try (firstBinder) {
171             firstBinder.bind(new InetSocketAddress(serverAddress, serverPort));
172
173             tcpHandler = new TcpHandler(serverAddress, serverPort, () -> { });
174             tcpHandler.setChannelInitializer(mockChannelInitializer);
175             //Use Epoll native transport
176             tcpHandler.initiateEventLoopGroups(null, true);
177             tcpHandler.run();
178             fail("Expected BindException or Errors.NativeIoException");
179         } catch (BindException | Errors.NativeIoException e) {
180             // expected
181         }
182     }
183
184     /**
185      * Trigger the server shutdown and wait 2 seconds for completion.
186      */
187     private void shutdownServer() throws InterruptedException, ExecutionException {
188         final var shutdownRet = tcpHandler.shutdown() ;
189         assertNull(shutdownRet.get());
190     }
191
192     private Boolean startupServer(final boolean isEpollEnabled) throws InterruptedException {
193         final var online = tcpHandler.getIsOnlineFuture();
194         /**
195          * Test EPoll based native transport if isEpollEnabled is true.
196          * Else use Nio based transport.
197          */
198         tcpHandler.initiateEventLoopGroups(null, isEpollEnabled);
199         new Thread(tcpHandler).start();
200         int retry = 0;
201         while (online.isDone() != true && retry++ < 20) {
202             Thread.sleep(100);
203         }
204         return online.isDone();
205     }
206
207     private static Boolean clientConnection(final int port) throws IOException {
208         // Connect, and disconnect
209         Socket socket = new Socket(InetAddress.getLoopbackAddress(), port);
210         Boolean result = socket.isConnected();
211         socket.close() ;
212         return result ;
213     }
214 }