*/
package org.opendaylight.yangtools.websocket;
-import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import java.net.URI;
import java.net.URISyntaxException;
+
import org.junit.Before;
import org.junit.Test;
-import org.opendaylight.yangtools.websocket.client.WebSocketIClient;
-import org.opendaylight.yangtools.websocket.server.WebSocketServer;
+import org.junit.Assert;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.opendaylight.yangtools.websocket.client.WebSocketIClient;
+import org.opendaylight.yangtools.websocket.server.WebSocketServer;
+
+import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
+
+import com.google.common.util.concurrent.SettableFuture;
+
public class WebSocketClientTest {
private static final Logger logger = LoggerFactory.getLogger(WebSocketClientTest.class.toString());
private static final String MESSAGE = "Take me to your leader!";
- private static final int port = 8080;
private Thread webSocketServerThread;
+ /**
+ * Tracks if the message from the server has been received
+ */
+ private SettableFuture<Boolean> messageReceived = SettableFuture.<Boolean>create();
+
+ /**
+ * Tracks the port on which the server is listening
+ */
+ private int port = 0;
@Before
public void startWebSocketServer(){
try {
- WebSocketServer webSocketServer = new WebSocketServer(port);
+ WebSocketServer webSocketServer = new WebSocketServer(0);
webSocketServerThread = new Thread(webSocketServer);
webSocketServerThread.setDaemon(false);
webSocketServerThread.start();
+ port = webSocketServer.getPort().get();
} catch (Exception e) {
logger.trace("Error starting websocket server");
}
}
+
@Test
public void connectAndSendData(){
URI uri = null;
try {
- uri = new URI("ws://localhost:8080/websocket");
+ uri = new URI(String.format("ws://localhost:%d/websocket", port));
+ logger.info("CLIENT: " + uri);
ClientMessageCallback messageCallback = new ClientMessageCallback();
WebSocketIClient wsClient = new WebSocketIClient(uri,messageCallback);
try {
wsClient.connect();
wsClient.writeAndFlush(MESSAGE);
wsClient.writeAndFlush(new CloseWebSocketFrame());
+
+ /*
+ * Wait for up to 5 seconds for the message to be received. If
+ * after that time, the message has not been received then
+ * consider this a failed test.
+ */
+ messageReceived.get(5, TimeUnit.SECONDS);
+
webSocketServerThread.interrupt();
} catch (InterruptedException e) {
- logger.info("WebSocket client couldn't connect to : "+uri);
+ logger.info("WebSocket client couldn't connect to : " + uri);
+ Assert.fail("WebSocker client could not connect to : " + uri);
+ } catch (ExecutionException | TimeoutException toe) {
+ logger.info("Message not received");
+ Assert.fail(toe.toString());
}
} catch (URISyntaxException e) {
logger.info("There is an error in URL sytnax {}",e);
+ Assert.fail("There is an error in URL sytnax");
}
}
private class ClientMessageCallback implements org.opendaylight.yangtools.websocket.client.callback.ClientMessageCallback {
@Override
public void onMessageReceived(Object message) {
- logger.info("received message {}",message);
- System.out.println("received message : " + message);
+ logger.info("received message {}",message);
+ messageReceived.set(true);
}
}
}
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import com.google.common.util.concurrent.SettableFuture;
+
/**
* A HTTP server which serves Web Socket requests at:
*
*/
public class WebSocketServer implements Runnable {
- private final int port;
+ /**
+ * Utilized to get the port on which the server listens. This is a future as
+ * the port is selected dynamically from available ports, thus until the
+ * server is started the value will not be established.
+ */
+ private final SettableFuture<Integer> port;
+
+ /**
+ * Maintains the port number with which the class was initialized.
+ */
+ private final int inPort;
private final ServerBootstrap bootstrap = new ServerBootstrap();
private final EventLoopGroup bossGroup = new NioEventLoopGroup();
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class.toString());
- public WebSocketServer(int port) {
- this.port = port;
+
+ public WebSocketServer(int inPort) {
+ this.inPort = inPort;
+ port = SettableFuture.<Integer>create();
}
- /**
- * Tries to start web socket server.
- */
public void run(){
try {
startServer();
logger.info("Exception occured while starting webSocket server {}",e);
}
}
-
- /**
- * Start web socket server at {@link #port}.
- * @throws Exception
- */
+
+ public Future<Integer> getPort() {
+ return port;
+ }
+
public void startServer() throws Exception {
try {
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new WebSocketServerInitializer());
- Channel ch = bootstrap.bind(port).sync().channel();
- logger.info("Web socket server started at port " + port + '.');
- logger.info("Open your browser and navigate to http://localhost:" + port + '/');
+ Channel ch = bootstrap.bind(inPort).sync().channel();
+ SocketAddress localSocket = ch.localAddress();
+ try {
+ port.set(((InetSocketAddress) localSocket).getPort());
+ } catch (ClassCastException cce) {
+ throw new ExecutionException("Unknown socket address type", cce);
+ }
+ logger.info("Web socket server started at port " + port.get() + '.');
+ logger.info("Open your browser and navigate to http://localhost:" + port.get() + '/');
- ch.closeFuture().sync();
+ try {
+ ch.closeFuture().sync();
+ } catch (InterruptedException ie) {
+ // No op, sometimes the server is shutdown hard
+ }
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
-
-
}