This is the mail archive of the
mauve-patches@sourceware.org
mailing list for the Mauve project.
small Harness improvement .. auto-detect bootclasspath
- From: Anthony Balkissoon <abalkiss at redhat dot com>
- To: mauve-patches at sources dot redhat dot com
- Date: Wed, 26 Apr 2006 14:14:27 -0400
- Subject: small Harness improvement .. auto-detect bootclasspath
Thanks to an idea by Tom Fitzsimmons, the Harness now auto-detects the
bootclasspath for the compiler based on the VM that is used to run the
tests. Because of this, auto-compilation can be enabled by default.
The README is updated to reflect these changes.
2006-04-26 Anthony Balkissoon <abalkiss@redhat.com>
* Harness.java:
(bcp_timeout): New field.
(showCompilationErrors): Set to true by default.
(setupHarness): Changed -showcompilefails option to -hidecompilefails
since fails are shown by default now. Also changed
-classpath-install-dir option to -bootclasspath to match the
configure option.
(getClasspathInstallString): If no bootclasspath was specified on the
command line or in configure, then auto-detect it with the new method
getBootClassPath.
(getBootClassPath): New method.
* README: Changed --with-classpath-install-dir to --with-bootclasspath,
changed text to reflect the fact that auto-compilation is now enabeld
by default. Added the -hidecompilefails option to the text.
* configure: Regenerated.
* configure.in: Changed --with-classpath-install-dir to
--with-bootclasspath, changed auto-compilation to be enabled by
default.
* gnu/testlet/DetectBootclasspath.java: New file.
--Tony
Index: Harness.java
===================================================================
RCS file: /cvs/mauve/mauve/Harness.java,v
retrieving revision 1.3
diff -u -r1.3 Harness.java
--- Harness.java 25 Apr 2006 16:22:36 -0000 1.3
+++ Harness.java 26 Apr 2006 18:04:26 -0000
@@ -73,6 +73,9 @@
// The location of the eclipse-ecj.jar file
private static String ecjJarLocation = null;
+ // How long the bootclasspath finder program can run before termination
+ private static long bcp_timeout = 60000;
+
// How long a test may run before it is considered hung
private static long runner_timeout = 60000;
@@ -93,7 +96,7 @@
private static boolean compileTests = true;
// Whether we should display information for failing compilations
- private static boolean showCompilationErrors = false;
+ private static boolean showCompilationErrors = true;
// The total number of tests run
private static int total_tests = 0;
@@ -244,8 +247,8 @@
else if (args[i].equals("no") || args[i].equals("false"))
compileTests = false;
}
- else if (args[i].equals("-showcompilefails"))
- showCompilationErrors = true;
+ else if (args[i].equals("-hidecompilefails"))
+ showCompilationErrors = false;
else if (args[i].equals("-help") || args[i].equals("--help")
|| args[i].equals("-h"))
printHelpMessage();
@@ -256,13 +259,13 @@
throw new RuntimeException("No file path after '-file'. Exit");
inputFile = args[i];
}
- else if (args[i].equalsIgnoreCase("-classpath-install-dir"))
+ else if (args[i].equalsIgnoreCase("-bootclasspath"))
{
// User is specifying the classpath installation folder to use
// as the compiler's bootclasspath.
if (++i >= args.length)
throw new RuntimeException("No file path " +
- "after '-classpath-install-dir'. Exit");
+ "after '-bootclasspath'. Exit");
classpathInstallDir = args[i];
}
else if (args[i].equalsIgnoreCase("-ecj-jar"))
@@ -400,7 +403,7 @@
" It is indirectly\n referenced from required " +
".class files,'\n\nthen try setting the " +
"bootclasspath by using the\n" +
- "--with-classpath-install-dir=CPINSTALLDIR option " +
+ "--with-bootclasspath=CPINSTALLDIR option " +
"in configure.");
ecjWriterErr.println("\nThe compiler command used was: \n " +
compileStringBase + "\n");
@@ -427,23 +430,103 @@
*/
private static String getClasspathInstallString()
{
- String temp = classpathInstallDir;
+ String temp = classpathInstallDir;
+
+ // If classpathInstallDir is null that means no bootclasspath was
+ // specified on the command line using -bootclasspath. In this case
+ // check if anything was supplied to configure with --with-bootclasspath.
if (temp == null)
{
temp = config.cpInstallDir;
+
+ // If temp is the empty string then nothing was supplied to configure
+ // so auto-detect the bootclasspath using getBootClasspath().
if (temp.equals(""))
- return temp;
+ {
+ temp = getBootClassPath();
+
+ // If auto-detect returned null we cannot auto-detect the
+ // bootclasspath and we should try invoking the compiler without
+ // specifying the bootclasspath. Otherwise, we should add
+ // " -bootclasspath " followed by the detected path.
+ if (temp != null)
+ return " -bootclasspath " + temp;
+ return temp;
+ }
}
+
+ // This section is for bootclasspath's specified with
+ // -bootclasspath or --with-bootclasspath (in configure), we need
+ // to add "/share/classpath/glibj.zip" onto the end and
+ // " -bootclasspath onto the start".
temp = " -bootclasspath " + temp;
if (!temp.endsWith(File.separator))
temp += File.separator;
temp += "share" + File.separator + "classpath";
+ // If (for some reason) there is no glibj.zip file in the specified
+ // folder, just use the folder as the bootclasspath, perhaps the folder
+ // contains an expanded view of the resources.
File f = new File (temp.substring(16) + File.separator + "glibj.zip");
if (f.exists())
temp += File.separator + "glibj.zip";
return temp;
}
+
+ /**
+ * Forks a process to run gnu/testlet/DetectBootclasspath on the VM that is
+ * being tested. This program detects the bootclasspath so we can use
+ * it for the compiler's bootclasspath.
+ * @return the bootclasspath as found, or null if none could be found.
+ */
+ private static String getBootClassPath()
+ {
+ try
+ {
+ String c = vmCommand + " gnu" + File.separator + "testlet"
+ + File.separator + "DetectBootclasspath";
+ Process p = Runtime.getRuntime().exec(c);
+ BufferedReader br =
+ new BufferedReader
+ (new InputStreamReader(p.getInputStream()));
+ String bcpOutput = null;
+ // Create a timer to watch this new process.
+ TimeoutWatcher tw = new TimeoutWatcher(bcp_timeout);
+ tw.start();
+ while (true)
+ {
+ // If for some reason the process hangs, return null, indicating we
+ // cannot auto-detect the bootclasspath.
+ if (testIsHung)
+ {
+ synchronized (runner_lock)
+ {
+ testIsHung = false;
+ }
+ br.close();
+ p.destroy();
+ return null;
+ }
+ if (br.ready())
+ {
+ bcpOutput = br.readLine();
+ if (bcpOutput.startsWith("BCP_FINDER:"))
+ return bcpOutput.substring(11);
+ else
+ {
+ // This means the auto-detection failed.
+ System.out.println(bcpOutput);
+ return null;
+ }
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ // Couldn't auto-fetch the bootclasspath.
+ return null;
+ }
+ }
/**
* This method takes a String and puts it into a consistent format so we can
@@ -518,7 +601,7 @@
"\n\nOutput Options:\n" +
" -showpasses: display passing tests as well as failing " +
"ones\n" +
- " -showcompilefails: display errors from the compiler when " +
+ " -hidecompilefails: hide errors from the compiler when " +
"tests fail to compile\n" +
" -exceptions: print stack traces for uncaught " +
"exceptions\n" +
@@ -940,8 +1023,7 @@
// If temp is null, we didn't find it. Otherwise, look for each
// individual failing compilation, count it as a fail, exclude it
- // from the test run, and if -showcompilefails was used, print
- // out the info.
+ // from the test run, and print out the info.
while (temp != null)
{
// If we've reached a part of the file that pertains to another
@@ -956,8 +1038,11 @@
loc = temp.indexOf("gnu" + File.separatorChar + "testlet");
if (loc != - 1)
{
- String name = temp.substring(loc);
- String shortName = stripPrefix(name);
+ String name = temp.substring(loc);
+ String shortName =
+ stripPrefix(name).replace(File.separatorChar, '.');
+ if (shortName.endsWith(".java"))
+ shortName = shortName.substring(0, shortName.length() - 5);
if (verbose && lastFailingTest != null)
System.out.println
("TEST FAILED: compilation failed " + lastFailingTest);
@@ -967,7 +1052,7 @@
System.out.println
("TEST: " + shortName + "\n FAIL: compilation failed.");
else
- System.out.println("FAIL: " + stripPrefix(name)
+ System.out.println("FAIL: " + shortName
+ ": compilation failed");
if (!showCompilationErrors)
System.out.println
@@ -1120,7 +1205,7 @@
}
}
if (config.cpInstallDir.equals(""))
- System.out.println(" Try setting --with-classpath-install-dir " +
+ System.out.println(" Try setting --with-bootclasspath " +
"when running configure.\n See the README file for details");
if (verbose)
System.out.println("TEST FAILED: compilation failed " + shortName);
Index: README
===================================================================
RCS file: /cvs/mauve/mauve/README,v
retrieving revision 1.23
diff -u -r1.23 README
--- README 24 Apr 2006 19:42:02 -0000 1.23
+++ README 26 Apr 2006 18:04:26 -0000
@@ -38,7 +38,7 @@
If you plan to use the auto-compilation feature of the Harness, which
compiles tests inline before running them (so new tests, or changed
tests are run properly without an additional step), you need to be sure
- it is properly configured. The following options are associated
+ it is properly configured. The following options are associated
with auto-compilation:
--enable-auto-compilation Enable the auto-compilation feature
@@ -49,9 +49,11 @@
machine is different from this. If no valid
ecj jar is found, auto-compilation will be
turned off.
- --with-classpath-install-dir Specify the location of the java implemenation
- installation. This will be used as the
- bootclasspath for the compiler.
+ --with-bootclasspath Specify the bootclasspath for the compiler.
+
+ Auto-compilation is enabled by default, and the bootclasspath is found
+ automatically. If you wish to disable auto-compilation or change the
+ bootclasspath you should use the appropriate option(s) above.
2. Environment variables for configure.
@@ -118,7 +120,7 @@
done via command line options to the Harness (which override the configure
options). To set the VM via the command line, use:
- -testvm [vmpath]
+ -vm [vmpath]
If, for example, I wanted to run all the JTable tests using JamVM, and then
run them all on Sun's VM for comparison, I would type:
@@ -211,45 +213,49 @@
only prints minimal information about uncaught exceptions. The following
options affect what is printed:
- -verbose: prints information about each passing harness.check() call within
- the tests, whether they pass or fail.
+ -hidecompilefails: hides failures from the compiler. These can still be
+ found in the .ecjErr file.
+
+ -verbose: prints information about each passing harness.check() call
+ within the tests, whether they pass or fail.
- -exceptions: prints full stack traces for uncaught exceptions
+ -exceptions: prints full stack traces for uncaught exceptions
- -showpasses: prints one-line summaries for passing tests
+ -showpasses: prints one-line summaries for passing tests
- -debug: prints toString() information when a
- harness.check(Object, Object) call fails.
+ -debug: prints toString() information when a
+ harness.check(Object, Object) call fails.
-6. Turning on (or off) test auto-compilation
- The auto-compilation feature is diabled by default, but can be turned on by
- using the --enable-auto-compilation option to configure. You can also turn
- on by using the following Harness option:
+6. Turning off (or on) test auto-compilation
+ The auto-compilation feature is enabled by default, but can be turned off by
+ using the --disable-auto-compilation option to configure. You can also turn
+ off the option by using the following Harness option:
- -compile yes OR -compile true
+ -compile no OR -compile false
- If you have enabled auto-compilation in configure but wish to turn it off
+ If you have disabled auto-compilation in configure but wish to turn it on
for a particular test run, use
- -compile no OR -compile false
+ -compile yes OR -compile true
Note that auto-compilation requires a correct path to eclipse-ecj.jar and
a correct bootclasspath. The following options deal with this:
- -classpath-install-dir CP_INSTALL_DIR
+ -bootclasspath BOOTCLASSPATH
-ecj-jar ECJ_JAR_LOCATION
These can also be specified at configure time via
- --with-classpath-installation-dir and --with-ecj-jar, the latter defaulting
- to /usr/share/java/eclipse-ecj.jar if no location is specified.
-
- The following example is for the case where auto-compilation is disabled by
- default in configure, but is turned on after a cvs update so that new tests
- are compiled and run.
-
- Example:
- - configure using --with-classpath-install-dir=CP_INSTALL_DIR
- - cvs update (downloads the new testcases)
- - HARNESSVM Harness -compile true
+ --with-bootclasspath and --with-ecj-jar, the latter defaulting
+ to /usr/share/java/eclipse-ecj.jar if no location is specified. The default
+ bootclasspath is found automatically and shouldn't need to be changed unless
+ you specifically want to specify an alternate location.
+
+ So the default setup of:
+ 1. ./configure
+ 2. make
+ 3. HARNESSVM Harness
+
+ will run with auto-compilation enabled with the ecj jar being
+ /usr/share/java/eclipse-ecj.jar and the bootclasspath found automatically.
Index: configure.in
===================================================================
RCS file: /cvs/mauve/mauve/configure.in,v
retrieving revision 1.15
diff -u -r1.15 configure.in
--- configure.in 24 Apr 2006 19:42:02 -0000 1.15
+++ configure.in 26 Apr 2006 18:04:27 -0000
@@ -21,13 +21,9 @@
AM_CONDITIONAL(USE_GCJ, test "$with_gcj" = yes)
-AC_ARG_WITH(classpath-install-dir,
-[ --with-classpath-install-dir=CPINSTALL Specify the location of Classpath's install dir],
-CP_INSTALL_DIR="$with_classpath_install_dir")
-if ! test -d "$CP_INSTALL_DIR"
-then
-CP_INSTALL_DIR=""
-fi
+AC_ARG_WITH(bootclasspath,
+[ --with-bootclasspath=BOOTCP Specify the bootclasspath for the compiler],
+CP_INSTALL_DIR="$with_bootclasspath")
AC_SUBST(CP_INSTALL_DIR)
@@ -49,7 +45,7 @@
dnl have the correct bootclasspath
AC_ARG_ENABLE(auto-compile,
[ --enable-auto-compile Use ecj to compile tests on the fly],
-AUTO_COMPILE="$enable_auto_compile",AUTO_COMPILE="no")
+AUTO_COMPILE="$enable_auto_compile",AUTO_COMPILE="yes")
AC_SUBST(AUTO_COMPILE)
dnl See if the user prefers to build .class files with gcj, or whether
Index: gnu/testlet/DetectBootclasspath.java
===================================================================
RCS file: gnu/testlet/DetectBootclasspath.java
diff -N gnu/testlet/DetectBootclasspath.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gnu/testlet/DetectBootclasspath.java 26 Apr 2006 18:04:27 -0000
@@ -0,0 +1,54 @@
+package gnu.testlet;
+
+
+/**
+ * This tiny class is used for finding the bootclasspath of the VM used
+ * to run the tests.
+ * @author Anthony Balkissoon abalkiss at redhat dot com
+ *
+ */
+public class DetectBootclasspath
+{
+ /**
+ * Look in the system properties for the bootclasspath of the VM and return
+ * it to the process that forked this process via the System.out stream.
+ *
+ * Tries first to get the property "sun.boot.class.path", if there is none,
+ * then it tries "java.boot.class.path", if there is still no match, looks
+ * to see if there is a unique property key that contains "boot.class.path".
+ * If this fails too, prints an error message.
+ */
+ public static void main (String[] args)
+ {
+ String result = "BCP_FINDER:";
+ // Sun's VM stores the bootclasspath as "sun.boot.class.path".
+ String temp = System.getProperty("sun.boot.class.path");
+ if (temp == null)
+ // JamVM stores it as "boot.class.path"
+ temp = System.getProperty("java.boot.class.path");
+ if (temp == null)
+ {
+ String[] s = (String[])(System.getProperties().keySet().toArray());
+ int count = 0;
+ String key = null;
+ for (int i = 0; i < s.length; i++)
+ {
+ if (s[i].indexOf("boot.class.path") != -1)
+ {
+ count ++;
+ key = s[i];
+ }
+ }
+ if (count == 1)
+ temp = System.getProperty(key);
+ else
+ {
+ System.out.println("WARNING: Cannot auto-detect the " +
+ "bootclasspath for your VM, please file a bug report" +
+ " specifying which VM you are testing.");
+ return;
+ }
+ }
+ System.out.println(result + temp);
+ }
+}