--- old/test/lib/share/classes/jdk/test/lib/apps/LingeredApp.java 2016-08-11 12:49:39.326208100 -0400 +++ /dev/null 2016-08-11 12:49:39.000000000 -0400 @@ -1,466 +0,0 @@ -/* - * Copyright (c) 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. - */ - -package jdk.test.lib.apps; - -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 static final int appWaitTime = 100; - - private final String lockFileName; - private long lockCreationTime; - private Process appProcess; - private final ArrayList storedAppOutput; - - /* - * Drain child process output, store it into string array - */ - class InputGobbler extends Thread { - - InputStream is; - List astr; - - InputGobbler(InputStream is, List 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(); - } - - public LingeredApp() { - final String lockName = UUID.randomUUID().toString() + ".lck"; - this.lockFileName = lockName; - this.storedAppOutput = new ArrayList(); - } - - /** - * - * @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 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 - } - } - } - - /** - * Run the app - * - * @param vmArguments - * @throws IOException - */ - public void runApp(List vmArguments) - throws IOException { - - // 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 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 cmd = new ArrayList(); - 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); - - cmd.add(this.getAppName()); - cmd.add(lockFileName); - - // Reporting - StringBuilder cmdLine = new StringBuilder(); - for (String strCmd : cmd) { - cmdLine.append("'").append(strCmd).append("' "); - } - - // A bit of verbosity - System.out.println("Command line: [" + cmdLine.toString() + "]"); - - ProcessBuilder pb = new ProcessBuilder(cmd); - // we don't expect any error output but make sure we are not stuck on pipe - // pb.redirectErrorStream(false); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - - appProcess = pb.start(); - - // Create pipe reader for process, and read stdin and stderr to array of strings - InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput); - gb.start(); - } - - /** - * Delete lock file that signals app to terminate, then - * wait until app is actually terminated. - * @throws IOException - */ - public void stopApp() throws IOException { - deleteLock(); - 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 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 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 2016-08-11 12:49:39.000000000 -0400 +++ new/test/lib/jdk/test/lib/apps/LingeredApp.java 2016-08-11 12:49:38.539610100 -0400 @@ -0,0 +1,466 @@ +/* + * Copyright (c) 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. + */ + +package jdk.test.lib.apps; + +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 static final int appWaitTime = 100; + + private final String lockFileName; + private long lockCreationTime; + private Process appProcess; + private final ArrayList storedAppOutput; + + /* + * Drain child process output, store it into string array + */ + class InputGobbler extends Thread { + + InputStream is; + List astr; + + InputGobbler(InputStream is, List 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(); + } + + public LingeredApp() { + final String lockName = UUID.randomUUID().toString() + ".lck"; + this.lockFileName = lockName; + this.storedAppOutput = new ArrayList(); + } + + /** + * + * @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 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 + } + } + } + + /** + * Run the app + * + * @param vmArguments + * @throws IOException + */ + public void runApp(List vmArguments) + throws IOException { + + // 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 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 cmd = new ArrayList(); + 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); + + cmd.add(this.getAppName()); + cmd.add(lockFileName); + + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String strCmd : cmd) { + cmdLine.append("'").append(strCmd).append("' "); + } + + // A bit of verbosity + System.out.println("Command line: [" + cmdLine.toString() + "]"); + + ProcessBuilder pb = new ProcessBuilder(cmd); + // we don't expect any error output but make sure we are not stuck on pipe + // pb.redirectErrorStream(false); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + + appProcess = pb.start(); + + // Create pipe reader for process, and read stdin and stderr to array of strings + InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput); + gb.start(); + } + + /** + * Delete lock file that signals app to terminate, then + * wait until app is actually terminated. + * @throws IOException + */ + public void stopApp() throws IOException { + deleteLock(); + 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 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 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); + } +}