1 /*
   2  * Copyright (c) 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 package jdk.testlibrary;
  25 
  26 import static jdk.testlibrary.Asserts.assertNotEquals;
  27 import static jdk.testlibrary.Asserts.assertTrue;
  28 
  29 import java.util.List;
  30 import java.util.concurrent.CountDownLatch;
  31 
  32 /**
  33  * The helper class for starting and stopping {@link Process} in a separate thread.
  34  */
  35 public class ProcessThread extends TestThread {
  36 
  37     /**
  38      * Creates a new {@code ProcessThread} object.
  39      *
  40      * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
  41      */
  42     public ProcessThread(List<String> cmd) {
  43         super(new ProcessRunnable(cmd));
  44     }
  45 
  46     /**
  47      * Creates a new {@code ProcessThread} object.
  48      *
  49      * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
  50      */
  51     public ProcessThread(String... cmd) {
  52         super(new ProcessRunnable(cmd));
  53     }
  54 
  55     /**
  56      * Creates a new {@code ProcessThread} object.
  57      *
  58      * @param threadName The name of thread
  59      * @param cmd The list of program and its arguments to pass to {@link ProcessBuilder}
  60      */
  61     public ProcessThread(String threadName, List<String> cmd) {
  62         super(new ProcessRunnable(cmd), threadName);
  63     }
  64 
  65     /**
  66      * Creates a new {@code ProcessThread} object.
  67      *
  68      * @param threadName The name of thread
  69      * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder}
  70      */
  71     public ProcessThread(String threadName, String... cmd) {
  72         super(new ProcessRunnable(cmd), threadName);
  73     }
  74 
  75     /**
  76      * Stops {@link Process} started by {@code ProcessRunnable}.
  77      *
  78      * @throws InterruptedException
  79      */
  80     public void stopProcess() throws InterruptedException {
  81         ((ProcessRunnable) getRunnable()).stopProcess();
  82     }
  83 
  84     /**
  85      * {@link Runnable} interface for starting and stopping {@link Process}.
  86      */
  87     static class ProcessRunnable extends XRun {
  88 
  89         private final ProcessBuilder processBuilder;
  90         private final CountDownLatch latch;
  91         private volatile Process process;
  92 
  93         /**
  94          * Creates a new {@code ProcessRunnable} object.
  95          *
  96          * @param cmd The list of program and its arguments to to pass to {@link ProcessBuilder}
  97          */
  98         public ProcessRunnable(List<String> cmd) {
  99             super();
 100             this.processBuilder = new ProcessBuilder(cmd);
 101             this.latch = new CountDownLatch(1);
 102         }
 103 
 104         /**
 105          * Creates a new {@code ProcessRunnable} object.
 106          *
 107          * @param cmd The string array of program and its arguments to to pass to {@link ProcessBuilder}
 108          */
 109         public ProcessRunnable(String... cmd) {
 110             super();
 111             this.processBuilder = new ProcessBuilder(cmd);
 112             this.latch = new CountDownLatch(1);
 113         }
 114 
 115         /**
 116          * Starts the process in {@code ProcessThread}.
 117          * All exceptions which occurs here will be caught and stored in {@code ProcessThread}.
 118          *
 119          * see {@link XRun}
 120          */
 121         @Override
 122         public void xrun() throws Throwable {
 123             this.process = processBuilder.start();
 124             // Release when process is started
 125             latch.countDown();
 126 
 127             // Will block...
 128             OutputAnalyzer output = new OutputAnalyzer(this.process);
 129 
 130             assertTrue(output.getOutput().isEmpty(), "Should get an empty output, got: "
 131                         + Utils.NEW_LINE + output.getOutput());
 132             assertNotEquals(output.getExitValue(), 0,
 133                     "Process exited with unexpected exit code");
 134         }
 135 
 136         /**
 137          * Stops the process.
 138          *
 139          * @throws InterruptedException
 140          */
 141         public void stopProcess() throws InterruptedException {
 142             // Wait until process is started
 143             latch.await();
 144             if (this.process != null) {
 145                 this.process.destroy();
 146             }
 147         }
 148 
 149     }
 150 
 151 }