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