/*
 * Copyright (c) 2005, 2006, 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       OnThrowTest.java
 *   @bug        6263814
 *   @summary    Test for -agentlib::[onthrow,launch]
 *   @author     Kelly O'Hair
 *
 *  @run compile -g OnThrowTest.java
 *  @run compile -g OnThrowTarget.java
 *  @run compile -g VMConnection.java
 *  @run main/othervm OnThrowTest
 */

import java.io.File;
import java.io.FileWriter;
import java.io.BufferedInputStream;
import java.io.IOException;

public class OnThrowTest extends Object {

    /* Full pathname for file to be touched or created by the launch */
    private String touchFile;

    OnThrowTest() throws Exception {
        /* Name of touch file */
        touchFile = System.getProperty("test.classes") +
                    File.separator + "OnThrowLaunchTouchFile";
        /* Make sure it's gone when we start */
        File f = new File(touchFile);
        f.delete();
        if ( f.exists() ) {
            throw new Exception("Test failed: Cannot remove old touch file: " +
                  touchFile);
        }
    }

    /* Used to see if touch file exists */
    private boolean touchFileExists() {
        File f = new File(touchFile);
        return f.exists();
    }

    /**
     * Run an arbitrary command
     *
     */
    public void run(String[] cmdStrings) throws Exception {
        StringBuffer stdoutBuffer = new StringBuffer();
        StringBuffer stderrBuffer = new StringBuffer();
        String CR = System.getProperty("line.separator");
        int subprocessStatus = 1;

        System.out.print(CR + "runCommand method about to execute: ");
        for (int iNdx = 0; iNdx < cmdStrings.length; iNdx++) {
            System.out.print(" ");
            System.out.print(cmdStrings[iNdx]);
        }
        System.out.println(CR);

        try {
            Process process = Runtime.getRuntime().
                exec(VMConnection.insertDebuggeeVMOptions(cmdStrings));
            int BUFFERSIZE = 4096;
            /*
             * Gather up the output of the subprocess using non-blocking
             * reads so we can get both the subprocess stdout and the
             * subprocess stderr without overfilling any buffers.
             */
            BufferedInputStream is =
                new BufferedInputStream(process.getInputStream());
            int isLen = 0;
            byte[] isBuf = new byte[BUFFERSIZE];

            BufferedInputStream es =
                new BufferedInputStream(process.getErrorStream());
            int esLen = 0;
            byte[] esBuf = new byte[BUFFERSIZE];

            do {
                isLen = is.read(isBuf);
                if (isLen > 0) {
                    stdoutBuffer.append(new String(isBuf, 0, isLen));
                }
                esLen = es.read(esBuf);
                if (esLen > 0) {
                    stderrBuffer.append(new String(esBuf, 0, esLen));
                }
            } while ((isLen > -1) || (esLen > -1));

            try {
                process.waitFor();
                subprocessStatus = process.exitValue();
                process = null;
            } catch(java.lang.InterruptedException e) {
                System.err.println("InterruptedException: " + e);
                throw new Exception("Test failed: process interrupted");
            }

        } catch(IOException ex) {
            System.err.println("IO error: " + ex);
            throw new Exception("Test failed: IO error running process");
        }

        System.out.println(CR + "--- Return code was: " +
                           CR + Integer.toString(subprocessStatus));
        System.out.println(CR + "--- Return stdout was: " +
                           CR + stdoutBuffer.toString());
        System.out.println(CR + "--- Return stderr was: " +
                           CR + stderrBuffer.toString());

    }

    public static void main(String[] args) throws Exception {

        OnThrowTest myTest = new OnThrowTest();

        String launch = System.getProperty("test.classes") +
                        File.separator + "OnThrowLaunch.sh";
        File f = new File(launch);
        f.delete();
        FileWriter fw = new FileWriter(f);
        fw.write("#!/bin/sh\n echo OK $* > " +
                 myTest.touchFile.replace('\\','/') + "\n exit 0\n");
        fw.flush();
        fw.close();
        if ( ! f.exists() ) {
            throw new Exception("Test failed: sh file not created: " + launch);
        }

        String javaExe = System.getProperty("java.home") +
                         File.separator + "bin" + File.separator + "java";
        String targetClass = "OnThrowTarget";
        String cmds [] = {javaExe,
                          "-agentlib:jdwp=transport=dt_socket," +
                          "onthrow=OnThrowException,server=y,suspend=n," +
                          "launch=" + "sh " + launch.replace('\\','/'),
                          targetClass};

        /* Run the target app, which will launch the launch script */
        myTest.run(cmds);
        if ( !myTest.touchFileExists() ) {
            throw new Exception("Test failed: touch file not found: " +
                  myTest.touchFile);
        }

        System.out.println("Test passed: launch create file");
    }

}
