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
5270N/Aimport java.lang.annotation.ElementType;
5270N/Aimport java.lang.annotation.Retention;
5270N/Aimport java.lang.annotation.RetentionPolicy;
5270N/Aimport java.lang.annotation.Target;
5270N/Aimport java.lang.reflect.Method;
5270N/Aimport java.util.regex.Pattern;
5270N/Aimport java.io.StringWriter;
5270N/Aimport java.io.PrintWriter;
4954N/Aimport java.util.Set;
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");
5270N/A static final String JAVA_BIN;
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;
5270N/A static final String jarCmd;
5270N/A
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 =
4944N/A System.getProperty("os.name", "unknown").contains("OS X");
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";
5270N/A static final String EXE_FILE_EXT = ".exe";
4854N/A static final String JLDEBUG_KEY = "_JAVA_LAUNCHER_DEBUG";
4854N/A static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";
5270N/A static final String TEST_PREFIX = "###TestError###: ";
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");
5270N/A JAVA_BIN = binDir.getAbsolutePath();
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
5270N/A File jarCmdFile = (isWindows)
5270N/A ? new File(binDir, "jar.exe")
5270N/A : new File(binDir, "jar");
5270N/A jarCmd = jarCmdFile.getAbsolutePath();
5270N/A if (!jarCmdFile.canExecute()) {
5270N/A throw new RuntimeException("java <" + TestHelper.jarCmd +
5270N/A "> must exist and should be executable");
5270N/A }
5270N/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 }
5270N/A void run(String[] args) throws Exception {
5270N/A int passed = 0, failed = 0;
5270N/A final Pattern p = (args != null && args.length > 0)
5270N/A ? Pattern.compile(args[0])
5270N/A : null;
5270N/A for (Method m : this.getClass().getDeclaredMethods()) {
5270N/A boolean selected = (p == null)
5270N/A ? m.isAnnotationPresent(Test.class)
5270N/A : p.matcher(m.getName()).matches();
5270N/A if (selected) {
5270N/A try {
5270N/A m.invoke(this, (Object[]) null);
5270N/A System.out.println(m.getName() + ": OK");
5270N/A passed++;
5272N/A System.out.printf("Passed: %d, Failed: %d, ExitValue: %d%n",
5272N/A passed, failed, testExitValue);
5270N/A } catch (Throwable ex) {
5270N/A System.out.printf("Test %s failed: %s %n", m, ex.getCause());
5270N/A failed++;
5270N/A }
5270N/A }
5270N/A }
5272N/A System.out.printf("Total: Passed: %d, Failed %d%n", passed, failed);
5270N/A if (failed > 0) {
5270N/A throw new RuntimeException("Tests failed: " + failed);
5270N/A }
5270N/A if (passed == 0 && failed == 0) {
5270N/A throw new AssertionError("No test(s) selected: passed = " +
5270N/A passed + ", failed = " + failed + " ??????????");
5270N/A }
5270N/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
5828N/A /**
5828N/A * Attempt to create a file at the given location. If an IOException
5828N/A * occurs then back off for a moment and try again. When a number of
5828N/A * attempts fail, give up and throw an exception.
5828N/A */
5828N/A void createAFile(File aFile, List<String> contents) throws IOException {
5828N/A IOException cause = null;
5828N/A for (int attempts = 0; attempts < 10; attempts++) {
5828N/A try {
5828N/A Files.write(aFile.getAbsoluteFile().toPath(), contents,
5828N/A Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING, WRITE);
5828N/A if (cause != null) {
5828N/A /*
5828N/A * report attempts and errors that were encountered
5828N/A * for diagnostic purposes
5828N/A */
5828N/A System.err.println("Created batch file " +
5828N/A aFile + " in " + (attempts + 1) +
5828N/A " attempts");
5828N/A System.err.println("Errors encountered: " + cause);
5828N/A cause.printStackTrace();
5828N/A }
5828N/A return;
5828N/A } catch (IOException ioe) {
5828N/A if (cause != null) {
5828N/A // chain the exceptions so they all get reported for diagnostics
5828N/A cause.addSuppressed(ioe);
5828N/A } else {
5828N/A cause = ioe;
5828N/A }
5828N/A }
5828N/A
5828N/A try {
5828N/A Thread.sleep(500);
5828N/A } catch (InterruptedException ie) {
5828N/A if (cause != null) {
5828N/A // cause should alway be non-null here
5828N/A ie.addSuppressed(cause);
5828N/A }
5828N/A throw new RuntimeException("Interrupted while creating batch file", ie);
5828N/A }
5828N/A }
5828N/A throw new RuntimeException("Unable to create batch file", cause);
5828N/A }
5828N/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) {
4954N/A return doExec(null, null, cmds);
1945N/A }
1945N/A
4954N/A static TestResult doExec(Map<String, String> envToSet, String...cmds) {
4954N/A return doExec(envToSet, null, cmds);
4954N/A }
647N/A /*
653N/A * A method which executes a java cmd and returns the results in a container
647N/A */
4954N/A static TestResult doExec(Map<String, String> envToSet,
4954N/A Set<String> envToRemove, 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();
4954N/A if (envToRemove != null) {
4954N/A for (String key : envToRemove) {
4954N/A env.remove(key);
4954N/A }
4954N/A }
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 {
5270N/A PrintWriter status;
5270N/A StringWriter sw;
647N/A int exitValue;
647N/A List<String> testOutput;
3986N/A Map<String, String> env;
3986N/A Throwable t;
5270N/A boolean testStatus;
647N/A
3986N/A public TestResult(String str, int rv, List<String> oList,
3986N/A Map<String, String> env, Throwable t) {
5270N/A sw = new StringWriter();
5270N/A status = new PrintWriter(sw);
5270N/A status.println("Executed command: " + str + "\n");
647N/A exitValue = rv;
647N/A testOutput = oList;
3986N/A this.env = env;
3986N/A this.t = t;
5270N/A testStatus = true;
647N/A }
647N/A
5270N/A void appendError(String x) {
5272N/A testStatus = false;
5272N/A testExitValue++;
5270N/A status.println(TEST_PREFIX + x);
5270N/A }
5270N/A
5270N/A void indentStatus(String x) {
5270N/A status.println(" " + x);
1945N/A }
1945N/A
647N/A void checkNegative() {
647N/A if (exitValue == 0) {
5270N/A appendError("test must not return 0 exit value");
647N/A }
647N/A }
647N/A
647N/A void checkPositive() {
647N/A if (exitValue != 0) {
5270N/A appendError("test did not return 0 exit value");
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()) {
5270N/A appendError("No message from cmd please");
647N/A return false;
647N/A }
647N/A return true;
647N/A }
647N/A
647N/A boolean isNotZeroOutput() {
647N/A if (testOutput.isEmpty()) {
5270N/A appendError("Missing message");
647N/A return false;
647N/A }
647N/A return true;
647N/A }
647N/A
1945N/A @Override
647N/A public String toString() {
5270N/A status.println("++++Begin Test Info++++");
5270N/A status.println("Test Status: " + (testStatus ? "PASS" : "FAIL"));
5270N/A status.println("++++Test Environment++++");
3986N/A for (String x : env.keySet()) {
5270N/A indentStatus(x + "=" + env.get(x));
3986N/A }
5270N/A status.println("++++Test Output++++");
1945N/A for (String x : testOutput) {
5270N/A indentStatus(x);
647N/A }
5270N/A status.println("++++Test Stack Trace++++");
5270N/A status.println(t.toString());
3986N/A for (StackTraceElement e : t.getStackTrace()) {
5270N/A indentStatus(e.toString());
3986N/A }
5270N/A status.println("++++End of Test Info++++");
5270N/A status.flush();
5270N/A String out = sw.toString();
5270N/A status.close();
5270N/A return out;
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 }
5270N/A appendError("string <" + str + "> not found");
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 }
5270N/A appendError("string <" + stringToMatch + "> not found");
647N/A return false;
647N/A }
647N/A }
5270N/A /**
5270N/A * Indicates that the annotated method is a test method.
5270N/A */
5270N/A @Retention(RetentionPolicy.RUNTIME)
5270N/A @Target(ElementType.METHOD)
5270N/A public @interface Test {}
647N/A}