Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/tools/launcher/TestHelper.java
38833 views
/*1* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.OutputStream;24import java.io.InputStream;25import java.lang.annotation.ElementType;26import java.lang.annotation.Retention;27import java.lang.annotation.RetentionPolicy;28import java.lang.annotation.Target;29import java.lang.reflect.Method;30import java.util.regex.Pattern;31import java.io.StringWriter;32import java.io.PrintWriter;33import java.util.Set;34import java.io.BufferedReader;35import java.io.File;36import java.io.FileFilter;37import java.io.FileNotFoundException;38import java.io.FileOutputStream;39import java.io.IOException;40import java.io.InputStreamReader;41import java.io.PrintStream;42import java.nio.charset.Charset;43import java.nio.file.attribute.BasicFileAttributes;44import java.nio.file.Files;45import java.nio.file.FileVisitResult;46import java.nio.file.SimpleFileVisitor;47import java.nio.file.Path;48import java.util.ArrayList;49import java.util.List;50import java.util.Locale;51import java.util.Map;52import javax.tools.JavaCompiler;53import javax.tools.ToolProvider;5455import static java.nio.file.StandardCopyOption.*;56import static java.nio.file.StandardOpenOption.*;5758/**59* This class provides some common utilities for the launcher tests.60*/61public class TestHelper {62// commonly used jtreg constants63static final File TEST_CLASSES_DIR;64static final File TEST_SOURCES_DIR;6566static final String JAVAHOME = System.getProperty("java.home");67static final String JAVA_BIN;68static final String JAVA_JRE_BIN;69static final String JAVA_LIB;70static final String JAVA_JRE_LIB;71static final boolean isSDK = JAVAHOME.endsWith("jre");72static final String javaCmd;73static final String javawCmd;74static final String javacCmd;75static final String jarCmd;76static final boolean haveServerVM;77static final boolean haveClientVM;7879static final JavaCompiler compiler;8081static final boolean debug = Boolean.getBoolean("TestHelper.Debug");82static final boolean isWindows =83System.getProperty("os.name", "unknown").startsWith("Windows");84static final boolean isMacOSX =85System.getProperty("os.name", "unknown").contains("OS X");86static final boolean is64Bit =87System.getProperty("sun.arch.data.model").equals("64");88static final boolean is32Bit =89System.getProperty("sun.arch.data.model").equals("32");90static final boolean isSolaris =91System.getProperty("os.name", "unknown").startsWith("SunOS");92static final boolean isLinux =93System.getProperty("os.name", "unknown").startsWith("Linux");94static final boolean isAIX =95System.getProperty("os.name", "unknown").startsWith("AIX");96static final String LIBJVM = isWindows97? "jvm.dll"98: "libjvm" + (isMacOSX ? ".dylib" : ".so");99100static final boolean isSparc = System.getProperty("os.arch").startsWith("sparc");101102// make a note of the golden default locale103static final Locale DefaultLocale = Locale.getDefault();104105static final String JAVA_FILE_EXT = ".java";106static final String CLASS_FILE_EXT = ".class";107static final String JAR_FILE_EXT = ".jar";108static final String EXE_FILE_EXT = ".exe";109static final String JLDEBUG_KEY = "_JAVA_LAUNCHER_DEBUG";110static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";111static final String TEST_PREFIX = "###TestError###: ";112113static int testExitValue = 0;114115static {116String tmp = System.getProperty("test.classes", null);117if (tmp == null) {118throw new Error("property test.classes not defined ??");119}120TEST_CLASSES_DIR = new File(tmp).getAbsoluteFile();121122tmp = System.getProperty("test.src", null);123if (tmp == null) {124throw new Error("property test.src not defined ??");125}126TEST_SOURCES_DIR = new File(tmp).getAbsoluteFile();127128if (is64Bit && is32Bit) {129throw new RuntimeException("arch model cannot be both 32 and 64 bit");130}131if (!is64Bit && !is32Bit) {132throw new RuntimeException("arch model is not 32 or 64 bit ?");133}134compiler = ToolProvider.getSystemJavaCompiler();135136File binDir = (isSDK)137? new File((new File(JAVAHOME)).getParentFile(), "bin")138: new File(JAVAHOME, "bin");139JAVA_BIN = binDir.getAbsolutePath();140JAVA_JRE_BIN = new File(JAVAHOME, "bin").getAbsolutePath();141142File libDir = (isSDK)143? new File((new File(JAVAHOME)).getParentFile(), "lib")144: new File(JAVAHOME, "lib");145JAVA_LIB = libDir.getAbsolutePath();146JAVA_JRE_LIB = new File(JAVAHOME, "lib").getAbsolutePath();147148File javaCmdFile = (isWindows)149? new File(binDir, "java.exe")150: new File(binDir, "java");151javaCmd = javaCmdFile.getAbsolutePath();152if (!javaCmdFile.canExecute()) {153throw new RuntimeException("java <" + TestHelper.javaCmd +154"> must exist and should be executable");155}156157File javacCmdFile = (isWindows)158? new File(binDir, "javac.exe")159: new File(binDir, "javac");160javacCmd = javacCmdFile.getAbsolutePath();161162File jarCmdFile = (isWindows)163? new File(binDir, "jar.exe")164: new File(binDir, "jar");165jarCmd = jarCmdFile.getAbsolutePath();166if (!jarCmdFile.canExecute()) {167throw new RuntimeException("java <" + TestHelper.jarCmd +168"> must exist and should be executable");169}170171if (isWindows) {172File javawCmdFile = new File(binDir, "javaw.exe");173javawCmd = javawCmdFile.getAbsolutePath();174if (!javawCmdFile.canExecute()) {175throw new RuntimeException("java <" + javawCmd +176"> must exist and should be executable");177}178} else {179javawCmd = null;180}181182if (!javacCmdFile.canExecute()) {183throw new RuntimeException("java <" + javacCmd +184"> must exist and should be executable");185}186187haveClientVM = haveVmVariant("client");188haveServerVM = haveVmVariant("server");189}190private static boolean haveVmVariant(String type) {191if (isWindows) {192File vmDir = new File(JAVA_JRE_BIN, type);193File jvmFile = new File(vmDir, LIBJVM);194return jvmFile.exists();195} else {196File vmDir = new File(JAVA_JRE_LIB, type);197File vmArchDir = new File(vmDir, getJreArch());198File jvmFile = new File(vmArchDir, LIBJVM);199return jvmFile.exists();200}201}202void run(String[] args) throws Exception {203int passed = 0, failed = 0;204final Pattern p = (args != null && args.length > 0)205? Pattern.compile(args[0])206: null;207for (Method m : this.getClass().getDeclaredMethods()) {208boolean selected = (p == null)209? m.isAnnotationPresent(Test.class)210: p.matcher(m.getName()).matches();211if (selected) {212try {213m.invoke(this, (Object[]) null);214System.out.println(m.getName() + ": OK");215passed++;216System.out.printf("Passed: %d, Failed: %d, ExitValue: %d%n",217passed, failed, testExitValue);218} catch (Throwable ex) {219System.out.printf("Test %s failed: %s %n", m, ex);220System.out.println("----begin detailed exceptions----");221ex.printStackTrace(System.out);222for (Throwable t : ex.getSuppressed()) {223t.printStackTrace(System.out);224}225System.out.println("----end detailed exceptions----");226failed++;227}228}229}230System.out.printf("Total: Passed: %d, Failed %d%n", passed, failed);231if (failed > 0) {232throw new RuntimeException("Tests failed: " + failed);233}234if (passed == 0 && failed == 0) {235throw new AssertionError("No test(s) selected: passed = " +236passed + ", failed = " + failed + " ??????????");237}238}239240/*241* usually the jre/lib/arch-name is the same as os.arch, except for x86.242*/243static String getJreArch() {244String arch = System.getProperty("os.arch");245return arch.equals("x86") ? "i386" : arch;246}247static String getArch() {248return System.getProperty("os.arch");249}250static File getClassFile(File javaFile) {251String s = javaFile.getAbsolutePath().replace(JAVA_FILE_EXT, CLASS_FILE_EXT);252return new File(s);253}254255static File getJavaFile(File classFile) {256String s = classFile.getAbsolutePath().replace(CLASS_FILE_EXT, JAVA_FILE_EXT);257return new File(s);258}259260static String baseName(File f) {261String s = f.getName();262return s.substring(0, s.indexOf("."));263}264265/*266* A convenience method to create a jar with jar file name and defs267*/268static void createJar(File jarName, String... mainDefs)269throws FileNotFoundException{270createJar(null, jarName, new File("Foo"), mainDefs);271}272273/*274* A convenience method to create a java file, compile and jar it up, using275* the sole class file name in the jar, as the Main-Class attribute value.276*/277static void createJar(File jarName, File mainClass, String... mainDefs)278throws FileNotFoundException {279createJar(null, jarName, mainClass, mainDefs);280}281282/*283* A convenience method to compile java files.284*/285static void compile(String... compilerArgs) {286if (compiler.run(null, null, null, compilerArgs) != 0) {287String sarg = "";288for (String x : compilerArgs) {289sarg.concat(x + " ");290}291throw new Error("compilation failed: " + sarg);292}293}294295/*296* A generic jar file creator to create a java file, compile it297* and jar it up, a specific Main-Class entry name in the298* manifest can be specified or a null to use the sole class file name299* as the Main-Class attribute value.300*/301static void createJar(String mEntry, File jarName, File mainClass,302String... mainDefs) throws FileNotFoundException {303if (jarName.exists()) {304jarName.delete();305}306try (PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"))) {307ps.println("public class Foo {");308if (mainDefs != null) {309for (String x : mainDefs) {310ps.println(x);311}312}313ps.println("}");314}315316String compileArgs[] = {317mainClass + ".java"318};319if (compiler.run(null, null, null, compileArgs) != 0) {320throw new RuntimeException("compilation failed " + mainClass + ".java");321}322if (mEntry == null) {323mEntry = mainClass.getName();324}325String jarArgs[] = {326(debug) ? "cvfe" : "cfe",327jarName.getAbsolutePath(),328mEntry,329mainClass.getName() + ".class"330};331createJar(jarArgs);332}333334static void createJar(String... args) {335sun.tools.jar.Main jarTool =336new sun.tools.jar.Main(System.out, System.err, "JarCreator");337if (!jarTool.run(args)) {338String message = "jar creation failed with command:";339for (String x : args) {340message = message.concat(" " + x);341}342throw new RuntimeException(message);343}344}345346static void copyStream(InputStream in, OutputStream out) throws IOException {347byte[] buf = new byte[8192];348int n = in.read(buf);349while (n > 0) {350out.write(buf, 0, n);351n = in.read(buf);352}353}354355static void copyFile(File src, File dst) throws IOException {356Path parent = dst.toPath().getParent();357if (parent != null) {358Files.createDirectories(parent);359}360Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING);361}362363/**364* Attempt to create a file at the given location. If an IOException365* occurs then back off for a moment and try again. When a number of366* attempts fail, give up and throw an exception.367*/368void createAFile(File aFile, List<String> contents) throws IOException {369IOException cause = null;370for (int attempts = 0; attempts < 10; attempts++) {371try {372Files.write(aFile.getAbsoluteFile().toPath(), contents,373Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING, WRITE);374if (cause != null) {375/*376* report attempts and errors that were encountered377* for diagnostic purposes378*/379System.err.println("Created batch file " +380aFile + " in " + (attempts + 1) +381" attempts");382System.err.println("Errors encountered: " + cause);383cause.printStackTrace();384}385return;386} catch (IOException ioe) {387if (cause != null) {388// chain the exceptions so they all get reported for diagnostics389cause.addSuppressed(ioe);390} else {391cause = ioe;392}393}394395try {396Thread.sleep(500);397} catch (InterruptedException ie) {398if (cause != null) {399// cause should alway be non-null here400ie.addSuppressed(cause);401}402throw new RuntimeException("Interrupted while creating batch file", ie);403}404}405throw new RuntimeException("Unable to create batch file", cause);406}407408static void createFile(File outFile, List<String> content) throws IOException {409Files.write(outFile.getAbsoluteFile().toPath(), content,410Charset.defaultCharset(), CREATE_NEW);411}412413static void recursiveDelete(File target) throws IOException {414if (!target.exists()) {415return;416}417Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {418@Override419public FileVisitResult postVisitDirectory(Path dir, IOException exc) {420try {421Files.deleteIfExists(dir);422} catch (IOException ex) {423System.out.println("Error: could not delete: " + dir.toString());424System.out.println(ex.getMessage());425return FileVisitResult.TERMINATE;426}427return FileVisitResult.CONTINUE;428}429@Override430public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {431try {432Files.deleteIfExists(file);433} catch (IOException ex) {434System.out.println("Error: could not delete: " + file.toString());435System.out.println(ex.getMessage());436return FileVisitResult.TERMINATE;437}438return FileVisitResult.CONTINUE;439}440});441}442443static TestResult doExec(String...cmds) {444return doExec(null, null, cmds);445}446447static TestResult doExec(Map<String, String> envToSet, String...cmds) {448return doExec(envToSet, null, cmds);449}450/*451* A method which executes a java cmd and returns the results in a container452*/453static TestResult doExec(Map<String, String> envToSet,454Set<String> envToRemove, String...cmds) {455String cmdStr = "";456for (String x : cmds) {457cmdStr = cmdStr.concat(x + " ");458}459ProcessBuilder pb = new ProcessBuilder(cmds);460Map<String, String> env = pb.environment();461if (envToRemove != null) {462for (String key : envToRemove) {463env.remove(key);464}465}466if (envToSet != null) {467env.putAll(envToSet);468}469BufferedReader rdr = null;470try {471List<String> outputList = new ArrayList<>();472pb.redirectErrorStream(true);473Process p = pb.start();474rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));475String in = rdr.readLine();476while (in != null) {477outputList.add(in);478in = rdr.readLine();479}480p.waitFor();481p.destroy();482483return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList,484env, new Throwable("current stack of the test"));485} catch (Exception ex) {486ex.printStackTrace();487throw new RuntimeException(ex.getMessage());488}489}490491static FileFilter createFilter(final String extension) {492return new FileFilter() {493@Override494public boolean accept(File pathname) {495String name = pathname.getName();496if (name.endsWith(extension)) {497return true;498}499return false;500}501};502}503504static boolean isEnglishLocale() {505return Locale.getDefault().getLanguage().equals("en");506}507508/*509* A class to encapsulate the test results and stuff, with some ease510* of use methods to check the test results.511*/512static class TestResult {513PrintWriter status;514StringWriter sw;515int exitValue;516List<String> testOutput;517Map<String, String> env;518Throwable t;519boolean testStatus;520521public TestResult(String str, int rv, List<String> oList,522Map<String, String> env, Throwable t) {523sw = new StringWriter();524status = new PrintWriter(sw);525status.println("Executed command: " + str + "\n");526exitValue = rv;527testOutput = oList;528this.env = env;529this.t = t;530testStatus = true;531}532533void appendError(String x) {534testStatus = false;535testExitValue++;536status.println(TEST_PREFIX + x);537}538539void indentStatus(String x) {540status.println(" " + x);541}542543void checkNegative() {544if (exitValue == 0) {545appendError("test must not return 0 exit value");546}547}548549void checkPositive() {550if (exitValue != 0) {551appendError("test did not return 0 exit value");552}553}554555boolean isOK() {556return exitValue == 0;557}558559boolean isZeroOutput() {560if (!testOutput.isEmpty()) {561appendError("No message from cmd please");562return false;563}564return true;565}566567boolean isNotZeroOutput() {568if (testOutput.isEmpty()) {569appendError("Missing message");570return false;571}572return true;573}574575@Override576public String toString() {577status.println("++++Begin Test Info++++");578status.println("Test Status: " + (testStatus ? "PASS" : "FAIL"));579status.println("++++Test Environment++++");580for (String x : env.keySet()) {581indentStatus(x + "=" + env.get(x));582}583status.println("++++Test Output++++");584for (String x : testOutput) {585indentStatus(x);586}587status.println("++++Test Stack Trace++++");588status.println(t.toString());589for (StackTraceElement e : t.getStackTrace()) {590indentStatus(e.toString());591}592status.println("++++End of Test Info++++");593status.flush();594String out = sw.toString();595status.close();596return out;597}598599boolean contains(String str) {600for (String x : testOutput) {601if (x.contains(str)) {602return true;603}604}605appendError("string <" + str + "> not found");606return false;607}608609boolean notContains(String str) {610for (String x : testOutput) {611if (x.contains(str)) {612appendError("string <" + str + "> found");613return false;614}615}616return true;617}618619boolean matches(String stringToMatch) {620for (String x : testOutput) {621if (x.matches(stringToMatch)) {622return true;623}624}625appendError("string <" + stringToMatch + "> not found");626return false;627}628629boolean notMatches(String stringToMatch) {630for (String x : testOutput) {631if (!x.matches(stringToMatch)) {632return true;633}634}635appendError("string <" + stringToMatch + "> found");636return false;637}638}639/**640* Indicates that the annotated method is a test method.641*/642@Retention(RetentionPolicy.RUNTIME)643@Target(ElementType.METHOD)644public @interface Test {}645}646647648