1 /* 2 * Copyright (c) 2016, 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 8170832 27 * @summary Arguments passed in environment variable 28 * @build TestHelper 29 * @run main ArgsEnvVar 30 */ 31 import java.io.File; 32 import java.io.IOException; 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.regex.Pattern; 38 39 public class ArgsEnvVar extends TestHelper { 40 private static File testJar = null; 41 private static Map<String, String> env = new HashMap<>(); 42 43 private static String JDK_JAVA_OPTIONS = "JDK_JAVA_OPTIONS"; 44 45 static void init() throws IOException { 46 if (testJar != null) { 47 return; 48 } 49 testJar = new File("test.jar"); 50 StringBuilder tsrc = new StringBuilder(); 51 tsrc.append("public static void main(String... args) {\n"); 52 tsrc.append(" for (String x : args) {\n"); 53 tsrc.append(" System.out.println(x);\n"); 54 tsrc.append(" }\n"); 55 tsrc.append("}\n"); 56 createJar(testJar, new File("Foo"), tsrc.toString()); 57 58 env.put(JLDEBUG_KEY, "true"); 59 } 60 61 private File createArgFile(String fname, List<String> lines) throws IOException { 62 File argFile = new File(fname); 63 argFile.delete(); 64 createAFile(argFile, lines); 65 return argFile; 66 } 67 68 private void verifyOptions(List<String> args, TestResult tr) { 69 if (args.isEmpty()) { 70 return; 71 } 72 73 int i = 1; 74 for (String x : args) { 75 tr.matches(".*argv\\[" + i + "\\] = " + Pattern.quote(x) + ".*"); 76 i++; 77 } 78 if (! tr.testStatus) { 79 System.out.println(tr); 80 throw new RuntimeException("test fails"); 81 } 82 } 83 84 private void verifyUserArgs(List<String> args, TestResult tr, int index) { 85 if (javaCmd != TestHelper.javaCmd) { 86 tr.contains("\tFirst application arg index: 1"); 87 } else { 88 tr.contains("\tFirst application arg index: " + index); 89 90 for (String arg: args) { 91 tr.matches("^" + Pattern.quote(arg) + "$"); 92 } 93 } 94 95 if (! tr.testStatus) { 96 System.out.println(tr); 97 throw new RuntimeException("test fails"); 98 } 99 } 100 101 @Test 102 // Verify prepend and @argfile expansion 103 public void basic() throws IOException { 104 File argFile1 = createArgFile("argFile1", List.of("-Xmx32m")); 105 File argFile2 = createArgFile("argFile2", List.of("-Darg.file2=TWO")); 106 File argFile3 = createArgFile("argFile3", List.of("-Darg.file3=THREE")); 107 108 env.put(JDK_JAVA_OPTIONS, "@argFile1\n-Xint\r-cp @@escaped\t@argFile2"); 109 110 TestResult tr = doExec(env, javaCmd, "@argFile3", "-cp", "test.jar", "Foo", "uarg1", "@uarg2"); 111 112 List<String> appArgs = new ArrayList<>(); 113 appArgs.add("uarg1"); 114 appArgs.add("@uarg2"); 115 116 List<String> options = new ArrayList<>(); 117 options.add("-Xmx32m"); 118 options.add("-Xint"); 119 options.add("-cp"); 120 options.add("@escaped"); 121 options.add("-Darg.file2=TWO"); 122 options.add("-Darg.file3=THREE"); 123 options.add("-cp"); 124 options.add("test.jar"); 125 options.add("Foo"); 126 options.addAll(appArgs); 127 128 verifyOptions(options, tr); 129 verifyUserArgs(appArgs, tr, 10); 130 argFile1.delete(); 131 argFile2.delete(); 132 argFile3.delete(); 133 } 134 135 private TestResult testInEnv(List<String> options) { 136 env.put(JDK_JAVA_OPTIONS, String.join(" ", options)); 137 return doExec(env, javaCmd, "-jar", "test.jar"); 138 } 139 140 private TestResult testInEnvAsArgFile(List<String> options) throws IOException { 141 File argFile = createArgFile("argFile", options); 142 env.put(JDK_JAVA_OPTIONS, "@argFile"); 143 TestResult tr = doExec(env, javaCmd, "-jar", "test.jar"); 144 argFile.delete(); 145 return tr; 146 } 147 148 @Test 149 public void noTerminalOpt() throws IOException { 150 List<List<String>> terminal_opts = List.of( 151 List.of("-jar", "test.jar"), 152 List.of("-m", "test/Foo"), 153 List.of("--module", "test/Foo"), 154 List.of("--dry-run"), 155 List.of("-h"), 156 List.of("-?"), 157 List.of("-help"), 158 List.of("--help"), 159 List.of("-X"), 160 List.of("--help-extra"), 161 List.of("-version"), 162 List.of("--version"), 163 List.of("-fullversion"), 164 List.of("--full-version")); 165 166 for (List<String> options: terminal_opts) { 167 // terminal opt in environment variable 168 TestResult tr = testInEnv(options); 169 tr.checkNegative(); 170 if (!tr.testStatus) { 171 System.out.println(tr); 172 throw new RuntimeException("test fails"); 173 } 174 175 // terminal opt in environment variable through @file 176 tr = testInEnvAsArgFile(options); 177 tr.checkNegative(); 178 if (!tr.testStatus) { 179 System.out.println(tr); 180 throw new RuntimeException("test fails"); 181 } 182 } 183 } 184 185 @Test 186 public void quote() throws IOException { 187 File argFile1 = createArgFile("arg File 1", List.of("-Xint")); 188 File argFile2 = createArgFile("arg File 2", List.of("-Dprop='value with spaces'")); 189 File argFile3 = createArgFile("arg File 3", List.of("-Xmx32m")); 190 env.put(JDK_JAVA_OPTIONS, "'@arg File 1' @\"arg File 2\" @'arg File'\" 3\""); 191 192 TestResult tr = doExec(env, javaCmd, "-jar", "test.jar"); 193 List<String> options = new ArrayList<>(); 194 options.add("-Xint"); 195 options.add("-Dprop=value with spaces"); 196 options.add("-Xmx32m"); 197 options.add("-jar"); 198 options.add("test.jar"); 199 verifyOptions(options, tr); 200 argFile1.delete(); 201 argFile2.delete(); 202 argFile3.delete(); 203 } 204 205 @Test 206 public void openQuoteShouldFail() { 207 env.put(JDK_JAVA_OPTIONS, "-Dprop='value missing close quote"); 208 TestResult tr = doExec(env, javaCmd, "-version"); 209 tr.checkNegative(); 210 if (!tr.testStatus) { 211 System.out.println(tr); 212 throw new RuntimeException("test fails"); 213 } 214 } 215 216 @Test 217 public void noWildcard() { 218 env.put(JDK_JAVA_OPTIONS, "-cp *"); 219 TestResult tr = doExec(env, javaCmd, "-jar", "test.jar"); 220 verifyOptions(List.of("-cp", "*", "-jar", "test.jar"), tr); 221 222 env.put(JDK_JAVA_OPTIONS, "-p ?"); 223 tr = doExec(env, javaCmd, "-jar", "test.jar", "one", "two"); 224 verifyOptions(List.of("-p", "?", "-jar", "test.jar", "one", "two"), tr); 225 } 226 227 public static void main(String... args) throws Exception { 228 init(); 229 ArgsEnvVar a = new ArgsEnvVar(); 230 a.run(args); 231 if (testExitValue > 0) { 232 System.out.println("Total of " + testExitValue + " failed"); 233 System.exit(1); 234 } else { 235 System.out.println("All tests pass"); 236 } 237 } 238 } 239