/** Tests if the Comet connection is closed if the Tomcat connector is stopped. */ @Test public void testCometConnectorStop() throws Exception { Assume.assumeTrue( "This test is skipped, because this connector does not support Comet.", isCometSupported()); // Setup Tomcat instance SimpleCometServlet servlet = new SimpleCometServlet(); Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context root = tomcat.addContext("", null); Tomcat.addServlet(root, "comet", servlet); root.addServletMapping("/", "comet"); tomcat.start(); // Create connection to Comet servlet final Socket socket = SocketFactory.getDefault().createSocket("localhost", getPort()); socket.setSoTimeout(10000); final OutputStream os = socket.getOutputStream(); String requestLine = "POST http://localhost:" + getPort() + "/ HTTP/1.1\r\n"; os.write(requestLine.getBytes()); os.write("transfer-encoding: chunked\r\n".getBytes()); os.write("\r\n".getBytes()); PingWriterThread writeThread = new PingWriterThread(100, os); writeThread.start(); InputStream is = socket.getInputStream(); ResponseReaderThread readThread = new ResponseReaderThread(is); readThread.start(); // Allow the first couple of PING messages to be written Thread.sleep(3000); tomcat.getConnector().stop(); // Wait for the read and write threads to stop readThread.join(5000); writeThread.join(5000); // Destroy the connector once the executor has sent the end event tomcat.getConnector().destroy(); String[] response = readThread.getResponse().split("\r\n"); String lastMessage = ""; String lastResponseLine = ""; for (int i = response.length; --i >= 0; ) { lastMessage = response[i]; if (lastMessage.startsWith("Client:")) { break; } } for (int i = response.length; --i >= 0; ) { lastResponseLine = response[i]; if (lastResponseLine.length() > 0) { break; } } StringBuilder status = new StringBuilder(); // Expected, but is not 100% reliable: // WriteThread exception: java.net.SocketException // ReaderThread exception: null // Last message: [Client: END] // Last response line: [0] (empty chunk) // Last comet event: [END] // END event occurred: [true] status.append("Status:"); status.append("\nWriterThread exception: " + writeThread.getException()); status.append("\nReaderThread exception: " + readThread.getException()); status.append("\nLast message: [" + lastMessage + "]"); status.append("\nLast response line: [" + lastResponseLine + "]"); status.append("\nLast comet event: [" + servlet.getLastEvent() + "]"); status.append("\nEND event occurred: [" + servlet.getEndEventOccurred() + "]"); if (writeThread.getException() == null || !lastMessage.contains("Client: END") || !EventType.END.equals(servlet.getLastEvent())) { log.error(status); } else { log.info(status); } assertTrue("Comet END event not received", servlet.getEndEventOccurred()); assertTrue( "Comet END event not last event received", EventType.END.equals(servlet.getLastEvent())); }
private void doSimpleCometTest(String initParam) throws Exception { Assume.assumeTrue( "This test is skipped, because this connector does not support Comet.", isCometSupported()); // Setup Tomcat instance Tomcat tomcat = getTomcatInstance(); // No file system docBase required Context root = tomcat.addContext("", null); Wrapper w = Tomcat.addServlet(root, "comet", new SimpleCometServlet()); if (initParam != null) { w.addInitParameter(initParam, "true"); } root.addServletMapping("/", "comet"); TesterAccessLogValve alv = new TesterAccessLogValve(); root.getPipeline().addValve(alv); tomcat.start(); // Create connection to Comet servlet final Socket socket = SocketFactory.getDefault().createSocket("localhost", getPort()); socket.setSoTimeout(60000); final OutputStream os = socket.getOutputStream(); String requestLine = "POST http://localhost:" + getPort() + "/ HTTP/1.1\r\n"; os.write(requestLine.getBytes()); os.write("transfer-encoding: chunked\r\n".getBytes()); os.write("\r\n".getBytes()); PingWriterThread writeThread = new PingWriterThread(4, os); writeThread.start(); socket.setSoTimeout(25000); InputStream is = socket.getInputStream(); ResponseReaderThread readThread = new ResponseReaderThread(is); readThread.start(); readThread.join(); os.close(); is.close(); String[] response = readThread.getResponse().split("\r\n"); if (initParam == null) { // Normal response expected // Validate response assertEquals("HTTP/1.1 200 OK", response[0]); assertEquals("Server: Apache-Coyote/1.1", response[1]); assertTrue(response[2].startsWith("Set-Cookie: JSESSIONID=")); assertEquals("Content-Type: text/plain;charset=ISO-8859-1", response[3]); assertEquals("Transfer-Encoding: chunked", response[4]); assertTrue(response[5].startsWith("Date: ")); assertEquals("", response[6]); assertEquals("7", response[7]); assertEquals("BEGIN", response[8]); assertEquals("", response[9]); assertEquals("17", response[10]); assertEquals("Client: READ: 4 bytes", response[11]); assertEquals("", response[12]); assertEquals("17", response[13]); assertEquals("Client: READ: 4 bytes", response[14]); assertEquals("", response[15]); assertEquals("17", response[16]); assertEquals("Client: READ: 4 bytes", response[17]); assertEquals("", response[18]); assertEquals("17", response[19]); assertEquals("Client: READ: 4 bytes", response[20]); assertEquals("", response[21]); assertEquals("d", response[22]); assertEquals("Client: END", response[23]); assertEquals("", response[24]); assertEquals("0", response[25]); // Expect 26 lines assertEquals(26, response.length); } else { // Failure expected only expected for the fail on begin // Failure at any later stage and the response headers (including // the 200 response code will already have been sent to the client if (SimpleCometServlet.FAIL_ON_BEGIN.equals(initParam)) { assertEquals("HTTP/1.1 500 Internal Server Error", response[0]); alv.validateAccessLog(1, 500, 0, 1000); } else { assertEquals("HTTP/1.1 200 OK", response[0]); alv.validateAccessLog(1, 200, 0, 5000); } } }