8165500: TestJpsJar shouldn't jar all test.classpath directories
Summary: Refactor test to better handle errors
Reviewed-by: sspitsyn
--- a/jdk/test/ProblemList.txt Mon Oct 24 14:52:07 2016 +0300
+++ b/jdk/test/ProblemList.txt Tue Oct 25 14:49:35 2016 +0300
@@ -289,10 +289,6 @@
sun/tools/jhsdb/HeapDumpTest.java 8168397 macosx-all
-sun/tools/jps/TestJpsJar.java 8165500 generic-all
-
-sun/tools/jps/TestJpsJarRelative.java 6456333 generic-all
-
sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java 8057732 generic-all
demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java 8151899 generic-all
--- a/jdk/test/sun/tools/jps/JpsBase.java Mon Oct 24 14:52:07 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.File;
-import java.net.URL;
-import java.util.List;
-
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-/**
- * The base class for testing the jps utility.
- * The test sequence is to start jps with different combinations of arguments
- * and verify the output contains proper values.
- */
-public final class JpsBase {
-
- /**
- * The jps output should contain processes' names
- * (except when jps is started in quite mode).
- * The expected name of the test process is prepared here.
- */
-
- private static String getShortProcessName() {
- URL url = JpsBase.class.getResource("JpsBase.class");
- boolean isJar = url.getProtocol().equals("jar");
- return (isJar) ? JpsBase.class.getSimpleName() + ".jar" : JpsBase.class.getSimpleName();
- }
-
- private static String getFullProcessName() {
- URL url = JpsBase.class.getResource("JpsBase.class");
- boolean isJar = url.getProtocol().equals("jar");
- if (isJar) {
- String urlPath = url.getPath();
- File jar = new File(urlPath.substring(urlPath.indexOf("file:") + 5, urlPath.indexOf("jar!") + 3));
- return jar.getAbsolutePath();
- }
-
- return JpsBase.class.getName();
- }
-
- private static boolean userDirSanityCheck(String fullProcessName) {
- String userDir = System.getProperty("user.dir");
- if (!fullProcessName.startsWith(userDir)) {
- System.err.printf("Test skipped. user.dir '%s' is not a prefix of '%s'\n", userDir, fullProcessName);
- return false;
- }
- return true;
- }
-
- public static void main(String[] args) throws Exception {
- System.out.printf("INFO: user.dir: '%s''\n", System.getProperty("user.dir"));
- long pid = ProcessTools.getProcessId();
-
- List<List<JpsHelper.JpsArg>> combinations = JpsHelper.JpsArg.generateCombinations();
- for (List<JpsHelper.JpsArg> combination : combinations) {
- OutputAnalyzer output = JpsHelper.jps(JpsHelper.JpsArg.asCmdArray(combination));
- output.shouldHaveExitValue(0);
-
- boolean isQuiet = false;
- boolean isFull = false;
- String pattern;
- for (JpsHelper.JpsArg jpsArg : combination) {
- switch (jpsArg) {
- case q:
- // If '-q' is specified output should contain only a list of local VM identifiers:
- // 30673
- isQuiet = true;
- JpsHelper.verifyJpsOutput(output, "^\\d+$");
- output.shouldContain(Long.toString(pid));
- break;
- case l:
- // If '-l' is specified output should contain the full package name for the application's main class
- // or the full path name to the application's JAR file:
- // 30673 /tmp/jtreg/jtreg-workdir/scratch/JpsBase.jar ...
- isFull = true;
- String fullProcessName = getFullProcessName();
- // Skip the test if user.dir is not a prefix of the current path
- // It's possible if the test is run from symlinked dir or windows alias drive
- if (userDirSanityCheck(fullProcessName)) {
- pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*";
- output.shouldMatch(pattern);
- }
- break;
- case m:
- // If '-m' is specified output should contain the arguments passed to the main method:
- // 30673 JpsBase monkey ...
- for (String arg : args) {
- pattern = "^" + pid + ".*" + replaceSpecialChars(arg) + ".*";
- output.shouldMatch(pattern);
- }
- break;
- case v:
- // If '-v' is specified output should contain VM arguments:
- // 30673 JpsBase -Xmx512m -XX:+UseParallelGC -XX:Flags=/tmp/jtreg/jtreg-workdir/scratch/vmflags ...
- for (String vmArg : JpsHelper.getVmArgs()) {
- pattern = "^" + pid + ".*" + replaceSpecialChars(vmArg) + ".*";
- output.shouldMatch(pattern);
- }
- break;
- case V:
- // If '-V' is specified output should contain VM flags:
- // 30673 JpsBase +DisableExplicitGC ...
- pattern = "^" + pid + ".*" + replaceSpecialChars(JpsHelper.VM_FLAG) + ".*";
- output.shouldMatch(pattern);
- break;
- }
-
- if (isQuiet) {
- break;
- }
- }
-
- if (!isQuiet) {
- // Verify output line by line.
- // Output should only contain lines with pids after the first line with pid.
- JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*");
- if (!isFull) {
- String shortProcessName = getShortProcessName();
- pattern = "^" + pid + "\\s+" + replaceSpecialChars(shortProcessName);
- if (combination.isEmpty()) {
- // If no arguments are specified output should only contain
- // pid and process name
- pattern += "$";
- } else {
- pattern += ".*";
- }
- output.shouldMatch(pattern);
- }
- }
- }
- }
-
- private static String replaceSpecialChars(String str) {
- String tmp = str.replace("\\", "\\\\");
- tmp = tmp.replace("+", "\\+");
- tmp = tmp.replace(".", "\\.");
- tmp = tmp.replace("\n", "\\\\n");
- tmp = tmp.replace("\r", "\\\\r");
- return tmp;
- }
-
-}
--- a/jdk/test/sun/tools/jps/JpsHelper.java Mon Oct 24 14:52:07 2016 +0300
+++ b/jdk/test/sun/tools/jps/JpsHelper.java Tue Oct 25 14:49:35 2016 +0300
@@ -204,44 +204,85 @@
"The ouput should contain all content of " + path.toAbsolutePath());
}
- private static File getManifest(String className) throws IOException {
- if (manifestFile == null) {
- manifestFile = new File(className + ".mf");
- try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) {
- output.write("Main-Class: " + className + Utils.NEW_LINE);
+ public static void runJpsVariants(Long pid, String processName, String fullProcessName, String argument) throws Exception {
+ System.out.printf("INFO: user.dir: '%s''\n", System.getProperty("user.dir"));
+ List<List<JpsHelper.JpsArg>> combinations = JpsHelper.JpsArg.generateCombinations();
+ for (List<JpsHelper.JpsArg> combination : combinations) {
+ OutputAnalyzer output = JpsHelper.jps(JpsHelper.JpsArg.asCmdArray(combination));
+ output.shouldHaveExitValue(0);
+
+ boolean isQuiet = false;
+ boolean isFull = false;
+ String pattern;
+ for (JpsHelper.JpsArg jpsArg : combination) {
+ switch (jpsArg) {
+ case q:
+ // If '-q' is specified output should contain only a list of local VM identifiers:
+ // 30673
+ isQuiet = true;
+ JpsHelper.verifyJpsOutput(output, "^\\d+$");
+ output.shouldContain(Long.toString(pid));
+ break;
+ case l:
+ // If '-l' is specified output should contain the full package name for the application's main class
+ // or the full path name to the application's JAR file:
+ // 30673 /tmp/jtreg/jtreg-workdir/scratch/LingeredAppForJps.jar ...
+ isFull = true;
+ pattern = "^" + pid + "\\s+" + replaceSpecialChars(fullProcessName) + ".*";
+ output.shouldMatch(pattern);
+ break;
+ case m:
+ // If '-m' is specified output should contain the arguments passed to the main method:
+ // 30673 LingeredAppForJps lockfilename ...
+ pattern = "^" + pid + ".*" + replaceSpecialChars(argument) + ".*";
+ output.shouldMatch(pattern);
+ break;
+ case v:
+ // If '-v' is specified output should contain VM arguments:
+ // 30673 LingeredAppForJps -Xmx512m -XX:+UseParallelGC -XX:Flags=/tmp/jtreg/jtreg-workdir/scratch/vmflags ...
+ for (String vmArg : JpsHelper.getVmArgs()) {
+ pattern = "^" + pid + ".*" + replaceSpecialChars(vmArg) + ".*";
+ output.shouldMatch(pattern);
+ }
+ break;
+ case V:
+ // If '-V' is specified output should contain VM flags:
+ // 30673 LingeredAppForJps +DisableExplicitGC ...
+ pattern = "^" + pid + ".*" + replaceSpecialChars(JpsHelper.VM_FLAG) + ".*";
+ output.shouldMatch(pattern);
+ break;
+ }
+
+ if (isQuiet) {
+ break;
+ }
+ }
+
+ if (!isQuiet) {
+ // Verify output line by line.
+ // Output should only contain lines with pids after the first line with pid.
+ JpsHelper.verifyJpsOutput(output, "^\\d+\\s+.*");
+ if (!isFull) {
+ pattern = "^" + pid + "\\s+" + replaceSpecialChars(processName);
+ if (combination.isEmpty()) {
+ // If no arguments are specified output should only contain
+ // pid and process name
+ pattern += "$";
+ } else {
+ pattern += ".*";
+ }
+ output.shouldMatch(pattern);
+ }
}
}
- return manifestFile;
}
- /**
- * Build a jar of test classes in runtime
- */
- public static File buildJar(String className) throws Exception {
- File jar = new File(className + ".jar");
-
- List<String> jarArgs = new ArrayList<>();
- jarArgs.add("-cfm");
- jarArgs.add(jar.getAbsolutePath());
- File manifestFile = getManifest(className);
- jarArgs.add(manifestFile.getAbsolutePath());
- String testClassPath = System.getProperty("test.class.path", "?");
- for (String path : testClassPath.split(File.pathSeparator)) {
- jarArgs.add("-C");
- jarArgs.add(path);
- jarArgs.add(".");
- }
-
- System.out.println("Running jar " + jarArgs.toString());
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) {
- throw new Exception("jar failed: args=" + jarArgs.toString());
- }
-
- manifestFile.delete();
- jar.deleteOnExit();
-
- return jar;
+ private static String replaceSpecialChars(String str) {
+ String tmp = str.replace("\\", "\\\\");
+ tmp = tmp.replace("+", "\\+");
+ tmp = tmp.replace(".", "\\.");
+ tmp = tmp.replace("\n", "\\\\n");
+ tmp = tmp.replace("\r", "\\\\r");
+ return tmp;
}
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jps/LingeredApp.java Tue Oct 25 14:49:35 2016 +0300
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * This is a framework to launch an app that could be synchronized with caller
+ * to make further attach actions reliable across supported platforms
+
+ * Caller example:
+ * SmartTestApp a = SmartTestApp.startApp(cmd);
+ * // do something
+ * a.stopApp();
+ *
+ * or fine grained control
+ *
+ * a = new SmartTestApp("MyLock.lck");
+ * a.createLock();
+ * a.runApp();
+ * a.waitAppReady();
+ * // do something
+ * a.deleteLock();
+ * a.waitAppTerminate();
+ *
+ * Then you can work with app output and process object
+ *
+ * output = a.getAppOutput();
+ * process = a.getProcess();
+ *
+ */
+public class LingeredApp {
+
+ private static final long spinDelay = 1000;
+
+ private long lockCreationTime;
+ private final ArrayList<String> storedAppOutput;
+
+ protected Process appProcess;
+ protected static final int appWaitTime = 100;
+ protected final String lockFileName;
+
+ /*
+ * Drain child process output, store it into string array
+ */
+ class InputGobbler extends Thread {
+
+ InputStream is;
+ List<String> astr;
+
+ InputGobbler(InputStream is, List<String> astr) {
+ this.is = is;
+ this.astr = astr;
+ }
+
+ public void run() {
+ try {
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line = null;
+ while ((line = br.readLine()) != null) {
+ astr.add(line);
+ }
+ } catch (IOException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Create LingeredApp object on caller side. Lock file have be a valid filename
+ * at writable location
+ *
+ * @param lockFileName - the name of lock file
+ */
+ public LingeredApp(String lockFileName) {
+ this.lockFileName = lockFileName;
+ this.storedAppOutput = new ArrayList<String>();
+ }
+
+ public LingeredApp() {
+ final String lockName = UUID.randomUUID().toString() + ".lck";
+ this.lockFileName = lockName;
+ this.storedAppOutput = new ArrayList<String>();
+ }
+
+ /**
+ *
+ * @return name of lock file
+ */
+ public String getLockFileName() {
+ return this.lockFileName;
+ }
+
+ /**
+ *
+ * @return name of testapp
+ */
+ public String getAppName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ *
+ * @return pid of java process running testapp
+ */
+ public long getPid() {
+ if (appProcess == null) {
+ throw new RuntimeException("Process is not alive");
+ }
+ return appProcess.getPid();
+ }
+
+ /**
+ *
+ * @return process object
+ */
+ public Process getProcess() {
+ return appProcess;
+ }
+
+ /**
+ *
+ * @return application output as string array. Empty array if application produced no output
+ */
+ public List<String> getAppOutput() {
+ if (appProcess.isAlive()) {
+ throw new RuntimeException("Process is still alive. Can't get its output.");
+ }
+ return storedAppOutput;
+ }
+
+ /* Make sure all part of the app use the same method to get dates,
+ as different methods could produce different results
+ */
+ private static long epoch() {
+ return new Date().getTime();
+ }
+
+ private static long lastModified(String fileName) throws IOException {
+ Path path = Paths.get(fileName);
+ BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
+ return attr.lastModifiedTime().toMillis();
+ }
+
+ private static void setLastModified(String fileName, long newTime) throws IOException {
+ Path path = Paths.get(fileName);
+ FileTime fileTime = FileTime.fromMillis(newTime);
+ Files.setLastModifiedTime(path, fileTime);
+ }
+
+ /**
+ * create lock
+ *
+ * @throws IOException
+ */
+ public void createLock() throws IOException {
+ Path path = Paths.get(lockFileName);
+ // Files.deleteIfExists(path);
+ Files.createFile(path);
+ lockCreationTime = lastModified(lockFileName);
+ }
+
+ /**
+ * Delete lock
+ *
+ * @throws IOException
+ */
+ public void deleteLock() throws IOException {
+ try {
+ Path path = Paths.get(lockFileName);
+ Files.delete(path);
+ } catch (NoSuchFileException ex) {
+ // Lock already deleted. Ignore error
+ }
+ }
+
+ public void waitAppTerminate() {
+ while (true) {
+ try {
+ appProcess.waitFor();
+ break;
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * The app touches the lock file when it's started
+ * wait while it happens. Caller have to delete lock on wait error.
+ *
+ * @param timeout
+ * @throws java.io.IOException
+ */
+ public void waitAppReady(long timeout) throws IOException {
+ long here = epoch();
+ while (true) {
+ long epoch = epoch();
+ if (epoch - here > (timeout * 1000)) {
+ throw new IOException("App waiting timeout");
+ }
+
+ // Live process should touch lock file every second
+ long lm = lastModified(lockFileName);
+ if (lm > lockCreationTime) {
+ break;
+ }
+
+ // Make sure process didn't already exit
+ if (!appProcess.isAlive()) {
+ throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
+ }
+
+ try {
+ Thread.sleep(spinDelay);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ }
+
+ /**
+ * Analyze an environment and prepare a command line to
+ * run the app, app name should be added explicitly
+ */
+ public List<String> runAppPrepare(List<String> vmArguments) {
+ // We should always use testjava or throw an exception,
+ // so we can't use JDKToolFinder.getJDKTool("java");
+ // that falls back to compile java on error
+ String jdkPath = System.getProperty("test.jdk");
+ if (jdkPath == null) {
+ // we are not under jtreg, try env
+ Map<String, String> env = System.getenv();
+ jdkPath = env.get("TESTJAVA");
+ }
+
+ if (jdkPath == null) {
+ throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
+ }
+
+ String osname = System.getProperty("os.name");
+ String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
+
+ List<String> cmd = new ArrayList<String>();
+ cmd.add(javapath);
+
+
+ if (vmArguments == null) {
+ // Propagate test.vm.options to LingeredApp, filter out possible empty options
+ String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
+ for (String s : testVmOpts) {
+ if (!s.equals("")) {
+ cmd.add(s);
+ }
+ }
+ }
+ else{
+ // Lets user manage LingeredApp options
+ cmd.addAll(vmArguments);
+ }
+
+ // Make sure we set correct classpath to run the app
+ cmd.add("-cp");
+ String classpath = System.getProperty("test.class.path");
+ cmd.add((classpath == null) ? "." : classpath);
+
+ return cmd;
+ }
+
+ /**
+ * Assemble command line to a printable string
+ */
+ public void printCommandLine(List<String> cmd) {
+ // A bit of verbosity
+ StringBuilder cmdLine = new StringBuilder();
+ for (String strCmd : cmd) {
+ cmdLine.append("'").append(strCmd).append("' ");
+ }
+
+ System.out.println("Command line: [" + cmdLine.toString() + "]");
+ }
+
+ public void startGobblerPipe() {
+ // Create pipe reader for process, and read stdin and stderr to array of strings
+ InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
+ gb.start();
+ }
+
+ /**
+ * Run the app.
+ *
+ * @param vmArguments
+ * @throws IOException
+ */
+ public void runApp(List<String> vmArguments)
+ throws IOException {
+
+ List<String> cmd = runAppPrepare(vmArguments);
+
+ cmd.add(this.getAppName());
+ cmd.add(lockFileName);
+
+ printCommandLine(cmd);
+
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ // we don't expect any error output but make sure we are not stuck on pipe
+ // pb.redirectErrorStream(false);
+ // ProcessBuilder.start can throw IOException
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+ appProcess = pb.start();
+
+ startGobblerPipe();
+ }
+
+ /**
+ * Delete lock file that signals app to terminate, then
+ * wait until app is actually terminated.
+ * @throws IOException
+ */
+ public void stopApp() throws IOException {
+ deleteLock();
+ // The startApp() of the derived app can throw
+ // an exception before the LA actually starts
+ if (appProcess != null) {
+ waitAppTerminate();
+ int exitcode = appProcess.exitValue();
+ if (exitcode != 0) {
+ throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
+ }
+ }
+ }
+
+ /**
+ * High level interface for test writers
+ */
+ /**
+ * Factory method that creates LingeredApp object with ready to use application
+ * lock name is autogenerated
+ * @param cmd - vm options, could be null to auto add testvm.options
+ * @return LingeredApp object
+ * @throws IOException
+ */
+ public static LingeredApp startApp(List<String> cmd) throws IOException {
+ LingeredApp a = new LingeredApp();
+ a.createLock();
+ try {
+ a.runApp(cmd);
+ a.waitAppReady(appWaitTime);
+ } catch (Exception ex) {
+ a.deleteLock();
+ throw ex;
+ }
+
+ return a;
+ }
+
+ /**
+ * Factory method that starts pre-created LingeredApp
+ * lock name is autogenerated
+ * @param cmd - vm options, could be null to auto add testvm.options
+ * @param theApp - app to start
+ * @return LingeredApp object
+ * @throws IOException
+ */
+
+ public static void startApp(List<String> cmd, LingeredApp theApp) throws IOException {
+ theApp.createLock();
+ try {
+ theApp.runApp(cmd);
+ theApp.waitAppReady(appWaitTime);
+ } catch (Exception ex) {
+ theApp.deleteLock();
+ throw ex;
+ }
+ }
+
+ public static LingeredApp startApp() throws IOException {
+ return startApp(null);
+ }
+
+ public static void stopApp(LingeredApp app) throws IOException {
+ if (app != null) {
+ // LingeredApp can throw an exception during the intialization,
+ // make sure we don't have cascade NPE
+ app.stopApp();
+ }
+ }
+
+ /**
+ * LastModified time might not work correctly in some cases it might
+ * cause later failures
+ */
+
+ public static boolean isLastModifiedWorking() {
+ boolean sane = true;
+ try {
+ long lm = lastModified(".");
+ if (lm == 0) {
+ System.err.println("SANITY Warning! The lastModifiedTime() doesn't work on this system, it returns 0");
+ sane = false;
+ }
+
+ long now = epoch();
+ if (lm > now) {
+ System.err.println("SANITY Warning! The Clock is wrong on this system lastModifiedTime() > getTime()");
+ sane = false;
+ }
+
+ setLastModified(".", epoch());
+ long lm1 = lastModified(".");
+ if (lm1 <= lm) {
+ System.err.println("SANITY Warning! The setLastModified doesn't work on this system");
+ sane = false;
+ }
+ }
+ catch(IOException e) {
+ System.err.println("SANITY Warning! IOException during sanity check " + e);
+ sane = false;
+ }
+
+ return sane;
+ }
+
+ /**
+ * This part is the application it self
+ */
+ public static void main(String args[]) {
+
+ if (args.length != 1) {
+ System.err.println("Lock file name is not specified");
+ System.exit(7);
+ }
+
+ String theLockFileName = args[0];
+
+ try {
+ Path path = Paths.get(theLockFileName);
+
+ while (Files.exists(path)) {
+ // Touch the lock to indicate our readiness
+ setLastModified(theLockFileName, epoch());
+ Thread.sleep(spinDelay);
+ }
+ } catch (NoSuchFileException ex) {
+ // Lock deleted while we are setting last modified time.
+ // Ignore error and lets the app exits
+ } catch (Exception ex) {
+ System.err.println("LingeredApp ERROR: " + ex);
+ // Leave exit_code = 1 to Java launcher
+ System.exit(3);
+ }
+
+ System.exit(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jps/LingeredAppForJps.java Tue Oct 25 14:49:35 2016 +0300
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.net.URL;
+
+public class LingeredAppForJps extends LingeredApp {
+
+ // Copy runApp logic here to be able to run an app from JarFile
+ public void runAppWithName(List<String> vmArguments, String runName)
+ throws IOException {
+
+ List<String> cmd = runAppPrepare(vmArguments);
+ if (runName.endsWith(".jar")) {
+ cmd.add("-Xdiag");
+ cmd.add("-jar");
+ }
+ cmd.add(runName);
+ cmd.add(lockFileName);
+
+ printCommandLine(cmd);
+
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ // we don't expect any error output but make sure we are not stuck on pipe
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+ appProcess = pb.start();
+ startGobblerPipe();
+ }
+
+ public static LingeredApp startAppJar(List<String> cmd, LingeredAppForJps app, File jar) throws IOException {
+ app.createLock();
+ try {
+ app.runAppWithName(cmd, jar.getAbsolutePath());
+ app.waitAppReady(appWaitTime);
+ } catch (Exception ex) {
+ app.deleteLock();
+ throw ex;
+ }
+
+ return app;
+ }
+
+ /**
+ * The jps output should contain processes' names
+ * (except when jps is started in quite mode).
+ * The expected name of the test process is prepared here.
+ */
+ public static String getProcessName() {
+ return LingeredAppForJps.class.getSimpleName();
+ }
+
+ public static String getProcessName(File jar) {
+ return jar.getName();
+ }
+
+ // full package name for the application's main class or the full path
+ // name to the application's JAR file:
+
+ public static String getFullProcessName() {
+ return LingeredAppForJps.class.getCanonicalName();
+ }
+
+ public static String getFullProcessName(File jar) {
+ return jar.getAbsolutePath();
+ }
+
+ public static File buildJar() throws IOException {
+ String className = LingeredAppForJps.class.getName();
+ File jar = new File(className + ".jar");
+ String testClassPath = System.getProperty("test.class.path", "?");
+
+ File manifestFile = new File(className + ".mf");
+ String nl = System.getProperty("line.separator");
+ try (BufferedWriter output = new BufferedWriter(new FileWriter(manifestFile))) {
+ output.write("Main-Class: " + className + nl);
+ }
+
+ List<String> jarArgs = new ArrayList<>();
+ jarArgs.add("-cfm");
+ jarArgs.add(jar.getAbsolutePath());
+ jarArgs.add(manifestFile.getAbsolutePath());
+
+ for (String path : testClassPath.split(File.pathSeparator)) {
+ String classFullName = path + File.separator + className + ".class";
+ File f = new File(classFullName);
+ if (f.exists()) {
+ jarArgs.add("-C");
+ jarArgs.add(path);
+ jarArgs.add(".");
+ System.out.println("INFO: scheduled to jar " + path);
+ break;
+ }
+ }
+
+ System.out.println("Running jar " + jarArgs.toString());
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) {
+ throw new IOException("jar failed: args=" + jarArgs.toString());
+ }
+
+ manifestFile.delete();
+ jar.deleteOnExit();
+
+ // Print content of jar file
+ System.out.println("Content of jar file" + jar.getAbsolutePath());
+
+ jarArgs = new ArrayList<>();
+ jarArgs.add("-tvf");
+ jarArgs.add(jar.getAbsolutePath());
+
+ jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(jarArgs.toArray(new String[jarArgs.size()]))) {
+ throw new IOException("jar failed: args=" + jarArgs.toString());
+ }
+
+ return jar;
+ }
+
+ public static void main(String args[]) {
+ LingeredApp.main(args);
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/tools/jps/TestJps.java Tue Oct 25 14:49:35 2016 +0300
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /lib/testlibrary /test/lib
+ * @modules jdk.jartool/sun.tools.jar
+ * @build LingeredAppForJps
+ * @build LingeredApp
+ * @run main/othervm TestJps
+ */
+
+ /*
+ * Notes:
+ * @modules tag is ignored in driver mode, so need main/othervm
+ *
+ * Launching the process with relative path to an app jar file is not tested
+ *
+ * This test resides in default package, so correct appearance
+ * of the full package name actually is not tested.
+ */
+
+import java.util.List;
+import java.io.File;
+
+public class TestJps {
+
+ public static void testJpsClass() throws Throwable {
+ LingeredApp app = new LingeredAppForJps();
+ try {
+ LingeredApp.startApp(JpsHelper.getVmArgs(), app);
+ JpsHelper.runJpsVariants(app.getPid(),
+ LingeredAppForJps.getProcessName(), LingeredAppForJps.getFullProcessName(), app.getLockFileName());
+
+ } finally {
+ LingeredApp.stopApp(app);
+ }
+ }
+
+ public static void testJpsJar() throws Throwable {
+ // Get any jar exception as early as possible
+ File jar = LingeredAppForJps.buildJar();
+
+ // Jar created go to the main test
+ LingeredAppForJps app = new LingeredAppForJps();
+ try {
+ LingeredAppForJps.startAppJar(JpsHelper.getVmArgs(), app, jar);
+ JpsHelper.runJpsVariants(app.getPid(),
+ LingeredAppForJps.getProcessName(jar), LingeredAppForJps.getFullProcessName(jar), app.getLockFileName());
+ } finally {
+ LingeredAppForJps.stopApp(app);
+ }
+
+ }
+
+ public static void main(String[] args) throws Throwable {
+ testJpsClass();
+ testJpsJar();
+ }
+}
--- a/jdk/test/sun/tools/jps/TestJpsClass.java Mon Oct 24 14:52:07 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.ArrayList;
-import java.util.List;
-
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-/*
- * @test
- * @summary The test application will be started with java class:
- * java JpsBase
- * For all possible combinations of jps arguments a jps process
- * will be started from within the test application.
- * The output should contain proper values.
- * @library /lib/testlibrary
- * @modules jdk.jartool/sun.tools.jar
- * java.management
- * @build jdk.testlibrary.* JpsHelper JpsBase
- * @run driver TestJpsClass
- */
-public class TestJpsClass {
-
- public static void main(String[] args) throws Throwable {
- String testJdk = System.getProperty("test.jdk", "?");
- String testSrc = System.getProperty("test.src", "?");
- String testClassPath = System.getProperty("test.class.path", "?");
-
- List<String> cmd = new ArrayList<>();
- cmd.addAll(JpsHelper.getVmArgs());
- cmd.add("-Dtest.jdk=" + testJdk);
- cmd.add("-Dtest.src=" + testSrc);
- cmd.add("-cp");
- cmd.add(testClassPath);
- cmd.add("JpsBase");
- cmd.add("monkey");
-
- ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()]));
- OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
- System.out.println(output.getOutput());
- output.shouldHaveExitValue(0);
- }
-
-}
--- a/jdk/test/sun/tools/jps/TestJpsJar.java Mon Oct 24 14:52:07 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-/*
- * @test
- * @summary The test application will be started with absolute jar:
- * java -jar /tmp/jtreg/jtreg-workdir/scratch/JpsBase.jar
- * For all possible combinations of jps arguments a jps process
- * will be started from within the test application.
- * The output should contain proper values.
- * @library /lib/testlibrary
- * @modules jdk.jartool/sun.tools.jar
- * java.management
- * @build JpsHelper JpsBase
- * @run main/othervm TestJpsJar
- */
-public class TestJpsJar {
-
- public static void main(String[] args) throws Throwable {
- String testJdk = System.getProperty("test.jdk", "?");
- String testSrc = System.getProperty("test.src", "?");
- File jar = JpsHelper.buildJar("JpsBase");
-
- List<String> cmd = new ArrayList<>();
- cmd.addAll(JpsHelper.getVmArgs());
- cmd.add("-Dtest.jdk=" + testJdk);
- cmd.add("-Dtest.src=" + testSrc);
- cmd.add("-Duser.dir=" + System.getProperty("user.dir"));
- cmd.add("-jar");
- cmd.add(jar.getAbsolutePath());
- cmd.add("monkey");
-
- ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()]));
- OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
- System.out.println(output.getOutput());
- output.shouldHaveExitValue(0);
- }
-
-}
--- a/jdk/test/sun/tools/jps/TestJpsJarRelative.java Mon Oct 24 14:52:07 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
-
-/*
- * @test
- * @summary The test application will be started with relative jar:
- * java -jar ./JpsBase.jar
- * For all possible combinations of jps arguments a jps process
- * will be started from within the test application.
- * The output should contain proper values.
- * @library /lib/testlibrary
- * @modules jdk.jartool/sun.tools.jar
- * java.management
- * @build jdk.testlibrary.* JpsHelper JpsBase
- * @run main/othervm TestJpsJarRelative
- */
-public class TestJpsJarRelative {
-
- public static void main(String[] args) throws Throwable {
- String testJdk = System.getProperty("test.jdk", "?");
- String testSrc = System.getProperty("test.src", "?");
- File jar = JpsHelper.buildJar("JpsBase");
-
- List<String> cmd = new ArrayList<>();
- cmd.addAll(JpsHelper.getVmArgs());
- cmd.add("-Dtest.jdk=" + testJdk);
- cmd.add("-Dtest.src=" + testSrc);
- cmd.add("-jar");
- cmd.add("." + File.separator + jar.getName());
- cmd.add("monkey");
-
- ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(cmd.toArray(new String[cmd.size()]));
- OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
- System.out.println(output.getOutput());
- output.shouldHaveExitValue(0);
- }
-
-}
--- a/jdk/test/sun/tools/jps/TestJpsSanity.java Mon Oct 24 14:52:07 2016 +0300
+++ b/jdk/test/sun/tools/jps/TestJpsSanity.java Tue Oct 25 14:49:35 2016 +0300
@@ -96,7 +96,7 @@
}
private static void testJpsUnknownHost() throws Exception {
- String invalidHostName = "Oja781nh2ev7vcvbajdg-Sda1-C";
+ String invalidHostName = "Oja781nh2ev7vcvbajdg-Sda1-C.invalid";
OutputAnalyzer output = JpsHelper.jps(invalidHostName);
Asserts.assertNotEquals(output.getExitValue(), 0, "Exit code shouldn't be 0");
Asserts.assertFalse(output.getStderr().isEmpty(), "Error output should not be empty");