// ======================================================================== // Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.client; import static org.junit.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketBuffers; import org.eclipse.jetty.websocket.WebSocketConnectionD00; import org.eclipse.jetty.websocket.WebSocketHandler; import org.junit.After; import org.junit.Before; import org.junit.Test; /* ------------------------------------------------------------ */ /** * Functional testing for HttpExchange. */ public class WebSocketUpgradeTest { protected Server _server; protected int _port; protected HttpClient _httpClient; protected Connector _connector; protected ConcurrentLinkedQueue<TestWebSocket> _webSockets= new ConcurrentLinkedQueue<TestWebSocket>(); protected WebSocketHandler _handler; protected TestWebSocket _websocket; final BlockingQueue<Object> _results = new ArrayBlockingQueue<Object>(100); /* ------------------------------------------------------------ */ @Before public void setUp() throws Exception { startServer(); _httpClient=new HttpClient(); _httpClient.setIdleTimeout(2000); _httpClient.setTimeout(2500); _httpClient.setConnectTimeout(1000); _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _httpClient.setMaxConnectionsPerAddress(10); _httpClient.start(); } /* ------------------------------------------------------------ */ @After public void tearDown() throws Exception { _httpClient.stop(); Thread.sleep(500); stopServer(); } /* ------------------------------------------------------------ */ @Test public void testGetWithContentExchange() throws Exception { final WebSocket clientWS = new WebSocket.OnTextMessage() { Connection _connection; /* ------------------------------------------------------------ */ public void onClose(int closeCode, String message) { } /* ------------------------------------------------------------ */ public void onOpen(Connection connection) { _connection=connection; _results.add("clientWS.onConnect"); _results.add(_connection); } /* ------------------------------------------------------------ */ public void onMessage(String data) { _results.add("clientWS.onMessage"); _results.add(data); } }; HttpExchange httpExchange=new HttpExchange() { /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer) */ @Override protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { waitFor(2); _results.add(new Integer(status)); super.onResponseStatus(version,status,reason); } /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.client.HttpExchange#onSwitchProtocol(org.eclipse.jetty.io.EndPoint) */ @Override protected Connection onSwitchProtocol(EndPoint endp) throws IOException { waitFor(3); WebSocketConnectionD00 connection = new WebSocketConnectionD00(clientWS,endp,new WebSocketBuffers(4096),System.currentTimeMillis(),1000,""); _results.add("onSwitchProtocol"); _results.add(connection); clientWS.onOpen(connection); return connection; } /* ------------------------------------------------------------ */ private void waitFor(int results) { try { int c=10; while(_results.size()<results && c-->0) Thread.sleep(10); } catch(InterruptedException e) { e.printStackTrace(); } } }; httpExchange.setURL("http://localhost:"+_port+"/"); httpExchange.setMethod(HttpMethods.GET); httpExchange.addRequestHeader("Upgrade","WebSocket"); httpExchange.addRequestHeader("Connection","Upgrade"); _httpClient.send(httpExchange); int status = httpExchange.waitForDone(); assertEquals(HttpExchange.STATUS_COMPLETED, status); assertEquals("serverWS.onConnect", _results.poll(1,TimeUnit.SECONDS)); TestWebSocket serverWS = (TestWebSocket)_results.poll(1,TimeUnit.SECONDS); assertEquals(new Integer(101), _results.poll(1,TimeUnit.SECONDS)); assertEquals("onSwitchProtocol", _results.poll(1,TimeUnit.SECONDS)); WebSocketConnectionD00 client_conn=(WebSocketConnectionD00)_results.poll(1,TimeUnit.SECONDS); assertEquals("clientWS.onConnect", _results.poll(1,TimeUnit.SECONDS)); assertEquals(client_conn, _results.poll(1,TimeUnit.SECONDS)); client_conn.sendMessage("hello world"); assertEquals("serverWS.onMessage", _results.poll(1,TimeUnit.SECONDS)); assertEquals("hello world", _results.poll(1,TimeUnit.SECONDS)); serverWS.sendMessage("buongiorno"); assertEquals("clientWS.onMessage", _results.poll(1,TimeUnit.SECONDS)); assertEquals("buongiorno", _results.poll(1,TimeUnit.SECONDS)); } /* ------------------------------------------------------------ */ protected void newServer() throws Exception { _server=new Server(); _server.setGracefulShutdown(500); _connector=new SelectChannelConnector(); _connector.setPort(0); _server.setConnectors(new Connector[] { _connector }); } /* ------------------------------------------------------------ */ protected void startServer() throws Exception { newServer(); _handler= new WebSocketHandler() { /* ------------------------------------------------------------ */ public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { _websocket = new TestWebSocket(); return _websocket; } }; _server.setHandler(_handler); _server.start(); _port=_connector.getLocalPort(); } /* ------------------------------------------------------------ */ private void stopServer() throws Exception { _server.stop(); _server.join(); } /* ------------------------------------------------------------ */ class TestWebSocket implements WebSocket.OnTextMessage { Connection _connection; /* ------------------------------------------------------------ */ public void onOpen(Connection connection) { _connection=connection; _webSockets.add(this); _results.add("serverWS.onConnect"); _results.add(this); } /* ------------------------------------------------------------ */ public void onMessage(final String data) { _results.add("serverWS.onMessage"); _results.add(data); } /* ------------------------------------------------------------ */ public void onClose(int code, String message) { _results.add("onClose"); _webSockets.remove(this); } /* ------------------------------------------------------------ */ public void sendMessage(String msg) throws IOException { _connection.sendMessage(msg); } } }