ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sbaill...@apache.org
Subject cvs commit: jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote MessageIds.java MessageReader.java MessageWriter.java Server.java TestRunner.java
Date Sat, 05 Jan 2002 20:18:34 GMT
sbailliez    02/01/05 12:18:34

  Added:       proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote
                        MessageIds.java MessageReader.java
                        MessageWriter.java Server.java TestRunner.java
  Log:
  initial commit.
  Code based from Erich Gamma's plugin for Eclipse.
  It has been heavily changed so I believe that not much is in
  common now except the content of the message identifiers. :-)
  
  I use Base64 encoding for transferring serialized objects and stacktrace.
  This can be greatly simplified but it is ok for now.
  
  Revision  Changes    Path
  1.1                  jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/MessageIds.java
  
  Index: MessageIds.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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", "Ant", 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 apache@apache.org.
   *
   * 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.tools.ant.taskdefs.optional.junit.remote;
  
  
  /**
   * A set of messages identifiers to be used for communication
   * between server/client(TestRunner).
   *
   * <i>
   * This code is based on the code from Erich Gamma made for the
   * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
   * with code originating from Ant 1.4.x.
   * </i>
   *
   * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   */
  public interface MessageIds {
      int MSG_HEADER_LENGTH = 8;
  
      // messages send by TestRunServer
      String TRACE_START = "%TRACES ";
      String TRACE_END = "%TRACEE ";
  
      // a line printed on stdout
      String STDOUT_START = "%STDOUTS";
      String STDOUT_END = "%STDOUTE";
  
      // a line printed on stderr
      String STDERR_START = "%STDERRS";
      String STDERR_END = "%STDERRE";
  
      // JVM system properties used in the VM
      String PROPS_START = "%SYSPROS";
      String PROPS_END = "%SYSPROE";
  
      // test run started...
      String TEST_COUNT = "%TESTC  ";
      // a test just started
      String TEST_START = "%TESTS  ";
      // a test is finished
      String TEST_END = "%TESTE  ";
      String TEST_ERROR = "%ERROR  ";
      String TEST_FAILED = "%FAILED ";
      String TEST_ELAPSED_TIME = "%RUNTIME";
      String TEST_STOPPED = "%TSTSTP ";
  
      // messages understood by the Server
      String TEST_STOP = ">STOP   ";
  }
  
  
  1.1                  jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/MessageReader.java
  
  Index: MessageReader.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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", "Ant", 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 apache@apache.org.
   *
   * 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.tools.ant.taskdefs.optional.junit.remote;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.ObjectInputStream;
  import java.io.ByteArrayInputStream;
  import java.util.Vector;
  import java.util.Properties;
  
  import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
  
  /**
   * Read and dispatch messages received via an input stream.
   * The inputstream should be the connection to the remote client.
   * <p>
   * All messages are dispatched to the registered listeners.
   * </p>
   * <i>
   * This code is based on the code from Erich Gamma made for the
   * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
   * with code originating from Ant 1.4.x.
   * </i>
   *
   * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   */
  public class MessageReader {
  
      /** the set of registered listeners */
      protected Vector listeners = new Vector();
  
      // communication states with client
      protected boolean inReadTrace = false;
      protected boolean inFailedMessage = false;
      protected String failedTest;
      protected String failedMessage;
      protected String failedTrace;
      protected int failureKind;
      protected long elapsedTime;
      protected Properties sysprops;
  
      public MessageReader() {
      }
  
      /**
       * Add a new listener.
       * @param listener a listener that will receive events from the client.
       */
      public void addListener(TestRunListener listener) {
          listeners.addElement(listener);
      }
  
      public void removeListener(TestRunListener listener) {
          listeners.removeElement(listener);
      }
  
      /**
       * Read a complete stream from a client, it will only return
       * once the connection is stopped. You'd better not reuse
       * an instance of this class since there are instance variables used
       * to keep track of the client state.
       * @param in the inputstream to the client.
       */
      public void process(InputStream in) throws IOException {
          BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF8"));
          String line;
          while ((line = reader.readLine()) != null) {
              processMessage(line);
          }
      }
  
      /**
       * Process a message from the client and dispatch the
       * appropriate message to the listeners.
       */
      protected void processMessage(String message) {
          if (message == null){
              return;
          }
  
          String arg = message.substring(MessageIds.MSG_HEADER_LENGTH);
          if (message.startsWith(MessageIds.TRACE_START)) {
              failedTrace = arg.substring(0, arg.indexOf(MessageIds.TRACE_END));
              failedTrace = new String(Base64.decode(failedTrace.getBytes()));
              notifyTestFailed(failureKind, failedTest, failedTrace);
              return;
          }
  
          if (message.startsWith(MessageIds.TEST_COUNT)) {
              int count = Integer.parseInt(arg);
              notifyTestSuiteStarted(count);
              return;
          }
          if (message.startsWith(MessageIds.TEST_START)) {
              notifyTestStarted(arg);
              return;
          }
          if (message.startsWith(MessageIds.TEST_END)) {
              notifyTestEnded(arg);
              return;
          }
          if (message.startsWith(MessageIds.TEST_ERROR)) {
              failedTest = arg;
              failureKind = TestRunListener.STATUS_ERROR;
              return;
          }
          if (message.startsWith(MessageIds.TEST_FAILED)) {
              failedTest = arg;
              failureKind = TestRunListener.STATUS_FAILURE;
              return;
          }
          if (message.startsWith(MessageIds.TEST_ELAPSED_TIME)) {
              elapsedTime = Long.parseLong(arg);
              notifyTestSuiteEnded(elapsedTime);
              return;
          }
          if (message.startsWith(MessageIds.TEST_STOPPED)) {
              elapsedTime = Long.parseLong(arg);
              notifyTestSuiteStopped(elapsedTime);
              return;
          }
          if (message.startsWith(MessageIds.PROPS_START)){
              try {
                  byte[] bytes = arg.substring(0, arg.indexOf(MessageIds.PROPS_END)).getBytes();
                  bytes = Base64.decode(bytes);
                  ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                  sysprops = (Properties)ois.readObject();
              } catch (Exception e){
                  // ignore now
                  e.printStackTrace();
              }
              notifyTestSystemProperties(sysprops);
          }
      }
  
      protected void notifyTestStarted(String testname) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testStarted(testname);
              }
          }
      }
  
      protected void notifyTestEnded(String testname) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testEnded(testname);
              }
          }
      }
  
      protected void notifyTestFailed(int kind, String testname, String trace) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testFailed(kind, testname, trace);
              }
          }
      }
  
      protected void notifyTestSuiteStarted(int count) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testRunStarted(count);
              }
          }
      }
  
      protected void notifyTestSuiteEnded(long elapsedtime) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testRunEnded(elapsedtime);
              }
          }
      }
  
      protected void notifyTestSuiteStopped(long elapsedtime) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testRunStopped(elapsedtime);
              }
          }
      }
  
      protected void notifyTestSystemProperties(Properties props) {
          synchronized (listeners) {
              for (int i = 0; i < listeners.size(); i++) {
                  ((TestRunListener) listeners.elementAt(i)).testRunSystemProperties(props);
              }
          }
      }
  
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/MessageWriter.java
  
  Index: MessageWriter.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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", "Ant", 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 apache@apache.org.
   *
   * 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.tools.ant.taskdefs.optional.junit.remote;
  
  import java.io.OutputStream;
  import java.io.PrintWriter;
  import java.io.ObjectOutputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  
  import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
  
  /**
   * A wrapper that sends string messages to a given stream.
   *
   * <i>
   * This code is based on the code from Erich Gamma made for the
   * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
   * with code originating from Ant 1.4.x.
   * </i>
   *
   * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   */
  public class MessageWriter implements MessageIds {
  
      private PrintWriter pw;
  
      public MessageWriter(OutputStream out) {
          this.pw = new PrintWriter(out, true);
      }
  
      protected void finalize(){
          close();
      }
  
      public void close() {
          if (pw != null){
              pw.close();
              pw = null;
          }
      }
  
      public void sendMessage(String msg) {
          pw.println(msg);
      }
  
  // --------  notifier helper methods
  
      public void notifyTestRunStarted(int testCount) {
          sendMessage(MessageIds.TEST_COUNT + testCount);
      }
  
      public void notifyTestRunEnded(long elapsedTime) {
          sendMessage(MessageIds.TEST_ELAPSED_TIME + elapsedTime);
      }
  
      public void notifyTestRunStopped(long elapsedTime) {
          sendMessage(MessageIds.TEST_STOPPED + elapsedTime);
      }
  
      public void notifyTestStarted(String testName) {
          sendMessage(MessageIds.TEST_START + testName);
      }
  
      public void notifyTestEnded(String testName) {
          sendMessage(MessageIds.TEST_END + testName);
      }
  
      public void notifyTestFailed(int status, String testName, String trace) {
          if (status == TestRunListener.STATUS_FAILURE) {
              sendMessage(MessageIds.TEST_FAILED + testName);
          } else {
              sendMessage(MessageIds.TEST_ERROR + testName);
          }
          sendMessage(MessageIds.TRACE_START + new String(Base64.encode(trace.getBytes()))
+ MessageIds.TRACE_END);
      }
  
      public void notifyStdOutLine(String testname, String line) {
          sendMessage(MessageIds.STDOUT_START);
          sendMessage(line);
          sendMessage(MessageIds.STDOUT_END);
      }
  
      public void notifyStdErrLine(String testname, String line) {
          sendMessage(MessageIds.STDERR_START);
          sendMessage(line);
          sendMessage(MessageIds.STDERR_END);
      }
  
      public void notifySystemProperties() {
          try {
              ByteArrayOutputStream out = new ByteArrayOutputStream();
              ObjectOutputStream oos = new ObjectOutputStream(out);
              oos.writeObject(System.getProperties());
              oos.close();
              String msg = new String(Base64.encode(out.toByteArray()));
              sendMessage(MessageIds.PROPS_START + msg + MessageIds.PROPS_END);
          } catch (IOException e){
              // ignore
              e.printStackTrace();
          }
      }
  
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/Server.java
  
  Index: Server.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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", "Ant", 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 apache@apache.org.
   *
   * 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.tools.ant.taskdefs.optional.junit.remote;
  
  import java.io.IOException;
  import java.io.PrintWriter;
  import java.net.ServerSocket;
  import java.net.Socket;
  
  import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
  
  /**
   * The server that will receive events from a remote client.
   *
   * <i>
   * This code is based on the code from Erich Gamma made for the
   * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
   * with code originating from Ant 1.4.x.
   * </i>
   *
   * @see TestRunner
   * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   */
  public class Server {
  
      /** the port where the server is listening */
      private int port = -1;
  
      /** the server socket */
      private ServerSocket server;
  
      /** the client that is connected to the server */
      private Socket client;
  
      /** the reader in charge of interpreting messages from the client */
      private MessageReader reader = new MessageReader();
  
      /** writer used to send message to clients */
      private PrintWriter writer;
  
      public Server(int port) {
          this.port = port;
      }
  
      /**
       * add a new listener
       * @param listener a instance of a listener.
       */
      public void addListener(TestRunListener listener) {
          reader.addListener(listener);
      }
  
      /**
       * remove an existing listener
       * @param listener a instance of a listener.
       */
      public void removeListener(TestRunListener listener) {
          reader.removeListener(listener);
      }
  
      /** return whether there is a client running or not */
      public boolean isRunning() {
          return client != null;
      }
  
      /** start a server to the specified port */
      public void start() {
          Worker worker = new Worker();
          worker.start();
      }
  
      /** cancel the connection to the client */
      public void cancel() {
          if (isRunning()) {
              //@fixme
          }
      }
  
      /** shutdown the server and any running client */
      public void shutdown() {
          try {
              if (client != null) {
                  client.shutdownInput();
                  client.shutdownOutput();
              }
              server.close();
          } catch (IOException e) {
          }
      }
  
  //-----
  
      private class Worker extends Thread {
          public void run() {
              try {
                  server = new ServerSocket(port);
                  client = server.accept();
                  writer = new PrintWriter(client.getOutputStream(), true);
                  reader.process(client.getInputStream());
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
                  stop();
                  shutdown();
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/proposal/sandbox/junit/src/main/org/apache/tools/ant/taskdefs/optional/junit/remote/TestRunner.java
  
  Index: TestRunner.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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", "Ant", 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 apache@apache.org.
   *
   * 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.tools.ant.taskdefs.optional.junit.remote;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.FileInputStream;
  import java.net.Socket;
  import java.util.Vector;
  import java.util.Properties;
  import java.util.StringTokenizer;
  
  import junit.framework.AssertionFailedError;
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestListener;
  import junit.framework.TestResult;
  import junit.framework.TestSuite;
  
  import org.apache.tools.ant.util.StringUtils;
  import org.apache.tools.ant.taskdefs.optional.junit.JUnitHelper;
  import org.apache.tools.ant.taskdefs.optional.junit.TestRunListener;
  
  /**
   * TestRunner for running tests and send results to a remote server.
   *
   * <i>
   * This code is originally based on the code from Erich Gamma made for the
   * JUnit plugin for Eclipse. {@link http://www.eclipse.org} and is merged
   * with code ideas originating from Ant 1.4.x.
   * </i>
   *
   * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   */
  public class TestRunner implements TestListener {
  
      /** host to connect to */
      private String host = "127.0.0.1";
  
      /** port to connect to */
      private int port = -1;
  
      private boolean debug = false;
  
      /** the list of test class names to run */
      private Vector testClassNames = new Vector();
  
      /** result of the current test */
      private TestResult testResult;
  
      /** client socket to communicate with the server */
      private Socket clientSocket;
  
      /** writer to send message to the server */
      private MessageWriter writer;
  
      /** reader to listen for a shutdown from the server */
      private BufferedReader reader;
  
      /** bean constructor */
      public TestRunner(){
      }
  
      /**
       * Set the debug mode.
       * @param debug true to set to debug mode otherwise false.
       */
      public void setDebug(boolean debug) {
          this.debug = debug;
      }
  
      /**
       * Set the port to connect to the server
       * @param port a valid port number.
       */
      public void setPort(int port) {
          this.port = port;
      }
  
      /**
       * Set the hostname of the server
       * @param host the hostname or ip of the server
       */
      public void setHost(String host) {
          this.host = host;
      }
  
      /**
       * Add a test class name to be executed by this runner.
       * @param classname the class name of the test to run.
       */
      public void addTestClassName(String classname) {
          testClassNames.addElement(classname);
      }
  
      /**
       * Thread listener for a shutdown from the server
       * Note that it will stop any running test.
       */
      private class StopThread extends Thread {
          public void run() {
              try {
                  String line = null;
                  if ((line = reader.readLine()) != null) {
                      if (line.startsWith(MessageIds.TEST_STOP)) {
                          TestRunner.this.stop();
                      }
                  }
              } catch (Exception e) {
                  TestRunner.this.stop();
              }
          }
      }
  
      /**
       * Entry point for command line.
       * Usage:
       * <pre>
       * TestRunner -classnames <classnames> -port <port> -host <host> -debug
       * -file
       * -classnames <list of whitespace separated classnames to run>
       * -port       <port to connect to>
       * -host       <host to connect to>
       * -debug      to run in debug mode
       * </pre>
       */
      public static void main(String[] args) throws Exception {
          TestRunner testRunServer = new TestRunner();
          testRunServer.init(args);
          testRunServer.run();
      }
  
      /**
       * Parses the arguments of command line.
       * testClassNames, host, port, listeners and debug mode are set
       * @see  #main(String[])
       */
      protected void init(String[] args) throws Exception {
          for (int i = 0; i < args.length; i++) {
              if ("-file".equalsIgnoreCase(args[i])) {
                  // @fixme if you mix file and other options it will be a mess,
                  // not important right now.
                  FileInputStream fis = new FileInputStream(args[i + 1]);
                  Properties props = new Properties();
                  props.load(fis);
                  fis.close();
                  init(props);
              }
              if ("-classnames".equalsIgnoreCase(args[i])) {
                  for (int j = i + 1; j < args.length; j++) {
                      if (args[j].startsWith("-"))
                          break;
                      addTestClassName(args[j]);
                  }
              }
              if ("-port".equalsIgnoreCase(args[i])) {
                  setPort(Integer.parseInt(args[i + 1]));
              }
              if ("-host".equalsIgnoreCase(args[i])) {
                  setHost(args[i + 1]);
              }
              if ("-debug".equalsIgnoreCase(args[i])) {
                  setDebug(true);
              }
          }
      }
      /**
       * Initialize the TestRunner from properties.
       * @param the properties containing configuration data.
       * @see #init(String[])
       */
      protected void init(Properties props){
          if ( props.getProperty("debug") != null ){
              setDebug(true);
          }
          String port = props.getProperty("port");
          if (port != null){
              setPort(Integer.parseInt(port));
          }
          String host = props.getProperty("host");
          if (host != null){
              setHost(host);
          }
          String classnames = props.getProperty("classnames");
          if (classnames != null){
              StringTokenizer st = new StringTokenizer(classnames);
              while (st.hasMoreTokens()){
                  addTestClassName( st.nextToken() );
              }
          }
      }
  
      public final void run() throws Exception {
          if (testClassNames.size() == 0) {
              throw new IllegalArgumentException("No TestCase specified");
          }
          connect();
  
          testResult = new TestResult();
          testResult.addListener(this);
          runTests();
  
          testResult.removeListener(this);
          if (testResult != null) {
              testResult.stop();
              testResult = null;
          }
      }
  
      /**
       * Transform all classnames into instantiated <tt>Test</tt>.
       * @throws Exception a generic exception that can be thrown while
       * instantiating a test case.
       */
      protected Test[] getSuites() throws Exception {
          final int count = testClassNames.size();
          log("Extracting testcases from " + count + " classnames...");
          final Vector suites = new Vector(count);
          for (int i = 0; i < count; i++) {
              String classname = (String) testClassNames.elementAt(i);
              try {
                  Test test = JUnitHelper.getTest(null, classname);
                  if (test != null){
                      suites.addElement(test);
                  }
              } catch (Exception e){
                  // notify log error instead ?
                  log("Could not get Test instance from " + classname);
                  log(e);
              }
          }
          log("Extracted " + suites.size() + " testcases.");
          Test[] array = new Test[suites.size()];
          suites.copyInto(array);
          return array;
      }
  
      /**
       * @param testClassNames String array of full qualified class names of test classes
       */
      private void runTests() throws Exception {
  
          Test[] suites = getSuites();
  
          // count all testMethods and inform TestRunListeners
          int count = countTests(suites);
          log("Total tests to run: " + count);
          writer.notifyTestRunStarted(count);
  
          // send system properties to know for the JVM status
          writer.notifySystemProperties();
  
          long startTime = System.currentTimeMillis();
          for (int i = 0; i < suites.length; i++) {
              if (suites[i] instanceof TestCase){
                  suites[i] = new TestSuite(suites[i].getClass().getName());
              }
              suites[i].run(testResult);
          }
  
          // inform TestRunListeners of test end
          long elapsedTime = System.currentTimeMillis() - startTime;
          if (testResult == null || testResult.shouldStop()) {
              writer.notifyTestRunStopped(elapsedTime);
          } else {
              writer.notifyTestRunEnded(elapsedTime);
          }
          log("Finished after " + elapsedTime + "ms");
          shutDown();
      }
  
      /** count the number of test methods in all tests */
      private final int countTests(Test[] tests) {
          int count = 0;
          for (int i = 0; i < tests.length; i++) {
              count = count + tests[i].countTestCases();
          }
          return count;
      }
  
      protected void stop() {
          if (testResult != null) {
              testResult.stop();
          }
      }
  
      /**
       * connect to the specified host and port.
       * @throws IOException if any error occurs during connection.
       */
      protected void connect() throws IOException {
          log("Connecting to " + host + " on port " + port + "...");
          clientSocket = new Socket(host, port);
          writer = new MessageWriter(clientSocket.getOutputStream());
          reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
          new StopThread().start();
      }
  
  
      protected void shutDown() {
  
          if (writer != null) {
              writer.close();
              writer = null;
          }
  
          try {
              if (reader != null) {
                  reader.close();
                  reader = null;
              }
          } catch (IOException e) {
              log(e);
          }
  
          try {
              if (clientSocket != null) {
                  clientSocket.close();
                  clientSocket = null;
              }
          } catch (IOException e) {
              log(e);
          }
      }
  
  
  // -------- JUnit TestListener implementation
  
  
      public void startTest(Test test) {
          String testName = test.toString();
          writer.notifyTestStarted(testName);
      }
  
      public void addError(Test test, Throwable t) {
          String testName = test.toString();
          String trace = StringUtils.getStackTrace(t);
          writer.notifyTestFailed(TestRunListener.STATUS_ERROR, testName, trace);
      }
  
      /**
       * this implementation is for JUnit &lt; 3.4
       * @see addFailure(Test, Throwable)
       */
      public void addFailure(Test test, AssertionFailedError afe) {
          addFailure(test, (Throwable) afe);
      }
  
      /**
       * This implementation is for JUnit &lt;= 3.4
       * @see addFailure(Test, AssertionFailedError)
       */
      public void addFailure(Test test, Throwable t) {
          String testName = test.toString();
          String trace = StringUtils.getStackTrace(t);
          writer.notifyTestFailed(TestRunListener.STATUS_FAILURE, testName, trace);
      }
  
      public void endTest(Test test) {
          String testName = test.toString();
          writer.notifyTestEnded(testName);
      }
  
      public void log(String msg){
          if (debug){
              System.out.println(msg);
          }
      }
  
      public void log(Throwable t){
          if (debug){
              t.printStackTrace();
          }
      }
  }
  
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message