/* * ChatServerTest.java * * Created on Jun 30, 2008, 10:37:06 AM * * Description: . * * Copyright (C) Mar 5, 2010 reed. * * This program is free software; you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.texai.webserver; import org.texai.util.EnvironmentUtils; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import org.apache.log4j.Logger; import org.jboss.netty.bootstrap.ClientBootstrap; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.http.DefaultHttpRequest; import org.jboss.netty.handler.codec.http.HttpHeaders; import org.jboss.netty.handler.codec.http.HttpMethod; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpVersion; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.texai.network.netty.handler.AbstractHTTPRequestHandlerFactory; import org.texai.network.netty.handler.AbstractHTTPResponseHandler; import org.texai.network.netty.handler.HTTPRequestHandler; import org.texai.network.netty.handler.HTTPRequestHandlerFactory; import org.texai.network.netty.pipeline.HTTPClientPipelineFactory; import org.texai.network.netty.pipeline.PortUnificationChannelPipelineFactory; import org.texai.util.StringUtils; import org.texai.x509.KeyStoreTestUtils; import org.texai.x509.X509SecurityInfo; import static org.junit.Assert.*; /** * * @author reed */ public class ChatServerTest { /** the logger */ private static final Logger LOGGER = Logger.getLogger(ChatServerTest.class); /** the server port */ private static final int SERVER_PORT = 8088; public ChatServerTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } /** * Test of class ChatServer. */ @Test public void testChatServer() { LOGGER.info("testChatServer"); if (EnvironmentUtils.isWindows()) { LOGGER.info("bypassing chat server test on Windows"); return; } // create the chat server and inject dependencies final ChatServer chatServer = new ChatServer(); chatServer.setChatSession(new TestChatSession()); // configure the HTTP request handler by registering the chat server final HTTPRequestHandler httpRequestHandler = HTTPRequestHandler.getInstance(); httpRequestHandler.register(chatServer); // configure the server channel pipeline factory final AbstractHTTPRequestHandlerFactory httpRequestHandlerFactory = new HTTPRequestHandlerFactory(); final X509SecurityInfo x509SecurityInfo = KeyStoreTestUtils.getServerX509SecurityInfo(); final ChannelPipelineFactory channelPipelineFactory = new PortUnificationChannelPipelineFactory( null, // albusHCNMessageHandlerFactory, null, // bitTorrentHandlerFactory, httpRequestHandlerFactory, x509SecurityInfo); // configure the server final ServerBootstrap serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); assertEquals("{}", serverBootstrap.getOptions().toString()); serverBootstrap.setPipelineFactory(channelPipelineFactory); // bind and start to accept incoming connections serverBootstrap.bind(new InetSocketAddress(SERVER_PORT)); // test chat server with mock client mockHTTPClient(); final Timer timer = new Timer(); timer.schedule(new ShutdownTimerTask(), 3000); // shut down executor threads to exit LOGGER.info("releasing server resources"); serverBootstrap.releaseExternalResources(); timer.cancel(); } /** Provides a task to run when the external resources cannot be released. */ private static final class ShutdownTimerTask extends TimerTask { /** Runs the timer task. */ @Override public void run() { LOGGER.info("server resources not released"); System.exit(0); } } /** Tests the HTTP request and response messages. */ @SuppressWarnings({"ThrowableResultIgnored", "null"}) private void mockHTTPClient() { final ClientBootstrap clientBootstrap = new ClientBootstrap(new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // configure the client pipeline final Object clientResume_lock = new Object(); final AbstractHTTPResponseHandler httpResponseHandler = new MockHTTPResponseHandler(clientResume_lock); final X509SecurityInfo x509SecurityInfo = KeyStoreTestUtils.getClientX509SecurityInfo(); final ChannelPipeline channelPipeline = HTTPClientPipelineFactory.getPipeline( httpResponseHandler, x509SecurityInfo); clientBootstrap.setPipeline(channelPipeline); LOGGER.info("client pipeline: " + channelPipeline.toString()); // start the connection attempt ChannelFuture channelFuture = clientBootstrap.connect(new InetSocketAddress("localhost", SERVER_PORT)); // wait until the connection attempt succeeds or fails final Channel channel = channelFuture.awaitUninterruptibly().getChannel(); if (!channelFuture.isSuccess()) { LOGGER.warn(StringUtils.getStackTraceAsString(channelFuture.getCause())); fail(channelFuture.getCause().getMessage()); } LOGGER.info("client connected"); URI uri = null; HttpRequest httpRequest; String host; // send the clear-file-cache request try { uri = new URI("https://localhost:" + SERVER_PORT + "/clear-file-cache"); } catch (URISyntaxException ex) { fail(ex.getMessage()); } httpRequest = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, uri.toASCIIString()); host = uri.getHost() == null ? "localhost" : uri.getHost(); httpRequest.setHeader(HttpHeaders.Names.HOST, host); httpRequest.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); LOGGER.info("client httpRequest ...\n" + httpRequest); channel.write(httpRequest); // wait for the request message to be sent channelFuture.awaitUninterruptibly(); if (!channelFuture.isSuccess()) { LOGGER.warn(StringUtils.getStackTraceAsString(channelFuture.getCause())); fail(channelFuture.getCause().getMessage()); } // the message response handler will signal this thread when the test exchanges are completed LOGGER.info("client waiting for server to process the request"); synchronized (clientResume_lock) { try { clientResume_lock.wait(); } catch (InterruptedException ex) { } } LOGGER.info("client releasing HTTP resources"); channel.close(); clientBootstrap.releaseExternalResources(); } }