/* * Copyright (c) 2016, Oracle and/or its affiliates. * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.oracle.truffle.llvm.test.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.TimeUnit; public class ProcessUtil { private static final int BUFFER_SIZE = 1024; private static final int PROCESS_WAIT_TIMEOUT = 5000; /** * This class represents the result of a native command executed by the operating system. */ public static final class ProcessResult { private final String originalCommand; private final String stdErr; private final String stdOutput; private final int returnValue; private ProcessResult(String originalCommand, int returnValue, String stdErr, String stdInput) { this.originalCommand = originalCommand; this.returnValue = returnValue; this.stdErr = stdErr; this.stdOutput = stdInput; } /** * Gets the Standard error stream of the executed native command. * * @return <code>stderr</code> as a string */ public String getStdErr() { return stdErr; } /** * Gets the Standard output stream of the executed native command. * * @return <code>stdout</code> as a string */ public String getStdOutput() { return stdOutput; } /** * Gets the return value of the executed native command. * * @return <code>stderr</code> as a string */ public int getReturnValue() { return returnValue; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("command : " + originalCommand + "\n"); sb.append("stderr: " + stdErr + "\n"); sb.append("stdout: " + stdOutput + "\n"); sb.append("return value: " + returnValue + "\n"); return sb.toString(); } } public static ProcessResult executeNativeCommandZeroReturn(String command) { ProcessResult result = executeNativeCommand(command); checkNoError(result); return result; } /** * Executes a native command and checks that the return value of the process is 0. */ public static ProcessResult executeNativeCommandZeroReturn(String... command) { ProcessResult result; if (command.length == 1) { result = executeNativeCommand(command[0]); } else { result = executeNativeCommand(concatCommand(command)); } checkNoError(result); return result; } /** * Concats a command by introducing whitespaces between the array elements. */ static String concatCommand(String[] command) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < command.length; i++) { if (i != 0) { sb.append(" "); } sb.append(command[i]); } return sb.toString(); } public static ProcessResult executeNativeCommand(String command) { if (command == null) { throw new IllegalArgumentException("command is null!"); } try { Process process = Runtime.getRuntime().exec(command); process.waitFor(PROCESS_WAIT_TIMEOUT, TimeUnit.MILLISECONDS); String readError = readStreamAndClose(process.getErrorStream()); String inputStream = readStreamAndClose(process.getInputStream()); int llvmResult = process.exitValue(); process.destroyForcibly(); return new ProcessResult(command, llvmResult, readError, inputStream); } catch (Exception e) { throw new RuntimeException(command + " ", e); } } public static void checkNoError(ProcessResult processResult) { if (processResult.getReturnValue() != 0) { throw new IllegalStateException(processResult.originalCommand + " exited with value " + processResult.getReturnValue() + " " + processResult.getStdErr()); } } public static String readStreamAndClose(InputStream inputStream) throws IOException { final ByteArrayOutputStream result = new ByteArrayOutputStream(); final byte[] buffer = new byte[BUFFER_SIZE]; int length; while ((length = inputStream.read(buffer)) != -1) { result.write(buffer, 0, length); } inputStream.close(); result.close(); return result.toString(); } }