1 /* 2 * Copyright (c) 2015, 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 8061999 8135195 8136552 27 * @summary Test "-XX:VMOptionsFile" VM option 28 * @library /testlibrary 29 * @modules java.base/jdk.internal.misc 30 * @modules jdk.management 31 * @run main TestVMOptionsFile 32 */ 33 34 import java.io.File; 35 import java.io.FileWriter; 36 import java.io.IOException; 37 import java.nio.file.Files; 38 import java.nio.file.Paths; 39 import java.nio.file.Path; 40 import java.nio.file.attribute.PosixFilePermissions; 41 import java.nio.file.attribute.AclEntry; 42 import java.nio.file.attribute.AclEntryPermission; 43 import java.nio.file.attribute.AclEntryType; 44 import java.nio.file.attribute.AclFileAttributeView; 45 import java.nio.file.attribute.UserPrincipal; 46 import java.nio.file.StandardCopyOption; 47 import java.util.ArrayList; 48 import java.util.Arrays; 49 import java.util.LinkedHashSet; 50 import java.util.List; 51 import java.util.Properties; 52 import java.util.Set; 53 import jdk.test.lib.Asserts; 54 import jdk.test.lib.DynamicVMOption; 55 import jdk.test.lib.OutputAnalyzer; 56 import jdk.test.lib.ProcessTools; 57 58 public class TestVMOptionsFile { 59 60 /* Various valid VM Option files */ 61 private static final String VM_OPTION_FILE_EMPTY = "optionfile_empty"; 62 private static final String VM_OPTION_FILE_TABS_AND_SPACES = "optionfile_only_tabsandspaces"; 63 private static final String VM_OPTION_FILE_1 = "optionfile_1"; 64 private static final String VM_OPTION_FILE_2 = "optionFILE_2"; 65 private static final String VM_OPTION_FILE_3 = "optionfile_3"; 66 private static final String VM_OPTION_FILE_QUOTE = "optionfile_quote"; 67 private static final String VM_OPTION_FILE_BIG = "optionfile_big"; 68 private static final int REPEAT_COUNT = 512; 69 /* Name of the file with flags for VM_OPTION_FILE_2 Option file */ 70 private static final String FLAGS_FILE = "flags_file"; 71 /* VM Option file with a lot of options with quote on separate lines */ 72 private static final String VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE = "optionfile_lot_of_options_quote"; 73 /* Number of properties defined in VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE */ 74 private static final int NUM_OF_PROP_IN_FILE_LOT_OF_OPTIONS_QUOTE = 70; 75 /* VM Option file with long property */ 76 private static final String VM_OPTION_FILE_WITH_LONG_PROPERTY = "optionfile_long_property"; 77 private static final String LONG_PROPERTY_NAME = "veryl'" + String.format("%1536s", "").replace(' ', 'o') + "ng'name"; 78 private static final String LONG_PROPERTY_VALUE = String.format("%2096s", "").replaceAll(" ", "long"); 79 /* 2 VM Option files with unmatched quotes */ 80 private static final String VM_OPTION_FILE_UNMATCHED_QUOTE_1 = "optionfile_unmatched_quote_1"; 81 private static final String VM_OPTION_FILE_UNMATCHED_QUOTE_2 = "optionfile_unmatched_quote_2"; 82 /* VM Option file with bad option in it */ 83 private static final String VM_OPTION_FILE_WITH_BAD_OPTION = "optionfile_bad_option"; 84 /* VM Option file with "-XX:VMOptionsFile=" option in it */ 85 private static final String VM_OPTION_FILE_WITH_VM_OPTION_FILE = "optionfile_with_optionfile"; 86 /* VM Option file with "-XX:VMOptionsFile=" option in it, where file is the same option file */ 87 private static final String VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE = "optionfile_with_same_optionfile"; 88 /* VM Option file without read permissions(not accessible) */ 89 private static final String VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS = "optionfile_wo_read_perm"; 90 /* VM Option file which does not exist */ 91 private static final String NOT_EXISTING_FILE = "not_exist_junk2123"; 92 93 /* JAVA_TOOL_OPTIONS environment variable */ 94 private static final String JAVA_TOOL_OPTIONS = "JAVA_TOOL_OPTIONS"; 95 /* _JAVA_OPTIONS environment variable */ 96 private static final String JAVA_OPTIONS = "_JAVA_OPTIONS"; 97 98 /* Exit code for JVM, zero - for success, non-zero for failure */ 99 private static final int JVM_SUCCESS = 0; 100 private static final int JVM_FAIL_WITH_EXIT_CODE_1 = 1; 101 102 /* Current working directory */ 103 private static final String CURRENT_DIR = System.getProperty("user.dir"); 104 105 /* Source directory */ 106 private static final String SOURCE_DIR = System.getProperty("test.src", "."); 107 108 /* VM Options which are passed to the JVM */ 109 private static final List<String> VMParams = new ArrayList<>(); 110 /* Argument passed to the PrintPropertyAndOptions.main */ 111 private static final Set<String> appParams = new LinkedHashSet<>(); 112 113 private static OutputAnalyzer output; 114 115 private static final String PRINT_PROPERTY_FORMAT = "Property %s=%s"; 116 private static final String PRINT_VM_OPTION_FORMAT = "Virtual Machine option %s=%s"; 117 118 /* 119 * Get absoulte path to file from folder with sources 120 */ 121 private static String getAbsolutePathFromSource(String fileName) { 122 return SOURCE_DIR + File.separator + fileName; 123 } 124 125 /* 126 * Make file non-readable by modifying its permissions. 127 * If file supports "posix" attributes, then modify it. 128 * Otherwise check for "acl" attributes. 129 */ 130 private static void makeFileNonReadable(String file) throws IOException { 131 Path filePath = Paths.get(file); 132 Set<String> supportedAttr = filePath.getFileSystem().supportedFileAttributeViews(); 133 134 if (supportedAttr.contains("posix")) { 135 Files.setPosixFilePermissions(filePath, PosixFilePermissions.fromString("-w--w----")); 136 } else if (supportedAttr.contains("acl")) { 137 UserPrincipal fileOwner = Files.getOwner(filePath); 138 139 AclFileAttributeView view = Files.getFileAttributeView(filePath, AclFileAttributeView.class); 140 141 AclEntry entry = AclEntry.newBuilder() 142 .setType(AclEntryType.DENY) 143 .setPrincipal(fileOwner) 144 .setPermissions(AclEntryPermission.READ_DATA) 145 .build(); 146 147 List<AclEntry> acl = view.getAcl(); 148 acl.add(0, entry); 149 view.setAcl(acl); 150 } 151 } 152 153 private static void copyFromSource(String fileName) throws IOException { 154 Files.copy(Paths.get(getAbsolutePathFromSource(fileName)), 155 Paths.get(fileName), StandardCopyOption.REPLACE_EXISTING); 156 } 157 158 private static void createOptionFiles() throws IOException { 159 FileWriter fw = new FileWriter(VM_OPTION_FILE_WITH_VM_OPTION_FILE); 160 161 /* Create VM option file with following parameters "-XX:VMOptionFile=<absolute_path_to_the_VM_option_file> */ 162 fw.write("-XX:VMOptionsFile=" + getAbsolutePathFromSource(VM_OPTION_FILE_1)); 163 fw.close(); 164 165 /* Create VM option file with following parameters "-XX:MinHeapFreeRatio=12 -XX:VMOptionFile=<absolute_path_to_the_same_VM_option_file> */ 166 fw = new FileWriter(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE); 167 fw.write("-XX:MinHeapFreeRatio=12 -XX:VMOptionsFile=" + (new File(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE)).getCanonicalPath()); 168 fw.close(); 169 170 /* Create VM option file with long property */ 171 fw = new FileWriter(VM_OPTION_FILE_WITH_LONG_PROPERTY); 172 fw.write("-D" + LONG_PROPERTY_NAME + "=" + LONG_PROPERTY_VALUE); 173 fw.close(); 174 175 /* Create big VM option file */ 176 fw = new FileWriter(VM_OPTION_FILE_BIG); 177 fw.write("-XX:MinHeapFreeRatio=17\n"); 178 for (int i = 0; i < REPEAT_COUNT; i++) { 179 if (i == REPEAT_COUNT / 2) { 180 fw.write("-XX:+PrintVMOptions "); 181 } 182 fw.write("-Dmy.property=value" + (i + 1) + "\n"); 183 } 184 fw.write("-XX:MaxHeapFreeRatio=85\n"); 185 fw.close(); 186 187 /* Copy valid VM option file and change its permission to make it not accessible */ 188 Files.copy(Paths.get(getAbsolutePathFromSource(VM_OPTION_FILE_1)), 189 Paths.get(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS), 190 StandardCopyOption.REPLACE_EXISTING); 191 192 makeFileNonReadable(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS); 193 194 /* Copy valid VM option file to perform test with relative path */ 195 copyFromSource(VM_OPTION_FILE_2); 196 197 /* Copy flags file to the current working folder */ 198 copyFromSource(FLAGS_FILE); 199 200 /* Create a new empty file */ 201 new File(VM_OPTION_FILE_EMPTY).createNewFile(); 202 } 203 204 /* 205 * Add parameters to the VM Parameters list 206 */ 207 private static void addVMParam(String... params) { 208 VMParams.addAll(Arrays.asList(params)); 209 } 210 211 /* 212 * Add VM option name to the application arguments list 213 */ 214 private static void addVMOptionsToCheck(String... params) { 215 for (String param : params) { 216 appParams.add("vmoption=" + param); 217 } 218 } 219 220 /* 221 * Add property to the VM Params list and to the application arguments list 222 */ 223 private static void addProperty(String propertyName, String propertyValue) { 224 addVMParam("-D" + propertyName + "=" + propertyValue); 225 } 226 227 /* 228 * Add "-XX:VMOptionsfile" parameter to the VM Params list 229 */ 230 private static void addVMOptionsFile(String fileName) { 231 addVMParam("-XX:VMOptionsFile=" + fileName); 232 } 233 234 private static void outputShouldContain(String expectedString) { 235 output.shouldContain(expectedString); 236 } 237 238 private static void outputShouldNotContain(String expectedString) { 239 output.shouldNotContain(expectedString); 240 } 241 242 private static ProcessBuilder createProcessBuilder() throws Exception { 243 ProcessBuilder pb; 244 List<String> runJava = new ArrayList<>(); 245 246 runJava.addAll(VMParams); 247 runJava.add(PrintPropertyAndOptions.class.getName()); 248 runJava.addAll(appParams); 249 250 pb = ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])); 251 252 VMParams.clear(); 253 appParams.clear(); 254 255 return pb; 256 } 257 258 private static void runJavaCheckExitValue(ProcessBuilder pb, int expectedExitValue) throws Exception { 259 output = new OutputAnalyzer(pb.start()); 260 output.shouldHaveExitValue(expectedExitValue); 261 } 262 263 private static void runJavaCheckExitValue(int expectedExitValue) throws Exception { 264 runJavaCheckExitValue(createProcessBuilder(), expectedExitValue); 265 } 266 267 /* 268 * Update environment variable in passed ProcessBuilder object to the passed value 269 */ 270 private static void updateEnvironment(ProcessBuilder pb, String name, String value) { 271 pb.environment().put(name, value); 272 } 273 274 /* 275 * Check property value by examining output 276 */ 277 private static void checkProperty(String property, String expectedValue) { 278 outputShouldContain(String.format(PRINT_PROPERTY_FORMAT, property, expectedValue)); 279 } 280 281 /* 282 * Check VM Option value by examining output 283 */ 284 private static void checkVMOption(String vmOption, String expectedValue) { 285 outputShouldContain(String.format(PRINT_VM_OPTION_FORMAT, vmOption, expectedValue)); 286 } 287 288 private static void testVMOptions() throws Exception { 289 ProcessBuilder pb; 290 291 /* Check that empty VM Option file is accepted without errors */ 292 addVMOptionsFile(VM_OPTION_FILE_EMPTY); 293 294 runJavaCheckExitValue(JVM_SUCCESS); 295 296 /* Check that VM Option file with tabs and spaces is accepted without errors */ 297 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_TABS_AND_SPACES)); 298 299 runJavaCheckExitValue(JVM_SUCCESS); 300 301 /* Check that parameters are gotten from first VM Option file. Pass absolute path to the VM Option file */ 302 addVMParam("-showversion"); 303 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1)); 304 addVMOptionsToCheck("SurvivorRatio", "MinHeapFreeRatio"); 305 306 runJavaCheckExitValue(JVM_SUCCESS); 307 outputShouldContain("interpreted mode"); 308 checkProperty("optfile_1", "option_file_1"); 309 checkVMOption("SurvivorRatio", "16"); 310 checkVMOption("MinHeapFreeRatio", "22"); 311 312 /* 313 * Check that parameters are gotten from second VM Option file which also contains flags file. 314 * Flags file and option file contains NewRatio, but since options from VM Option file 315 * are processed later NewRatio should be set to value from VM Option file 316 * Pass relative path to the VM Option file in form "vmoptionfile" 317 */ 318 addVMOptionsFile(VM_OPTION_FILE_2); 319 addVMOptionsToCheck("UseGCOverheadLimit", "NewRatio", "MinHeapFreeRatio", "MaxFDLimit", "AlwaysPreTouch"); 320 321 runJavaCheckExitValue(JVM_SUCCESS); 322 checkProperty("javax.net.ssl.keyStorePassword", "someVALUE123+"); 323 checkVMOption("UseGCOverheadLimit", "true"); 324 checkVMOption("NewRatio", "4"); 325 checkVMOption("MinHeapFreeRatio", "3"); 326 checkVMOption("MaxFDLimit", "true"); 327 checkVMOption("AlwaysPreTouch", "false"); 328 329 /* Check that parameters are gotten from third VM Option file which contains a mix of the options */ 330 addVMParam("-showversion"); 331 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_3)); 332 addVMOptionsToCheck("UseGCOverheadLimit", "NewRatio"); 333 334 runJavaCheckExitValue(JVM_SUCCESS); 335 outputShouldContain("interpreted mode"); 336 checkProperty("other.secret.data", "qwerty"); 337 checkProperty("property", "second"); 338 checkVMOption("UseGCOverheadLimit", "false"); 339 checkVMOption("NewRatio", "16"); 340 341 /* Check that quotes are processed normally in VM Option file */ 342 addVMParam("-showversion"); 343 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_QUOTE)); 344 addVMOptionsToCheck("ErrorFile"); 345 346 runJavaCheckExitValue(JVM_SUCCESS); 347 348 outputShouldContain("interpreted mode"); 349 checkProperty("my.quote.single", "Property in single quote. Here a double qoute\" Add some slashes \\/"); 350 checkProperty("my.quote.double", "Double qoute. Include single '."); 351 checkProperty("javax.net.ssl.trustStorePassword", "data @+NEW"); 352 checkVMOption("ErrorFile", "./my error file"); 353 354 /* 355 * Verify that VM Option file accepts a file with 70 properties and with two options on separate 356 * lines and properties that use quotes a lot. 357 */ 358 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_LOT_OF_OPTIONS_QUOTE)); 359 addVMOptionsToCheck("MinHeapFreeRatio", "MaxHeapFreeRatio"); 360 361 runJavaCheckExitValue(JVM_SUCCESS); 362 363 for (int i = 1; i <= NUM_OF_PROP_IN_FILE_LOT_OF_OPTIONS_QUOTE; i++) { 364 checkProperty(String.format("prop%02d", i), String.format("%02d", i)); 365 } 366 checkVMOption("MinHeapFreeRatio", "7"); 367 checkVMOption("MaxHeapFreeRatio", "96"); 368 369 /* 370 * Verify that VM Option file accepts a file with very long property. 371 */ 372 addVMOptionsFile(VM_OPTION_FILE_WITH_LONG_PROPERTY); 373 374 runJavaCheckExitValue(JVM_SUCCESS); 375 376 checkProperty(LONG_PROPERTY_NAME.replaceAll("'", ""), LONG_PROPERTY_VALUE); 377 378 /* 379 * Verify that VM Option file accepts a big VM Option file 380 */ 381 addVMOptionsFile(VM_OPTION_FILE_BIG); 382 addVMOptionsToCheck("MinHeapFreeRatio"); 383 addVMOptionsToCheck("MaxHeapFreeRatio"); 384 385 runJavaCheckExitValue(JVM_SUCCESS); 386 387 outputShouldContain("VM option '+PrintVMOptions'"); 388 checkProperty("my.property", "value" + REPEAT_COUNT); 389 checkVMOption("MinHeapFreeRatio", "17"); 390 checkVMOption("MaxHeapFreeRatio", "85"); 391 392 /* Pass VM Option file in _JAVA_OPTIONS environment variable */ 393 addVMParam("-showversion"); 394 addVMOptionsToCheck("SurvivorRatio", "MinHeapFreeRatio"); 395 pb = createProcessBuilder(); 396 397 updateEnvironment(pb, JAVA_OPTIONS, "-XX:VMOptionsFile=" + getAbsolutePathFromSource(VM_OPTION_FILE_1)); 398 399 runJavaCheckExitValue(pb, JVM_SUCCESS); 400 outputShouldContain("interpreted mode"); 401 checkProperty("optfile_1", "option_file_1"); 402 checkVMOption("SurvivorRatio", "16"); 403 checkVMOption("MinHeapFreeRatio", "22"); 404 405 /* Pass VM Option file in JAVA_TOOL_OPTIONS environment variable */ 406 addVMOptionsToCheck("UseGCOverheadLimit", "NewRatio", "MinHeapFreeRatio", "MaxFDLimit", "AlwaysPreTouch"); 407 pb = createProcessBuilder(); 408 409 updateEnvironment(pb, JAVA_TOOL_OPTIONS, "-XX:VMOptionsFile=" + VM_OPTION_FILE_2); 410 411 runJavaCheckExitValue(pb, JVM_SUCCESS); 412 checkProperty("javax.net.ssl.keyStorePassword", "someVALUE123+"); 413 checkVMOption("UseGCOverheadLimit", "true"); 414 checkVMOption("NewRatio", "4"); 415 checkVMOption("MinHeapFreeRatio", "3"); 416 checkVMOption("MaxFDLimit", "true"); 417 checkVMOption("AlwaysPreTouch", "false"); 418 } 419 420 private static ProcessBuilder prepareTestCase(int testCase) throws Exception { 421 ProcessBuilder pb; 422 423 Asserts.assertTrue(0 < testCase && testCase < 6, "testCase should be from 1 to 5"); 424 425 addVMParam("-showversion"); 426 addVMOptionsToCheck("MinHeapFreeRatio", "SurvivorRatio", "NewRatio"); 427 428 if (testCase < 5) { 429 addVMParam("-XX:Flags=flags_file", "-XX:-PrintVMOptions"); 430 addProperty("shared.property", "command_line_before"); 431 addProperty("clb", "unique_command_line_before"); 432 addVMParam("-XX:MinHeapFreeRatio=7"); 433 } 434 435 if (testCase < 4) { 436 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1)); 437 } 438 439 if (testCase < 3) { 440 addVMParam("-XX:MinHeapFreeRatio=9", "-XX:-PrintVMOptions"); 441 addProperty("shared.property", "command_line_after"); 442 addProperty("cla", "unique_command_line_after"); 443 } 444 445 /* Create ProcessBuilder after all setup is done to update environment variables */ 446 pb = createProcessBuilder(); 447 448 if (testCase < 2) { 449 updateEnvironment(pb, JAVA_OPTIONS, "-Dshared.property=somevalue -Djo=unique_java_options " 450 + "-XX:MinHeapFreeRatio=18 -Dshared.property=java_options -XX:MinHeapFreeRatio=11 -XX:+PrintVMOptions"); 451 } 452 453 if (testCase < 6) { 454 updateEnvironment(pb, JAVA_TOOL_OPTIONS, "-Dshared.property=qwerty -Djto=unique_java_tool_options " 455 + "-XX:MinHeapFreeRatio=15 -Dshared.property=java_tool_options -XX:MinHeapFreeRatio=6 -XX:+PrintVMOptions"); 456 } 457 458 return pb; 459 } 460 461 private static void testVMOptionsLastArgumentsWins() throws Exception { 462 ProcessBuilder pb; 463 464 /* 465 * "shared.property" property and "MinHeapFreeRatio" XX VM Option are defined 466 * in flags file, JAVA_TOOL_OPTIONS and _JAVA_OPTIONS environment variables, 467 * on command line before VM Option file, on command line after VM Option file 468 * and also in VM Option file. Verify that last argument wins. Also check 469 * unique properties and VM Options. 470 * Here is the order of options processing and last argument wins: 471 * 1) Flags file 472 * 2) JAVA_TOOL_OPTIONS environment variables 473 * 3) Pseudo command line from launcher 474 * 4) _JAVA_OPTIONS 475 * In every category arguments processed from left to right and from up to down 476 * and the last processed arguments wins, i.e. if argument is defined several 477 * times the value of argument will be equal to the last processed argument. 478 * 479 * "shared.property" property and "MinHeapFreeRatio" should be equal to the 480 * value from _JAVA_OPTIONS environment variable 481 */ 482 pb = prepareTestCase(1); 483 484 runJavaCheckExitValue(pb, JVM_SUCCESS); 485 486 outputShouldContain("interpreted mode"); 487 outputShouldContain("VM option '+PrintVMOptions'"); 488 checkProperty("shared.property", "java_options"); 489 checkVMOption("MinHeapFreeRatio", "11"); 490 /* Each category defines its own properties */ 491 checkProperty("jto", "unique_java_tool_options"); 492 checkProperty("jo", "unique_java_options"); 493 checkProperty("clb", "unique_command_line_before"); 494 checkProperty("optfile_1", "option_file_1"); 495 checkProperty("cla", "unique_command_line_after"); 496 /* SurvivorRatio defined only in VM Option file */ 497 checkVMOption("SurvivorRatio", "16"); 498 /* NewRatio defined only in flags file */ 499 checkVMOption("NewRatio", "5"); 500 501 /* 502 * The same as previous but without _JAVA_OPTIONS environment variable. 503 * "shared.property" property and "MinHeapFreeRatio" should be equal to the 504 * value from pseudo command line after VM Option file 505 */ 506 pb = prepareTestCase(2); 507 508 runJavaCheckExitValue(pb, JVM_SUCCESS); 509 510 outputShouldContain("interpreted mode"); 511 outputShouldNotContain("VM option '+PrintVMOptions'"); 512 checkProperty("shared.property", "command_line_after"); 513 checkVMOption("MinHeapFreeRatio", "9"); 514 515 /* 516 * The same as previous but without arguments in pseudo command line after 517 * VM Option file. 518 * "shared.property" property and "MinHeapFreeRatio" should be equal to the 519 * value from VM Option file. 520 */ 521 pb = prepareTestCase(3); 522 523 runJavaCheckExitValue(pb, JVM_SUCCESS); 524 525 outputShouldContain("interpreted mode"); 526 outputShouldContain("VM option '+PrintVMOptions'"); 527 checkProperty("shared.property", "vmoptfile"); 528 checkVMOption("MinHeapFreeRatio", "22"); 529 530 /* 531 * The same as previous but without arguments in VM Option file. 532 * "shared.property" property and "MinHeapFreeRatio" should be equal to the 533 * value from pseudo command line. 534 */ 535 pb = prepareTestCase(4); 536 537 runJavaCheckExitValue(pb, JVM_SUCCESS); 538 539 outputShouldNotContain("VM option '+PrintVMOptions'"); 540 checkProperty("shared.property", "command_line_before"); 541 checkVMOption("MinHeapFreeRatio", "7"); 542 543 /* 544 * The same as previous but without arguments from pseudo command line. 545 * "shared.property" property and "MinHeapFreeRatio" should be equal to the 546 * value from JAVA_TOOL_OPTIONS environment variable. 547 */ 548 pb = prepareTestCase(5); 549 550 runJavaCheckExitValue(pb, JVM_SUCCESS); 551 552 outputShouldContain("VM option '+PrintVMOptions'"); 553 checkProperty("shared.property", "java_tool_options"); 554 checkVMOption("MinHeapFreeRatio", "6"); 555 } 556 557 private static void testVMOptionsInvalid() throws Exception { 558 ProcessBuilder pb; 559 560 /* Pass directory instead of file */ 561 addVMOptionsFile(CURRENT_DIR); 562 563 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 564 565 /* Pass not existing file */ 566 addVMOptionsFile(getAbsolutePathFromSource(NOT_EXISTING_FILE)); 567 568 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 569 outputShouldContain("Could not open options file"); 570 571 /* Pass VM option file with bad option */ 572 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITH_BAD_OPTION)); 573 574 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 575 outputShouldContain("Unrecognized VM option"); 576 577 /* Pass VM option file with same VM option file option in it */ 578 addVMOptionsFile(VM_OPTION_FILE_WITH_SAME_VM_OPTION_FILE); 579 580 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 581 outputShouldContain("A VM options file may not refer to a VM options file. Specification of '-XX:VMOptionsFile=<file-name>' in the options file"); 582 583 /* Pass VM option file with VM option file option in it */ 584 addVMOptionsFile(VM_OPTION_FILE_WITH_VM_OPTION_FILE); 585 586 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 587 outputShouldContain("A VM options file may not refer to a VM options file. Specification of '-XX:VMOptionsFile=<file-name>' in the options file"); 588 589 /* Pass VM option file which is not accessible (without read permissions) */ 590 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_WITHOUT_READ_PERMISSIONS)); 591 592 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 593 outputShouldContain("Could not open options file"); 594 595 /* Pass two VM option files */ 596 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_1)); 597 addVMOptionsFile(VM_OPTION_FILE_2); 598 599 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 600 outputShouldContain("is already specified in the"); 601 602 /* Pass empty option file i.e. pass "-XX:VMOptionsFile=" */ 603 addVMOptionsFile(""); 604 605 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 606 outputShouldContain("Could not open options file"); 607 608 /* Pass VM option file with unmatched single quote */ 609 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_UNMATCHED_QUOTE_1)); 610 611 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 612 outputShouldContain("Unmatched quote in"); 613 614 /* Pass VM option file with unmatched double quote in X option */ 615 addVMOptionsFile(getAbsolutePathFromSource(VM_OPTION_FILE_UNMATCHED_QUOTE_2)); 616 617 runJavaCheckExitValue(JVM_FAIL_WITH_EXIT_CODE_1); 618 outputShouldContain("Unmatched quote in"); 619 } 620 621 public static void main(String[] args) throws Exception { 622 /* 623 * Preparation before actual testing - create two VM Option files 624 * which contains VM Option file in it and copy other files to the 625 * current working folder 626 */ 627 createOptionFiles(); 628 629 testVMOptions(); /* Test VM Option file general functionality */ 630 testVMOptionsLastArgumentsWins(); /* Verify that last argument wins */ 631 testVMOptionsInvalid(); /* Test invalid VM Option file functionality */ 632 633 } 634 635 public static class PrintPropertyAndOptions { 636 637 public static void main(String[] arguments) { 638 String vmOption; 639 Properties properties = System.getProperties(); 640 641 for (String propertyName : properties.stringPropertyNames()) { 642 System.out.println(String.format(PRINT_PROPERTY_FORMAT, propertyName, System.getProperty(propertyName, "NOT DEFINED"))); 643 } 644 645 for (String arg : arguments) { 646 if (arg.startsWith("vmoption=")) { 647 vmOption = arg.substring(9); 648 System.out.println(String.format(PRINT_VM_OPTION_FORMAT, vmOption, new DynamicVMOption(vmOption).getValue())); 649 } 650 } 651 } 652 } 653 }