Hi Vincent and Dave, Sorry, I had take mistake.
In article <[EMAIL PROTECTED]>, Tue, 3 Feb 2004 16:30:47 +1200, [EMAIL PROTECTED] wrote: dsearle> 2 Modify Servlet Test Runner (or create a new runner) that can run in a dsearle> asynchronous mode. dsearle> This would involve spawning a thread to run the actual test and storing the dsearle> TestResult somewhere (e.g. ServletContext) with an ID. dsearle> The browser could then reload the page (automatically if required) with an ID dsearle> for the TestResult. My only concern with this approach is any threading issues? I wrote such kind of Servlet Test Runner before, and find it. I don't use this Servlet Test Runner because I decided to not use browser interface. So, the classes are not maintaind for a long time. However, I think this is good enough for the stat point. Regards, ---- Kazuhito SUGURI mailto:[EMAIL PROTECTED]
/* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Cactus" and "Apache Software * Foundation" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.cactus.server.runner; import java.io.InputStream; import java.io.IOException; import java.io.Reader; import java.io.PrintWriter; import java.io.StringReader; import java.io.Writer; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Hashtable; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.UnavailableException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import junit.framework.Test; import junit.framework.TestResult; import org.apache.cactus.configuration.BaseConfiguration; /** * Helper servlet to start a JUnit Test Runner in a webapp. * * <p> * This class currently does a couple of reflection tricks to avoid a direct * dependancy on the TraX API (<code>javax.xml.transform.*</code>), * encapsulated in the [EMAIL PROTECTED] XMLTransformer} class. * </p> * * @author <a href="mailto:[EMAIL PROTECTED]">Vincent Massol</a> * @author <a href="mailto:[EMAIL PROTECTED]">Christopher Lenz</a> * * @author Kazuhito SUGURI * * @version $Id$ */ public class CustomServletTestRunner extends HttpServlet { /** * ServletContext attribute name for ThreadTestRunner Container. */ private static final String TEST_RUNNER_CONTAINER_ATTR = "org.apache.cactus.server.runner.ThreadTestRunnerContainer"; /** * HTTP parameter containing id to find existing TestTestRunner. */ private static final String HTTP_ORDERID_PARAM = "orderid"; /** * HTTP parameter containing name of test suite to execute */ private static final String HTTP_SUITE_PARAM = "suite"; /** * HTTP parameter that determines whether the XML test results should be * transformed using the XSLT stylesheet specified as initialization * parameter. */ private static final String HTTP_TRANSFORM_PARAM = "transform"; /** * HTTP parameter containing name of the XSL stylesheet to put in the * returned XML test result. It will only work if the browser supports * this feature (IE does, I don't know about others). */ private static final String HTTP_XSL_PARAM = "xsl"; /** * Name of the servlet initialization parameter that contains the path to * the XSLT stylesheet for transforming the XML report into HTML. */ private static final String XSL_STYLESHEET_PARAM = "xsl-stylesheet"; /** * Name of the servlet initialization parameter that specifies * web-refresh interval time in sec. */ private static final String REFRESH_INTERVAL_PARAM = "refresh-interval"; /** * The default web-refresh interval time in sec. */ private static final int DEFAULT_REFRESH_INTERVAL = 5; /** * The XML transformer. Avoid direct dependancy by using reflection. */ private Object transformer = null; /** * Indicates whether the servlet has sufficient permissions to set a * system property, to be able to set the cactus.contentURL property. This * is set to false if the first attempt to set the property throws a * SecurityException. */ private boolean canSetSystemProperty = true; private int refreshInterval; /** * Called by the container when the servlet is initialized. * * @throws ServletException If an initialization parameter contains an * illegal value */ public void init() throws ServletException { initXSLTprocessor(); initTestRunnerContainer(); refreshInterval = getRefreshInterval(); } private void initXSLTprocessor() throws ServletException { // Check whether XSLT transformations should be done server-side and // build the templates if an XSLT processor is available String xslStylesheetParam = getInitParameter(XSL_STYLESHEET_PARAM); if (xslStylesheetParam != null) { InputStream xslStylesheet = getServletContext().getResourceAsStream(xslStylesheetParam); if (xslStylesheet != null) { try { Class transformerClass = Class.forName( "org.apache.cactus.server.runner.XMLTransformer"); Constructor transformerCtor = transformerClass.getConstructor( new Class[] {InputStream.class}); transformer = transformerCtor.newInstance( new Object[] {xslStylesheet}); } catch (Throwable t) { log("Could not instantiate XMLTransformer - will not " + "perform server-side XSLT transformations", t); } } else { throw new UnavailableException( "The initialization parameter 'xsl-stylesheet' does not " + "refer to an existing resource"); } } } /** * Prepare ThreadTestRunner Container. */ private synchronized void initTestRunnerContainer(){ Hashtable container = getTestRunnerContainer(); if(container==null){ setTestRunnerContainer(new Hashtable()); } } private synchronized void setTestRunnerContainer(Hashtable container){ getServletContext().setAttribute(TEST_RUNNER_CONTAINER_ATTR, container); } /** * Get current ThreadTestRunner Container. */ private Hashtable getTestRunnerContainer(){ ServletContext context = getServletContext(); return (Hashtable)context.getAttribute(TEST_RUNNER_CONTAINER_ATTR); } /** * get refresh interval value. */ private int getRefreshInterval(){ try{ String interval = getInitParameter(REFRESH_INTERVAL_PARAM); return Integer.parseInt(interval); }catch(Exception e){ return DEFAULT_REFRESH_INTERVAL; } } /** * Starts the test suite passed as a HTTP parameter * * @param theRequest the incoming HTTP client request * @param theResponse the outgoing HTTP client request to send back. * * @exception ServletException if an error occurs when servicing the * request * @exception IOException if an error occurs when servicing the request */ public void doGet(HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException { ThreadTestRunner runner; String orderId = theRequest.getParameter(HTTP_ORDERID_PARAM); if(orderId==null){ try{ runner = getNewTestRunner(theRequest, theResponse); runner.start(); }catch(Exception e){ throw new ServletException("cannot start ThreadTestRunner", e); } addTestRunner(runner.getId(), runner); responseRedirect(theRequest, theResponse, runner); return; } runner = getTestRunner(orderId); if(runner==null){ throw new ServletException("no ThreadTestRunner exists [id=" + orderId + "]"); } if(runner.isAlive()){ responseRefresh(theRequest, theResponse, runner); }else{ responseResult(theRequest, theResponse, runner); } } private void responseRefresh(HttpServletRequest theRequest, HttpServletResponse theResponse, ThreadTestRunner runner) throws ServletException, IOException { theResponse.setHeader("Pragma", "no-cache"); theResponse.setHeader("Cache-Control", "no-cache"); theResponse.setIntHeader("Refresh", refreshInterval); theResponse.setContentType("text/plain"); PrintWriter out = theResponse.getWriter(); out.print("now testing (id="); out.print(runner.getId()); out.println(")"); } private void responseRedirect(HttpServletRequest theRequest, HttpServletResponse theResponse, ThreadTestRunner runner) throws ServletException, IOException { theResponse.setStatus(theResponse.SC_MOVED_TEMPORARILY); theResponse.setHeader("Location", theRequest.getRequestURI() + "?" + HTTP_ORDERID_PARAM + "=" + runner.getId()); } private void responseResult(HttpServletRequest theRequest, HttpServletResponse theResponse, ThreadTestRunner runner) throws ServletException, IOException { String xml = runner.getResult(); removeTestRunner(runner); if(runner.transformRequired() && (transformer!=null)){ try { Method getContentTypeMethod = transformer.getClass().getMethod("getContentType", new Class[0]); String contentType = (String)getContentTypeMethod.invoke(transformer, new Object[0]); theResponse.setContentType(contentType); PrintWriter out = theResponse.getWriter(); Method transformMethod = transformer.getClass().getMethod("transform", new Class[]{Reader.class, Writer.class}); transformMethod.invoke(transformer, new Object[]{new StringReader(xml), out}); }catch (Exception e){ throw new ServletException("Problem applying the XSLT transformation", e); } }else{ // Transform client side (or not at all) theResponse.setContentType("text/xml"); PrintWriter pw = theResponse.getWriter(); pw.println(xml); } } private ThreadTestRunner getNewTestRunner(HttpServletRequest theRequest, HttpServletResponse theResponse) throws Exception { String orderId = getNewOrderId(theRequest); ThreadTestRunner runner = new ThreadTestRunner(orderId); // Verify if a suite parameter exists String suiteClassName = theRequest.getParameter(HTTP_SUITE_PARAM); if(suiteClassName==null){ throw new ServletException("Missing HTTP parameter [" + HTTP_SUITE_PARAM + "] in request"); } runner.setTestSuite(suiteClassName); // Get the XSL stylesheet parameter if any String xslParam = theRequest.getParameter(HTTP_XSL_PARAM); runner.setXslFilename(xslParam); // Get the transform parameter if any String transformParam = theRequest.getParameter(HTTP_TRANSFORM_PARAM); runner.setTransform((transformParam!=null)); String contextURL = getContextURL(theRequest); runner.setSystemProperty(BaseConfiguration.CACTUS_CONTEXT_URL_PROPERTY, contextURL); return runner; } private ThreadTestRunner getTestRunner(String orderId){ Hashtable container = getTestRunnerContainer(); return (ThreadTestRunner)container.get(orderId); } /** * add new ThreadTestRunner instance associated with orderId * to the Container. */ private synchronized void addTestRunner(String orderId, ThreadTestRunner runner) { Hashtable container = getTestRunnerContainer(); container.put(runner.getId(), runner); setTestRunnerContainer(container); } private synchronized void removeTestRunner(ThreadTestRunner runner){ Hashtable container = getTestRunnerContainer(); container.remove(runner.getId()); setTestRunnerContainer(container); } private String getNewOrderId(HttpServletRequest theRequest){ // TODO: more stronger.. StringBuffer id = new StringBuffer(); id.append(theRequest.getServerName()); id.append("-"); id.append(Long.toHexString(System.currentTimeMillis())); return id.toString(); } private String getContextURL(HttpServletRequest theRequest){ StringBuffer context = new StringBuffer(); context.append("http://"); context.append(theRequest.getServerName()); context.append(":"); context.append(theRequest.getServerPort()); context.append(theRequest.getContextPath()); return context.toString(); } }
/* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Cactus" and "Apache Software * Foundation" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.cactus.server.runner; import junit.framework.Test; import junit.framework.TestResult; public class ThreadTestRunner extends Thread { private boolean canSetSystemProperty = true; private XMLFormatter formatter; private String id; private TestResult result; private Test suite; private WebappTestRunner testRunner; private boolean transform = false; public ThreadTestRunner(String orderId){ id = orderId; formatter = new XMLFormatter(); result = new TestResult(); testRunner = new WebappTestRunner(); } public void setTestSuite(String theSuiteClassName) throws Exception { suite = testRunner.getTest(theSuiteClassName); if(suite==null){ throw new Exception("Failed to load test suite [" + theSuiteClassName + "], Reason is [" + testRunner.getErrorMessage() + "]"); } formatter.setSuiteClassName(theSuiteClassName); } public void setXslFilename(String theXslFileName){ formatter.setXslFileName(theXslFileName); } public void setTransform(boolean flag){ transform = flag; } /** * Set System property for test-runner. */ public void setSystemProperty(String name, String value) throws SecurityException { if(! this.canSetSystemProperty){ return; } if((name==null) || (value==null)){ return; } try { System.setProperty(name, value); }catch (SecurityException se){ this.canSetSystemProperty = false; throw se; } } /** * Run the suite tests. */ public void run(){ result.addListener(formatter); long startTime = System.currentTimeMillis(); suite.run(this.result); long endTime = System.currentTimeMillis(); formatter.setTotalDuration(endTime - startTime); } /** * return the result. */ public String getResult(){ if(! this.isAlive()){ return formatter.toXML(this.result); }else{ return "now running"; } } public boolean transformRequired(){ return transform; } public String getId(){ return this.id; } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
