1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.lib;
  28 
  29 import java.io.File;
  30 import java.io.PrintWriter;
  31 import com.sun.javatest.Command;
  32 import com.sun.javatest.Status;
  33 import com.sun.javatest.Test;
  34 import com.sun.javatest.util.DirectoryClassLoader;
  35 
  36 
  37 /**
  38  * ExecStdTestSameJVMCmd executes a standard test (one that implements
  39  * the Test interface) in the same Java Virtual Machine as the caller.
  40  *
  41  * It can use either a private class loader or the system class loader.
  42  * A private class loader will be created if the -loadDir option is given;
  43  * otherwise the system class loader will be used.  A private class
  44  * loader minimises the interference between tests, but you may be
  45  * restricted from using private class loaders if you are running the
  46  * harness inside a web browser.
  47  *
  48  * <p> If the the <code>-repeat</code> option is provided, then the test will be
  49  * run multiple times in the same JVM.  <code>Status.error()</code> will be
  50  * returned (and the remainder of the iterations will not be performed) if any
  51  * repetition of the test returns an error, or if the status return type changes
  52  * between iterations.  The returned status after each iteration will be
  53  * included in the log. If this option is not given, the test will be run once.
  54  *
  55  * @see com.sun.javatest.lib.ExecStdTestOtherJVMCmd
  56  */
  57 public class ExecStdTestSameJVMCmd extends Command
  58 {
  59     /**
  60      * The method that that does the work of the command.
  61      * @param args      [-loadDir <em>dir</em>] [-saveProps] <em>executeClass</em> <em>executeArgs</em>
  62      * @param log       A stream to which to report messages and errors
  63      * @param ref       A stream to which to write reference output
  64      * @return          The result of the command
  65      */
  66     public Status run(String[] args, PrintWriter log, PrintWriter ref) {
  67         int repeat = 1;
  68         String className = null;
  69         String[] executeArgs = { };
  70         ClassLoader loader = getClassLoader();
  71 
  72         int i = 0;
  73 
  74         for (; i < args.length && args[i].startsWith("-"); i++) {
  75             if ("-loadDir".equals(args[i]) && i+1 < args.length) {
  76                 // -loadDir is optional; if given, a new class loader will be created
  77                 // to load the class to execute;  if not given, the system class loader
  78                 // will be used.
  79                 loader = new DirectoryClassLoader(new File(args[++i]));
  80             } else if ("-repeat".equals(args[i]) && i+1 < args.length) {
  81                 // -repeat is optional; if given, the test will be run that
  82                 // number of times (in the same JVM)
  83                 try {
  84                     if ((repeat = Integer.parseInt(args[++i])) < 1)
  85                         return Status.error("Unexpected number of repetitions: " + repeat);
  86                 }
  87                 catch (NumberFormatException e) {
  88                     return Status.error("Unrecognized number of repetitions: " + repeat);
  89                 }
  90             }
  91         }
  92 
  93         // Next must come the executeClass
  94         if (i < args.length) {
  95             className = args[i];
  96             i++;
  97         } else
  98             return Status.failed("No executeClass specified");
  99 
 100         // Finally, any optional args
 101         if (i < args.length) {
 102             executeArgs = new String[args.length - i];
 103             System.arraycopy(args, i, executeArgs, 0, executeArgs.length);
 104         }
 105 
 106         Status status = null;
 107         try {
 108             Class<?> c;
 109             if (loader == null)
 110                 c = Class.forName(className);
 111             else
 112                 c = loader.loadClass(className);
 113 
 114             Status prevStatus = null;
 115             for (int j = 0; j < repeat; j++) {
 116                 if (repeat > 1)
 117                     log.println("iteration: " + (j+1));
 118 
 119                 Test t = (Test) (c.newInstance());
 120                 status = t.run(executeArgs, log, ref);
 121 
 122                 if (repeat > 1)
 123                     log.println("   " + status);
 124 
 125                 if ((prevStatus != null) && status.getType() != prevStatus.getType())
 126                     status = Status.error("Return status type changed at repetition: " + (j+1));
 127 
 128                 if (status.isError())
 129                     return status;
 130                 else
 131                     prevStatus = status;
 132             }
 133         }
 134         catch (ClassCastException e) {
 135             status = Status.failed("Can't load test: required interface not found");
 136         }
 137         catch (ClassNotFoundException e) {
 138             status = Status.failed("Can't load test: " + e);
 139         }
 140         catch (InstantiationException e) {
 141             status = Status.failed("Can't instantiate test: " + e);
 142         }
 143         catch (IllegalAccessException e) {
 144             status = Status.failed("Illegal access to test: " + e);
 145         }
 146         catch (VerifyError e) {
 147             return Status.failed("Class verification error while trying to load test class `" + className + "': " + e);
 148         }
 149         catch (LinkageError e) {
 150             return Status.failed("Class linking error while trying to load test class `" + className + "': " + e);
 151         }
 152         return status;
 153     }
 154 }
 155