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