blob: 6465811cebfed850bda3d0886cc1dbd50507ce12 [file] [log] [blame]
ksrini20a64b22008-09-24 15:07:41 -07001/*
katleman7d8178b2011-05-25 13:32:36 -07002 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
ksrini20a64b22008-09-24 15:07:41 -07003 * 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 *
ohair2283b9d2010-05-25 15:58:33 -070019 * 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.
ksrini20a64b22008-09-24 15:07:41 -070022 */
23
ksrinif8cc5972011-04-07 12:06:32 -070024import java.nio.file.attribute.BasicFileAttributes;
25import java.nio.file.FileVisitResult;
26import java.nio.file.SimpleFileVisitor;
ksrini20a64b22008-09-24 15:07:41 -070027import javax.tools.ToolProvider;
28import java.io.BufferedReader;
29import java.io.File;
30import java.io.FileNotFoundException;
31import java.io.FileOutputStream;
ksrinif8cc5972011-04-07 12:06:32 -070032import java.io.IOException;
ksrini20a64b22008-09-24 15:07:41 -070033import java.io.InputStreamReader;
34import java.io.PrintStream;
ksrinif8cc5972011-04-07 12:06:32 -070035import java.nio.file.Files;
36import java.nio.file.Path;
ksrini20a64b22008-09-24 15:07:41 -070037import java.util.ArrayList;
38import java.util.List;
39import java.util.Map;
40import javax.tools.JavaCompiler;
41
ksrinif8cc5972011-04-07 12:06:32 -070042import static java.nio.file.StandardCopyOption.*;
43
ksrini20a64b22008-09-24 15:07:41 -070044/**
ksrinif8cc5972011-04-07 12:06:32 -070045 * This class provides some common utilities for the launcher tests.
ksrini20a64b22008-09-24 15:07:41 -070046 */
47public enum TestHelper {
48 INSTANCE;
ksrini11e7f1b2009-11-20 11:01:32 -080049 static final String JAVAHOME = System.getProperty("java.home");
ksrini20a64b22008-09-24 15:07:41 -070050 static final boolean isSDK = JAVAHOME.endsWith("jre");
51 static final String javaCmd;
ksrinidd194042012-01-03 08:33:30 -080052 static final String javawCmd;
ksrini11e7f1b2009-11-20 11:01:32 -080053 static final String java64Cmd;
ksrini20a64b22008-09-24 15:07:41 -070054 static final String javacCmd;
55 static final JavaCompiler compiler;
56
ksrini11e7f1b2009-11-20 11:01:32 -080057 static final boolean debug = Boolean.getBoolean("TestHelper.Debug");
ksrini20a64b22008-09-24 15:07:41 -070058 static final boolean isWindows =
59 System.getProperty("os.name", "unknown").startsWith("Windows");
ksrini11e7f1b2009-11-20 11:01:32 -080060 static final boolean is64Bit =
61 System.getProperty("sun.arch.data.model").equals("64");
62 static final boolean is32Bit =
63 System.getProperty("sun.arch.data.model").equals("32");
64 static final boolean isSolaris =
65 System.getProperty("os.name", "unknown").startsWith("SunOS");
66 static final boolean isLinux =
67 System.getProperty("os.name", "unknown").startsWith("Linux");
68 static final boolean isDualMode = isSolaris;
69 static final boolean isSparc = System.getProperty("os.arch").startsWith("sparc");
70
ksrini20a64b22008-09-24 15:07:41 -070071 static int testExitValue = 0;
72
73 static {
ksrini11e7f1b2009-11-20 11:01:32 -080074 if (is64Bit && is32Bit) {
75 throw new RuntimeException("arch model cannot be both 32 and 64 bit");
76 }
77 if (!is64Bit && !is32Bit) {
78 throw new RuntimeException("arch model is not 32 or 64 bit ?");
79 }
ksrini20a64b22008-09-24 15:07:41 -070080 compiler = ToolProvider.getSystemJavaCompiler();
81 File binDir = (isSDK) ? new File((new File(JAVAHOME)).getParentFile(), "bin")
82 : new File(JAVAHOME, "bin");
83 File javaCmdFile = (isWindows)
84 ? new File(binDir, "java.exe")
85 : new File(binDir, "java");
86 javaCmd = javaCmdFile.getAbsolutePath();
87 if (!javaCmdFile.canExecute()) {
ksrinidd194042012-01-03 08:33:30 -080088 throw new RuntimeException("java <" + TestHelper.javaCmd +
89 "> must exist and should be executable");
ksrini20a64b22008-09-24 15:07:41 -070090 }
91
92 File javacCmdFile = (isWindows)
93 ? new File(binDir, "javac.exe")
94 : new File(binDir, "javac");
95 javacCmd = javacCmdFile.getAbsolutePath();
ksrinidd194042012-01-03 08:33:30 -080096
97 if (isWindows) {
98 File javawCmdFile = new File(binDir, "javaw.exe");
99 javawCmd = javawCmdFile.getAbsolutePath();
100 if (!javawCmdFile.canExecute()) {
101 throw new RuntimeException("java <" + javawCmd +
102 "> must exist and should be executable");
103 }
104 } else {
105 javawCmd = null;
106 }
107
ksrini20a64b22008-09-24 15:07:41 -0700108 if (!javacCmdFile.canExecute()) {
ksrinidd194042012-01-03 08:33:30 -0800109 throw new RuntimeException("java <" + javacCmd +
110 "> must exist and should be executable");
ksrini20a64b22008-09-24 15:07:41 -0700111 }
ksrini11e7f1b2009-11-20 11:01:32 -0800112 if (isSolaris) {
113 File sparc64BinDir = new File(binDir,isSparc ? "sparcv9" : "amd64");
114 File java64CmdFile= new File(sparc64BinDir, "java");
115 if (java64CmdFile.exists() && java64CmdFile.canExecute()) {
116 java64Cmd = java64CmdFile.getAbsolutePath();
117 } else {
118 java64Cmd = null;
119 }
120 } else {
121 java64Cmd = null;
122 }
123 }
124
125 /*
ksrinif8cc5972011-04-07 12:06:32 -0700126 * is a dual mode available in the test jdk
127 */
128 static boolean dualModePresent() {
129 return isDualMode && java64Cmd != null;
130 }
131
132 /*
ksrini11e7f1b2009-11-20 11:01:32 -0800133 * usually the jre/lib/arch-name is the same as os.arch, except for x86.
134 */
135 static String getJreArch() {
136 String arch = System.getProperty("os.arch");
137 return arch.equals("x86") ? "i386" : arch;
138 }
139
140 /*
ksrinif8cc5972011-04-07 12:06:32 -0700141 * get the complementary jre arch ie. if sparc then return sparcv9 and
142 * vice-versa.
143 */
144 static String getComplementaryJreArch() {
145 String arch = System.getProperty("os.arch");
146 if (arch != null) {
147 switch (arch) {
148 case "sparc":
149 return "sparcv9";
150 case "sparcv9":
151 return "sparc";
152 case "x86":
153 return "amd64";
154 case "amd64":
155 return "i386";
156 }
157 }
158 return null;
159 }
160
161 /*
ksrini11e7f1b2009-11-20 11:01:32 -0800162 * A convenience method to create a jar with jar file name and defs
163 */
164 static void createJar(File jarName, String... mainDefs)
165 throws FileNotFoundException{
166 createJar(null, jarName, new File("Foo"), mainDefs);
ksrini20a64b22008-09-24 15:07:41 -0700167 }
168
169 /*
ksrinicafaf7c2008-10-01 09:04:42 -0700170 * A convenience method to create a java file, compile and jar it up, using
171 * the sole class file name in the jar, as the Main-Class attribute value.
ksrini20a64b22008-09-24 15:07:41 -0700172 */
173 static void createJar(File jarName, File mainClass, String... mainDefs)
174 throws FileNotFoundException {
175 createJar(null, jarName, mainClass, mainDefs);
176 }
177
178 /*
ksrinicafaf7c2008-10-01 09:04:42 -0700179 * A generic jar file creator to create a java file, compile it
180 * and jar it up, a specific Main-Class entry name in the
181 * manifest can be specified or a null to use the sole class file name
182 * as the Main-Class attribute value.
ksrini20a64b22008-09-24 15:07:41 -0700183 */
ksrinicafaf7c2008-10-01 09:04:42 -0700184 static void createJar(String mEntry, File jarName, File mainClass,
185 String... mainDefs) throws FileNotFoundException {
ksrini20a64b22008-09-24 15:07:41 -0700186 if (jarName.exists()) {
187 jarName.delete();
188 }
ksrini37e8b502011-07-19 10:58:50 -0700189 try (PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"))) {
190 ps.println("public class Foo {");
191 if (mainDefs != null) {
192 for (String x : mainDefs) {
193 ps.println(x);
194 }
ksrini20a64b22008-09-24 15:07:41 -0700195 }
ksrini37e8b502011-07-19 10:58:50 -0700196 ps.println("}");
ksrini20a64b22008-09-24 15:07:41 -0700197 }
ksrini20a64b22008-09-24 15:07:41 -0700198
199 String compileArgs[] = {
200 mainClass + ".java"
201 };
202 if (compiler.run(null, null, null, compileArgs) != 0) {
203 throw new RuntimeException("compilation failed " + mainClass + ".java");
204 }
ksrinicafaf7c2008-10-01 09:04:42 -0700205 if (mEntry == null) {
ksrini20a64b22008-09-24 15:07:41 -0700206 mEntry = mainClass.getName();
207 }
208 String jarArgs[] = {
209 (debug) ? "cvfe" : "cfe",
210 jarName.getAbsolutePath(),
211 mEntry,
212 mainClass.getName() + ".class"
213 };
ksrini37e8b502011-07-19 10:58:50 -0700214 createJar(jarArgs);
215 }
216
217 static void createJar(String... args) {
ksrini20a64b22008-09-24 15:07:41 -0700218 sun.tools.jar.Main jarTool =
219 new sun.tools.jar.Main(System.out, System.err, "JarCreator");
ksrini37e8b502011-07-19 10:58:50 -0700220 if (!jarTool.run(args)) {
221 String message = "jar creation failed with command:";
222 for (String x : args) {
223 message = message.concat(" " + x);
224 }
225 throw new RuntimeException(message);
ksrini20a64b22008-09-24 15:07:41 -0700226 }
ksrini37e8b502011-07-19 10:58:50 -0700227 }
ksrini20a64b22008-09-24 15:07:41 -0700228
ksrinif8cc5972011-04-07 12:06:32 -0700229 static void copyFile(File src, File dst) throws IOException {
230 Path parent = dst.toPath().getParent();
231 if (parent != null) {
232 Files.createDirectories(parent);
233 }
234 Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING);
235 }
236
237 static void recursiveDelete(File target) throws IOException {
238 if (!target.exists()) {
239 return;
240 }
241 Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {
242 @Override
243 public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
244 try {
245 Files.deleteIfExists(dir);
246 } catch (IOException ex) {
247 System.out.println("Error: could not delete: " + dir.toString());
248 System.out.println(ex.getMessage());
249 return FileVisitResult.TERMINATE;
250 }
251 return FileVisitResult.CONTINUE;
252 }
253 @Override
254 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
255 try {
256 Files.deleteIfExists(file);
257 } catch (IOException ex) {
258 System.out.println("Error: could not delete: " + file.toString());
259 System.out.println(ex.getMessage());
260 return FileVisitResult.TERMINATE;
261 }
262 return FileVisitResult.CONTINUE;
263 }
264 });
265 }
266
ksrini11e7f1b2009-11-20 11:01:32 -0800267 static TestResult doExec(String...cmds) {
268 return doExec(null, cmds);
269 }
270
ksrini20a64b22008-09-24 15:07:41 -0700271 /*
ksrinicafaf7c2008-10-01 09:04:42 -0700272 * A method which executes a java cmd and returns the results in a container
ksrini20a64b22008-09-24 15:07:41 -0700273 */
ksrini11e7f1b2009-11-20 11:01:32 -0800274 static TestResult doExec(Map<String, String> envToSet, String...cmds) {
ksrini20a64b22008-09-24 15:07:41 -0700275 String cmdStr = "";
276 for (String x : cmds) {
277 cmdStr = cmdStr.concat(x + " ");
278 }
279 ProcessBuilder pb = new ProcessBuilder(cmds);
280 Map<String, String> env = pb.environment();
ksrini11e7f1b2009-11-20 11:01:32 -0800281 if (envToSet != null) {
282 env.putAll(envToSet);
283 }
ksrini20a64b22008-09-24 15:07:41 -0700284 BufferedReader rdr = null;
285 try {
ksrinif8cc5972011-04-07 12:06:32 -0700286 List<String> outputList = new ArrayList<>();
ksrini20a64b22008-09-24 15:07:41 -0700287 pb.redirectErrorStream(true);
288 Process p = pb.start();
289 rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
290 String in = rdr.readLine();
291 while (in != null) {
292 outputList.add(in);
293 in = rdr.readLine();
294 }
295 p.waitFor();
296 p.destroy();
ksrinif8cc5972011-04-07 12:06:32 -0700297
298 return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList,
299 env, new Throwable("current stack of the test"));
ksrini20a64b22008-09-24 15:07:41 -0700300 } catch (Exception ex) {
301 ex.printStackTrace();
302 throw new RuntimeException(ex.getMessage());
303 }
304 }
305
306 /*
307 * A class to encapsulate the test results and stuff, with some ease
308 * of use methods to check the test results.
309 */
310 static class TestResult {
311 StringBuilder status;
312 int exitValue;
313 List<String> testOutput;
ksrinif8cc5972011-04-07 12:06:32 -0700314 Map<String, String> env;
315 Throwable t;
ksrini20a64b22008-09-24 15:07:41 -0700316
ksrinif8cc5972011-04-07 12:06:32 -0700317 public TestResult(String str, int rv, List<String> oList,
318 Map<String, String> env, Throwable t) {
ksrini11e7f1b2009-11-20 11:01:32 -0800319 status = new StringBuilder("Executed command: " + str + "\n");
ksrini20a64b22008-09-24 15:07:41 -0700320 exitValue = rv;
321 testOutput = oList;
ksrinif8cc5972011-04-07 12:06:32 -0700322 this.env = env;
323 this.t = t;
ksrini20a64b22008-09-24 15:07:41 -0700324 }
325
ksrini11e7f1b2009-11-20 11:01:32 -0800326 void appendStatus(String x) {
327 status = status.append(" " + x + "\n");
328 }
329
ksrini20a64b22008-09-24 15:07:41 -0700330 void checkNegative() {
331 if (exitValue == 0) {
ksrini11e7f1b2009-11-20 11:01:32 -0800332 appendStatus("Error: test must not return 0 exit value");
ksrini20a64b22008-09-24 15:07:41 -0700333 testExitValue++;
334 }
335 }
336
337 void checkPositive() {
338 if (exitValue != 0) {
ksrini11e7f1b2009-11-20 11:01:32 -0800339 appendStatus("Error: test did not return 0 exit value");
ksrini20a64b22008-09-24 15:07:41 -0700340 testExitValue++;
341 }
342 }
343
344 boolean isOK() {
345 return exitValue == 0;
346 }
347
348 boolean isZeroOutput() {
349 if (!testOutput.isEmpty()) {
ksrini11e7f1b2009-11-20 11:01:32 -0800350 appendStatus("Error: No message from cmd please");
ksrini20a64b22008-09-24 15:07:41 -0700351 testExitValue++;
352 return false;
353 }
354 return true;
355 }
356
357 boolean isNotZeroOutput() {
358 if (testOutput.isEmpty()) {
ksrini11e7f1b2009-11-20 11:01:32 -0800359 appendStatus("Error: Missing message");
ksrini20a64b22008-09-24 15:07:41 -0700360 testExitValue++;
361 return false;
362 }
363 return true;
364 }
365
ksrini11e7f1b2009-11-20 11:01:32 -0800366 @Override
ksrini20a64b22008-09-24 15:07:41 -0700367 public String toString() {
ksrinif8cc5972011-04-07 12:06:32 -0700368 status.append("++++Begin Test Info++++\n");
369 status.append("++++Test Environment++++\n");
370 for (String x : env.keySet()) {
371 status.append(x).append("=").append(env.get(x)).append("\n");
372 }
373 status.append("++++Test Output++++\n");
ksrini11e7f1b2009-11-20 11:01:32 -0800374 for (String x : testOutput) {
375 appendStatus(x);
ksrini20a64b22008-09-24 15:07:41 -0700376 }
ksrinif8cc5972011-04-07 12:06:32 -0700377 status.append("++++Test Stack Trace++++\n");
378 status.append(t.toString());
379 for (StackTraceElement e : t.getStackTrace()) {
380 status.append(e.toString());
381 }
382 status.append("++++End of Test Info++++\n");
ksrini20a64b22008-09-24 15:07:41 -0700383 return status.toString();
384 }
385
386 boolean contains(String str) {
387 for (String x : testOutput) {
388 if (x.contains(str)) {
389 return true;
390 }
391 }
ksrini11e7f1b2009-11-20 11:01:32 -0800392 appendStatus("Error: string <" + str + "> not found");
393 testExitValue++;
394 return false;
395 }
396
397 boolean matches(String stringToMatch) {
398 for (String x : testOutput) {
399 if (x.matches(stringToMatch)) {
400 return true;
401 }
402 }
403 appendStatus("Error: string <" + stringToMatch + "> not found");
ksrini20a64b22008-09-24 15:07:41 -0700404 testExitValue++;
405 return false;
406 }
407 }
408}