1 /* 2 * Copyright (c) 2007, 2013, 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 checkArgumentParsing("a b\\ c", "a", "b\\", "c"); 313 } 314 315 private void initEmptyDir(File emptyDir) throws IOException { 316 if (emptyDir.exists()) { 317 recursiveDelete(emptyDir); 318 } 319 emptyDir.mkdir(); 320 } 321 322 private void initDirWithJavaFiles(File libDir) throws IOException { 323 324 if (libDir.exists()) { 325 recursiveDelete(libDir); 326 } 327 libDir.mkdirs(); 328 ArrayList<String> scratchpad = new ArrayList<>(); 329 scratchpad.add("package lib;"); 330 scratchpad.add("public class Fbo {"); 331 scratchpad.add("public static void main(String... args){Foo.f();}"); 332 scratchpad.add("public static void f(){}"); 333 scratchpad.add("}"); 334 createFile(new File(libDir, "Fbo.java"), scratchpad); 335 336 scratchpad.clear(); 337 scratchpad.add("package lib;"); 338 scratchpad.add("public class Foo {"); 339 scratchpad.add("public static void main(String... args){"); 340 scratchpad.add("for (String x : args) {"); 341 scratchpad.add("System.out.println(x);"); 342 scratchpad.add("}"); 343 scratchpad.add("Fbo.f();"); 344 scratchpad.add("}"); 345 scratchpad.add("public static void f(){}"); 346 scratchpad.add("}"); 347 createFile(new File(libDir, "Foo.java"), scratchpad); 348 } 349 350 void checkArgumentWildcard(String inArgs, String... expArgs) throws IOException { 351 String[] in = {inArgs}; 352 checkArgumentWildcard(in, expArgs); 353 354 // now add arbitrary arguments before and after 355 String[] outInArgs = { "-Q", inArgs, "-R"}; 356 357 String[] outExpArgs = new String[expArgs.length + 2]; 358 outExpArgs[0] = "-Q"; 359 System.arraycopy(expArgs, 0, outExpArgs, 1, expArgs.length); 360 outExpArgs[expArgs.length + 1] = "-R"; 361 checkArgumentWildcard(outInArgs, outExpArgs); 362 } 363 364 void checkArgumentWildcard(String[] inArgs, String[] expArgs) throws IOException { 365 ArrayList<String> argList = new ArrayList<>(); 366 argList.add(javaCmd); 367 argList.add("-cp"); 368 argList.add("lib" + File.separator + "*"); 369 argList.add("lib.Foo"); 370 argList.addAll(Arrays.asList(inArgs)); 371 String[] cmds = new String[argList.size()]; 372 argList.toArray(cmds); 373 TestResult tr = doExec(cmds); 374 if (!tr.isOK()) { 375 System.out.println(tr); 376 throw new RuntimeException("Error: classpath single entry wildcard entry"); 377 } 378 379 ArrayList<String> expList = new ArrayList<>(); 380 expList.addAll(Arrays.asList(expArgs)); 381 382 List<String> gotList = new ArrayList<>(); 383 for (String x : tr.testOutput) { 384 gotList.add(x.trim()); 385 } 386 if (!gotList.equals(expList)) { 387 System.out.println(tr); 388 System.out.println("Expected args:"); 389 System.out.println(expList); 390 System.out.println("Obtained args:"); 391 System.out.println(gotList); 392 throw new RuntimeException("Error: args do not match"); 393 } 394 System.out.print("\'"); 395 for (String x : inArgs) { 396 System.out.print(x + " "); 397 } 398 System.out.println("\'" + " - Test passed"); 399 } 400 401 /* 402 * These tests are not expected to work on *nixes, and are ignored. 403 */ 404 @Test 405 void testWildCardArgumentProcessing() throws IOException { 406 if (!isWindows) 407 return; 408 File cwd = new File("."); 409 File libDir = new File(cwd, "lib"); 410 initDirWithJavaFiles(libDir); 411 initEmptyDir(new File(cwd, "empty")); 412 413 // test if javac (the command) can compile *.java 414 TestResult tr = doExec(javacCmd, libDir.getName() + File.separator + "*.java"); 415 if (!tr.isOK()) { 416 System.out.println(tr); 417 throw new RuntimeException("Error: compiling java wildcards"); 418 } 419 420 // use the jar cmd to create jars using the ? wildcard 421 File jarFoo = new File(libDir, "Foo.jar"); 422 tr = doExec(jarCmd, "cvf", jarFoo.getAbsolutePath(), "lib" + File.separator + "F?o.class"); 423 if (!tr.isOK()) { 424 System.out.println(tr); 425 throw new RuntimeException("Error: creating jar with wildcards"); 426 } 427 428 // now the litmus test!, this should work 429 checkArgumentWildcard("a", "a"); 430 431 // test for basic expansion 432 checkArgumentWildcard("lib\\F*java", "lib\\Fbo.java", "lib\\Foo.java"); 433 434 // basic expansion in quotes 435 checkArgumentWildcard("\"lib\\F*java\"", "lib\\F*java"); 436 437 checkArgumentWildcard("lib\\**", "lib\\Fbo.class", "lib\\Fbo.java", 438 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 439 440 checkArgumentWildcard("lib\\*?", "lib\\Fbo.class", "lib\\Fbo.java", 441 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 442 443 checkArgumentWildcard("lib\\?*", "lib\\Fbo.class", "lib\\Fbo.java", 444 "lib\\Foo.class", "lib\\Foo.jar", "lib\\Foo.java"); 445 446 checkArgumentWildcard("lib\\?", "lib\\?"); 447 448 // test for basic expansion 449 checkArgumentWildcard("lib\\*java", "lib\\Fbo.java", "lib\\Foo.java"); 450 451 // basic expansion in quotes 452 checkArgumentWildcard("\"lib\\*.java\"", "lib\\*.java"); 453 454 // suffix expansion 455 checkArgumentWildcard("lib\\*.class", "lib\\Fbo.class", "lib\\Foo.class"); 456 457 // suffix expansion in quotes 458 checkArgumentWildcard("\"lib\\*.class\"", "lib\\*.class"); 459 460 // check for ? expansion now 461 checkArgumentWildcard("lib\\F?o.java", "lib\\Fbo.java", "lib\\Foo.java"); 462 463 // check ? in quotes 464 checkArgumentWildcard("\"lib\\F?o.java\"", "lib\\F?o.java"); 465 466 // check ? as suffixes 467 checkArgumentWildcard("lib\\F?o.????", "lib\\Fbo.java", "lib\\Foo.java"); 468 469 // check ? in a leading role 470 checkArgumentWildcard("lib\\???.java", "lib\\Fbo.java", "lib\\Foo.java"); 471 checkArgumentWildcard("\"lib\\???.java\"", "lib\\???.java"); 472 473 // check ? prefixed with - 474 checkArgumentWildcard("-?", "-?"); 475 476 // check * prefixed with - 477 checkArgumentWildcard("-*", "-*"); 478 479 // check on empty directory 480 checkArgumentWildcard("empty\\*", "empty\\*"); 481 checkArgumentWildcard("empty\\**", "empty\\**"); 482 checkArgumentWildcard("empty\\?", "empty\\?"); 483 checkArgumentWildcard("empty\\??", "empty\\??"); 484 checkArgumentWildcard("empty\\*?", "empty\\*?"); 485 checkArgumentWildcard("empty\\?*", "empty\\?*"); 486 487 } 488 489 void doArgumentCheck(String inArgs, String... expArgs) { 490 Map<String, String> env = new HashMap<>(); 491 env.put(JLDEBUG_KEY, "true"); 492 TestResult tr = doExec(env, javaCmd, inArgs); 493 System.out.println(tr); 494 int sindex = tr.testOutput.indexOf("Command line args:"); 495 if (sindex < 0) { 496 System.out.println(tr); 497 throw new RuntimeException("Error: no output"); 498 } 499 sindex++; // skip over the tag 500 List<String> gotList = new ArrayList<>(); 501 for (String x : tr.testOutput.subList(sindex, sindex + expArgs.length)) { 502 String a[] = x.split("="); 503 gotList.add(a[a.length - 1].trim()); 504 } 505 List<String> expList = Arrays.asList(expArgs); 506 if (!gotList.equals(expList)) { 507 System.out.println(tr); 508 System.out.println("Expected args:"); 509 System.out.println(expList); 510 System.out.println("Obtained args:"); 511 System.out.println(gotList); 512 throw new RuntimeException("Error: args do not match"); 513 } 514 } 515 516 517 /* 518 * These tests are usually run on non-existent targets to check error results 519 */ 520 @Test 521 void testBasicErrorMessages() { 522 // Tests for 5030233 523 TestResult tr = doExec(javaCmd, "-cp"); 524 tr.checkNegative(); 525 tr.isNotZeroOutput(); 526 if (!tr.testStatus) 527 System.out.println(tr); 528 529 tr = doExec(javaCmd, "-classpath"); 530 tr.checkNegative(); 531 tr.isNotZeroOutput(); 532 if (!tr.testStatus) 533 System.out.println(tr); 534 535 tr = doExec(javaCmd, "-jar"); 536 tr.checkNegative(); 537 tr.isNotZeroOutput(); 538 if (!tr.testStatus) 539 System.out.println(tr); 540 541 tr = doExec(javacCmd, "-cp"); 542 tr.checkNegative(); 543 tr.isNotZeroOutput(); 544 if (!tr.testStatus) 545 System.out.println(tr); 546 547 // Test for 6356475 "REGRESSION:"java -X" from cmdline fails" 548 tr = doExec(javaCmd, "-X"); 549 tr.checkPositive(); 550 tr.isNotZeroOutput(); 551 if (!tr.testStatus) 552 System.out.println(tr); 553 554 tr = doExec(javaCmd, "-help"); 555 tr.checkPositive(); 556 tr.isNotZeroOutput(); 557 if (!tr.testStatus) 558 System.out.println(tr); 559 560 // 6753938, test for non-negative exit value for an incorrectly formed 561 // command line, '% java' 562 tr = doExec(javaCmd); 563 tr.checkNegative(); 564 tr.isNotZeroOutput(); 565 if (!tr.testStatus) 566 System.out.println(tr); 567 568 // 6753938, test for non-negative exit value for an incorrectly formed 569 // command line, '% java -Xcomp' 570 tr = doExec(javaCmd, "-Xcomp"); 571 tr.checkNegative(); 572 tr.isNotZeroOutput(); 573 if (!tr.testStatus) 574 System.out.println(tr); 575 576 // 7151434, test for non-negative exit value for an incorrectly formed 577 // command line, '% java -jar -W', note the bogus -W 578 tr = doExec(javaCmd, "-jar", "-W"); 579 tr.checkNegative(); 580 tr.contains("Unrecognized option: -W"); 581 if (!tr.testStatus) 582 System.out.println(tr); 583 } 584 585 /* 586 * Tests various dispositions of the main method, these tests are limited 587 * to English locales as they check for error messages that are localized. 588 */ 589 @Test 590 void testMainMethod() throws FileNotFoundException { 591 if (!isEnglishLocale()) { 592 return; 593 } 594 595 TestResult tr = null; 596 597 // a missing class 598 createJar("MIA", new File("some.jar"), new File("Foo"), 599 (String[])null); 600 tr = doExec(javaCmd, "-jar", "some.jar"); 601 tr.contains("Error: Could not find or load main class MIA"); 602 if (!tr.testStatus) 603 System.out.println(tr); 604 // use classpath to check 605 tr = doExec(javaCmd, "-cp", "some.jar", "MIA"); 606 tr.contains("Error: Could not find or load main class MIA"); 607 if (!tr.testStatus) 608 System.out.println(tr); 609 610 // incorrect method access 611 createJar(new File("some.jar"), new File("Foo"), 612 "private static void main(String[] args){}"); 613 tr = doExec(javaCmd, "-jar", "some.jar"); 614 tr.contains("Error: Main method not found in class Foo"); 615 if (!tr.testStatus) 616 System.out.println(tr); 617 // use classpath to check 618 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 619 tr.contains("Error: Main method not found in class Foo"); 620 if (!tr.testStatus) 621 System.out.println(tr); 622 623 // incorrect return type 624 createJar(new File("some.jar"), new File("Foo"), 625 "public static int main(String[] args){return 1;}"); 626 tr = doExec(javaCmd, "-jar", "some.jar"); 627 tr.contains("Error: Main method must return a value of type void in class Foo"); 628 if (!tr.testStatus) 629 System.out.println(tr); 630 // use classpath to check 631 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 632 tr.contains("Error: Main method must return a value of type void in class Foo"); 633 if (!tr.testStatus) 634 System.out.println(tr); 635 636 // incorrect parameter type 637 createJar(new File("some.jar"), new File("Foo"), 638 "public static void main(Object[] args){}"); 639 tr = doExec(javaCmd, "-jar", "some.jar"); 640 tr.contains("Error: Main method not found in class Foo"); 641 if (!tr.testStatus) 642 System.out.println(tr); 643 // use classpath to check 644 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 645 tr.contains("Error: Main method not found in class Foo"); 646 if (!tr.testStatus) 647 System.out.println(tr); 648 649 // incorrect method type - non-static 650 createJar(new File("some.jar"), new File("Foo"), 651 "public void main(String[] args){}"); 652 tr = doExec(javaCmd, "-jar", "some.jar"); 653 tr.contains("Error: Main method is not static in class Foo"); 654 if (!tr.testStatus) 655 System.out.println(tr); 656 // use classpath to check 657 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 658 tr.contains("Error: Main method is not static in class Foo"); 659 if (!tr.testStatus) 660 System.out.println(tr); 661 662 // amongst a potpourri of kindred main methods, is the right one chosen ? 663 createJar(new File("some.jar"), new File("Foo"), 664 "void main(Object[] args){}", 665 "int main(Float[] args){return 1;}", 666 "private void main() {}", 667 "private static void main(int x) {}", 668 "public int main(int argc, String[] argv) {return 1;}", 669 "public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}"); 670 tr = doExec(javaCmd, "-jar", "some.jar"); 671 tr.contains("THE_CHOSEN_ONE"); 672 if (!tr.testStatus) 673 System.out.println(tr); 674 // use classpath to check 675 tr = doExec(javaCmd, "-cp", "some.jar", "Foo"); 676 tr.contains("THE_CHOSEN_ONE"); 677 if (!tr.testStatus) 678 System.out.println(tr); 679 680 // test for extraneous whitespace in the Main-Class attribute 681 createJar(" Foo ", new File("some.jar"), new File("Foo"), 682 "public static void main(String... args){}"); 683 tr = doExec(javaCmd, "-jar", "some.jar"); 684 tr.checkPositive(); 685 if (!tr.testStatus) 686 System.out.println(tr); 687 } 688 /* 689 * tests 6968053, ie. we turn on the -Xdiag (for now) flag and check if 690 * the suppressed stack traces are exposed, ignore these tests for localized 691 * locales, limiting to English only. 692 */ 693 @Test 694 void testDiagOptions() throws FileNotFoundException { 695 if (!isEnglishLocale()) { // only english version 696 return; 697 } 698 TestResult tr = null; 699 // a missing class 700 createJar("MIA", new File("some.jar"), new File("Foo"), 701 (String[])null); 702 tr = doExec(javaCmd, "-Xdiag", "-jar", "some.jar"); 703 tr.contains("Error: Could not find or load main class MIA"); 704 tr.contains("java.lang.ClassNotFoundException: MIA"); 705 if (!tr.testStatus) 706 System.out.println(tr); 707 708 // use classpath to check 709 tr = doExec(javaCmd, "-Xdiag", "-cp", "some.jar", "MIA"); 710 tr.contains("Error: Could not find or load main class MIA"); 711 tr.contains("java.lang.ClassNotFoundException: MIA"); 712 if (!tr.testStatus) 713 System.out.println(tr); 714 715 // a missing class on the classpath 716 tr = doExec(javaCmd, "-Xdiag", "NonExistentClass"); 717 tr.contains("Error: Could not find or load main class NonExistentClass"); 718 tr.contains("java.lang.ClassNotFoundException: NonExistentClass"); 719 if (!tr.testStatus) 720 System.out.println(tr); 721 } 722 723 @Test 724 static void testJreRestrictSearchFlag() { 725 // test both arguments to ensure they exist 726 TestResult tr = null; 727 tr = doExec(javaCmd, 728 "-no-jre-restrict-search", "-version"); 729 tr.checkPositive(); 730 if (!tr.testStatus) 731 System.out.println(tr); 732 733 tr = doExec(javaCmd, 734 "-jre-restrict-search", "-version"); 735 tr.checkPositive(); 736 if (!tr.testStatus) 737 System.out.println(tr); 738 } 739 740 /** 741 * @param args the command line arguments 742 * @throws java.io.FileNotFoundException 743 */ 744 public static void main(String[] args) throws Exception { 745 if (debug) { 746 System.out.println("Starting Arrrghs tests"); 747 } 748 Arrrghs a = new Arrrghs(); 749 a.run(args); 750 if (testExitValue > 0) { 751 System.out.println("Total of " + testExitValue + " failed"); 752 System.exit(1); 753 } else { 754 System.out.println("All tests pass"); 755 } 756 } 757 }