changeset 33:d02552d5c1bd

patches from jtreg 4.1 RC
author jrose
date Tue, 20 Oct 2009 15:47:36 -0700
parents 7caa97f6f7b6
children 1317d1aa6fdf
files jtreg/jtreg-no-junit.zip jtreg/junitsupport.patch jtreg/junitsupport.txt
diffstat 3 files changed, 305 insertions(+), 158 deletions(-) [+]
line wrap: on
line diff
Binary file jtreg/jtreg-no-junit.zip has changed
--- a/jtreg/junitsupport.patch	Wed Oct 14 18:06:15 2009 -0700
+++ b/jtreg/junitsupport.patch	Tue Oct 20 15:47:36 2009 -0700
@@ -1,26 +1,20 @@
 6891715: jtreg should be able to run tests in JUnit format
+Reviewed-by: jjg, mr
+Portions are coded by jjg; these are reviewed by jrose.
 
-diff --git a/.hgignore b/.hgignore
---- a/.hgignore
-+++ b/.hgignore
-@@ -1,2 +1,3 @@
- ^(build|dist)/
--nbproject/private/
-\ No newline at end of file
-+nbproject/private/
-+^make/faq.*html
 diff --git a/make/Defs.gmk b/make/Defs.gmk
 --- a/make/Defs.gmk
 +++ b/make/Defs.gmk
-@@ -84,6 +84,12 @@
+@@ -84,6 +84,13 @@
  
  JAVATEST_JAR = $(JAVATEST_HOME)/lib/javatest.jar
  
-+#----- JUnit 4: see http://www.junit.org/
-+
++#----- JUnit 4.5: see http://www.junit.org/
 +# http://sourceforge.net/projects/junit/files/junit/4.5/junit-4.5.jar/download
 +
-+JUNIT_JAR = /w/jjg/work/os-jtreg/junit-4.5.jar
++ifndef JUNIT_JAR
++  JUNIT_JAR = /java/devtools/share/junit/junit-4.5/junit.jar
++endif
 +
  #----- Ant: see http://ant.apache.org/
  
@@ -39,12 +33,30 @@
 diff --git a/make/build.properties b/make/build.properties
 --- a/make/build.properties
 +++ b/make/build.properties
-@@ -39,6 +39,9 @@
+@@ -26,19 +26,25 @@
+ # set locations here, or in ${root}/build.properties, or set on the
+ # ant command line
+ 
++jtreg.build.resources = /w/jjg/work/jtreg
++# FIXME
++
+ # JTHarness or JavaTest (should be should be 4.1.3 or better)
+ #javatest.home = /w/jjg/work/os-jtreg/jtharness-4_1_2-MR1-Rel-b07/JTHarness-build/binaries/
+-javatest.home = /w/jjg/work/jtreg/jtharness-4_1_3-MR1-Rel-b08/JTHarness-build/binaries/
++javatest.home = ${jtreg.build.resources}/jtharness-4_1_3-MR1-Rel-b08/JTHarness-build/binaries/
+ javatest.jar = ${javatest.home}/lib/javatest.jar
+ #   the following is only true for older versions of JavaTest.
+ #   can't use <available> to set it automatically for some reason
+ #javatest.includes.javahelp.ok = true
+ 
+ # JavaHelp (should be version 2.0 or better)
+-javahelp.home = /w/jjg/work/jtreg/javahelp/javahelp_nbproject/dist
++javahelp.home = ${jtreg.build.resources}/javahelp/javahelp_nbproject/dist
  jhall.jar = ${javahelp.home}/lib/jhall.jar
  jh.jar = ${javahelp.home}/lib/jh.jar
  
 +# JUnit (should be 4.5 or better)
-+junit.jar = /w/jjg/work/os-jtreg/junit-4.5.jar
++junit.jar = ${jtreg.build.resources}/junit-4.5.jar
 +
  # Ant ((should be version 1.6.5 or better)
  #ant.home = 
@@ -295,53 +307,12 @@
 diff --git a/make/netbeans/jtreg/nbproject/project.xml b/make/netbeans/jtreg/nbproject/project.xml
 --- a/make/netbeans/jtreg/nbproject/project.xml
 +++ b/make/netbeans/jtreg/nbproject/project.xml
-@@ -56,16 +56,16 @@
-                     <location>${root}/make</location>
-                 </source-folder>
-                 <source-folder>
-+                    <label>jtreg</label>
-+                    <location>.</location>
-+                    <encoding>UTF-8</encoding>
-+                </source-folder>
-+                <source-folder>
-                     <label>Source files</label>
-                     <type>java</type>
-                     <location>${root}/src/share/classes</location>
-                     <encoding>UTF-8</encoding>
-                 </source-folder>
--                <source-folder>
--                    <label>jtreg</label>
--                    <location>.</location>
--                    <encoding>UTF-8</encoding>
--                </source-folder>
-             </folders>
-             <ide-actions>
-                 <action name="build">
-@@ -85,6 +85,10 @@
-                     <target>clean</target>
-                     <target>build</target>
-                 </action>
-+                <action name="debug">
-+                    <script>nbproject/ide-file-targets.xml</script>
-+                    <target>debug-nb</target>
-+                </action>
-             </ide-actions>
-             <view>
-                 <items>
-@@ -106,6 +110,7 @@
-                     <ide-action name="rebuild"/>
-                     <ide-action name="clean"/>
-                     <ide-action name="test"/>
-+                    <ide-action name="debug"/>
-                 </context-menu>
-             </view>
-             <subprojects/>
-@@ -113,7 +118,7 @@
+@@ -113,7 +113,7 @@
          <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/1">
              <compilation-unit>
                  <package-root>${root}/src/share/classes</package-root>
 -                <classpath mode="compile">${javatest.jar}:${jh.jar}:${ant.jar}</classpath>
-+                <classpath mode="compile">/Users/jrose/Downloads/jtharness-4_2_1-dev-bin-b10-24_sep_2009/lib/javatest.jar:/Users/jrose/Downloads/jtharness-4_2_1-dev-bin-b10-24_sep_2009/lib/jh.jar:/Users/jrose/Downloads/jtharness-4_2_1-dev-bin-b10-24_sep_2009/lib/jt-junit.jar:/Users/jrose/env/ANT_HOME/lib/ant.jar:/Users/jrose/Projects/jtharness/code/src:../../../../../env/jars/junit-4.5.jar</classpath>
++                <classpath mode="compile">${javatest.jar}:${jh.jar}:${ant.jar}:${junit.jar}</classpath>
                  <source-level>1.5</source-level>
              </compilation-unit>
          </java-data>
@@ -371,7 +342,7 @@
 new file mode 100644
 --- /dev/null
 +++ b/src/share/classes/com/sun/javatest/regtest/JUnitAction.java
-@@ -0,0 +1,143 @@
+@@ -0,0 +1,102 @@
 +/*
 + * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -411,10 +382,10 @@
 +/**
 + * This class implements the "junit" action, which is a variation of "main".
 + *
-+ * @author Iris A Garcia
-+ * @see Action
++ * @author John R. Rose
++ * @see MainAction
 + */
-+public class JUnitAction extends Action
++public class JUnitAction extends MainAction
 +{
 +    /**
 +     * This method does initial processing of the options and arguments for the
@@ -436,31 +407,18 @@
 +                     RegressionScript script)
 +        throws ParseException
 +    {
-+        this.script = script;
-+        this.reason = reason;
-+
-+        Class<?> junitRunner = junitRunnerClass();
-+        if (junitRunner == null)
-+            throw new ParseException(JUNIT_NO_DRIVER);
-+
 +        if (args.length == 0)
 +            throw new ParseException(JUNIT_NO_CLASSNAME);
 +
-+        mainAction = new MainAction();
-+        mainAction.init(opts, args, reason, script, junitRunner.getName());
++        init(opts, args, reason, script, JUnitRunner.class.getName());
 +
-+        if (mainAction.getMainArgs().length() != 0)
++        if (getMainArgs().length() != 0)
 +            throw new ParseException(JUNIT_BAD_MAIN_ARG);
 +
 +    } // init()
-+    
-+    @Override
-+    public File[] getSourceFiles() {
-+        return mainAction.getSourceFiles();
-+    }
 +
-+    public Class<?> junitRunnerClass() {
-+        return JUnitRunner.class;
++    protected String getActionName() {
++        return "junit";
 +    }
 +
 +    public static class JUnitRunner {
@@ -472,7 +430,7 @@
 +            try {
 +                result = org.junit.runner.JUnitCore.runClasses(mainClass);
 +            } catch (NoClassDefFoundError ex) {
-+                throw new Exception("Cannot load JUnit test harness", ex);
++                throw new Exception(JUNIT_NO_DRIVER, ex);
 +            }
 +            if (!result.wasSuccessful()) {
 +                List<org.junit.runner.notification.Failure> failures = result.getFailures();
@@ -486,34 +444,6 @@
 +        }
 +    }
 +
-+    /**
-+     * The method that does the work of the action.  The necessary work for the
-+     * given action is defined by the tag specification.
-+     *
-+     * Invoke the specified class as a JUnit 4 test, using the same
-+     * rules as for a {@link MainAction}.
-+     *
-+     * @return     The result of the action.
-+     * @exception  TestRunException If an unexpected error occurs while running
-+     *             the test.
-+     */
-+    public Status run() throws TestRunException {
-+        Status status;
-+
-+        section = startAction("junit", mainAction.getMainClassName(), reason);
-+
-+        status = mainAction.run();
-+
-+        endAction(status, section);
-+        return status;
-+    } // run()
-+
-+    //----------internal methods------------------------------------------------
-+
-+    //----------member variables------------------------------------------------
-+
-+    private TestResult.Section section;
-+    private MainAction mainAction;
 +}
 diff --git a/src/share/classes/com/sun/javatest/regtest/Main.java b/src/share/classes/com/sun/javatest/regtest/Main.java
 --- a/src/share/classes/com/sun/javatest/regtest/Main.java
@@ -525,10 +455,11 @@
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
-@@ -1174,11 +1174,27 @@
+@@ -1174,11 +1174,20 @@
          File jtreg_jar = findJar("jtreg.jar", "lib/jtreg.jar", getClass());
          if (jtreg_jar == null)
              throw new Fault(i18n, "main.cantFind.jtreg.jar");
+-
 +        
 +        File junit_jar = null;
 +        try {
@@ -536,16 +467,9 @@
 +        } catch (NoClassDefFoundError ex) {
 +        }
 +        if (junit_jar == null) {
-+            // Leave a place-holder.
-+            String p = jtreg_jar.getPath();
-+            int i = p.lastIndexOf("jtreg.jar");
-+            if (i + "jtreg.jar".length() == p.length())
-+                junit_jar = new File(p.substring(0, i) + "junit.jar");
++            // Leave a place-holder for the optional jar.
++            junit_jar = new File(jtreg_jar.getParentFile(), "junit.jar");
 +        }
- 
-+        // Optional jar:
-+        //if (junit_jar == null)
-+        //    throw new Fault(...);
 +        
          File childJDKHome = jdk.getAbsoluteFile();
          File childJava = new File(new File(childJDKHome, "bin"), "java");
@@ -554,22 +478,27 @@
          File scratchDir = canon(new File(workDirArg, "scratch"));
  
          List<String> c = new ArrayList<String>();
-@@ -1187,6 +1203,7 @@
-         c.add("-classpath");
-         List<File> classpath = new ArrayList<File>();
-         classpath.add(jtreg_jar);
-+        if (junit_jar != null)  classpath.add(junit_jar);
-         classpath.add(childTools);
-         classpath.addAll(classPathAppendArg);
-         c.add(filesToAbsolutePath(classpath));
-@@ -1245,6 +1262,7 @@
-                 // Note the CLASSPATH will not be exactly the same as for otherVM tests,
-                 // because it will not have (and cannot have) the test-specific values.
-                 String cp = "CLASSPATH=" + javatest_jar + PATHSEP + jtreg_jar
-+                        + (junit_jar == null ? "" : PATHSEP + junit_jar)
-                         + PATHSEP + jdk.getToolsJar();
+@@ -1215,6 +1224,9 @@
  
-                 String[] env = getEnvVars();
+         c.add("-Djavatest.child=true");
+ 
++        if (junit_jar != null)
++            c.add("-Djunit.jar=" + junit_jar.getPath());
++
+         c.add(Main.class.getName());
+ 
+         for (String o: testVMOpts)
+@@ -1543,6 +1555,10 @@
+             if (ignoreKind != null)
+                 rp.setIgnoreKind(ignoreKind);
+ 
++            String junit_jar = System.getProperty("junit.jar");
++            if (junit_jar != null)
++                rp.setJUnitJar(new File(junit_jar));
++
+             return rp;
+         } catch (TestSuite.Fault f) {
+             f.printStackTrace();
 diff --git a/src/share/classes/com/sun/javatest/regtest/MainAction.java b/src/share/classes/com/sun/javatest/regtest/MainAction.java
 --- a/src/share/classes/com/sun/javatest/regtest/MainAction.java
 +++ b/src/share/classes/com/sun/javatest/regtest/MainAction.java
@@ -628,9 +557,23 @@
      @Override
      public File[] getSourceFiles() {
          List<File> l = new ArrayList<File>();
-@@ -220,6 +247,16 @@
+@@ -202,7 +229,7 @@
+         if (!(status = ba.build(buildOpts, buildArgs, SREASON_ASSUMED_BUILD, script)).isPassed())
+             return status;
+ 
+-        section = startAction("main", javaArgs + buildFN + mainArgs, reason);
++        section = startAction(getActionName(), javaArgs + buildFN + mainArgs, reason);
+ 
+         if (script.isCheck()) {
+             status = Status.passed(CHECK_PASS);
+@@ -219,7 +246,21 @@
+ 
      //----------internal methods------------------------------------------------
  
++    protected String getActionName() {
++        return "main";
++    }
++
      private Status runOtherJVM() throws TestRunException {
 +        // Arguments to wrapper:
 +        String mainClass = buildFN;
@@ -645,7 +588,7 @@
  
          // WRITE ARGUMENT FILE
          String mainArgFileName = script.absTestClsDir() + FILESEP + buildFN
-@@ -227,8 +264,8 @@
+@@ -227,8 +268,8 @@
          FileWriter fw;
          try {
              fw = new FileWriter(mainArgFileName);
@@ -656,7 +599,7 @@
              fw.close();
          } catch (IOException e) {
              return Status.error(MAIN_CANT_WRITE_ARGS);
-@@ -287,7 +324,7 @@
+@@ -287,7 +328,7 @@
          command.add("com.sun.javatest.regtest.MainWrapper");
          command.add(mainArgFileName);
  
@@ -665,7 +608,16 @@
          for (int i = 0; i < mArgs.length; i++)
              command.add(mArgs[i]);
  
-@@ -394,6 +431,16 @@
+@@ -305,7 +346,7 @@
+         PrintWriter sysErr = section.createOutput("System.err");
+         try {
+             if (showCmd)
+-                JTCmd("main", cmdArgs, section);
++                JTCmd(getActionName(), cmdArgs, section);
+ //          for (int i = 0; i < cmdArgs.length; i++)
+ //              System.out.print(" " + cmdArgs[i]);
+ //          System.out.println();
+@@ -394,6 +435,16 @@
                  //return Status.error(MAIN_SECMGR_BAD);
              }
          }
@@ -682,7 +634,7 @@
  
          ByteArrayOutputStream newOut = new ByteArrayOutputStream();
          ByteArrayOutputStream newErr = new ByteArrayOutputStream();
-@@ -417,15 +464,21 @@
+@@ -417,15 +468,21 @@
                      }
                  }
              }
@@ -709,7 +661,7 @@
              Status stat = redirectOutput(psOut, psErr);
              if (!stat.isPassed()) {
                  return stat;
-@@ -489,14 +542,14 @@
+@@ -489,14 +546,14 @@
              e.printStackTrace(new PrintWriter(psErr, true));
              psErr.println();
              psErr.println("JavaTest Message: main() method must be in a public class named");
@@ -726,7 +678,7 @@
              psErr.println();
              status = Status.error(MAIN_CANT_FIND_MAIN);
          } finally {
-@@ -697,6 +750,7 @@
+@@ -697,6 +754,7 @@
  
      private String  javaArgs = "";
      private String  mainArgs = "";
@@ -744,7 +696,63 @@
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
-@@ -438,11 +438,14 @@
+@@ -139,6 +139,7 @@
+     private static final String TEST_JAVA_OPTIONS = ".testJavaOpts";
+     private static final String IGNORE = ".ignore";
+     private static final String RETAIN_ARGS = ".retain";
++    private static final String JUNIT = ".junit";
+     
+     @Override
+     public void load(Map data, boolean checkChecksum) throws Interview.Fault {
+@@ -182,6 +183,10 @@
+         v = (String) data.get(prefix + RETAIN_ARGS);
+         if (v != null)
+             setRetainArgs(Arrays.asList(StringArray.splitSeparator("\n", v)));
++
++        v = (String) data.get(prefix + JUNIT);
++        if (v != null)
++            setJUnitJar(new File(v));
+     }
+     
+     @SuppressWarnings("unchecked")
+@@ -214,7 +219,10 @@
+             data.put(prefix + TEST_COMPILER_OPTIONS, StringUtils.join(testCompilerOpts, "\n"));
+         
+         if (testJavaOpts != null) 
+-            data.put(prefix + TEST_JAVA_OPTIONS, StringUtils.join(testJavaOpts, "\n")); 
++            data.put(prefix + TEST_JAVA_OPTIONS, StringUtils.join(testJavaOpts, "\n"));
++
++        if (junitJar != null)
++            data.put(prefix + JUNIT, junitJar.getPath());
+     }
+ 
+     //---------------------------------------------------------------------
+@@ -288,7 +296,23 @@
+         return jdk;
+     }
+ 
+-    JDK jdk; 
++    JDK jdk;
++
++    //---------------------------------------------------------------------
++
++    void setJUnitJar(File junitJar) {
++        junitJar.getClass(); // null check
++        this.junitJar = junitJar;
++    }
++
++    File getJUnitJar() {
++        if (junitJar == null) {
++            File jtClsDir = ProductInfo.getJavaTestClassDir();
++            junitJar = new File(jtClsDir.getParentFile(), "junit.jar");
++        }
++        return junitJar;
++    }
++    private File junitJar;
+ 
+     //---------------------------------------------------------------------
+     
+@@ -438,10 +462,10 @@
              javaTestClassPath = jtClsDir.getPath();
              
              int index = javaTestClassPath.indexOf("javatest.jar");
@@ -756,12 +764,8 @@
 -                    javaTestClassPath.substring(0, index) + "jtreg.jar";
 +                String jtregClassDir = installDir + "jtreg.jar";
                  javaTestClassPath += PATHSEP + jtregClassDir;
-+                // append junit.jar to the path, in case it exists
-+                String junit4ClassDir = installDir + "junit.jar";
-+                javaTestClassPath += PATHSEP + junit4ClassDir;
              }
          }
-         return javaTestClassPath;
 diff --git a/src/share/classes/com/sun/javatest/regtest/RegressionScript.java b/src/share/classes/com/sun/javatest/regtest/RegressionScript.java
 --- a/src/share/classes/com/sun/javatest/regtest/RegressionScript.java
 +++ b/src/share/classes/com/sun/javatest/regtest/RegressionScript.java
@@ -772,7 +776,92 @@
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
-@@ -414,6 +414,7 @@
+@@ -32,9 +32,11 @@
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.LinkedHashSet;
++import java.util.LinkedList;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
++import java.util.regex.Pattern;
+ 
+ import com.sun.javatest.Script;
+ import com.sun.javatest.Status;
+@@ -42,9 +44,6 @@
+ import com.sun.javatest.TestEnvironment;
+ import com.sun.javatest.TestResult;
+ 
+-import com.sun.javatest.util.Fifo; 
+-import java.util.regex.Pattern;
+-
+ /**
+   * This class interprets the TestDescription as specified by the JDK tag
+   * specification.
+@@ -82,9 +81,17 @@
+                 
+         try {
+             setLibList(td.getParameter("library"));
+-            
+-            Fifo actionList = parseActions(actions, true);
+-            
++
++            LinkedList<Action> actionList = parseActions(actions, true);
++
++            boolean needJUnit = false;
++            for (Action a: actionList) {
++                if (a instanceof JUnitAction)
++                    needJUnit = true;
++            }
++            if (needJUnit)
++                addClsLib(params.getJUnitJar());
++
+             initScratchDirectory();
+             
+             testResult = getTestResult();
+@@ -97,7 +104,7 @@
+                 status = Status.error(td.getParameter("error"));
+             else {
+                 while (! actionList.isEmpty()) {
+-                    Action action = (Action) actionList.remove();
++                    Action action = actionList.remove();
+                     status = action.run();
+                     if (status.getType() != Status.PASSED)
+                         break;
+@@ -122,10 +129,10 @@
+         try {
+             setLibList(td.getParameter("library"));
+             String actions = td.getParameter("run");
+-            Fifo actionList = parseActions(actions, false);
++            LinkedList<Action> actionList = parseActions(actions, false);
+             Set<File> files = new LinkedHashSet<File>();
+             while (! actionList.isEmpty()) {
+-                Action action = (Action) actionList.remove();
++                Action action = actionList.remove();
+                 File[] a = action.getSourceFiles();
+                 if (a != null)
+                     files.addAll(Arrays.asList(a));
+@@ -157,8 +164,8 @@
+      * is found, a ParseActionsException will be thrown, giving a detail message.
+      * @return a Fifo of Action objects
+      */
+-    Fifo parseActions(String actions, boolean stopOnError) throws ParseActionsException, ParseException {   
+-        Fifo actionList = new Fifo(2);
++    LinkedList<Action> parseActions(String actions, boolean stopOnError) throws ParseActionsException, ParseException {
++        LinkedList<Action> actionList = new LinkedList<Action>();
+         String[] runCmds = StringArray.splitTerminator(LINESEP, actions);
+         populateActionTable();
+         
+@@ -193,7 +200,7 @@
+                 }
+                 Action action = (Action)(c.newInstance());
+                 action.init(opts, args, getReason(tokens), this);
+-                actionList.insert(action);
++                actionList.add(action);
+             } catch (InstantiationException e) {
+                 if (stopOnError)
+                     throw new ParseActionsException(CANT_INSTANTIATE + c + NOT_EXT_ACTION);
+@@ -414,6 +421,7 @@
          addAction("compile", CompileAction.class);
          addAction("ignore", IgnoreAction.class);
          addAction("main", MainAction.class);
@@ -780,7 +869,7 @@
          addAction("shell", ShellAction.class);
      } // populateActionTable()
  
-@@ -759,7 +760,22 @@
+@@ -759,7 +767,22 @@
              System.arraycopy(cacheAbsSrcLibList, 0, cacheJavaSrcPath, 1,
                               cacheAbsSrcLibList.length);
          }
@@ -804,6 +893,60 @@
      } // locateJavaSrc()
  
      /**
+@@ -799,13 +822,31 @@
+         }
+     } // setLibList()
+ 
++    private void addClsLib(File lib) {
++        assert cacheAbsClsLibListStr == null;
++        File[] newList = new File[cacheAbsClsLibList.length + 1];
++        System.arraycopy(cacheAbsClsLibList, 0, newList, 0, cacheAbsClsLibList.length);
++        newList[newList.length - 1] = lib;
++        cacheAbsClsLibList = newList;
++    } // addClsLib()
++
+     private String cacheAbsClsLibListStr;
+     String absClsLibListStr() throws TestClassException {
+         if (cacheAbsClsLibListStr == null) {
+             cacheAbsClsLibListStr = "";
+             for (int i = 0; i < cacheAbsClsLibList.length; i++) {
++                // It is not clear why the first of the following two statements
++                // was commented out in favor of the second. With the addition
++                // of addClsLib(), above, it is important to use cacheAbsClsLibList
++                // instead of recalculating the entries from  cacheRelSrcLibList.
++                // It is possible the change was made as a defensive measure when
++                // "if (hasEnv()) { ..}" was added to setLibList for the benefit
++                // of the GUI (i.e. getSourceFiles()).  But, absClsLibListStr()
++                // should only be called when hasEnv() is true, implying that
++                // cacheAbsClsLibList is already initialized correctly.
+ //              String curr = cacheAbsClsLibList[i];
+-                File curr = new File(absTestClsDir(), cacheRelSrcLibList[i]);
++//                File curr = new File(absTestClsDir(), cacheRelSrcLibList[i]);
++                File curr = cacheAbsClsLibList[i];
+                 cacheAbsClsLibListStr += curr.getPath() + PATHSEP;
+             }
+         }
+diff --git a/src/share/classes/com/sun/javatest/regtest/RegressionTestFinder.java b/src/share/classes/com/sun/javatest/regtest/RegressionTestFinder.java
+--- a/src/share/classes/com/sun/javatest/regtest/RegressionTestFinder.java
++++ b/src/share/classes/com/sun/javatest/regtest/RegressionTestFinder.java
+@@ -184,6 +184,9 @@
+         if (match(value, SHELL_ACTION))
+             addKeywords += " shell";
+ 
++        if (match(value, JUNIT_ACTION))
++            addKeywords += " junit";
++
+         if (match(value, IGNORE_ACTION))
+             addKeywords += " ignore";
+ 
+@@ -558,6 +561,7 @@
+         OTHERVM_OPTION = Pattern.compile(".*/othervm[/ \t].*",    Pattern.DOTALL),
+         MANUAL_OPTION  = Pattern.compile(".*/manual[/= \t].*",    Pattern.DOTALL),
+         SHELL_ACTION   = Pattern.compile(".*[ \t]shell[/ \t].*",  Pattern.DOTALL),
++        JUNIT_ACTION   = Pattern.compile(".*[ \t]junit[/ \t].*",  Pattern.DOTALL),
+         IGNORE_ACTION  = Pattern.compile(".*[ \t]ignore[/ \t].*", Pattern.DOTALL);
+ 
+     //----------member variables------------------------------------------------
 diff --git a/src/share/doc/javatest/regtest/tag-spec.txt b/src/share/doc/javatest/regtest/tag-spec.txt
 --- a/src/share/doc/javatest/regtest/tag-spec.txt
 +++ b/src/share/doc/javatest/regtest/tag-spec.txt
@@ -815,21 +958,21 @@
  
  
  This is a specification document, not a tutorial.  For more basic information
-@@ -307,6 +307,33 @@
+@@ -307,6 +307,36 @@
  main/othervm actions is also discouraged; the /policy and /secure options
  should be used instead.
  
 +    junit[/fail][/manual][/othervm][/policy=<file>][/secure=<class>]
 +        [/timeout=<seconds>] <vm-opt>* <class>
 +
-+Invoke the specified class as a JUnit 4 test, passing any arguments after the
-+class name.  Roughly equivalent to "@run main org.junit.runner.JUnitCore <class>".
-+All initial argument tokens beginning with a dash are considered to be VM options;
-+the first argument not beginning with a dash is the <class> to be invoked.
-+Passes only if the main method of JUnitCore returns normally and does not
-+cause an exception to be thrown, from the main thread or from any other thread.
-+As with a "main" action, a "junit" action is considered to be finished when the
-+main method of JUnitCore returns.
++Invoke the specified class as a JUnit 4.5 test.  Roughly equivalent to "@run
++main org.junit.runner.JUnitCore <class>".  All initial argument tokens
++beginning with a dash are considered to be VM options; the first argument not
++beginning with a dash is the <class> to be invoked.  No additional arguments
++are allowed.  Passes only if the main method of JUnitCore returns normally and
++does not cause an exception to be thrown, from the main thread or from any
++other thread.  As with a "main" action, a "junit" action is considered to be
++finished when the main method of JUnitCore returns.
 +
 +The named <class> will be compiled on demand, just as though an "@run build
 +<class>" action had been inserted before this action.  If this action requires
@@ -840,12 +983,15 @@
 +The use of the @library tag, and of the /othervm, /manual, /policy, and /secure
 +options, are the same for a "junit" action as for a "main" action; see above.
 +
-+In order to use a "junit" action, the JUnit 4 jar file may need to be placed
-+manually alongside the jtreg and javatest jar files in the jtreg installed.
++In order to use a "junit" action, the JUnit 4.5 jar file may need to be placed
++manually alongside the jtreg and javatest jar files in the jtreg installation.
 +If junit.jar file is not found, and if no class named org.junit.runner.JUnitCore
 +can be found, any "junit" actions will fail, regardless of whether the /fail
 +option was selected.
 +
++This action executes all the tests in a single JUnit test file.  All the tests
++in that one file will be grouped as a single jtreg test for reporting purposes.
++
      applet[/fail][/manual[=(yesno|done)]][/othervm][/policy=<file>]
          [/secure=<class>][/timeout=<sec>] <html-file>
  
--- a/jtreg/junitsupport.txt	Wed Oct 14 18:06:15 2009 -0700
+++ b/jtreg/junitsupport.txt	Tue Oct 20 15:47:36 2009 -0700
@@ -1,4 +1,5 @@
 Patches to JTReg test harness to allow OpenJDK unit tests to use JUnit.
+These changes are relative to JTreg 4.0, and will likely be released as JTReg 4.1.
 
 To build JTReg:
 * start with http://openjdk.java.net/jtreg/build.html