1 /*
   2  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 /*
  26  *
  27  * Support classes for running jhat tests
  28  *
  29  */
  30 
  31 import java.io.InputStream;
  32 import java.io.IOException;
  33 import java.io.File;
  34 import java.io.BufferedInputStream;
  35 import java.io.PrintStream;
  36 
  37 /*
  38  * Helper class to direct process output to a StringBuffer
  39  */
  40 class MyInputStream implements Runnable {
  41     private String              name;
  42     private BufferedInputStream in;
  43     private StringBuffer        buffer;
  44 
  45     /* Create MyInputStream that saves all output to a StringBuffer */
  46     MyInputStream(String name, InputStream in) {
  47         this.name = name;
  48         this.in = new BufferedInputStream(in);
  49         buffer = new StringBuffer(4096);
  50         Thread thr = new Thread(this);
  51         thr.setDaemon(true);
  52         thr.start();
  53     }
  54 
  55     /* Dump the buffer */
  56     void dump(PrintStream x) {
  57         String str = buffer.toString();
  58         x.println("<beginning of " + name + " buffer>");
  59         x.println(str);
  60         x.println("<end of buffer>");
  61     }
  62 
  63     /* Check to see if a pattern is inside the output. */
  64     boolean contains(String pattern) {
  65         String str = buffer.toString();
  66         return str.contains(pattern);
  67     }
  68 
  69     /* Runs as a separate thread capturing all output in a StringBuffer */
  70     public void run() {
  71         try {
  72             byte b[] = new byte[100];
  73             for (;;) {
  74                 int n = in.read(b);
  75                 String str;
  76                 if (n < 0) {
  77                     break;
  78                 }
  79                 str = new String(b, 0, n);
  80                 buffer.append(str);
  81                 System.out.print(str);
  82             }
  83         } catch (IOException ioe) { /* skip */ }
  84     }
  85 }
  86 
  87 /*
  88  * Main jhat run
  89  */
  90 public class HatRun {
  91 
  92     private String        all_hprof_options;
  93     private String        all_hat_options;
  94     private String        dumpfile;
  95     private MyInputStream output;
  96     private MyInputStream error;
  97 
  98     /* Create a Hat run process */
  99     public HatRun(String hprof_options, String hat_options)
 100     {
 101         all_hprof_options = hprof_options;
 102         all_hat_options   = hat_options;
 103     }
 104 
 105     /*
 106      * Execute a process with an -agentpath or -agentlib command option
 107      */
 108     public void runit(String class_name)
 109     {
 110         runit(class_name, null);
 111     }
 112 
 113     /*
 114      * Execute a command.
 115      */
 116     private void execute(String cmd[])
 117     {
 118         /* Begin process */
 119         Process p;
 120         String cmdLine = "";
 121         int i;
 122 
 123         for ( i = 0 ; i < cmd.length; i++ ) {
 124           cmdLine += cmd[i];
 125           cmdLine += " ";
 126         }
 127         System.out.println("Starting: " + cmdLine);
 128 
 129         try {
 130             p = Runtime.getRuntime().exec(cmd);
 131         } catch ( IOException e ) {
 132             throw new RuntimeException("Test failed - exec got IO exception");
 133         }
 134 
 135         /* Save process output in StringBuffers */
 136         output = new MyInputStream("Input Stream", p.getInputStream());
 137         error  = new MyInputStream("Error Stream", p.getErrorStream());
 138 
 139         /* Wait for process to complete, and if exit code is non-zero we fail */
 140         try {
 141             int exitStatus;
 142             exitStatus = p.waitFor();
 143             if ( exitStatus != 0) {
 144                 System.out.println("Exit code is " + exitStatus);
 145                 error.dump(System.out);
 146                 output.dump(System.out);
 147                 throw new RuntimeException("Test failed - " +
 148                                     "exit return code non-zero " +
 149                                     "(exitStatus==" + exitStatus + ")");
 150             }
 151         } catch ( InterruptedException e ) {
 152             throw new RuntimeException("Test failed - process interrupted");
 153         }
 154         System.out.println("Completed: " + cmdLine);
 155     }
 156 
 157     /*
 158      * Execute a process with an -agentpath or -agentlib command option
 159      *    plus any set of other java options.
 160      */
 161     public void runit(String class_name, String vm_options[])
 162     {
 163         String jre_home  = System.getProperty("java.home");
 164         String sdk_home  = (jre_home.endsWith("jre") ?
 165                             (jre_home + File.separator + "..") :
 166                             jre_home );
 167         String cdir      = System.getProperty("test.classes", ".");
 168         String os_arch   = System.getProperty("os.arch");
 169         String os_name   = System.getProperty("os.name");
 170         boolean d64      = os_name.equals("SunOS");
 171         String java      = jre_home
 172                              + File.separator + "bin"
 173                              + File.separator + "java";
 174         String jhat      = sdk_home + File.separator + "bin"
 175                            + File.separator + "jhat";
 176         /* Array of strings to be passed in for exec:
 177          *   1. java
 178          *   2. -Dtest.classes=.
 179          *   3. -d64                 (optional)
 180          *   4. -Xcheck:jni          (Just because it finds bugs)
 181          *   5. -Xverify:all         (Make sure verification is on full blast)
 182          *   6. -agent
 183          *       vm_options
 184          *   7+i. classname
 185          */
 186         int nvm_options = 0;
 187         if ( vm_options != null ) nvm_options = vm_options.length;
 188         String cmd[]     = new String[1 + (d64?1:0) + 7 + nvm_options];
 189         int i,j;
 190 
 191         i = 0;
 192         cmd[i++] = java;
 193         cmd[i++] = "-cp";
 194         cmd[i++] = cdir;
 195         cmd[i++] = "-Dtest.classes=" + cdir;
 196         if ( d64 ) {
 197             cmd[i++] = "-d64";
 198         }
 199         cmd[i++] = "-Xcheck:jni";
 200         cmd[i++] = "-Xverify:all";
 201         dumpfile= cdir + File.separator + class_name + ".hdump";
 202         cmd[i++] = "-agentlib:hprof=" + all_hprof_options
 203                     + ",format=b,file=" + dumpfile;
 204         /* Add any special VM options */
 205         for ( j = 0; j < nvm_options; j++ ) {
 206             cmd[i++] = vm_options[j];
 207         }
 208         /* Add classname */
 209         cmd[i++] = class_name;
 210 
 211         /* Execute process */
 212         execute(cmd);
 213 
 214         /* Run jhat */
 215         String jhat_cmd[] = new String[4];
 216         jhat_cmd[0] = jhat;
 217         jhat_cmd[1] = "-debug";
 218         jhat_cmd[2] = "2";
 219         jhat_cmd[3] = dumpfile;
 220 
 221         /* Execute process */
 222         execute(jhat_cmd);
 223 
 224     }
 225 
 226     /* Does the pattern appear in the output of this process */
 227     public boolean output_contains(String pattern)
 228     {
 229         return output.contains(pattern) || error.contains(pattern);
 230     }
 231 }