diff -r fd16c54261b3 -r 90ce3da70b43 jdk/test/tools/launcher/Arrrghs.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/tools/launcher/Arrrghs.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,206 @@ +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +public class Arrrghs{ + + /** + * A group of tests to ensure that arguments are passed correctly to + * a child java process upon a re-exec, this typically happens when + * a version other than the one being executed is requested by the user. + * + * History: these set of tests were part of Arrrghs.sh. The MKS shell + * implementations are notoriously buggy. Implementing these tests purely + * in Java is not only portable but also robust. + * + */ + + /* Do not instantiate */ + private Arrrghs() {} + + static String javaCmd; + + // The version string to force a re-exec + final static String VersionStr = "-version:1.1+"; + + // The Cookie or the pattern we match in the debug output. + final static String Cookie = "ReExec Args: "; + + private static boolean _debug = Boolean.getBoolean("Arrrghs.Debug"); + private static boolean isWindows = System.getProperty("os.name", "unknown").startsWith("Windows"); + private static int exitValue = 0; + + private static void doUsage(String message) { + if (message != null) System.out.println("Error: " + message); + System.out.println("Usage: Arrrghs path_to_java"); + System.exit(1); + } + + /* + * SIGH, On Windows all strings are quoted, we need to unwrap it + */ + private static String removeExtraQuotes(String in) { + if (isWindows) { + // Trim the string and remove the enclosed quotes if any. + in = in.trim(); + if (in.startsWith("\"") && in.endsWith("\"")) { + return in.substring(1, in.length()-1); + } + } + return in; + } + + + /* + * This method detects the cookie in the output stream of the process. + */ + private static boolean detectCookie(InputStream istream, String expectedArguments) throws IOException { + BufferedReader rd = new BufferedReader(new InputStreamReader(istream)); + boolean retval = false; + + String in = rd.readLine(); + while (in != null) { + if (_debug) System.out.println(in); + if (in.startsWith(Cookie)) { + String detectedArgument = removeExtraQuotes(in.substring(Cookie.length())); + if (expectedArguments.equals(detectedArgument)) { + retval = true; + } else { + System.out.println("Error: Expected Arguments\t:'" + expectedArguments + "'"); + System.out.println(" Detected Arguments\t:'" + detectedArgument + "'"); + } + // Return the value asap if not in debug mode. + if (!_debug) { + rd.close(); + istream.close(); + return retval; + } + } + in = rd.readLine(); + } + return retval; + } + + + + private static boolean doExec0(ProcessBuilder pb, String expectedArguments) { + boolean retval = false; + try { + pb.redirectErrorStream(_debug); + Process p = pb.start(); + retval = detectCookie(p.getInputStream(), expectedArguments); + p.waitFor(); + p.destroy(); + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + return retval; + } + + /** + * This method return true if the expected and detected arguments are the same. + * Quoting could cause dissimilar testArguments and expected arguments. + */ + static boolean doExec(String testArguments, String expectedPattern) { + ProcessBuilder pb = new ProcessBuilder(javaCmd, VersionStr, testArguments); + + Map env = pb.environment(); + env.put("_JAVA_LAUNCHER_DEBUG", "true"); + return doExec0(pb, testArguments); + } + + /** + * A convenience method for identical test pattern and expected arguments + */ + static boolean doExec(String testPattern) { + return doExec(testPattern, testPattern); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + if (args.length < 1 && args[0] == null) { + doUsage("Invalid number of arguments"); + } + + javaCmd = args[0]; + + if (!new File(javaCmd).canExecute()) { + if (isWindows && new File(javaCmd + ".exe").canExecute()) { + javaCmd = javaCmd + ".exe"; + } else { + doUsage("The java executable must exist"); + } + } + + + if (_debug) System.out.println("Starting Arrrghs tests"); + // Basic test + if (!doExec("-a -b -c -d")) exitValue++; + + // Basic test with many spaces + if (!doExec("-a -b -c -d")) exitValue++; + + // Quoted whitespace does matter ? + if (!doExec("-a \"\"-b -c\"\" -d")) exitValue++; + + // Escaped quotes outside of quotes as literals + if (!doExec("-a \\\"-b -c\\\" -d")) exitValue++; + + // Check for escaped quotes inside of quotes as literal + if (!doExec("-a \"-b \\\"stuff\\\"\" -c -d")) exitValue++; + + // A quote preceeded by an odd number of slashes is a literal quote + if (!doExec("-a -b\\\\\\\" -c -d")) exitValue++; + + // A quote preceeded by an even number of slashes is a literal quote + // see 6214916. + if (!doExec("-a -b\\\\\\\\\" -c -d")) exitValue++; + + // Make sure that whitespace doesn't interfere with the removal of the + // appropriate tokens. (space-tab-space preceeds -jre-restict-search). + if (!doExec("-a -b \t -jre-restrict-search -c -d","-a -b -c -d")) exitValue++; + + // Make sure that the mJRE tokens being stripped, aren't stripped if + // they happen to appear as arguments to the main class. + if (!doExec("foo -version:1.1+")) exitValue++; + + System.out.println("Completed Arrrghs arguments quoting/matching tests with " + exitValue + " errors"); + System.exit(exitValue); + } + +}