Home | History | Annotate | Download | only in support
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package tests.support;
     19 
     20 import junit.framework.AssertionFailedError;
     21 import junit.framework.TestCase;
     22 
     23 import java.io.File;
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.io.InputStreamReader;
     27 import java.io.Reader;
     28 import java.io.StringWriter;
     29 import java.util.Arrays;
     30 import java.util.concurrent.Callable;
     31 import java.util.concurrent.ExecutorService;
     32 import java.util.concurrent.Executors;
     33 import java.util.concurrent.Future;
     34 import java.util.concurrent.TimeUnit;
     35 
     36 public class Support_Exec extends TestCase {
     37 
     38     private static final boolean againstDalvik
     39             = System.getProperty("java.vendor").contains("Android");
     40 
     41     /**
     42      * Returns a builder configured with the appropriate VM ("dalvikvm" or
     43      * "java") and arguments (as specified by the system property
     44      * {@code hy.test.vmargs}).
     45      */
     46     public static ProcessBuilder javaProcessBuilder()
     47             throws IOException, InterruptedException {
     48         ProcessBuilder builder = new ProcessBuilder();
     49 
     50         // construct the name of executable file
     51         builder.command().add(againstDalvik ? "dalvikvm" : "java");
     52 
     53         // parse hy.test.vmargs if was given
     54         String testVMArgs = System.getProperty("hy.test.vmargs");
     55         if (testVMArgs != null) {
     56             builder.command().addAll(Arrays.asList(testVMArgs.split("\\s+")));
     57         }
     58 
     59         return builder;
     60     }
     61 
     62     /**
     63      * Returns a command-line ready path formed by joining the path elements
     64      * with the system path separator as a separator.
     65      */
     66     public static String createPath(String... elements) {
     67         StringBuilder result = new StringBuilder();
     68         for (String element : elements) {
     69             result.append(File.pathSeparator);
     70             result.append(element);
     71         }
     72         return result.toString();
     73     }
     74 
     75     /**
     76      * Starts the specified process, collects its output from standard out and
     77      * standard err, and returns. If the stream emits anything to standard err,
     78      * an AssertionFailedError will be thrown.
     79      *
     80      * <p>This method assumes the target process will complete within ten
     81      * seconds. If it does not, an AssertionFailedError will be thrown.
     82      */
     83     public static String execAndGetOutput(ProcessBuilder builder) throws IOException {
     84         Process process = builder.start();
     85         ExecutorService executorService = Executors.newFixedThreadPool(2);
     86         try {
     87             Future<String> errFuture = executorService.submit(
     88                     streamToStringCallable(process.getErrorStream()));
     89             Future<String> outFuture = executorService.submit(
     90                     streamToStringCallable(process.getInputStream()));
     91 
     92             Throwable failure;
     93             String out = "";
     94             try {
     95                 out = outFuture.get(10, TimeUnit.SECONDS);
     96                 String err = errFuture.get(10, TimeUnit.SECONDS);
     97                 failure = err.length() > 0
     98                         ? new AssertionFailedError("Unexpected err stream data:\n" + err)
     99                         : null;
    100             } catch (Exception e) {
    101                 failure = e;
    102             }
    103 
    104             if (failure != null) {
    105                 AssertionFailedError error = new AssertionFailedError(
    106                         "Failed to execute " + builder.command() + "; output was:\n" + out);
    107                 error.initCause(failure);
    108                 throw error;
    109             } else {
    110                 return out;
    111             }
    112         } finally {
    113             executorService.shutdown();
    114         }
    115     }
    116 
    117     /**
    118      * Starts the process described by 'builder', and asserts that it sees
    119      * 'expectedOut' on stdout and 'expectedErr' on stderr. Times out after
    120      * 10s.
    121      */
    122     public static void execAndCheckOutput(ProcessBuilder builder,
    123             String expectedOut, String expectedErr) throws Exception {
    124         Process process = builder.start();
    125         ExecutorService executorService = Executors.newFixedThreadPool(2);
    126         try {
    127             Future<String> errFuture =
    128                     executorService.submit(streamToStringCallable(process.getErrorStream()));
    129             Future<String> outFuture =
    130                     executorService.submit(streamToStringCallable(process.getInputStream()));
    131             assertEquals(expectedOut, outFuture.get(10, TimeUnit.SECONDS));
    132             assertEquals(expectedErr, errFuture.get(10, TimeUnit.SECONDS));
    133         } finally {
    134             executorService.shutdown();
    135             process.waitFor();
    136         }
    137     }
    138 
    139     private static Callable<String> streamToStringCallable(final InputStream in) {
    140         return new Callable<String>() {
    141             public String call() throws Exception {
    142                 StringWriter writer = new StringWriter();
    143                 Reader reader = new InputStreamReader(in);
    144                 int c;
    145                 while ((c = reader.read()) != -1) {
    146                     writer.write(c);
    147                 }
    148                 return writer.toString();
    149             }
    150         };
    151     }
    152 }
    153