1 /* 2 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 27 * 6894719 6968053 7151434 7146424 28 * @summary Argument parsing validation. 29 * @compile -XDignore.symbol.file Arrrghs.java 30 * @run main/othervm Arrrghs 31 */ 32 33 import java.io.BufferedReader; 34 import java.io.File; 35 import java.io.FileNotFoundException; 36 import java.io.IOException; 37 import java.io.InputStream; 38 import java.io.InputStreamReader; 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.HashMap; 42 import java.util.List; 43 import java.util.Map; 44 import java.util.regex.Matcher; 45 import java.util.regex.Pattern; 46 47 public class Arrrghs extends TestHelper { 48 private Arrrghs(){} 49 /** 50 * This class provides various tests for arguments processing. 51 * A group of tests to ensure that arguments are passed correctly to 52 * a child java process upon a re-exec, this typically happens when 53 * a version other than the one being executed is requested by the user. 54 * 55 * History: these set of tests were part of Arrrghs.sh. The MKS shell 56 * implementations were notoriously buggy. Implementing these tests purely 57 * in Java is not only portable but also robust. 58 * 59 */ 60 61 // The version string to force a re-exec 62 final static String VersionStr = "-version:1.1+"; 63 64 // The Cookie or the pattern we match in the debug output. 65 final static String Cookie = "ReExec Args: "; 66 67 /* 68 * SIGH, On Windows all strings are quoted, we need to unwrap it 69 */ 70 private static String removeExtraQuotes(String in) { 71 if (isWindows) { 72 // Trim the string and remove the enclosed quotes if any. 73 in = in.trim(); 74 if (in.startsWith("\"") && in.endsWith("\"")) { 75 return in.substring(1, in.length()-1); 76 } 77 } 78 return in; 79 } 80 81 /* 82 * This method detects the cookie in the output stream of the process. 83 */ 84 private boolean detectCookie(InputStream istream, 85 String expectedArguments) throws IOException { 86 BufferedReader rd = new BufferedReader(new InputStreamReader(istream)); 87 boolean retval = false; 88 89 String in = rd.readLine(); 90 while (in != null) { 91 if (debug) System.out.println(in); 92 if (in.startsWith(Cookie)) { 93 String detectedArgument = removeExtraQuotes(in.substring(Cookie.length())); 94 if (expectedArguments.equals(detectedArgument)) { 95 retval = true; 96 } else { 97 System.out.println("Error: Expected Arguments\t:'" + 98 expectedArguments + "'"); 99 System.out.println(" Detected Arguments\t:'" + 100 detectedArgument + "'"); 101 } 102 // Return the value asap if not in debug mode. 103 if (!debug) { 104 rd.close(); 105 istream.close(); 106 return retval; 107 } 108 } 109 in = rd.readLine(); 110 } 111 return retval; 112 } 113 114 private boolean doReExecTest0(ProcessBuilder pb, String expectedArguments) { 115 boolean retval = false; 116 try { 117 pb.redirectErrorStream(true); 118 Process p = pb.start(); 119 retval = detectCookie(p.getInputStream(), expectedArguments); 120 p.waitFor(); 121 p.destroy(); 122 } catch (Exception ex) { 123 ex.printStackTrace(); 124 throw new RuntimeException(ex.getMessage()); 125 } 126 return retval; 127 } 128 129 /** 130 * This method returns true if the expected and detected arguments are the same. 131 * Quoting could cause dissimilar testArguments and expected arguments. 132 */ 133 int doReExecTest(String testArguments, String expectedPattern) { 134 ProcessBuilder pb = new ProcessBuilder(javaCmd, 135 VersionStr, testArguments); 136 137 Map<String, String> env = pb.environment(); 138 env.put(JLDEBUG_KEY, "true"); 139 return doReExecTest0(pb, testArguments) ? 0 : 1; 140 } 141 142 /** 143 * A convenience method for identical test pattern and expected arguments 144 */ 145 int doReExecTest(String testPattern) { 146 return doReExecTest(testPattern, testPattern); 147 } 148 149 @Test 150 void testQuoteParsingThroughReExec() { 151 /* 152 * Tests for 6214916 153 * These tests require that a JVM (any JVM) be installed in the system registry. 154 * If none is installed, skip this test. 155 */ 156 TestResult tr = doExec(javaCmd, VersionStr, "-version"); 157 if (!tr.isOK()) { 158 System.err.println("Warning:Argument Passing Tests were skipped, " + 159 "no java found in system registry."); 160 return; 161 } 162 163 // Basic test 164 testExitValue += doReExecTest("-a -b -c -d"); 165 166 // Basic test with many spaces 167 testExitValue += doReExecTest("-a -b -c -d"); 168 169 // Quoted whitespace does matter ? 170 testExitValue += doReExecTest("-a \"\"-b -c\"\" -d"); 171 172 173 // Escaped quotes outside of quotes as literals 174 testExitValue += doReExecTest("-a \\\"-b -c\\\" -d"); 175 176 // Check for escaped quotes inside of quotes as literal 177 testExitValue += doReExecTest("-a \"-b \\\"stuff\\\"\" -c -d"); 178 179 // A quote preceeded by an odd number of slashes is a literal quote 180 testExitValue += doReExecTest("-a -b\\\\\\\" -c -d"); 181 182 // A quote preceeded by an even number of slashes is a literal quote 183 // see 6214916. 184 testExitValue += doReExecTest("-a -b\\\\\\\\\" -c -d"); 185 186 // Make sure that whitespace doesn't interfere with the removal of the 187 // appropriate tokens. (space-tab-space preceeds -jre-restict-search). 188 testExitValue += doReExecTest("-a -b \t -jre-restrict-search -c -d", "-a -b -c -d"); 189 190 // Make sure that the mJRE tokens being stripped, aren't stripped if 191 // they happen to appear as arguments to the main class. 192 testExitValue += doReExecTest("foo -version:1.1+"); 193 194 System.out.println("Completed arguments quoting tests with " 195 + testExitValue + " errors"); 196 } 197 // the pattern we hope to see in the output 198 static final Pattern ArgPattern = Pattern.compile("\\s*argv\\[[0-9]*\\].*=.*"); 199 200 void checkArgumentParsing(String inArgs, String... expArgs) throws IOException { 201 List<String> scratchpad = new ArrayList<>(); 202 scratchpad.add("set " + JLDEBUG_KEY + "=true"); 203 // GAK, -version needs to be added so that windows can flush its stderr 204 // exiting the process prematurely can terminate the stderr. 205 scratchpad.add(javaCmd + " -version " + inArgs); 206 File batFile = new File("atest.bat"); 207 createAFile(batFile, scratchpad); 208 209 TestResult tr = doExec(batFile.getName()); 210 211 ArrayList<String> expList = new ArrayList<>(); 212 expList.add(javaCmd); 213 expList.add("-version"); 214 expList.addAll(Arrays.asList(expArgs)); 215 216 List<String> gotList = new ArrayList<>(); 217 for (String x : tr.testOutput) { 218 Matcher m = ArgPattern.matcher(x); 219 if (m.matches()) { 220 String a[] = x.split("="); 221 gotList.add(a[a.length - 1].trim()); 222 } 223 } 224 if (!gotList.equals(expList)) { 225 System.out.println(tr); 226 System.out.println("Expected args:"); 227 System.out.println(expList); 228 System.out.println("Obtained args:"); 229 System.out.println(gotList); 230 throw new RuntimeException("Error: args do not match"); 231 } 232 System.out.println("\'" + inArgs + "\'" + " - Test passed"); 233 } 234 235 /* 236 * This tests general quoting and are specific to Windows, *nixes 237 * need not worry about this, these have been tested with Windows 238 * implementation and those that are known to work are used against 239 * the java implementation. Note that the ProcessBuilder gets in the 240 * way when testing some of these arguments, therefore we need to 241 * create and execute a .bat file containing the arguments. 242 */ 243 @Test 244 void testArgumentParsing() throws IOException { 245 if (!isWindows) 246 return; 247 // no quotes 248 checkArgumentParsing("a b c d", "a", "b", "c", "d"); 249 250 // single quotes 251 checkArgumentParsing("\"a b c d\"", "a b c d"); 252 253 //double quotes 254 checkArgumentParsing("\"\"a b c d\"\"", "a", "b", "c", "d"); 255 256 // triple quotes 257 checkArgumentParsing("\"\"\"a b c d\"\"\"", "\"a b c d\""); 258 259 // a literal within single quotes 260 checkArgumentParsing("\"a\"b c d\"e\"", "ab", "c", "de"); 261 262 // a literal within double quotes 263 checkArgumentParsing("\"\"a\"b c d\"e\"\"", "ab c de"); 264 265 // a literal quote 266 checkArgumentParsing("a\\\"b", "a\"b"); 267 268 // double back-slash 269 checkArgumentParsing("\"a b c d\\\\\"", "a b c d\\"); 270 271 // triple back-slash 272 checkArgumentParsing("a\\\\\\\"b", "a\\\"b"); 273 274 // dangling quote 275 checkArgumentParsing("\"a b c\"\"", "a b c\""); 276 277 // expansions of white space separators 278 checkArgumentParsing("a b", "a", "b"); 279 checkArgumentParsing("a\tb", "a", "b"); 280 checkArgumentParsing("a \t b", "a", "b"); 281 282 checkArgumentParsing("\"C:\\TEST A\\\\\"", "C:\\TEST A\\"); 283 checkArgumentParsing("\"\"C:\\TEST A\\\\\"\"", "C:\\TEST", "A\\"); 284 285 // MS Windows tests 286 // triple back-slash 287 checkArgumentParsing("a\\\\\\d", "a\\\\\\d"); 288 289 // triple back-slash in quotes 290 checkArgumentParsing("\"a\\\\\\d\"", "a\\\\\\d"); 291 292 // slashes separating characters 293 checkArgumentParsing("X\\Y\\Z", "X\\Y\\Z"); 294 checkArgumentParsing("\\X\\Y\\Z", "\\X\\Y\\Z"); 295 296 // literals within dangling quotes, etc. 297 checkArgumentParsing("\"a b c\" d e", "a b c", "d", "e"); 298 checkArgumentParsing("\"ab\\\"c\" \"\\\\\" d", "ab\"c", "\\", "d"); 299 checkArgumentParsing("a\\\\\\c d\"e f\"g h", "a\\\\\\c", "de fg", "h"); 300 checkArgumentParsing("a\\\\\\\"b c d", "a\\\"b", "c", "d"); 301 checkArgumentParsing("a\\\\\\\\\"g c\" d e", "a\\\\g c", "d", "e"); 302 303 // treatment of back-slashes 304 checkArgumentParsing("*\\", "*\\"); 305 checkArgumentParsing("*/", "*/"); 306 checkArgumentParsing(".\\*", ".\\*"); 307 checkArgumentParsing("./*", "./*"); 308 checkArgumentParsing("..\\..\\*", "..\\..\\*"); 309 checkArgumentParsing("../../*", "../../*"); 310 checkArgumentParsing("..\\..\\", "..\\..\\"); 311 checkArgumentParsing("../../", "../../"); 312 } 313 314 private void initEmptyDir(File emptyDir) throws IOException { 315 if (emptyDir.exists()) { 316 recursiveDelete(emptyDir); 317 } 318 emptyDir.mkdir(); 319 } 320 321 private void initDirWithJavaFiles(File libDir) throws IOException { 322 323 if (libDir.exists()) { 324 recursiveDelete(libDir); 325 } 326 libDir.mkdirs(); 327 ArrayList<String> scratchpad = new ArrayList<>(); 328 scratchpad.add("package lib;"); 329 scratchpad.add("public class Fbo {"); 330 scratchpad.add("public static void main(String... args){Foo.f();}"); 331 scratchpad.add("public static void f(){}"); 332 scratchpad.add("}"); 333 createFile(new File(libDir, "Fbo.java"), scratchpad); 334 335 scratchpad.clear(); 336 scratchpad.add("package lib;"); 337 scratchpad.add("public class Foo {"); 338 scratchpad.add("public static void main(String... args){"); 339 scratchpad.add("for (String x : args) {"); 340 scratchpad.add("System.out.println(x);"); 341 scratchpad.add("}"); 342 scratchpad.add("Fbo.f();"); 343 scratchpad.add("}"); 344 scratchpad.add("public static void f(){}"); 345 scratchpad.add("}"); 346 createFile(new File(libDir, "Foo.java"), scratchpad); 347 } 348 349 void checkArgumentWildcard(String inArgs, String... expArgs) throws IOException { 350 String[] in = {inArgs}; 351 checkArgumentWildcard(in, expArgs); 352 353 // now add arbitrary arguments before and after 354 String[] outInArgs = { "-Q", inArgs, "-R"}; 355 356 String[] outExpArgs = new String[expArgs.length + 2]; 357 outExpArgs[0] = "-Q"; 358 System.arraycopy(expArgs, 0, outExpArgs, 1, expArgs.length); 359 outExpArgs[expArgs.length + 1] = "-R"; 360 checkArgumentWildcard(outInArgs, outExpArgs); 361 } 362 363 void checkArgumentWildcard(String[] inArgs, String[] expArgs) throws IOException { 364 ArrayList<String> argList = new ArrayList<>(); 365 argList.add(javaCmd); 366 argList.add("-cp"); 367 argList.add("lib" + File.separator + "*"); 368 argList.add("lib.Foo"); 369 argList.addAll(Arrays.asList(inArgs)); 370 String[] cmds = new String[argList.size()]; 371 argList.toArray(cmds); 372 TestResult tr = doExec(cmds); 373 if (!tr.isOK()) { 374 System.out.println(tr); 375 throw new RuntimeException("Error: classpath single entry wildcard entry"); 376 } 377 378 ArrayList<String> expList = new ArrayList<>(); 379 expList.addAll(Arrays.asList(expArgs)); 380 381 List<String> gotList = new ArrayList<>(); 382 for (String x : tr.testOutput) { 383 gotList.add(x.trim()); 384 } 385 if (!gotList.equals(expList)) { 386 System.out.println(tr); 387 System.out.println("Expected args:"); 388 System.out.println(expList); 389 System.out.println("Obtained args:"); 390 System.out.println(gotList); 391 throw new RuntimeException("Error: args do not match"); 392 } 393 System.out.print("\'"); 394 for (String x : inArgs) { 395 System.out.print(x + " "); 396 } 397 System.out.println("\'" + " - Test passed"); 398 } 399 400 /* 401 * These tests are not expected to work on *nixes, and are ignored. 402 */ 403 @Test 404 void testWildCardArgumentProcessing() throws IOException { 405 if (!isWindows) 406 return; 407 File cwd = new File("."); 408 File libDir = new File(cwd, "lib"); 409 initDirWithJavaFiles(libDir); 410 initEmptyDir(new File(cwd, "empty")); 411 412 // test if javac (the command) can compile *.java 413 TestResult tr = doExec(javacCmd, libDir.getName() + File.separator + "*.java"); 414 if (!tr.isOK()) { 415 System.out.println(tr); 416 throw new RuntimeException("Error: compiling java wildcards"); 417 } 418 419 // use the jar cmd to create jars using the ? wildcard 420 File jarFoo = new File(libDir, "Foo.jar"); 421 tr = doExec(jarCmd, "cvf", jarFoo.getAbsolutePath(), "lib" + File.separator + "F?o.class"); 422 if (!tr.isOK()) { 423 System.out.println(tr); 424 throw new RuntimeException("Error: creating jar with wildcards"); 425 } 426 427 // now the litmus test!, this should work 428 checkArgumentWildcard("a", "a"); 429 430 // test for basic expansion 431 checkArgumentWildcard("lib\\F*java", "lib\\Fbo.java", "lib\\Foo.java"); 432 433 // basic expansion in quotes 434 checkArgumentWildcard("\"lib\\F*java\"", "lib\\F*java"); 435 436 checkArgumentWildcard("lib\\**", "lib\\Fbo.class", "lib\\Fbo.java", 437 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 438 439 checkArgumentWildcard("lib\\*?", "lib\\Fbo.class", "lib\\Fbo.java", 440 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 441 442 checkArgumentWildcard("lib\\?*", "lib\\Fbo.class", "lib\\Fbo.java", 443 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 444 445 checkArgumentWildcard("lib\\?", "lib\\?"); 446 447 // test for basic expansion 448 checkArgumentWildcard("lib\\*java", "lib\\Fbo.java", "lib\\Foo.java"); 449 450 // basic expansion in quotes 451 checkArgumentWildcard("\"lib\\*.java\"", "lib\\*.java"); 452 453 // suffix expansion 454 checkArgumentWildcard("lib\\*.class", "lib\\Fbo.class", "lib\\Foo.class"); 455 456 // suffix expansion in quotes 457 checkArgumentWildcard("\"lib\\*.class\"", "lib\\*.class"); 458 459 // check for ? expansion now 460 checkArgumentWildcard("lib\\F?o.java", "lib\\Fbo.java", "lib\\Foo.java"); 461 462 // check ? in quotes 463 checkArgumentWildcard("\"lib\\F?o.java\"", "lib\\F?o.java"); 464 465 // check ? as suffixes 466 checkArgumentWildcard("lib\\F?o.????", "lib\\Fbo.java", "lib\\Foo.java"); 467 468 // check ? in a leading role 469 checkArgumentWildcard("lib\\???.java", "lib\\Fbo.java", "lib\\Foo.java"); 470 checkArgumentWildcard("\"lib\\???.java\"", "lib\\???.java"); 471 472 // check ? prefixed with - 473 checkArgumentWildcard("-?", "-?"); 474 475 // check * prefixed with - 476 checkArgumentWildcard("-*", "-*"); 477 478 // check on empty directory 479 checkArgumentWildcard("empty\\*", "empty\\*"); 480 checkArgumentWildcard("empty\\**", "empty\\**"); 481 checkArgumentWildcard("empty\\?", "empty\\?"); 482 checkArgumentWildcard("empty\\??", "empty\\??"); 483 checkArgumentWildcard("empty\\*?", "empty\\*?"); 484 checkArgumentWildcard("empty\\?*", "empty\\?*"); 485 486 } 487 488 void doArgumentCheck(String inArgs, String... expArgs) { 489 Map<String, String> env = new HashMap<>(); 490 env.put(JLDEBUG_KEY, "true"); 491 TestResult tr = doExec(env, javaCmd, inArgs); 492 System.out.println(tr); 493 int sindex = tr.testOutput.indexOf("Command line args:"); 494 if (sindex < 0) { 495 System.out.println(tr); 496 throw new RuntimeException("Error: no output"); 497 } 498 sindex++; // skip over the tag 499 List<String> gotList = new ArrayList<>(); 500 for (String x : tr.testOutput.subList(sindex, sindex + expArgs.length)) { 501 String a[] = x.split("="); 502 gotList.add(a[a.length - 1].trim()); 503 } 504 List<String> expList = Arrays.asList(expArgs); 505 if (!gotList.equals(expList)) { 506 System.out.println(tr); 507 System.out.println("Expected args:"); 508 System.out.println(expList); 509 System.out.println("Obtained args:"); 510 System.out.println(gotList); 511 throw new RuntimeException("Error: args do not match"); 512 } 513 } 514 515 516 /* 517 * These tests are usually run on non-existent targets to check error results 518 */ 519 @Test 520 void testBasicErrorMessages() { 521 // Tests for 5030233 522 TestResult tr = doExec(javaCmd, "-cp"); 523 tr.checkNegative(); 524 tr.isNotZeroOutput(); 525 if (!tr.testStatus) 526 System.out.println(tr); 527 528 tr = doExec(javaCmd, "-classpath"); 529 tr.checkNegative(); 530 tr.isNotZeroOutput(); 531 if (!tr.testStatus) 532 System.out.println(tr); 533 534 tr = doExec(javaCmd, "-jar"); 535 tr.checkNegative(); 536 tr.isNotZeroOutput(); 537 if (!tr.testStatus) 538 System.out.println(tr); 539 540 tr = doExec(javacCmd, "-cp"); 541 tr.checkNegative(); 542 tr.isNotZeroOutput(); 543 if (!tr.testStatus) 544 System.out.println(tr); 545 546 // Test for 6356475 "REGRESSION:"java -X" from cmdline fails" 547 tr = doExec(javaCmd, "-X"); 548 tr.checkPositive(); 549 tr.isNotZeroOutput(); 550 if (!tr.testStatus) 551 System.out.println(tr); 552 553 tr = doExec(javaCmd, "-help"); 554 tr.checkPositive(); 555 tr.isNotZeroOutput(); 556 if (!tr.testStatus) 557 System.out.println(tr); 558 559 // 6753938, test for non-negative exit value for an incorrectly formed 560 // command line, '% java' 561 tr = doExec(javaCmd); 562 tr.checkNegative(); 563 tr.isNotZeroOutput(); 564 if (!tr.testStatus) 565 System.out.println(tr); 566 567 // 6753938, test for non-negative exit value for an incorrectly formed 568 // command line, '% java -Xcomp' 569 tr = doExec(javaCmd, "-Xcomp"); 570 tr.checkNegative(); 571 tr.isNotZeroOutput(); 572 if (!tr.testStatus) 573 System.out.println(tr); 574 575 // 7151434, test for non-negative exit value for an incorrectly formed 576 // command line, '% java -jar -W', note the bogus -W 577 tr = doExec(javaCmd, "-jar", "-W"); 578 tr.checkNegative(); 579 tr.contains("Unrecognized option: -W"); 580 if (!tr.testStatus) 581 System.out.println(tr); 582 } 583 584 /* 585 * Tests various dispositions of the main method, these tests are limited 586 * to English locales as they check for error messages that are localized. 587 */ 588 @Test 589 void testMainMethod() throws FileNotFoundException { 590 if (!isEnglishLocale()) { 591 return; 592 } 593 594 TestResult tr = null; 595 596 // a missing class 597 createJar("MIA", new File("some.jar"), new File("Foo"), 598 (String[])null); 599 tr = doExec(javaCmd, "-jar", "some.jar"); 600 tr.contains("Error: Could not find or load main class MIA"); 601 if (!tr.testStatus) 602 System.out.println(tr); 603 // use classpath to check 604 tr = doExec(javaCmd, "-cp", "some.jar", "MIA"); 605 tr.contains("Error: Could not find or load main class MIA"); 606 if (!tr.testStatus) 607 System.out.println(tr); 608 609 // incorrect method access 610 createJar(new File("some.jar"), new File("Foo"), 611 "private static void main(String[] args){}"); 612 tr = doExec(javaCmd, "-jar", "some.jar"); 613 tr.contains("Error: Main method not found in class Foo"); 614 if (!tr.testStatus) 615 System.out.println(tr); 616 // use classpath to check 617 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 618 tr.contains("Error: Main method not found in class Foo"); 619 if (!tr.testStatus) 620 System.out.println(tr); 621 622 // incorrect return type 623 createJar(new File("some.jar"), new File("Foo"), 624 "public static int main(String[] args){return 1;}"); 625 tr = doExec(javaCmd, "-jar", "some.jar"); 626 tr.contains("Error: Main method must return a value of type void in class Foo"); 627 if (!tr.testStatus) 628 System.out.println(tr); 629 // use classpath to check 630 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 631 tr.contains("Error: Main method must return a value of type void in class Foo"); 632 if (!tr.testStatus) 633 System.out.println(tr); 634 635 // incorrect parameter type 636 createJar(new File("some.jar"), new File("Foo"), 637 "public static void main(Object[] args){}"); 638 tr = doExec(javaCmd, "-jar", "some.jar"); 639 tr.contains("Error: Main method not found in class Foo"); 640 if (!tr.testStatus) 641 System.out.println(tr); 642 // use classpath to check 643 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 644 tr.contains("Error: Main method not found in class Foo"); 645 if (!tr.testStatus) 646 System.out.println(tr); 647 648 // incorrect method type - non-static 649 createJar(new File("some.jar"), new File("Foo"), 650 "public void main(String[] args){}"); 651 tr = doExec(javaCmd, "-jar", "some.jar"); 652 tr.contains("Error: Main method is not static in class Foo"); 653 if (!tr.testStatus) 654 System.out.println(tr); 655 // use classpath to check 656 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 657 tr.contains("Error: Main method is not static in class Foo"); 658 if (!tr.testStatus) 659 System.out.println(tr); 660 661 // amongst a potpourri of kindred main methods, is the right one chosen ? 662 createJar(new File("some.jar"), new File("Foo"), 663 "void main(Object[] args){}", 664 "int main(Float[] args){return 1;}", 665 "private void main() {}", 666 "private static void main(int x) {}", 667 "public int main(int argc, String[] argv) {return 1;}", 668 "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); 669 tr = doExec(javaCmd, "-jar", "some.jar"); 670 tr.contains("THE_CHOSEN_ONE"); 671 if (!tr.testStatus) 672 System.out.println(tr); 673 // use classpath to check 674 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 675 tr.contains("THE_CHOSEN_ONE"); 676 if (!tr.testStatus) 677 System.out.println(tr); 678 679 // test for extraneous whitespace in the Main-Class attribute 680 createJar(" Foo ", new File("some.jar"), new File("Foo"), 681 "public static void main(String... args){}"); 682 tr = doExec(javaCmd, "-jar", "some.jar"); 683 tr.checkPositive(); 684 if (!tr.testStatus) 685 System.out.println(tr); 686 } 687 /* 688 * tests 6968053, ie. we turn on the -Xdiag (for now) flag and check if 689 * the suppressed stack traces are exposed, ignore these tests for localized 690 * locales, limiting to English only. 691 */ 692 @Test 693 void testDiagOptions() throws FileNotFoundException { 694 if (!isEnglishLocale()) { // only english version 695 return; 696 } 697 TestResult tr = null; 698 // a missing class 699 createJar("MIA", new File("some.jar"), new File("Foo"), 700 (String[])null); 701 tr = doExec(javaCmd, "-Xdiag", "-jar", "some.jar"); 702 tr.contains("Error: Could not find or load main class MIA"); 703 tr.contains("java.lang.ClassNotFoundException: MIA"); 704 if (!tr.testStatus) 705 System.out.println(tr); 706 707 // use classpath to check 708 tr = doExec(javaCmd, "-Xdiag", "-cp", "some.jar", "MIA"); 709 tr.contains("Error: Could not find or load main class MIA"); 710 tr.contains("java.lang.ClassNotFoundException: MIA"); 711 if (!tr.testStatus) 712 System.out.println(tr); 713 714 // a missing class on the classpath 715 tr = doExec(javaCmd, "-Xdiag", "NonExistentClass"); 716 tr.contains("Error: Could not find or load main class NonExistentClass"); 717 tr.contains("java.lang.ClassNotFoundException: NonExistentClass"); 718 if (!tr.testStatus) 719 System.out.println(tr); 720 } 721 722 @Test 723 static void testJreRestrictSearchFlag() { 724 // test both arguments to ensure they exist 725 TestResult tr = null; 726 tr = doExec(javaCmd, 727 "-no-jre-restrict-search", "-version"); 728 tr.checkPositive(); 729 if (!tr.testStatus) 730 System.out.println(tr); 731 732 tr = doExec(javaCmd, 733 "-jre-restrict-search", "-version"); 734 tr.checkPositive(); 735 if (!tr.testStatus) 736 System.out.println(tr); 737 } 738 739 /** 740 * @param args the command line arguments 741 * @throws java.io.FileNotFoundException 742 */ 743 public static void main(String[] args) throws Exception { 744 if (debug) { 745 System.out.println("Starting Arrrghs tests"); 746 } 747 Arrrghs a = new Arrrghs(); 748 a.run(args); 749 if (testExitValue > 0) { 750 System.out.println("Total of " + testExitValue + " failed"); 751 System.exit(1); 752 } else { 753 System.out.println("All tests pass"); 754 } 755 } 756 }