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