TestHelper.java revision 4854
647N/A/*
4609N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
647N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
647N/A *
647N/A * This code is free software; you can redistribute it and/or modify it
647N/A * under the terms of the GNU General Public License version 2 only, as
647N/A * published by the Free Software Foundation.
647N/A *
647N/A * This code is distributed in the hope that it will be useful, but WITHOUT
647N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
647N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
647N/A * version 2 for more details (a copy is included in the LICENSE file that
647N/A * accompanied this code).
647N/A *
647N/A * You should have received a copy of the GNU General Public License version
647N/A * 2 along with this work; if not, write to the Free Software Foundation,
647N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
647N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
647N/A */
647N/A
647N/Aimport java.io.BufferedReader;
647N/Aimport java.io.File;
4609N/Aimport java.io.FileFilter;
647N/Aimport java.io.FileNotFoundException;
647N/Aimport java.io.FileOutputStream;
3986N/Aimport java.io.IOException;
647N/Aimport java.io.InputStreamReader;
647N/Aimport java.io.PrintStream;
4854N/Aimport java.nio.charset.Charset;
4609N/Aimport java.nio.file.attribute.BasicFileAttributes;
3986N/Aimport java.nio.file.Files;
4609N/Aimport java.nio.file.FileVisitResult;
4609N/Aimport java.nio.file.SimpleFileVisitor;
3986N/Aimport java.nio.file.Path;
647N/Aimport java.util.ArrayList;
647N/Aimport java.util.List;
4854N/Aimport java.util.Locale;
647N/Aimport java.util.Map;
647N/Aimport javax.tools.JavaCompiler;
4609N/Aimport javax.tools.ToolProvider;
647N/A
3986N/Aimport static java.nio.file.StandardCopyOption.*;
4854N/Aimport static java.nio.file.StandardOpenOption.*;
3986N/A
647N/A/**
3986N/A * This class provides some common utilities for the launcher tests.
647N/A */
4854N/Apublic class TestHelper {
4854N/A // commonly used jtreg constants
4854N/A static final File TEST_CLASSES_DIR;
4854N/A static final File TEST_SOURCES_DIR;
4854N/A
1945N/A static final String JAVAHOME = System.getProperty("java.home");
647N/A static final boolean isSDK = JAVAHOME.endsWith("jre");
647N/A static final String javaCmd;
4854N/A static final String javawCmd;
1945N/A static final String java64Cmd;
647N/A static final String javacCmd;
647N/A static final JavaCompiler compiler;
647N/A
1945N/A static final boolean debug = Boolean.getBoolean("TestHelper.Debug");
647N/A static final boolean isWindows =
647N/A System.getProperty("os.name", "unknown").startsWith("Windows");
4651N/A static final boolean isMacOSX =
4651N/A System.getProperty("os.name", "unknown").startsWith("Mac");
1945N/A static final boolean is64Bit =
1945N/A System.getProperty("sun.arch.data.model").equals("64");
1945N/A static final boolean is32Bit =
1945N/A System.getProperty("sun.arch.data.model").equals("32");
1945N/A static final boolean isSolaris =
1945N/A System.getProperty("os.name", "unknown").startsWith("SunOS");
1945N/A static final boolean isLinux =
1945N/A System.getProperty("os.name", "unknown").startsWith("Linux");
1945N/A static final boolean isDualMode = isSolaris;
1945N/A static final boolean isSparc = System.getProperty("os.arch").startsWith("sparc");
1945N/A
4854N/A // make a note of the golden default locale
4854N/A static final Locale DefaultLocale = Locale.getDefault();
4854N/A
4609N/A static final String JAVA_FILE_EXT = ".java";
4609N/A static final String CLASS_FILE_EXT = ".class";
4609N/A static final String JAR_FILE_EXT = ".jar";
4854N/A static final String JLDEBUG_KEY = "_JAVA_LAUNCHER_DEBUG";
4854N/A static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";
4609N/A
647N/A static int testExitValue = 0;
647N/A
647N/A static {
4854N/A String tmp = System.getProperty("test.classes", null);
4854N/A if (tmp == null) {
4854N/A throw new Error("property test.classes not defined ??");
4854N/A }
4854N/A TEST_CLASSES_DIR = new File(tmp).getAbsoluteFile();
4854N/A
4854N/A tmp = System.getProperty("test.src", null);
4854N/A if (tmp == null) {
4854N/A throw new Error("property test.src not defined ??");
4854N/A }
4854N/A TEST_SOURCES_DIR = new File(tmp).getAbsoluteFile();
4854N/A
1945N/A if (is64Bit && is32Bit) {
1945N/A throw new RuntimeException("arch model cannot be both 32 and 64 bit");
1945N/A }
1945N/A if (!is64Bit && !is32Bit) {
1945N/A throw new RuntimeException("arch model is not 32 or 64 bit ?");
1945N/A }
647N/A compiler = ToolProvider.getSystemJavaCompiler();
647N/A File binDir = (isSDK) ? new File((new File(JAVAHOME)).getParentFile(), "bin")
647N/A : new File(JAVAHOME, "bin");
647N/A File javaCmdFile = (isWindows)
647N/A ? new File(binDir, "java.exe")
647N/A : new File(binDir, "java");
647N/A javaCmd = javaCmdFile.getAbsolutePath();
647N/A if (!javaCmdFile.canExecute()) {
4854N/A throw new RuntimeException("java <" + TestHelper.javaCmd +
4854N/A "> must exist and should be executable");
647N/A }
647N/A
647N/A File javacCmdFile = (isWindows)
647N/A ? new File(binDir, "javac.exe")
647N/A : new File(binDir, "javac");
647N/A javacCmd = javacCmdFile.getAbsolutePath();
4854N/A
4854N/A if (isWindows) {
4854N/A File javawCmdFile = new File(binDir, "javaw.exe");
4854N/A javawCmd = javawCmdFile.getAbsolutePath();
4854N/A if (!javawCmdFile.canExecute()) {
4854N/A throw new RuntimeException("java <" + javawCmd +
4854N/A "> must exist and should be executable");
4854N/A }
4854N/A } else {
4854N/A javawCmd = null;
4854N/A }
4854N/A
647N/A if (!javacCmdFile.canExecute()) {
4854N/A throw new RuntimeException("java <" + javacCmd +
4854N/A "> must exist and should be executable");
647N/A }
1945N/A if (isSolaris) {
1945N/A File sparc64BinDir = new File(binDir,isSparc ? "sparcv9" : "amd64");
1945N/A File java64CmdFile= new File(sparc64BinDir, "java");
1945N/A if (java64CmdFile.exists() && java64CmdFile.canExecute()) {
1945N/A java64Cmd = java64CmdFile.getAbsolutePath();
1945N/A } else {
1945N/A java64Cmd = null;
1945N/A }
1945N/A } else {
1945N/A java64Cmd = null;
1945N/A }
1945N/A }
1945N/A
1945N/A /*
3986N/A * is a dual mode available in the test jdk
3986N/A */
3986N/A static boolean dualModePresent() {
3986N/A return isDualMode && java64Cmd != null;
3986N/A }
3986N/A
3986N/A /*
1945N/A * usually the jre/lib/arch-name is the same as os.arch, except for x86.
1945N/A */
1945N/A static String getJreArch() {
1945N/A String arch = System.getProperty("os.arch");
1945N/A return arch.equals("x86") ? "i386" : arch;
1945N/A }
1945N/A
1945N/A /*
3986N/A * get the complementary jre arch ie. if sparc then return sparcv9 and
3986N/A * vice-versa.
3986N/A */
3986N/A static String getComplementaryJreArch() {
3986N/A String arch = System.getProperty("os.arch");
3986N/A if (arch != null) {
3986N/A switch (arch) {
3986N/A case "sparc":
3986N/A return "sparcv9";
3986N/A case "sparcv9":
3986N/A return "sparc";
3986N/A case "x86":
3986N/A return "amd64";
3986N/A case "amd64":
3986N/A return "i386";
3986N/A }
3986N/A }
3986N/A return null;
3986N/A }
3986N/A
3986N/A /*
1945N/A * A convenience method to create a jar with jar file name and defs
1945N/A */
1945N/A static void createJar(File jarName, String... mainDefs)
1945N/A throws FileNotFoundException{
1945N/A createJar(null, jarName, new File("Foo"), mainDefs);
647N/A }
647N/A
647N/A /*
653N/A * A convenience method to create a java file, compile and jar it up, using
653N/A * the sole class file name in the jar, as the Main-Class attribute value.
647N/A */
647N/A static void createJar(File jarName, File mainClass, String... mainDefs)
647N/A throws FileNotFoundException {
647N/A createJar(null, jarName, mainClass, mainDefs);
647N/A }
647N/A
647N/A /*
4854N/A * A convenience method to compile java files.
4854N/A */
4854N/A static void compile(String... compilerArgs) {
4854N/A if (compiler.run(null, null, null, compilerArgs) != 0) {
4854N/A String sarg = "";
4854N/A for (String x : compilerArgs) {
4854N/A sarg.concat(x + " ");
4854N/A }
4854N/A throw new Error("compilation failed: " + sarg);
4854N/A }
4854N/A }
4854N/A
4854N/A /*
653N/A * A generic jar file creator to create a java file, compile it
653N/A * and jar it up, a specific Main-Class entry name in the
653N/A * manifest can be specified or a null to use the sole class file name
653N/A * as the Main-Class attribute value.
647N/A */
653N/A static void createJar(String mEntry, File jarName, File mainClass,
653N/A String... mainDefs) throws FileNotFoundException {
647N/A if (jarName.exists()) {
647N/A jarName.delete();
647N/A }
4343N/A try (PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"))) {
4343N/A ps.println("public class Foo {");
4343N/A if (mainDefs != null) {
4343N/A for (String x : mainDefs) {
4343N/A ps.println(x);
4343N/A }
647N/A }
4343N/A ps.println("}");
647N/A }
647N/A
647N/A String compileArgs[] = {
647N/A mainClass + ".java"
647N/A };
647N/A if (compiler.run(null, null, null, compileArgs) != 0) {
647N/A throw new RuntimeException("compilation failed " + mainClass + ".java");
647N/A }
653N/A if (mEntry == null) {
647N/A mEntry = mainClass.getName();
647N/A }
647N/A String jarArgs[] = {
647N/A (debug) ? "cvfe" : "cfe",
647N/A jarName.getAbsolutePath(),
647N/A mEntry,
647N/A mainClass.getName() + ".class"
647N/A };
4343N/A createJar(jarArgs);
4343N/A }
4343N/A
4343N/A static void createJar(String... args) {
647N/A sun.tools.jar.Main jarTool =
647N/A new sun.tools.jar.Main(System.out, System.err, "JarCreator");
4343N/A if (!jarTool.run(args)) {
4343N/A String message = "jar creation failed with command:";
4343N/A for (String x : args) {
4343N/A message = message.concat(" " + x);
4343N/A }
4343N/A throw new RuntimeException(message);
647N/A }
4343N/A }
647N/A
3986N/A static void copyFile(File src, File dst) throws IOException {
3986N/A Path parent = dst.toPath().getParent();
3986N/A if (parent != null) {
3986N/A Files.createDirectories(parent);
3986N/A }
3986N/A Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING);
3986N/A }
3986N/A
4854N/A static void createFile(File outFile, List<String> content) throws IOException {
4854N/A Files.write(outFile.getAbsoluteFile().toPath(), content,
4854N/A Charset.defaultCharset(), CREATE_NEW);
4854N/A }
4854N/A
3986N/A static void recursiveDelete(File target) throws IOException {
3986N/A if (!target.exists()) {
3986N/A return;
3986N/A }
3986N/A Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {
3986N/A @Override
3986N/A public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
3986N/A try {
3986N/A Files.deleteIfExists(dir);
3986N/A } catch (IOException ex) {
3986N/A System.out.println("Error: could not delete: " + dir.toString());
3986N/A System.out.println(ex.getMessage());
3986N/A return FileVisitResult.TERMINATE;
3986N/A }
3986N/A return FileVisitResult.CONTINUE;
3986N/A }
3986N/A @Override
3986N/A public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
3986N/A try {
3986N/A Files.deleteIfExists(file);
3986N/A } catch (IOException ex) {
3986N/A System.out.println("Error: could not delete: " + file.toString());
3986N/A System.out.println(ex.getMessage());
3986N/A return FileVisitResult.TERMINATE;
3986N/A }
3986N/A return FileVisitResult.CONTINUE;
3986N/A }
3986N/A });
3986N/A }
3986N/A
1945N/A static TestResult doExec(String...cmds) {
1945N/A return doExec(null, cmds);
1945N/A }
1945N/A
647N/A /*
653N/A * A method which executes a java cmd and returns the results in a container
647N/A */
1945N/A static TestResult doExec(Map<String, String> envToSet, String...cmds) {
647N/A String cmdStr = "";
647N/A for (String x : cmds) {
647N/A cmdStr = cmdStr.concat(x + " ");
647N/A }
647N/A ProcessBuilder pb = new ProcessBuilder(cmds);
647N/A Map<String, String> env = pb.environment();
1945N/A if (envToSet != null) {
1945N/A env.putAll(envToSet);
1945N/A }
647N/A BufferedReader rdr = null;
647N/A try {
3986N/A List<String> outputList = new ArrayList<>();
647N/A pb.redirectErrorStream(true);
647N/A Process p = pb.start();
647N/A rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
647N/A String in = rdr.readLine();
647N/A while (in != null) {
647N/A outputList.add(in);
647N/A in = rdr.readLine();
647N/A }
647N/A p.waitFor();
647N/A p.destroy();
3986N/A
3986N/A return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList,
3986N/A env, new Throwable("current stack of the test"));
647N/A } catch (Exception ex) {
647N/A ex.printStackTrace();
647N/A throw new RuntimeException(ex.getMessage());
647N/A }
647N/A }
647N/A
4609N/A static FileFilter createFilter(final String extension) {
4609N/A return new FileFilter() {
4609N/A @Override
4609N/A public boolean accept(File pathname) {
4609N/A String name = pathname.getName();
4609N/A if (name.endsWith(extension)) {
4609N/A return true;
4609N/A }
4609N/A return false;
4609N/A }
4609N/A };
4609N/A }
4609N/A
4854N/A static boolean isEnglishLocale() {
4854N/A return Locale.getDefault().getLanguage().equals("en");
4854N/A }
4854N/A
647N/A /*
647N/A * A class to encapsulate the test results and stuff, with some ease
647N/A * of use methods to check the test results.
647N/A */
647N/A static class TestResult {
647N/A StringBuilder status;
647N/A int exitValue;
647N/A List<String> testOutput;
3986N/A Map<String, String> env;
3986N/A Throwable t;
647N/A
3986N/A public TestResult(String str, int rv, List<String> oList,
3986N/A Map<String, String> env, Throwable t) {
1945N/A status = new StringBuilder("Executed command: " + str + "\n");
647N/A exitValue = rv;
647N/A testOutput = oList;
3986N/A this.env = env;
3986N/A this.t = t;
647N/A }
647N/A
1945N/A void appendStatus(String x) {
1945N/A status = status.append(" " + x + "\n");
1945N/A }
1945N/A
647N/A void checkNegative() {
647N/A if (exitValue == 0) {
1945N/A appendStatus("Error: test must not return 0 exit value");
647N/A testExitValue++;
647N/A }
647N/A }
647N/A
647N/A void checkPositive() {
647N/A if (exitValue != 0) {
1945N/A appendStatus("Error: test did not return 0 exit value");
647N/A testExitValue++;
647N/A }
647N/A }
647N/A
647N/A boolean isOK() {
647N/A return exitValue == 0;
647N/A }
647N/A
647N/A boolean isZeroOutput() {
647N/A if (!testOutput.isEmpty()) {
1945N/A appendStatus("Error: No message from cmd please");
647N/A testExitValue++;
647N/A return false;
647N/A }
647N/A return true;
647N/A }
647N/A
647N/A boolean isNotZeroOutput() {
647N/A if (testOutput.isEmpty()) {
1945N/A appendStatus("Error: Missing message");
647N/A testExitValue++;
647N/A return false;
647N/A }
647N/A return true;
647N/A }
647N/A
1945N/A @Override
647N/A public String toString() {
3986N/A status.append("++++Begin Test Info++++\n");
3986N/A status.append("++++Test Environment++++\n");
3986N/A for (String x : env.keySet()) {
3986N/A status.append(x).append("=").append(env.get(x)).append("\n");
3986N/A }
3986N/A status.append("++++Test Output++++\n");
1945N/A for (String x : testOutput) {
1945N/A appendStatus(x);
647N/A }
3986N/A status.append("++++Test Stack Trace++++\n");
3986N/A status.append(t.toString());
3986N/A for (StackTraceElement e : t.getStackTrace()) {
3986N/A status.append(e.toString());
3986N/A }
3986N/A status.append("++++End of Test Info++++\n");
647N/A return status.toString();
647N/A }
647N/A
647N/A boolean contains(String str) {
647N/A for (String x : testOutput) {
647N/A if (x.contains(str)) {
647N/A return true;
647N/A }
647N/A }
1945N/A appendStatus("Error: string <" + str + "> not found");
1945N/A testExitValue++;
1945N/A return false;
1945N/A }
1945N/A
1945N/A boolean matches(String stringToMatch) {
1945N/A for (String x : testOutput) {
1945N/A if (x.matches(stringToMatch)) {
1945N/A return true;
1945N/A }
1945N/A }
1945N/A appendStatus("Error: string <" + stringToMatch + "> not found");
647N/A testExitValue++;
647N/A return false;
647N/A }
647N/A }
647N/A}