Path: blob/master/test/jdk/tools/launcher/Arrrghs.java
41144 views
/*1* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 675393826* 6894719 6968053 7151434 7146424 8007333 8077822 8143640 8132379 821854727* @summary Argument parsing validation.28* @modules jdk.compiler29* jdk.zipfs30* @compile -XDignore.symbol.file Arrrghs.java31* @run main/othervm Arrrghs32*/333435import java.io.File;36import java.io.FileNotFoundException;37import java.io.IOException;38import java.nio.file.Files;39import java.nio.file.Paths;40import java.nio.file.Path;41import java.util.ArrayList;42import java.util.Arrays;43import java.util.HashMap;44import java.util.List;45import java.util.Map;46import java.util.regex.Matcher;47import java.util.regex.Pattern;4849public class Arrrghs extends TestHelper {50private Arrrghs(){}51/**52* This class provides various tests for arguments processing.53*54* History: these set of tests were part of Arrrghs.sh. The MKS shell55* implementations were notoriously buggy. Implementing these tests purely56* in Java is not only portable but also robust.57*58*/5960// the pattern we hope to see in the output61static final Pattern ArgPattern = Pattern.compile("\\s*argv\\[[0-9]*\\].*=.*");6263void checkArgumentParsing(String inArgs, String... expArgs) throws IOException {64List<String> scratchpad = new ArrayList<>();65scratchpad.add("set " + JLDEBUG_KEY + "=true");66// GAK, -version needs to be added so that windows can flush its stderr67// exiting the process prematurely can terminate the stderr.68scratchpad.add(javaCmd + " -version " + inArgs);69File batFile = new File("atest.bat");70createAFile(batFile, scratchpad);7172TestResult tr = doExec(batFile.getName());7374ArrayList<String> expList = new ArrayList<>();75expList.add(javaCmd);76expList.add("-version");77expList.addAll(Arrays.asList(expArgs));7879List<String> gotList = new ArrayList<>();80for (String x : tr.testOutput) {81Matcher m = ArgPattern.matcher(x);82if (m.matches()) {83String a[] = x.split("=");84gotList.add(a[a.length - 1].trim());85}86}87if (!gotList.equals(expList)) {88System.out.println(tr);89System.out.println("Expected args:");90System.out.println(expList);91System.out.println("Obtained args:");92System.out.println(gotList);93throw new RuntimeException("Error: args do not match");94}95System.out.println("\'" + inArgs + "\'" + " - Test passed");96}9798/*99* This tests general quoting and are specific to Windows, *nixes100* need not worry about this, these have been tested with Windows101* implementation and those that are known to work are used against102* the java implementation. Note that the ProcessBuilder gets in the103* way when testing some of these arguments, therefore we need to104* create and execute a .bat file containing the arguments.105*/106@Test107void testArgumentParsing() throws IOException {108if (!isWindows)109return;110// no quotes111checkArgumentParsing("a b c d", "a", "b", "c", "d");112113// single quotes114checkArgumentParsing("\"a b c d\"", "a b c d");115116//double quotes117checkArgumentParsing("\"\"a b c d\"\"", "a", "b", "c", "d");118119// triple quotes120checkArgumentParsing("\"\"\"a b c d\"\"\"", "\"a b c d\"");121122// a literal within single quotes123checkArgumentParsing("\"a\"b c d\"e\"", "ab", "c", "de");124125// a literal within double quotes126checkArgumentParsing("\"\"a\"b c d\"e\"\"", "ab c de");127128// a literal quote129checkArgumentParsing("a\\\"b", "a\"b");130131// double back-slash132checkArgumentParsing("\"a b c d\\\\\"", "a b c d\\");133134// triple back-slash135checkArgumentParsing("a\\\\\\\"b", "a\\\"b");136137// dangling quote138checkArgumentParsing("\"a b c\"\"", "a b c\"");139140// expansions of white space separators141checkArgumentParsing("a b", "a", "b");142checkArgumentParsing("a\tb", "a", "b");143checkArgumentParsing("a \t b", "a", "b");144145checkArgumentParsing("\"C:\\TEST A\\\\\"", "C:\\TEST A\\");146checkArgumentParsing("\"\"C:\\TEST A\\\\\"\"", "C:\\TEST", "A\\");147148// MS Windows tests149// triple back-slash150checkArgumentParsing("a\\\\\\d", "a\\\\\\d");151152// triple back-slash in quotes153checkArgumentParsing("\"a\\\\\\d\"", "a\\\\\\d");154155// slashes separating characters156checkArgumentParsing("X\\Y\\Z", "X\\Y\\Z");157checkArgumentParsing("\\X\\Y\\Z", "\\X\\Y\\Z");158159// literals within dangling quotes, etc.160checkArgumentParsing("\"a b c\" d e", "a b c", "d", "e");161checkArgumentParsing("\"ab\\\"c\" \"\\\\\" d", "ab\"c", "\\", "d");162checkArgumentParsing("a\\\\\\c d\"e f\"g h", "a\\\\\\c", "de fg", "h");163checkArgumentParsing("a\\\\\\\"b c d", "a\\\"b", "c", "d");164checkArgumentParsing("a\\\\\\\\\"g c\" d e", "a\\\\g c", "d", "e");165166// treatment of back-slashes167checkArgumentParsing("*\\", "*\\");168checkArgumentParsing("*/", "*/");169checkArgumentParsing(".\\*", ".\\*");170checkArgumentParsing("./*", "./*");171checkArgumentParsing("..\\..\\*", "..\\..\\*");172checkArgumentParsing("../../*", "../../*");173checkArgumentParsing("..\\..\\", "..\\..\\");174checkArgumentParsing("../../", "../../");175checkArgumentParsing("a b\\ c", "a", "b\\", "c");176// 2 back-slashes177checkArgumentParsing("\\\\?", "\\\\?");178// 3 back-slashes179checkArgumentParsing("\\\\\\?", "\\\\\\?");180// 4 back-slashes181checkArgumentParsing("\\\\\\\\?", "\\\\\\\\?");182// 5 back-slashes183checkArgumentParsing("\\\\\\\\\\?", "\\\\\\\\\\?");184// 6 back-slashes185checkArgumentParsing("\\\\\\\\\\\\?", "\\\\\\\\\\\\?");186187// more treatment of mixed slashes188checkArgumentParsing("f1/ f3\\ f4/", "f1/", "f3\\", "f4/");189checkArgumentParsing("f1/ f2\' ' f3/ f4/", "f1/", "f2\'", "'", "f3/", "f4/");190191checkArgumentParsing("a\\*\\b", "a\\*\\b");192}193194private void initEmptyDir(File emptyDir) throws IOException {195if (emptyDir.exists()) {196recursiveDelete(emptyDir);197}198emptyDir.mkdir();199}200201private void initDirWithJavaFiles(File libDir) throws IOException {202203if (libDir.exists()) {204recursiveDelete(libDir);205}206libDir.mkdirs();207ArrayList<String> scratchpad = new ArrayList<>();208scratchpad.add("package lib;");209scratchpad.add("public class Fbo {");210scratchpad.add("public static void main(String... args){Foo.f();}");211scratchpad.add("public static void f(){}");212scratchpad.add("}");213createFile(new File(libDir, "Fbo.java"), scratchpad);214215scratchpad.clear();216scratchpad.add("package lib;");217scratchpad.add("public class Foo {");218scratchpad.add("public static void main(String... args){");219scratchpad.add("for (String x : args) {");220scratchpad.add("System.out.println(x);");221scratchpad.add("}");222scratchpad.add("Fbo.f();");223scratchpad.add("}");224scratchpad.add("public static void f(){}");225scratchpad.add("}");226createFile(new File(libDir, "Foo.java"), scratchpad);227}228229void checkArgumentWildcard(String inArgs, String... expArgs) throws IOException {230String[] in = {inArgs};231checkArgumentWildcard(in, expArgs);232233// now add arbitrary arguments before and after234String[] outInArgs = { "-Q", inArgs, "-R"};235236String[] outExpArgs = new String[expArgs.length + 2];237outExpArgs[0] = "-Q";238System.arraycopy(expArgs, 0, outExpArgs, 1, expArgs.length);239outExpArgs[expArgs.length + 1] = "-R";240checkArgumentWildcard(outInArgs, outExpArgs);241}242243void checkArgumentWildcard(String[] inArgs, String[] expArgs) throws IOException {244ArrayList<String> argList = new ArrayList<>();245argList.add(javaCmd);246argList.add("-cp");247argList.add("lib" + File.separator + "*");248argList.add("lib.Foo");249argList.addAll(Arrays.asList(inArgs));250String[] cmds = new String[argList.size()];251argList.toArray(cmds);252TestResult tr = doExec(cmds);253if (!tr.isOK()) {254System.out.println(tr);255throw new RuntimeException("Error: classpath single entry wildcard entry");256}257258ArrayList<String> expList = new ArrayList<>();259expList.addAll(Arrays.asList(expArgs));260261List<String> gotList = new ArrayList<>();262for (String x : tr.testOutput) {263gotList.add(x.trim());264}265if (!gotList.equals(expList)) {266System.out.println(tr);267System.out.println("Expected args:");268System.out.println(expList);269System.out.println("Obtained args:");270System.out.println(gotList);271throw new RuntimeException("Error: args do not match");272}273System.out.print("\'");274for (String x : inArgs) {275System.out.print(x + " ");276}277System.out.println("\'" + " - Test passed");278}279280/*281* These tests are not expected to work on *nixes, and are ignored.282*/283@Test284void testWildCardArgumentProcessing() throws IOException {285if (!isWindows)286return;287File cwd = new File(".");288File libDir = new File(cwd, "lib");289initDirWithJavaFiles(libDir);290initEmptyDir(new File(cwd, "empty"));291292// test if javac (the command) can compile *.java293TestResult tr = doExec(javacCmd, libDir.getName() + File.separator + "*.java");294if (!tr.isOK()) {295System.out.println(tr);296throw new RuntimeException("Error: compiling java wildcards");297}298299// test if javac (the command) can compile *.java with a vmoption300tr = doExec(javacCmd, "-cp", ".",301"-J-showversion", "-J-Dsomeproperty=foo",302libDir.getName() + File.separator + "*.java");303if (!tr.isOK()) {304System.out.println(tr);305throw new RuntimeException("Error: compiling java wildcards with vmoptions");306}307308309// use the jar cmd to create jars using the ? wildcard310File jarFoo = new File(libDir, "Foo.jar");311tr = doExec(jarCmd, "cvf", jarFoo.getAbsolutePath(), "lib" + File.separator + "F?o.class");312if (!tr.isOK()) {313System.out.println(tr);314throw new RuntimeException("Error: creating jar with wildcards");315}316317// now the litmus test!, this should work318checkArgumentWildcard("a", "a");319320// test for basic expansion321checkArgumentWildcard("lib\\F*java", "lib\\Fbo.java", "lib\\Foo.java");322323// basic expansion in quotes324checkArgumentWildcard("\"lib\\F*java\"", "lib\\F*java");325326checkArgumentWildcard("lib\\**", "lib\\Fbo.class", "lib\\Fbo.java",327"lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java");328329checkArgumentWildcard("lib\\*?", "lib\\Fbo.class", "lib\\Fbo.java",330"lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java");331332checkArgumentWildcard("lib\\?*", "lib\\Fbo.class", "lib\\Fbo.java",333"lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java");334335checkArgumentWildcard("lib\\?", "lib\\?");336337// test for basic expansion338checkArgumentWildcard("lib\\*java", "lib\\Fbo.java", "lib\\Foo.java");339340// basic expansion in quotes341checkArgumentWildcard("\"lib\\*.java\"", "lib\\*.java");342343// suffix expansion344checkArgumentWildcard("lib\\*.class", "lib\\Fbo.class", "lib\\Foo.class");345346// suffix expansion in quotes347checkArgumentWildcard("\"lib\\*.class\"", "lib\\*.class");348349// check for ? expansion now350checkArgumentWildcard("lib\\F?o.java", "lib\\Fbo.java", "lib\\Foo.java");351352// check ? in quotes353checkArgumentWildcard("\"lib\\F?o.java\"", "lib\\F?o.java");354355// check ? as suffixes356checkArgumentWildcard("lib\\F?o.????", "lib\\Fbo.java", "lib\\Foo.java");357358// check ? in a leading role359checkArgumentWildcard("lib\\???.java", "lib\\Fbo.java", "lib\\Foo.java");360checkArgumentWildcard("\"lib\\???.java\"", "lib\\???.java");361362// check ? prefixed with -363checkArgumentWildcard("-?", "-?");364365// check * prefixed with -366checkArgumentWildcard("-*", "-*");367368// check on empty directory369checkArgumentWildcard("empty\\*", "empty\\*");370checkArgumentWildcard("empty\\**", "empty\\**");371checkArgumentWildcard("empty\\?", "empty\\?");372checkArgumentWildcard("empty\\??", "empty\\??");373checkArgumentWildcard("empty\\*?", "empty\\*?");374checkArgumentWildcard("empty\\?*", "empty\\?*");375376// 8132379: java should not filter out -J options for application377String[] args = { "-J-one", "-Jtwo", "lib\\???.java", "-J-Dsomething",378"a", "-J-Dlast.arg" };379String[] expected = { "-J-one", "-Jtwo", "lib\\Fbo.java",380"lib\\Foo.java", "-J-Dsomething", "a", "-J-Dlast.arg" };381checkArgumentWildcard(args, expected);382}383384void doArgumentCheck(String inArgs, String... expArgs) {385Map<String, String> env = new HashMap<>();386env.put(JLDEBUG_KEY, "true");387TestResult tr = doExec(env, javaCmd, inArgs);388System.out.println(tr);389int sindex = tr.testOutput.indexOf("Command line args:");390if (sindex < 0) {391System.out.println(tr);392throw new RuntimeException("Error: no output");393}394sindex++; // skip over the tag395List<String> gotList = new ArrayList<>();396for (String x : tr.testOutput.subList(sindex, sindex + expArgs.length)) {397String a[] = x.split("=");398gotList.add(a[a.length - 1].trim());399}400List<String> expList = Arrays.asList(expArgs);401if (!gotList.equals(expList)) {402System.out.println(tr);403System.out.println("Expected args:");404System.out.println(expList);405System.out.println("Obtained args:");406System.out.println(gotList);407throw new RuntimeException("Error: args do not match");408}409}410411412/*413* These tests are usually run on non-existent targets to check error results414*/415@Test416void testBasicErrorMessages() {417// Tests for 5030233418TestResult tr = doExec(javaCmd, "-cp");419tr.checkNegative();420tr.isNotZeroOutput();421if (!tr.testStatus)422System.out.println(tr);423424tr = doExec(javaCmd, "-classpath");425tr.checkNegative();426tr.isNotZeroOutput();427if (!tr.testStatus)428System.out.println(tr);429430tr = doExec(javaCmd, "-jar");431tr.checkNegative();432tr.isNotZeroOutput();433if (!tr.testStatus)434System.out.println(tr);435436tr = doExec(javacCmd, "-cp");437tr.checkNegative();438tr.isNotZeroOutput();439if (!tr.testStatus)440System.out.println(tr);441442// Test for 6356475 "REGRESSION:"java -X" from cmdline fails"443tr = doExec(javaCmd, "-X");444tr.checkPositive();445tr.isNotZeroOutput();446if (!tr.testStatus)447System.out.println(tr);448449tr = doExec(javaCmd, "-help");450tr.checkPositive();451tr.isNotZeroOutput();452if (!tr.testStatus)453System.out.println(tr);454455// 6753938, test for non-negative exit value for an incorrectly formed456// command line, '% java'457tr = doExec(javaCmd);458tr.checkNegative();459tr.isNotZeroOutput();460if (!tr.testStatus)461System.out.println(tr);462463// 6753938, test for non-negative exit value for an incorrectly formed464// command line, '% java -Xcomp'465tr = doExec(javaCmd, "-Xcomp");466tr.checkNegative();467tr.isNotZeroOutput();468if (!tr.testStatus)469System.out.println(tr);470471// 7151434, test for non-negative exit value for an incorrectly formed472// command line, '% java -jar -W', note the bogus -W473tr = doExec(javaCmd, "-jar", "-W");474tr.checkNegative();475tr.contains("Unrecognized option: -W");476if (!tr.testStatus)477System.out.println(tr);478}479480/*481* Tests -jar command on a jar file with "long" (> 260 chars) full path on Windows482*/483@Test484void testLongPathJarFile() throws IOException {485if (!isWindows) {486return;487}488// put the jar file to a location with long path489String longPathPart = "longpathtest_longpathtest/";490String longPathStr = longPathPart.repeat(15);491Path longPath = Paths.get(longPathStr);492Path jarPath = Files.createDirectories(longPath).resolve("elp.jar");493File elp = jarPath.toFile();494createJar(elp, new File("Foo"), "public static void main(String[] args){ System.out.println(\"Hello from ELP\"); }");495System.out.println("execute " + elp.getAbsolutePath());496TestResult tr = doExec(javaCmd, "-jar", elp.getAbsolutePath());497tr.checkPositive();498tr.contains("Hello from ELP");499}500501/*502* Tests various dispositions of the main method, these tests are limited503* to English locales as they check for error messages that are localized.504*/505@Test506void testMainMethod() throws FileNotFoundException {507if (!isEnglishLocale()) {508return;509}510511TestResult tr;512513// a missing class514createJar("MIA", new File("some.jar"), new File("Foo"),515(String[])null);516tr = doExec(javaCmd, "-jar", "some.jar");517tr.contains("Error: Could not find or load main class MIA");518if (!tr.testStatus)519System.out.println(tr);520// use classpath to check521tr = doExec(javaCmd, "-cp", "some.jar", "MIA");522tr.contains("Error: Could not find or load main class MIA");523if (!tr.testStatus)524System.out.println(tr);525526// incorrect method access527createJar(new File("some.jar"), new File("Foo"),528"private static void main(String[] args){}");529tr = doExec(javaCmd, "-jar", "some.jar");530tr.contains("Error: Main method not found in class Foo");531if (!tr.testStatus)532System.out.println(tr);533// use classpath to check534tr = doExec(javaCmd, "-cp", "some.jar", "Foo");535tr.contains("Error: Main method not found in class Foo");536if (!tr.testStatus)537System.out.println(tr);538539// incorrect return type540createJar(new File("some.jar"), new File("Foo"),541"public static int main(String[] args){return 1;}");542tr = doExec(javaCmd, "-jar", "some.jar");543tr.contains("Error: Main method must return a value of type void in class Foo");544if (!tr.testStatus)545System.out.println(tr);546// use classpath to check547tr = doExec(javaCmd, "-cp", "some.jar", "Foo");548tr.contains("Error: Main method must return a value of type void in class Foo");549if (!tr.testStatus)550System.out.println(tr);551552// incorrect parameter type553createJar(new File("some.jar"), new File("Foo"),554"public static void main(Object[] args){}");555tr = doExec(javaCmd, "-jar", "some.jar");556tr.contains("Error: Main method not found in class Foo");557if (!tr.testStatus)558System.out.println(tr);559// use classpath to check560tr = doExec(javaCmd, "-cp", "some.jar", "Foo");561tr.contains("Error: Main method not found in class Foo");562if (!tr.testStatus)563System.out.println(tr);564565// incorrect method type - non-static566createJar(new File("some.jar"), new File("Foo"),567"public void main(String[] args){}");568tr = doExec(javaCmd, "-jar", "some.jar");569tr.contains("Error: Main method is not static in class Foo");570if (!tr.testStatus)571System.out.println(tr);572// use classpath to check573tr = doExec(javaCmd, "-cp", "some.jar", "Foo");574tr.contains("Error: Main method is not static in class Foo");575if (!tr.testStatus)576System.out.println(tr);577578// amongst a potpourri of kindred main methods, is the right one chosen ?579createJar(new File("some.jar"), new File("Foo"),580"void main(Object[] args){}",581"int main(Float[] args){return 1;}",582"private void main() {}",583"private static void main(int x) {}",584"public int main(int argc, String[] argv) {return 1;}",585"public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}");586tr = doExec(javaCmd, "-jar", "some.jar");587tr.contains("THE_CHOSEN_ONE");588if (!tr.testStatus)589System.out.println(tr);590// use classpath to check591tr = doExec(javaCmd, "-cp", "some.jar", "Foo");592tr.contains("THE_CHOSEN_ONE");593if (!tr.testStatus)594System.out.println(tr);595596// test for extraneous whitespace in the Main-Class attribute597createJar(" Foo ", new File("some.jar"), new File("Foo"),598"public static void main(String... args){}");599tr = doExec(javaCmd, "-jar", "some.jar");600tr.checkPositive();601if (!tr.testStatus)602System.out.println(tr);603}604/*605* tests 6968053, ie. we turn on the -Xdiag (for now) flag and check if606* the suppressed stack traces are exposed, ignore these tests for localized607* locales, limiting to English only.608*/609@Test610void testDiagOptions() throws FileNotFoundException {611if (!isEnglishLocale()) { // only english version612return;613}614TestResult tr;615// a missing class616createJar("MIA", new File("some.jar"), new File("Foo"),617(String[])null);618tr = doExec(javaCmd, "-Xdiag", "-jar", "some.jar");619tr.contains("Error: Could not find or load main class MIA");620tr.contains("java.lang.ClassNotFoundException: MIA");621if (!tr.testStatus)622System.out.println(tr);623624// use classpath to check625tr = doExec(javaCmd, "-Xdiag", "-cp", "some.jar", "MIA");626tr.contains("Error: Could not find or load main class MIA");627tr.contains("java.lang.ClassNotFoundException: MIA");628if (!tr.testStatus)629System.out.println(tr);630631// a missing class on the classpath632tr = doExec(javaCmd, "-Xdiag", "NonExistentClass");633tr.contains("Error: Could not find or load main class NonExistentClass");634tr.contains("java.lang.ClassNotFoundException: NonExistentClass");635if (!tr.testStatus)636System.out.println(tr);637}638639/**640* @param args the command line arguments641* @throws java.io.FileNotFoundException642*/643public static void main(String[] args) throws Exception {644if (debug) {645System.out.println("Starting Arrrghs tests");646}647Arrrghs a = new Arrrghs();648a.run(args);649if (testExitValue > 0) {650System.out.println("Total of " + testExitValue + " failed");651System.exit(1);652} else {653System.out.println("All tests pass");654}655}656}657658659